浏览代码

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`.
Daniel Rudolf 8 年之前
父节点
当前提交
9b7523b
共有 6 个文件被更改,包括 121 次插入91 次删除
  1. 1 1
      .gitignore
  2. 0 61
      config/config.php.template
  3. 41 0
      config/config.yml.template
  4. 6 4
      content-sample/index.md
  5. 18 17
      lib/Pico.php
  6. 55 8
      plugins/00-PicoDeprecated.php

+ 1 - 1
.gitignore

@@ -21,7 +21,7 @@ desktop.ini
 /_build/deploy-*.git
 
 # User config
-/config/config.php
+/config/config.yml
 
 # User themes
 /themes/*

+ 0 - 61
config/config.php.template

@@ -1,61 +0,0 @@
-<?php
-/**
- * Pico configuration
- *
- * This is the configuration file for {@link Pico}. It comes loaded with the
- * default values, which can be found in {@link Pico::getConfig()} (see
- * {@path "lib/Pico.php"}).
- *
- * To override any of the default settings below, copy this file to
- * {@path "config/config.php"}, uncomment the line, then make and
- * save your changes.
- *
- * @link    http://picocms.org
- * @license http://opensource.org/licenses/MIT The MIT License
- * @version 2.0
- */
-
-/*
- * BASIC
- */
-// $config['site_title'] = 'Pico';              // Site title
-// $config['base_url'] = '';                    // Override base URL (e.g. http://example.com/pico/)
-// $config['rewrite_url'] = null;               // A boolean indicating forced URL rewriting
-
-/*
- * THEME
- */
-// $config['theme'] = 'default';                // Set the theme (defaults to "default")
-// $config['theme_url'] = '';                   // Override the base URL of the themes folder (e.g. http://example.com/pico/themes/)
-// $config['theme_config'] = array(             // Settings of the theme; depends on the theme used
-//     'widescreen' => 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

+ 41 - 0
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 }}

+ 6 - 4
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
 

+ 18 - 17
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;

+ 55 - 8
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
      *