From 9b7523b9e8fd418d9307208b8cde5b190703b1fb Mon Sep 17 00:00:00 2001 From: Daniel Rudolf Date: Sun, 5 Feb 2017 16:52:18 +0100 Subject: [PATCH] Use .yml files to configure Pico Instead of using `*.config.php` files, use `*.yml` files to configure Pico. YAML is much easier to understand, more user friendly and (at least a bit) more error-tolerant, but still very powerful. Don't break BC by letting `PicoDeprecated` still read `config/config.php`. --- .gitignore | 2 +- config/config.php.template | 61 --------------------------------- config/config.yml.template | 41 +++++++++++++++++++++++ content-sample/index.md | 10 +++--- lib/Pico.php | 35 +++++++++---------- plugins/00-PicoDeprecated.php | 63 ++++++++++++++++++++++++++++++----- 6 files changed, 121 insertions(+), 91 deletions(-) delete mode 100644 config/config.php.template create mode 100644 config/config.yml.template diff --git a/.gitignore b/.gitignore index 673e405..7cb4a74 100644 --- a/.gitignore +++ b/.gitignore @@ -21,7 +21,7 @@ desktop.ini /_build/deploy-*.git # User config -/config/config.php +/config/config.yml # User themes /themes/* diff --git a/config/config.php.template b/config/config.php.template deleted file mode 100644 index dc19eff..0000000 --- a/config/config.php.template +++ /dev/null @@ -1,61 +0,0 @@ - false // Default theme: Allocate more horicontal space (i.e. make the site container wider) -// ); -// $config['twig_config'] = array( // Twig settings -// 'cache' => false, // To enable Twig caching change this to a path to a writable directory -// 'autoescape' => false, // Auto-escape Twig vars -// 'debug' => false // Enable Twig debug -// ); - -/* - * CONTENT - */ -// $config['date_format'] = '%D %T'; // Set the PHP date format as described here: http://php.net/manual/en/function.strftime.php -// $config['pages_order_by'] = 'alpha'; // Order pages by "alpha" or "date" -// $config['pages_order'] = 'asc'; // Order pages "asc" or "desc" -// $config['content_dir'] = 'content-sample/'; // Content directory -// $config['content_ext'] = '.md'; // File extension of content files to serve - -/* - * TIMEZONE - */ -// $config['timezone'] = 'UTC'; // Timezone may be required by your php install - -/* - * PLUGINS - */ -// $config['DummyPlugin.enabled'] = false; // Force DummyPlugin to be disabled - -/* - * CUSTOM - */ -// $config['custom_setting'] = 'Hello'; // Can be accessed by {{ config.custom_setting }} in a theme diff --git a/config/config.yml.template b/config/config.yml.template new file mode 100644 index 0000000..aed7698 --- /dev/null +++ b/config/config.yml.template @@ -0,0 +1,41 @@ +## +# Basic +# +site_title: Pico # The title of your website +base_url: ~ # Pico will try to guess its base URL, if this fails, override it here + # Example: http://example.com/pico/ +rewrite_url: ~ # A boolean (true or false) indicating whether URL rewriting is forced +timezone: UTC # Your PHP installation might require you to manually specify a timezone + +## +# Theme +# +theme: default # The name of your custom theme +theme_url: ~ # Pico will try to guess the URL to the themes dir of your installation + # If this fails, override it here. Example: http://example.com/pico/themes/ +theme_config: + widescreen: false # Default theme: Use more horicontal space (i.e. make the site container wider) +twig_config: + cache: false # Enable Twig template caching by specifying a path to a writable directory + autoescape: false # Let Twig escape variables by default + debug: false # Enable Twig's debugging mode + +## +# Content +# +date_format: %D %T # Pico's default date format + # List of available variables: http://php.net/manual/en/function.strftime.php +pages_order_by: alpha # Change how Pico sorts pages ("alpha" for alphabetical order, or "date") +pages_order: asc # Sort pages in ascending ("asc") or descending ("desc") order +content_dir: content/ # The path to Pico's content directory +content_ext: .md # The file extension of your Markdown files + +## +# Plugins +# +DummyPlugin.enabled: false # Force the plugin "DummyPlugin" to be disabled + +## +# Custom +# +my_custom_setting: Hello World! # You can access custom settings in themes using {{ config.my_custom_setting }} diff --git a/content-sample/index.md b/content-sample/index.md index bb5d334..11f4943 100644 --- a/content-sample/index.md +++ b/content-sample/index.md @@ -263,10 +263,12 @@ to the brand new plugin system introduced with Pico 1.0. Please refer to the ## Config You can override the default Pico settings (and add your own custom settings) -by editing `config/config.php` in the Pico directory. For a brief overview of -the available settings and their defaults see `config/config.php.template`. To -override a setting, copy `config/config.php.template` to `config/config.php`, -uncomment the setting and set your custom value. +by editing `config/config.yml` in the Pico directory. For a brief overview of +the available settings and their defaults see `config/config.yml.template`. To +override a setting, simply copy the line from `config/config.yml.template` +to `config/config.yml` and set your custom value. Pico will read all `*.yml` +files in the `config/` dir, thus you can even use a distinct settings file to +configure your custom theme (e.g. `config/my_theme.yml`). ### URL Rewriting diff --git a/lib/Pico.php b/lib/Pico.php index b49ea36..3c96bd6 100644 --- a/lib/Pico.php +++ b/lib/Pico.php @@ -670,25 +670,26 @@ class Pico */ protected function loadConfig() { - // scope isolated require() - $includeClosure = function ($configFile) { - require($configFile); - return (isset($config) && is_array($config)) ? $config : array(); + // load config closure + $yamlParser = $this->getYamlParser(); + $loadConfigClosure = function ($configFile) use ($yamlParser) { + $yaml = file_get_contents($configFile); + $config = $yamlParser->parse($yaml); + return is_array($config) ? $config : array(); }; - if (PHP_VERSION_ID >= 50400) { - $includeClosure = $includeClosure->bindTo(null); - } - // load main config file (config/config.php) + // load main config file (config/config.yml) $this->config = is_array($this->config) ? $this->config : array(); - if (file_exists($this->getConfigDir() . 'config.php')) { - $this->config += $includeClosure($this->getConfigDir() . 'config.php'); + if (file_exists($this->getConfigDir() . 'config.yml')) { + $this->config += $loadConfigClosure($this->getConfigDir() . 'config.yml'); } - // merge $config of config/*.config.php files - $configFiles = $this->getFilesGlob($this->getConfigDir() . '?*.config.php'); + // merge $config of config/*.yml files + $configFiles = $this->getFilesGlob($this->getConfigDir() . '*.yml'); foreach ($configFiles as $configFile) { - $this->config += $includeClosure($configFile); + if ($configFile !== 'config.yml') { + $this->config += $loadConfigClosure($configFile); + } } // merge default config @@ -697,14 +698,14 @@ class Pico 'base_url' => '', 'rewrite_url' => null, 'theme' => 'default', - 'theme_url' => '', + 'theme_url' => null, 'date_format' => '%D %T', 'twig_config' => array('cache' => false, 'autoescape' => false, 'debug' => false), 'pages_order_by' => 'alpha', 'pages_order' => 'asc', 'content_dir' => null, 'content_ext' => '.md', - 'timezone' => '' + 'timezone' => null ); if (!$this->config['base_url']) { @@ -1333,8 +1334,8 @@ class Pico protected function sortPages() { // sort pages - $order = $this->getConfig('pages_order'); - $orderBy = $this->getConfig('pages_order_by'); + $order = strtolower($this->getConfig('pages_order')); + $orderBy = strtolower($this->getConfig('pages_order_by')); if (($orderBy !== 'date') && ($orderBy !== 'alpha')) { return; diff --git a/plugins/00-PicoDeprecated.php b/plugins/00-PicoDeprecated.php index c79d7f3..ed00e7e 100644 --- a/plugins/00-PicoDeprecated.php +++ b/plugins/00-PicoDeprecated.php @@ -4,11 +4,9 @@ * Maintain backward compatibility to older Pico releases * * This plugin exists for backward compatibility and is disabled by default. - * It gets automatically enabled when a plugin which doesn't implement - * {@link PicoPluginInterface} is loaded. This plugin triggers deprecated - * events and automatically enables {@link PicoParsePagesContent} and - * {@link PicoExcerpt}. These plugins heavily impact Pico's performance! You - * can disable this plugin by calling {@link PicoDeprecated::setEnabled()}. + * It gets automatically enabled when a plugin which either doesn't implement + * {@link PicoPluginInterface} (plugins for Pico 0.X) or define the + * {@link PicoDeprecated::API_VERSION} (plugins for Pico 1.0) is loaded. * * The following deprecated events are triggered by this plugin: * @@ -32,9 +30,10 @@ * | onPageRendering | before_render($twigVariables, $twig, $templateName) | * | onPageRendered | after_render($output) | * - * Since Pico 1.0 the config is stored in {@path "config/config.php"}. This - * plugin tries to read {@path "config.php"} in Pico's root dir and overwrites - * all settings previously specified in {@path "config/config.php"}. + * Since Pico 2.0 the config is stored in `config/*.yml` files. This plugin + * also tries to read {@path "config/config.php"} (Pico 1.0) and + * {@path "config.php"} in Pico's root dir (Pico 0.X) and overwrites all + * previously specified settings. * * @author Daniel Rudolf * @link http://picocms.org @@ -110,6 +109,7 @@ class PicoDeprecated extends AbstractPicoPlugin public function onConfigLoaded(array &$config) { $this->defineConstants(); + $this->loadScriptedConfig($config); $this->loadRootDirConfig($config); $this->enablePlugins(); $GLOBALS['config'] = &$config; @@ -154,6 +154,53 @@ class PicoDeprecated extends AbstractPicoPlugin } } + /** + * Read config.php in Pico's config dir (i.e. config/config.php) + * + * @see PicoDeprecated::onConfigLoaded() + * @see Pico::loadConfig() + * @param array &$realConfig array of config variables + * @return void + */ + protected function loadScriptedConfig(array &$realConfig) + { + if (file_exists($this->getConfigDir() . 'config.php')) { + // scope isolated require() + $includeClosure = function ($configFile) { + require($configFile); + return (isset($config) && is_array($config)) ? $config : array(); + }; + if (PHP_VERSION_ID >= 50400) { + $includeClosure = $includeClosure->bindTo(null); + } + + // config.php in Pico::$configDir (i.e. config/config.php) is deprecated + // use *.yml files in Pico::$configDir instead + $config = $includeClosure($this->getConfigDir() . 'config.php'); + + if ($config) { + if (!empty($config['base_url'])) { + $config['base_url'] = rtrim($config['base_url'], '/') . '/'; + } + if (!empty($config['content_dir'])) { + $config['content_dir'] = $this->getAbsolutePath($config['content_dir']); + } + if (!empty($config['theme_url'])) { + if (preg_match('#^[A-Za-z][A-Za-z0-9+\-.]*://#', $config['theme_url'])) { + $config['theme_url'] = rtrim($config['theme_url'], '/') . '/'; + } else { + $config['theme_url'] = $this->getBaseUrl() . rtrim($config['theme_url'], '/') . '/'; + } + } + if (!empty($config['timezone'])) { + date_default_timezone_set($config['timezone']); + } + + $realConfig = $config + $realConfig; + } + } + } + /** * Read config.php in Pico's root dir *