From 510377d2cb4b12d1a421e8a88bd7edb86f223451 Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Tue, 12 Jan 2016 19:50:48 +0100 Subject: Introduce the Updater class which * contains methods designed to be run once. * is able to upgrade the datastore or the configuration. * is based on methods names, stored in a text file with ';' separator (updates.txt). * begins with existing function 'mergeDeprecatedConfigFile()' (options.php). --- application/Config.php | 27 ------ application/LinkDB.php | 10 +- application/LinkFilter.php | 1 - application/Updater.php | 228 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 232 insertions(+), 34 deletions(-) create mode 100644 application/Updater.php (limited to 'application') diff --git a/application/Config.php b/application/Config.php index 9af5a535..05a59452 100644 --- a/application/Config.php +++ b/application/Config.php @@ -173,33 +173,6 @@ function load_plugin_parameter_values($plugins, $config) return $out; } -/** - * Milestone 0.9 - shaarli/Shaarli#41: options.php is not supported anymore. - * ==> if user is loggedIn, merge its content with config.php, then delete options.php. - * - * @param array $config contains all configuration fields. - * @param bool $isLoggedIn true if user is logged in. - * - * @return void - */ -function mergeDeprecatedConfig($config, $isLoggedIn) -{ - $config_file = $config['config']['CONFIG_FILE']; - - if (is_file($config['config']['DATADIR'].'/options.php') && $isLoggedIn) { - include $config['config']['DATADIR'].'/options.php'; - - // Load GLOBALS into config - foreach ($GLOBALS as $key => $value) { - $config[$key] = $value; - } - $config['config']['CONFIG_FILE'] = $config_file; - writeConfig($config, $isLoggedIn); - - unlink($config['config']['DATADIR'].'/options.php'); - } -} - /** * Exception used if a mandatory field is missing in given configuration. */ diff --git a/application/LinkDB.php b/application/LinkDB.php index 19ca6435..a95b3f36 100644 --- a/application/LinkDB.php +++ b/application/LinkDB.php @@ -260,14 +260,11 @@ You use the community supported version of the original Shaarli project, by Seba } } - // Keep the list of the mapping URLs-->linkdate up-to-date. $this->_urls = array(); - foreach ($this->_links as $link) { + foreach ($this->_links as &$link) { + // Keep the list of the mapping URLs-->linkdate up-to-date. $this->_urls[$link['url']] = $link['linkdate']; - } - - // Escape links data - foreach($this->_links as &$link) { + // Sanitize data fields. sanitizeLink($link); // Do not use the redirector for internal links (Shaarli note URL starting with a '?'). if (!empty($this->_redirector) && !startsWith($link['url'], '?')) { @@ -381,6 +378,7 @@ You use the community supported version of the original Shaarli project, by Seba } $linkDays = array_keys($linkDays); sort($linkDays); + return $linkDays; } } diff --git a/application/LinkFilter.php b/application/LinkFilter.php index b2e6530f..096d3b04 100644 --- a/application/LinkFilter.php +++ b/application/LinkFilter.php @@ -260,7 +260,6 @@ class LinkFilter * Convert a list of tags (str) to an array. Also * - handle case sensitivity. * - accepts spaces commas as separator. - * - remove private tags for loggedout users. * * @param string $tags string containing a list of tags. * @param bool $casesensitive will convert everything to lowercase if false. diff --git a/application/Updater.php b/application/Updater.php new file mode 100644 index 00000000..20ae0c4d --- /dev/null +++ b/application/Updater.php @@ -0,0 +1,228 @@ +doneUpdates = $doneUpdates; + $this->config = $config; + $this->linkDB = $linkDB; + $this->isLoggedIn = $isLoggedIn; + + // Retrieve all update methods. + $class = new ReflectionClass($this); + $this->methods = $class->getMethods(); + } + + /** + * Run all new updates. + * Update methods have to start with 'updateMethod' and return true (on success). + * + * @return array An array containing ran updates. + * + * @throws UpdaterException If something went wrong. + */ + public function update() + { + $updatesRan = array(); + + // If the user isn't logged in, exit without updating. + if ($this->isLoggedIn !== true) { + return $updatesRan; + } + + if ($this->methods == null) { + throw new UpdaterException('Couldn\'t retrieve Updater class methods.'); + } + + foreach ($this->methods as $method) { + // Not an update method or already done, pass. + if (! startsWith($method->getName(), 'updateMethod') + || in_array($method->getName(), $this->doneUpdates) + ) { + continue; + } + + try { + $method->setAccessible(true); + $res = $method->invoke($this); + // Update method must return true to be considered processed. + if ($res === true) { + $updatesRan[] = $method->getName(); + } + } catch (Exception $e) { + throw new UpdaterException($method, $e); + } + } + + $this->doneUpdates = array_merge($this->doneUpdates, $updatesRan); + + return $updatesRan; + } + + /** + * @return array Updates methods already processed. + */ + public function getDoneUpdates() + { + return $this->doneUpdates; + } + + /** + * Move deprecated options.php to config.php. + * + * Milestone 0.9 (old versioning) - shaarli/Shaarli#41: + * options.php is not supported anymore. + */ + public function updateMethodMergeDeprecatedConfigFile() + { + $config_file = $this->config['config']['CONFIG_FILE']; + + if (is_file($this->config['config']['DATADIR'].'/options.php')) { + include $this->config['config']['DATADIR'].'/options.php'; + + // Load GLOBALS into config + foreach ($GLOBALS as $key => $value) { + $this->config[$key] = $value; + } + $this->config['config']['CONFIG_FILE'] = $config_file; + writeConfig($this->config, $this->isLoggedIn); + + unlink($this->config['config']['DATADIR'].'/options.php'); + } + + return true; + } +} + +/** + * Class UpdaterException. + */ +class UpdaterException extends Exception +{ + /** + * @var string Method where the error occurred. + */ + protected $method; + + /** + * @var Exception The parent exception. + */ + protected $previous; + + /** + * Constructor. + * + * @param string $message Force the error message if set. + * @param string $method Method where the error occurred. + * @param Exception|bool $previous Parent exception. + */ + public function __construct($message = '', $method = '', $previous = false) + { + $this->method = $method; + $this->previous = $previous; + $this->message = $this->buildMessage($message); + } + + /** + * Build the exception error message. + * + * @param string $message Optional given error message. + * + * @return string The built error message. + */ + private function buildMessage($message) + { + $out = ''; + if (! empty($message)) { + $out .= $message . PHP_EOL; + } + + if (! empty($this->method)) { + $out .= 'An error occurred while running the update '. $this->method . PHP_EOL; + } + + if (! empty($this->previous)) { + $out .= ' '. $this->previous->getMessage(); + } + + return $out; + } +} + + +/** + * Read the updates file, and return already done updates. + * + * @param string $updatesFilepath Updates file path. + * + * @return array Already done update methods. + */ +function read_updates_file($updatesFilepath) +{ + if (! empty($updatesFilepath) && is_file($updatesFilepath)) { + $content = file_get_contents($updatesFilepath); + if (! empty($content)) { + return explode(';', $content); + } + } + return array(); +} + +/** + * Write updates file. + * + * @param string $updatesFilepath Updates file path. + * @param array $updates Updates array to write. + * + * @throws Exception Couldn't write version number. + */ +function write_updates_file($updatesFilepath, $updates) +{ + if (empty($updatesFilepath)) { + throw new Exception('Updates file path is not set, can\'t write updates.'); + } + + $res = file_put_contents($updatesFilepath, implode(';', $updates)); + if ($res === false) { + throw new Exception('Unable to write updates in '. $updatesFilepath . '.'); + } +} -- cgit v1.2.3