aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--application/ApplicationUtils.php20
-rw-r--r--application/ThemeUtils.php33
-rw-r--r--application/Updater.php29
-rw-r--r--composer.json1
-rw-r--r--tests/ApplicationUtilsTest.php44
-rw-r--r--tests/ThemeUtilsTest.php55
-rw-r--r--tests/Updater/UpdaterTest.php44
-rw-r--r--tpl/default/configure.html6
8 files changed, 163 insertions, 69 deletions
diff --git a/application/ApplicationUtils.php b/application/ApplicationUtils.php
index cc009a1d..a0f482b0 100644
--- a/application/ApplicationUtils.php
+++ b/application/ApplicationUtils.php
@@ -195,24 +195,4 @@ class ApplicationUtils
195 195
196 return $errors; 196 return $errors;
197 } 197 }
198
199 /**
200 * Get a list of available themes.
201 *
202 * It will return the name of any directory present in the template folder.
203 *
204 * @param string $tplDir Templates main directory.
205 *
206 * @return array List of theme names.
207 */
208 public static function getThemes($tplDir)
209 {
210 $allTheme = glob($tplDir.'/*', GLOB_ONLYDIR);
211 $themes = [];
212 foreach ($allTheme as $value) {
213 $themes[] = str_replace($tplDir.'/', '', $value);
214 }
215
216 return $themes;
217 }
218} 198}
diff --git a/application/ThemeUtils.php b/application/ThemeUtils.php
new file mode 100644
index 00000000..2718ed13
--- /dev/null
+++ b/application/ThemeUtils.php
@@ -0,0 +1,33 @@
1<?php
2
3namespace Shaarli;
4
5/**
6 * Class ThemeUtils
7 *
8 * Utility functions related to theme management.
9 *
10 * @package Shaarli
11 */
12class ThemeUtils
13{
14 /**
15 * Get a list of available themes.
16 *
17 * It will return the name of any directory present in the template folder.
18 *
19 * @param string $tplDir Templates main directory.
20 *
21 * @return array List of theme names.
22 */
23 public static function getThemes($tplDir)
24 {
25 $allTheme = glob($tplDir.'/*', GLOB_ONLYDIR);
26 $themes = [];
27 foreach ($allTheme as $value) {
28 $themes[] = str_replace($tplDir.'/', '', $value);
29 }
30
31 return $themes;
32 }
33}
diff --git a/application/Updater.php b/application/Updater.php
index 38de3350..621c7238 100644
--- a/application/Updater.php
+++ b/application/Updater.php
@@ -279,6 +279,35 @@ class Updater
279 $this->conf->write($this->isLoggedIn); 279 $this->conf->write($this->isLoggedIn);
280 return true; 280 return true;
281 } 281 }
282
283 /**
284 * New setting: theme name. If the default theme is used, nothing to do.
285 *
286 * If the user uses a custom theme, raintpl_tpl dir is updated to the parent directory,
287 * and the current theme is set as default in the theme setting.
288 *
289 * @return bool true if the update is successful, false otherwise.
290 */
291 public function updateMethodDefaultTheme()
292 {
293 // raintpl_tpl isn't the root template directory anymore.
294 // We run the update only if this folder still contains the template files.
295 $tplDir = $this->conf->get('resource.raintpl_tpl');
296 $tplFile = $tplDir . '/linklist.html';
297 if (! file_exists($tplFile)) {
298 return true;
299 }
300
301 $parent = dirname($tplDir);
302 $this->conf->set('resource.raintpl_tpl', $parent);
303 $this->conf->set('resource.theme', trim(str_replace($parent, '', $tplDir), '/'));
304 $this->conf->write($this->isLoggedIn);
305
306 // Dependency injection gore
307 RainTPL::$tpl_dir = $tplDir;
308
309 return true;
310 }
282} 311}
283 312
284/** 313/**
diff --git a/composer.json b/composer.json
index cfbde1a0..2fed0df7 100644
--- a/composer.json
+++ b/composer.json
@@ -24,6 +24,7 @@
24 }, 24 },
25 "autoload": { 25 "autoload": {
26 "psr-4": { 26 "psr-4": {
27 "Shaarli\\": "application",
27 "Shaarli\\Api\\": "application/api/", 28 "Shaarli\\Api\\": "application/api/",
28 "Shaarli\\Api\\Controllers\\": "application/api/controllers", 29 "Shaarli\\Api\\Controllers\\": "application/api/controllers",
29 "Shaarli\\Api\\Exceptions\\": "application/api/exceptions" 30 "Shaarli\\Api\\Exceptions\\": "application/api/exceptions"
diff --git a/tests/ApplicationUtilsTest.php b/tests/ApplicationUtilsTest.php
index c39649e8..634bd0ed 100644
--- a/tests/ApplicationUtilsTest.php
+++ b/tests/ApplicationUtilsTest.php
@@ -331,48 +331,4 @@ class ApplicationUtilsTest extends PHPUnit_Framework_TestCase
331 ApplicationUtils::checkResourcePermissions($conf) 331 ApplicationUtils::checkResourcePermissions($conf)
332 ); 332 );
333 } 333 }
334
335 /**
336 * Test getThemes() with existing theme directories.
337 */
338 public function testGetThemes()
339 {
340 $themes = ['theme1', 'default', 'Bl1p_- bL0p'];
341 foreach ($themes as $theme) {
342 mkdir('sandbox/tpl/'. $theme, 0777, true);
343 }
344
345 // include a file which should be ignored
346 touch('sandbox/tpl/supertheme');
347
348 $res = ApplicationUtils::getThemes('sandbox/tpl/');
349 foreach ($res as $theme) {
350 $this->assertTrue(in_array($theme, $themes));
351 }
352 $this->assertFalse(in_array('supertheme', $res));
353
354 foreach ($themes as $theme) {
355 rmdir('sandbox/tpl/'. $theme);
356 }
357 unlink('sandbox/tpl/supertheme');
358 rmdir('sandbox/tpl');
359 }
360
361 /**
362 * Test getThemes() without any theme dir.
363 */
364 public function testGetThemesEmpty()
365 {
366 mkdir('sandbox/tpl/', 0777, true);
367 $this->assertEquals([], ApplicationUtils::getThemes('sandbox/tpl/'));
368 rmdir('sandbox/tpl/');
369 }
370
371 /**
372 * Test getThemes() with an invalid path.
373 */
374 public function testGetThemesInvalid()
375 {
376 $this->assertEquals([], ApplicationUtils::getThemes('nope'));
377 }
378} 334}
diff --git a/tests/ThemeUtilsTest.php b/tests/ThemeUtilsTest.php
new file mode 100644
index 00000000..e44564be
--- /dev/null
+++ b/tests/ThemeUtilsTest.php
@@ -0,0 +1,55 @@
1<?php
2
3namespace Shaarli;
4
5/**
6 * Class ThemeUtilsTest
7 *
8 * @package Shaarli
9 */
10class ThemeUtilsTest extends \PHPUnit_Framework_TestCase
11{
12 /**
13 * Test getThemes() with existing theme directories.
14 */
15 public function testGetThemes()
16 {
17 $themes = ['theme1', 'default', 'Bl1p_- bL0p'];
18 foreach ($themes as $theme) {
19 mkdir('sandbox/tpl/'. $theme, 0755, true);
20 }
21
22 // include a file which should be ignored
23 touch('sandbox/tpl/supertheme');
24
25 $res = ThemeUtils::getThemes('sandbox/tpl/');
26 foreach ($res as $theme) {
27 $this->assertTrue(in_array($theme, $themes));
28 }
29 $this->assertFalse(in_array('supertheme', $res));
30
31 foreach ($themes as $theme) {
32 rmdir('sandbox/tpl/'. $theme);
33 }
34 unlink('sandbox/tpl/supertheme');
35 rmdir('sandbox/tpl');
36 }
37
38 /**
39 * Test getThemes() without any theme dir.
40 */
41 public function testGetThemesEmpty()
42 {
43 mkdir('sandbox/tpl/', 0755, true);
44 $this->assertEquals([], ThemeUtils::getThemes('sandbox/tpl/'));
45 rmdir('sandbox/tpl/');
46 }
47
48 /**
49 * Test getThemes() with an invalid path.
50 */
51 public function testGetThemesInvalid()
52 {
53 $this->assertEquals([], ThemeUtils::getThemes('nope'));
54 }
55}
diff --git a/tests/Updater/UpdaterTest.php b/tests/Updater/UpdaterTest.php
index a1530996..1d15cfaa 100644
--- a/tests/Updater/UpdaterTest.php
+++ b/tests/Updater/UpdaterTest.php
@@ -422,4 +422,48 @@ $GLOBALS[\'privateLinkByDefault\'] = true;';
422 $this->assertTrue($updater->updateMethodDatastoreIds()); 422 $this->assertTrue($updater->updateMethodDatastoreIds());
423 $this->assertEquals($checksum, hash_file('sha1', self::$testDatastore)); 423 $this->assertEquals($checksum, hash_file('sha1', self::$testDatastore));
424 } 424 }
425
426 /**
427 * Test defaultTheme update with default settings: nothing to do.
428 */
429 public function testDefaultThemeWithDefaultSettings()
430 {
431 $sandbox = 'sandbox/config';
432 copy(self::$configFile . '.json.php', $sandbox . '.json.php');
433 $this->conf = new ConfigManager($sandbox);
434 $updater = new Updater([], [], $this->conf, true);
435 $this->assertTrue($updater->updateMethodDefaultTheme());
436
437 $this->assertEquals('tpl/', $this->conf->get('resource.raintpl_tpl'));
438 $this->assertEquals('default', $this->conf->get('resource.theme'));
439 $this->conf = new ConfigManager($sandbox);
440 $this->assertEquals('tpl/', $this->conf->get('resource.raintpl_tpl'));
441 $this->assertEquals('default', $this->conf->get('resource.theme'));
442 unlink($sandbox . '.json.php');
443 }
444
445 /**
446 * Test defaultTheme update with a custom theme in a subfolder
447 */
448 public function testDefaultThemeWithCustomTheme()
449 {
450 $theme = 'iamanartist';
451 $sandbox = 'sandbox/config';
452 copy(self::$configFile . '.json.php', $sandbox . '.json.php');
453 $this->conf = new ConfigManager($sandbox);
454 mkdir('sandbox/'. $theme);
455 touch('sandbox/'. $theme .'/linklist.html');
456 $this->conf->set('resource.raintpl_tpl', 'sandbox/'. $theme .'/');
457 $updater = new Updater([], [], $this->conf, true);
458 $this->assertTrue($updater->updateMethodDefaultTheme());
459
460 $this->assertEquals('sandbox', $this->conf->get('resource.raintpl_tpl'));
461 $this->assertEquals($theme, $this->conf->get('resource.theme'));
462 $this->conf = new ConfigManager($sandbox);
463 $this->assertEquals('sandbox', $this->conf->get('resource.raintpl_tpl'));
464 $this->assertEquals($theme, $this->conf->get('resource.theme'));
465 unlink($sandbox . '.json.php');
466 unlink('sandbox/'. $theme .'/linklist.html');
467 rmdir('sandbox/'. $theme);
468 }
425} 469}
diff --git a/tpl/default/configure.html b/tpl/default/configure.html
index e71133b4..5820e6e4 100644
--- a/tpl/default/configure.html
+++ b/tpl/default/configure.html
@@ -25,11 +25,7 @@
25 <td> 25 <td>
26 <select name="theme" id="theme"> 26 <select name="theme" id="theme">
27 {loop="$theme_available"} 27 {loop="$theme_available"}
28 <option value="{$value}" 28 <option value="{$value}" {if="$value===$theme"}selected{/if}>
29 {if="$value===$theme"}
30 selected="selected"
31 {/if}
32 >
33 {$value|ucfirst} 29 {$value|ucfirst}
34 </option> 30 </option>
35 {/loop} 31 {/loop}