Updater: keep custom theme preference with the new theme setting

This commit is contained in:
ArthurHoaro 2017-01-03 12:01:25 +01:00
parent a0df06517b
commit 04a0e8ea34
8 changed files with 163 additions and 69 deletions

View file

@ -195,24 +195,4 @@ public static function checkResourcePermissions($conf)
return $errors; return $errors;
} }
/**
* Get a list of available themes.
*
* It will return the name of any directory present in the template folder.
*
* @param string $tplDir Templates main directory.
*
* @return array List of theme names.
*/
public static function getThemes($tplDir)
{
$allTheme = glob($tplDir.'/*', GLOB_ONLYDIR);
$themes = [];
foreach ($allTheme as $value) {
$themes[] = str_replace($tplDir.'/', '', $value);
}
return $themes;
}
} }

View file

@ -0,0 +1,33 @@
<?php
namespace Shaarli;
/**
* Class ThemeUtils
*
* Utility functions related to theme management.
*
* @package Shaarli
*/
class ThemeUtils
{
/**
* Get a list of available themes.
*
* It will return the name of any directory present in the template folder.
*
* @param string $tplDir Templates main directory.
*
* @return array List of theme names.
*/
public static function getThemes($tplDir)
{
$allTheme = glob($tplDir.'/*', GLOB_ONLYDIR);
$themes = [];
foreach ($allTheme as $value) {
$themes[] = str_replace($tplDir.'/', '', $value);
}
return $themes;
}
}

View file

@ -279,6 +279,35 @@ public function updateMethodApiSettings()
$this->conf->write($this->isLoggedIn); $this->conf->write($this->isLoggedIn);
return true; return true;
} }
/**
* New setting: theme name. If the default theme is used, nothing to do.
*
* If the user uses a custom theme, raintpl_tpl dir is updated to the parent directory,
* and the current theme is set as default in the theme setting.
*
* @return bool true if the update is successful, false otherwise.
*/
public function updateMethodDefaultTheme()
{
// raintpl_tpl isn't the root template directory anymore.
// We run the update only if this folder still contains the template files.
$tplDir = $this->conf->get('resource.raintpl_tpl');
$tplFile = $tplDir . '/linklist.html';
if (! file_exists($tplFile)) {
return true;
}
$parent = dirname($tplDir);
$this->conf->set('resource.raintpl_tpl', $parent);
$this->conf->set('resource.theme', trim(str_replace($parent, '', $tplDir), '/'));
$this->conf->write($this->isLoggedIn);
// Dependency injection gore
RainTPL::$tpl_dir = $tplDir;
return true;
}
} }
/** /**

View file

@ -24,6 +24,7 @@
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {
"Shaarli\\": "application",
"Shaarli\\Api\\": "application/api/", "Shaarli\\Api\\": "application/api/",
"Shaarli\\Api\\Controllers\\": "application/api/controllers", "Shaarli\\Api\\Controllers\\": "application/api/controllers",
"Shaarli\\Api\\Exceptions\\": "application/api/exceptions" "Shaarli\\Api\\Exceptions\\": "application/api/exceptions"

View file

@ -331,48 +331,4 @@ public function testCheckCurrentResourcePermissionsErrors()
ApplicationUtils::checkResourcePermissions($conf) ApplicationUtils::checkResourcePermissions($conf)
); );
} }
/**
* Test getThemes() with existing theme directories.
*/
public function testGetThemes()
{
$themes = ['theme1', 'default', 'Bl1p_- bL0p'];
foreach ($themes as $theme) {
mkdir('sandbox/tpl/'. $theme, 0777, true);
}
// include a file which should be ignored
touch('sandbox/tpl/supertheme');
$res = ApplicationUtils::getThemes('sandbox/tpl/');
foreach ($res as $theme) {
$this->assertTrue(in_array($theme, $themes));
}
$this->assertFalse(in_array('supertheme', $res));
foreach ($themes as $theme) {
rmdir('sandbox/tpl/'. $theme);
}
unlink('sandbox/tpl/supertheme');
rmdir('sandbox/tpl');
}
/**
* Test getThemes() without any theme dir.
*/
public function testGetThemesEmpty()
{
mkdir('sandbox/tpl/', 0777, true);
$this->assertEquals([], ApplicationUtils::getThemes('sandbox/tpl/'));
rmdir('sandbox/tpl/');
}
/**
* Test getThemes() with an invalid path.
*/
public function testGetThemesInvalid()
{
$this->assertEquals([], ApplicationUtils::getThemes('nope'));
}
} }

