diff options
author | Olivier Paroz <github@oparoz.com> | 2015-09-07 23:06:17 +0300 |
---|---|---|
committer | Olivier Paroz <github@oparoz.com> | 2015-09-07 23:06:17 +0300 |
commit | bbdc4d6a5b728bdcff680b7de66b336dc476828f (patch) | |
tree | a9ebbd2c06f2e3a96b77321281978b94ebb05cd1 /config | |
parent | 812c24e735ede2be70af5d618f5626504e872db7 (diff) |
Unit tests for ConfigParser
Diffstat (limited to 'config')
-rw-r--r-- | config/configexception.php | 28 | ||||
-rw-r--r-- | config/configparser.php | 215 |
2 files changed, 243 insertions, 0 deletions
diff --git a/config/configexception.php b/config/configexception.php new file mode 100644 index 00000000..d421f70f --- /dev/null +++ b/config/configexception.php @@ -0,0 +1,28 @@ +<?php +/** + * ownCloud - gallery + * + * This file is licensed under the Affero General Public License version 3 or + * later. See the COPYING file. + * + * @author Olivier Paroz <owncloud@interfasys.ch> + * + * @copyright Olivier Paroz 2015 + */ + +namespace OCA\Gallery\Config; + +/** + * Thrown when the configuration parser cannot parse a file + */ +class ConfigException extends \Exception { + + /** + * Constructor + * + * @param string $msg the message contained in the exception + */ + public function __construct($msg) { + parent::__construct($msg); + } +} diff --git a/config/configparser.php b/config/configparser.php new file mode 100644 index 00000000..2d81210e --- /dev/null +++ b/config/configparser.php @@ -0,0 +1,215 @@ +<?php +/** + * ownCloud - gallery + * + * This file is licensed under the Affero General Public License version 3 or + * later. See the COPYING file. + * + * @author Olivier Paroz <owncloud@interfasys.ch> + * + * @copyright Olivier Paroz 2015 + */ + +namespace OCA\Gallery\Config; + +use Symfony\Component\Yaml\Parser; +use Symfony\Component\Yaml\Exception\ParseException; + +use OCP\Files\Folder; +use OCP\Files\File; + +/** + * Parses configuration files + * + * @package OCA\Gallery\Config + */ +class ConfigParser { + + /** + * Returns a parsed global configuration if one was found in the root folder + * + * @param Folder $folder the current folder + * @param string $configName name of the configuration file + * + * @return null|array + */ + public function getFeaturesList($folder, $configName) { + $featuresList = []; + $parsedConfig = $this->parseConfig($folder, $configName); + $key = 'features'; + if (array_key_exists($key, $parsedConfig)) { + $featuresList = $parsedConfig[$key]; + } + + return $featuresList; + } + + /** + * Returns a parsed configuration if one was found in the current folder + * + * @param Folder $folder the current folder + * @param string $configName name of the configuration file + * @param array $currentConfig the configuration collected so far + * @param array <string,bool> $completionStatus determines if we already have all we need for a + * config sub-section + * @param int $level the starting level is 0 and we add 1 each time we visit a parent folder + * + * @return array <null|array,array<string,bool>> + * @throws ConfigException + */ + public function getFolderConfig($folder, $configName, $currentConfig, $completionStatus, $level + ) { + $parsedConfig = $this->parseConfig($folder, $configName); + list($config, $completionStatus) = + $this->buildAlbumConfig($currentConfig, $parsedConfig, $completionStatus, $level); + + return [$config, $completionStatus]; + } + + /** + * Returns a parsed configuration + * + * @param Folder $folder the current folder + * @param string $configName + * + * @return array|string[] + * + * @throws ConfigException + */ + private function parseConfig($folder, $configName) { + try { + /** @var File $configFile */ + $configFile = $folder->get($configName); + $rawConfig = $configFile->getContent(); + $saneConfig = $this->bomFixer($rawConfig); + $yaml = new Parser(); + $parsedConfig = $yaml->parse($saneConfig); + + //\OC::$server->getLogger()->debug("rawConfig : {path}", ['path' => $rawConfig]); + + return $parsedConfig; + } catch (\Exception $exception) { + $errorMessage = "Problem while reading or parsing the configuration file"; + throw new ConfigException($errorMessage); + } + } + + /** + * Removes the BOM from a file + * + * http://us.php.net/manual/en/function.pack.php#104151 + * + * @param string $file + * + * @return string + */ + private function bomFixer($file) { + $bom = pack("CCC", 0xef, 0xbb, 0xbf); + if (strncmp($file, $bom, 3) === 0) { + $file = substr($file, 3); + } + + return $file; + } + + /** + * Returns either the local config or one merged with a config containing sorting information + * + * @param array $currentConfig the configuration collected so far + * @param array $parsedConfig the configuration collected in the current folder + * @param array <string,bool> $completionStatus determines if we already have all we need for a + * config sub-section + * @param int $level the starting level is 0 and we add 1 each time we visit a parent folder + * + * @return array <null|array,array<string,bool>> + */ + private function buildAlbumConfig($currentConfig, $parsedConfig, $completionStatus, $level) { + foreach ($completionStatus as $key => $complete) { + if (!$this->isConfigItemComplete($key, $parsedConfig, $complete)) { + $parsedConfigItem = $parsedConfig[$key]; + if ($this->isConfigUsable($parsedConfigItem, $level)) { + list($configItem, $itemComplete) = + $this->addConfigItem($key, $parsedConfigItem, $level); + $currentConfig = array_merge($currentConfig, $configItem); + $completionStatus[$key] = $itemComplete; + } + } + } + + return [$currentConfig, $completionStatus]; + } + + /** + * Determines if we already have everything we need for this configuration sub-section + * + * @param string $key the configuration sub-section identifier + * @param array $parsedConfig the configuration for that sub-section + * @param bool $complete + * + * @return bool + */ + private function isConfigItemComplete($key, $parsedConfig, $complete) { + return !(!$complete && array_key_exists($key, $parsedConfig)); + } + + /** + * Determines if we can use this configuration sub-section + * + * It's possible in two cases: + * * the configuration was collected from the currently opened folder + * * the configuration was collected in a parent folder and is inheritable + * + * @param array $parsedConfigItem the configuration for a sub-section + * @param int $level the starting level is 0 and we add 1 each time we visit a parent folder + * + * @return bool + */ + private function isConfigUsable($parsedConfigItem, $level) { + $inherit = $this->isConfigInheritable($parsedConfigItem); + + return $level === 0 || $inherit; + } + + /** + * Adds a config sub-section to the global config + * + * @param string $key the configuration sub-section identifier + * @param array $parsedConfigItem the configuration for a sub-section + * @param int $level the starting level is 0 and we add 1 each time we visit a parent folder + * + * @return array<null|array<string,string>,bool> + */ + private function addConfigItem($key, $parsedConfigItem, $level) { + if ($key === 'sorting' && !array_key_exists('type', $parsedConfigItem)) { + + return [[], false]; + } else { + $parsedConfigItem['level'] = $level; + $configItem = [$key => $parsedConfigItem]; + $itemComplete = true; + + return [$configItem, $itemComplete]; + } + } + + /** + * Determines if we can use a configuration sub-section found in parent folders + * + * @param array $parsedConfigItem the configuration for a sub-section + * + * @return bool + */ + private function isConfigInheritable($parsedConfigItem) { + $inherit = false; + if (array_key_exists('inherit', $parsedConfigItem)) { + $inherit = $parsedConfigItem['inherit']; + } + + if ($inherit === 'yes') { + $inherit = true; + } + + return $inherit; + } + +} |