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`.
This commit is contained in:
Daniel Rudolf 2017-02-05 16:52:18 +01:00
parent 0a080c8965
commit 9b7523b9e8
No known key found for this signature in database
GPG key ID: A061F02CD8DE4538
6 changed files with 121 additions and 91 deletions

2
.gitignore vendored
View file

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

View file

@ -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

View file

@ -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 }}

View file

@ -263,10 +263,12 @@ to the brand new plugin system introduced with Pico 1.0. Please refer to the
## Config ## Config
You can override the default Pico settings (and add your own custom settings) 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 by editing `config/config.yml` in the Pico directory. For a brief overview of
the available settings and their defaults see `config/config.php.template`. To the available settings and their defaults see `config/config.yml.template`. To
override a setting, copy `config/config.php.template` to `config/config.php`, override a setting, simply copy the line from `config/config.yml.template`
uncomment the setting and set your custom value. 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 ### URL Rewriting

View file

@ -670,25 +670,26 @@ class Pico
*/ */
protected function loadConfig() protected function loadConfig()
{ {
// scope isolated require() // load config closure
$includeClosure = function ($configFile) { $yamlParser = $this->getYamlParser();
require($configFile); $loadConfigClosure = function ($configFile) use ($yamlParser) {
return (isset($config) && is_array($config)) ? $config : array(); $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(); $this->config = is_array($this->config) ? $this->config : array();
if (file_exists($this->getConfigDir() . 'config.php')) { if (file_exists($this->getConfigDir() . 'config.yml')) {
$this->config += $includeClosure($this->getConfigDir() . 'config.php'); $this->config += $loadConfigClosure($this->getConfigDir() . 'config.yml');
} }
// merge $config of config/*.config.php files // merge $config of config/*.yml files
$configFiles = $this->getFilesGlob($this->getConfigDir() . '?*.config.php'); $configFiles = $this->getFilesGlob($this->getConfigDir() . '*.yml');
foreach ($configFiles as $configFile) { foreach ($configFiles as $configFile) {
$this->config += $includeClosure($configFile); if ($configFile !== 'config.yml') {
$this->config += $loadConfigClosure($configFile);
}
} }
// merge default config // merge default config
@ -697,14 +698,14 @@ class Pico
'base_url' => '', 'base_url' => '',
'rewrite_url' => null, 'rewrite_url' => null,
'theme' => 'default', 'theme' => 'default',
'theme_url' => '', 'theme_url' => null,
'date_format' => '%D %T', 'date_format' => '%D %T',
'twig_config' => array('cache' => false, 'autoescape' => false, 'debug' => false), 'twig_config' => array('cache' => false, 'autoescape' => false, 'debug' => false),
'pages_order_by' => 'alpha', 'pages_order_by' => 'alpha',
'pages_order' => 'asc', 'pages_order' => 'asc',
'content_dir' => null, 'content_dir' => null,
'content_ext' => '.md', 'content_ext' => '.md',
'timezone' => '' 'timezone' => null
); );
if (!$this->config['base_url']) { if (!$this->config['base_url']) {
@ -1333,8 +1334,8 @@ class Pico
protected function sortPages() protected function sortPages()
{ {
// sort pages // sort pages
$order = $this->getConfig('pages_order'); $order = strtolower($this->getConfig('pages_order'));
$orderBy = $this->getConfig('pages_order_by'); $orderBy = strtolower($this->getConfig('pages_order_by'));
if (($orderBy !== 'date') && ($orderBy !== 'alpha')) { if (($orderBy !== 'date') && ($orderBy !== 'alpha')) {
return; return;

View file

@ -4,11 +4,9 @@
* Maintain backward compatibility to older Pico releases * Maintain backward compatibility to older Pico releases
* *
* This plugin exists for backward compatibility and is disabled by default. * This plugin exists for backward compatibility and is disabled by default.
* It gets automatically enabled when a plugin which doesn't implement * It gets automatically enabled when a plugin which either doesn't implement
* {@link PicoPluginInterface} is loaded. This plugin triggers deprecated * {@link PicoPluginInterface} (plugins for Pico 0.X) or define the
* events and automatically enables {@link PicoParsePagesContent} and * {@link PicoDeprecated::API_VERSION} (plugins for Pico 1.0) is loaded.
* {@link PicoExcerpt}. These plugins heavily impact Pico's performance! You
* can disable this plugin by calling {@link PicoDeprecated::setEnabled()}.
* *
* The following deprecated events are triggered by this plugin: * The following deprecated events are triggered by this plugin:
* *
@ -32,9 +30,10 @@
* | onPageRendering | before_render($twigVariables, $twig, $templateName) | * | onPageRendering | before_render($twigVariables, $twig, $templateName) |
* | onPageRendered | after_render($output) | * | onPageRendered | after_render($output) |
* *
* Since Pico 1.0 the config is stored in {@path "config/config.php"}. This * Since Pico 2.0 the config is stored in `config/*.yml` files. This plugin
* plugin tries to read {@path "config.php"} in Pico's root dir and overwrites * also tries to read {@path "config/config.php"} (Pico 1.0) and
* all settings previously specified in {@path "config/config.php"}. * {@path "config.php"} in Pico's root dir (Pico 0.X) and overwrites all
* previously specified settings.
* *
* @author Daniel Rudolf * @author Daniel Rudolf
* @link http://picocms.org * @link http://picocms.org
@ -110,6 +109,7 @@ class PicoDeprecated extends AbstractPicoPlugin
public function onConfigLoaded(array &$config) public function onConfigLoaded(array &$config)
{ {
$this->defineConstants(); $this->defineConstants();
$this->loadScriptedConfig($config);
$this->loadRootDirConfig($config); $this->loadRootDirConfig($config);
$this->enablePlugins(); $this->enablePlugins();
$GLOBALS['config'] = &$config; $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 * Read config.php in Pico's root dir
* *