55
tests/ThemeUtilsTest.php Normal file
View file

@ -0,0 +1,55 @@
<?php
namespace Shaarli;
/**
* Class ThemeUtilsTest
*
* @package Shaarli
*/
class ThemeUtilsTest extends \PHPUnit_Framework_TestCase
{
/**
* Test getThemes() with existing theme directories.
*/
public function testGetThemes()
{
$themes = ['theme1', 'default', 'Bl1p_- bL0p'];
foreach ($themes as $theme) {
mkdir('sandbox/tpl/'. $theme, 0755, true);
}
// include a file which should be ignored
touch('sandbox/tpl/supertheme');
$res = ThemeUtils::getThemes('sandbox/tpl/');
foreach ($res as $theme) {
$this->assertTrue(in_array($theme, $themes));
}
$this->assertFalse(in_array('supertheme', $res));
foreach ($themes as $theme) {
rmdir('sandbox/tpl/'. $theme);
}
unlink('sandbox/tpl/supertheme');
rmdir('sandbox/tpl');
}
/**
* Test getThemes() without any theme dir.
*/
public function testGetThemesEmpty()
{
mkdir('sandbox/tpl/', 0755, true);
$this->assertEquals([], ThemeUtils::getThemes('sandbox/tpl/'));
rmdir('sandbox/tpl/');
}
/**
* Test getThemes() with an invalid path.
*/
public function testGetThemesInvalid()
{
$this->assertEquals([], ThemeUtils::getThemes('nope'));
}
}

View file

@ -422,4 +422,48 @@ public function testDatastoreIdsNothingToDo()
$this->assertTrue($updater->updateMethodDatastoreIds()); $this->assertTrue($updater->updateMethodDatastoreIds());
$this->assertEquals($checksum, hash_file('sha1', self::$testDatastore)); $this->assertEquals($checksum, hash_file('sha1', self::$testDatastore));
} }
/**
* Test defaultTheme update with default settings: nothing to do.
*/
public function testDefaultThemeWithDefaultSettings()
{
$sandbox = 'sandbox/config';
copy(self::$configFile . '.json.php', $sandbox . '.json.php');
$this->conf = new ConfigManager($sandbox);
$updater = new Updater([], [], $this->conf, true);
$this->assertTrue($updater->updateMethodDefaultTheme());
$this->assertEquals('tpl/', $this->conf->get('resource.raintpl_tpl'));
$this->assertEquals('default', $this->conf->get('resource.theme'));
$this->conf = new ConfigManager($sandbox);
$this->assertEquals('tpl/', $this->conf->get('resource.raintpl_tpl'));
$this->assertEquals('default', $this->conf->get('resource.theme'));
unlink($sandbox . '.json.php');
}
/**
* Test defaultTheme update with a custom theme in a subfolder
*/
public function testDefaultThemeWithCustomTheme()
{
$theme = 'iamanartist';
$sandbox = 'sandbox/config';
copy(self::$configFile . '.json.php', $sandbox . '.json.php');
$this->conf = new ConfigManager($sandbox);
mkdir('sandbox/'. $theme);
touch('sandbox/'. $theme .'/linklist.html');
$this->conf->set('resource.raintpl_tpl', 'sandbox/'. $theme .'/');
$updater = new Updater([], [], $this->conf, true);
$this->assertTrue($updater->updateMethodDefaultTheme());
$this->assertEquals('sandbox', $this->conf->get('resource.raintpl_tpl'));
$this->assertEquals($theme, $this->conf->get('resource.theme'));
$this->conf = new ConfigManager($sandbox);
$this->assertEquals('sandbox', $this->conf->get('resource.raintpl_tpl'));
$this->assertEquals($theme, $this->conf->get('resource.theme'));
unlink($sandbox . '.json.php');
unlink('sandbox/'. $theme .'/linklist.html');
rmdir('sandbox/'. $theme);
}
} }

View file

@ -25,11 +25,7 @@
<td> <td>
<select name="theme" id="theme"> <select name="theme" id="theme">
{loop="$theme_available"} {loop="$theme_available"}
<option value="{$value}" <option value="{$value}" {if="$value===$theme"}selected{/if}>
{if="$value===$theme"}
selected="selected"
{/if}
>
{$value|ucfirst} {$value|ucfirst}
</option> </option>
{/loop} {/loop}