Files
Grav/system/src/Grav/Common/Config/Setup.php

322 lines
9.7 KiB
PHP
Raw Normal View History

2015-11-18 15:14:27 +02:00
<?php
2019-01-31 10:04:57 +02:00
2016-07-11 16:07:14 -06:00
/**
2019-01-31 10:04:57 +02:00
* @package Grav\Common\Config
2016-07-11 16:07:14 -06:00
*
2019-01-31 10:04:57 +02:00
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
2016-07-11 16:07:14 -06:00
* @license MIT License; see LICENSE file for details.
*/
2015-11-18 15:14:27 +02:00
namespace Grav\Common\Config;
use Grav\Common\File\CompiledYamlFile;
use Grav\Common\Data\Data;
use Grav\Common\Utils;
2016-03-03 14:15:29 +02:00
use Pimple\Container;
2019-01-31 17:32:06 +02:00
use Psr\Http\Message\ServerRequestInterface;
2015-11-18 15:14:27 +02:00
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
class Setup extends Data
{
/**
* @var array Environment aliases normalized to lower case.
*/
public static $environments = [
'' => 'unknown',
'127.0.0.1' => 'localhost',
'::1' => 'localhost'
];
/**
* @var string Current environment normalized to lower case.
*/
2016-09-01 21:27:08 +03:00
public static $environment;
2015-11-18 15:14:27 +02:00
protected $streams = [
'system' => [
'type' => 'ReadOnlyStream',
'prefixes' => [
'' => ['system'],
]
],
'user' => [
'type' => 'ReadOnlyStream',
'force' => true,
2015-11-18 15:14:27 +02:00
'prefixes' => [
'' => ['user'],
]
],
'environment' => [
'type' => 'ReadOnlyStream'
// If not defined, environment will be set up in the constructor.
],
'asset' => [
2018-09-04 09:24:18 +03:00
'type' => 'Stream',
2015-11-18 15:14:27 +02:00
'prefixes' => [
'' => ['assets'],
]
],
'blueprints' => [
'type' => 'ReadOnlyStream',
'prefixes' => [
'' => ['environment://blueprints', 'user://blueprints', 'system://blueprints'],
2015-11-18 15:14:27 +02:00
]
],
'config' => [
'type' => 'ReadOnlyStream',
'prefixes' => [
'' => ['environment://config', 'user://config', 'system://config'],
2015-11-18 15:14:27 +02:00
]
],
'plugins' => [
'type' => 'ReadOnlyStream',
'prefixes' => [
'' => ['user://plugins'],
]
],
'plugin' => [
'type' => 'ReadOnlyStream',
'prefixes' => [
'' => ['user://plugins'],
]
],
'themes' => [
'type' => 'ReadOnlyStream',
'prefixes' => [
'' => ['user://themes'],
]
],
'languages' => [
'type' => 'ReadOnlyStream',
'prefixes' => [
'' => ['environment://languages', 'user://languages', 'system://languages'],
2015-11-18 15:14:27 +02:00
]
],
'cache' => [
'type' => 'Stream',
'force' => true,
2015-11-18 15:14:27 +02:00
'prefixes' => [
'' => ['cache'],
'images' => ['images']
]
],
'log' => [
'type' => 'Stream',
'force' => true,
2015-11-18 15:14:27 +02:00
'prefixes' => [
'' => ['logs']
]
],
'backup' => [
'type' => 'Stream',
'force' => true,
2015-11-18 15:14:27 +02:00
'prefixes' => [
'' => ['backup']
]
],
'tmp' => [
'type' => 'Stream',
'force' => true,
'prefixes' => [
'' => ['tmp']
]
],
2015-11-18 15:14:27 +02:00
'image' => [
2018-09-04 09:24:18 +03:00
'type' => 'Stream',
2015-11-18 15:14:27 +02:00
'prefixes' => [
'' => ['user://images', 'system://images']
]
],
'page' => [
'type' => 'ReadOnlyStream',
'prefixes' => [
'' => ['user://pages']
]
],
'user-data' => [
'type' => 'Stream',
'force' => true,
'prefixes' => [
'' => ['user://data']
]
],
2015-11-18 15:14:27 +02:00
'account' => [
'type' => 'ReadOnlyStream',
'prefixes' => [
'' => ['user://accounts']
]
],
];
2016-03-03 14:15:29 +02:00
/**
* @param Container|array $container
*/
2015-12-07 19:20:10 +01:00
public function __construct($container)
2015-11-18 15:14:27 +02:00
{
// If no environment is set, make sure we get one (CLI or hostname).
if (!static::$environment) {
if (\defined('GRAV_CLI')) {
static::$environment = 'cli';
} else {
2019-01-31 17:32:06 +02:00
/** @var ServerRequestInterface $request */
$request = $container['request'];
$host = $request->getUri()->getHost();
2019-01-14 13:55:29 -07:00
static::$environment = Utils::substrToString($host, ':');
}
}
// Resolve server aliases to the proper environment.
$environment = $this->environments[static::$environment] ?? static::$environment;
2015-12-07 19:20:10 +01:00
2015-11-18 15:14:27 +02:00
// Pre-load setup.php which contains our initial configuration.
// Configuration may contain dynamic parts, which is why we need to always load it.
// If "GRAV_SETUP_PATH" has been defined, use it, otherwise use defaults.
2018-09-14 15:36:25 +03:00
$file = \defined('GRAV_SETUP_PATH') ? GRAV_SETUP_PATH : GRAV_ROOT . '/setup.php';
2015-11-18 15:14:27 +02:00
$setup = is_file($file) ? (array) include $file : [];
// Add default streams defined in beginning of the class.
if (!isset($setup['streams']['schemes'])) {
$setup['streams']['schemes'] = [];
}
$setup['streams']['schemes'] += $this->streams;
// Initialize class.
parent::__construct($setup);
// Set up environment.
$this->def('environment', $environment);
$this->def('streams.schemes.environment.prefixes', ['' => ["user://{$this->get('environment')}"]]);
2015-11-18 15:14:27 +02:00
}
/**
* @return $this
2017-11-06 10:18:22 +02:00
* @throws \RuntimeException
* @throws \InvalidArgumentException
2015-11-18 15:14:27 +02:00
*/
public function init()
{
$locator = new UniformResourceLocator(GRAV_ROOT);
$files = [];
$guard = 5;
do {
$check = $files;
$this->initializeLocator($locator);
$files = $locator->findResources('config://streams.yaml');
if ($check === $files) {
break;
}
// Update streams.
2016-01-12 12:53:54 +02:00
foreach (array_reverse($files) as $path) {
2015-11-18 15:14:27 +02:00
$file = CompiledYamlFile::instance($path);
2017-11-06 10:18:22 +02:00
$content = (array)$file->content();
2015-11-18 15:14:27 +02:00
if (!empty($content['schemes'])) {
$this->items['streams']['schemes'] = $content['schemes'] + $this->items['streams']['schemes'];
}
}
} while (--$guard);
if (!$guard) {
throw new \RuntimeException('Setup: Configuration reload loop detected!');
}
// Make sure we have valid setup.
$this->check($locator);
2015-11-18 15:14:27 +02:00
return $this;
}
/**
* Initialize resource locator by using the configuration.
*
* @param UniformResourceLocator $locator
2017-11-06 10:18:22 +02:00
* @throws \BadMethodCallException
2015-11-18 15:14:27 +02:00
*/
public function initializeLocator(UniformResourceLocator $locator)
{
$locator->reset();
$schemes = (array) $this->get('streams.schemes', []);
foreach ($schemes as $scheme => $config) {
if (isset($config['paths'])) {
$locator->addPath($scheme, '', $config['paths']);
}
2018-09-14 15:36:25 +03:00
$override = $config['override'] ?? false;
$force = $config['force'] ?? false;
2015-11-18 15:14:27 +02:00
if (isset($config['prefixes'])) {
2017-11-06 10:18:22 +02:00
foreach ((array)$config['prefixes'] as $prefix => $paths) {
$locator->addPath($scheme, $prefix, $paths, $override, $force);
2015-11-18 15:14:27 +02:00
}
}
}
}
/**
* Get available streams and their types from the configuration.
*
* @return array
*/
public function getStreams()
{
$schemes = [];
foreach ((array) $this->get('streams.schemes') as $scheme => $config) {
2018-09-14 15:36:25 +03:00
$type = $config['type'] ?? 'ReadOnlyStream';
2017-11-06 10:18:22 +02:00
if ($type[0] !== '\\') {
2015-11-18 15:14:27 +02:00
$type = '\\RocketTheme\\Toolbox\\StreamWrapper\\' . $type;
}
$schemes[$scheme] = $type;
}
return $schemes;
}
/**
* @param UniformResourceLocator $locator
2015-11-18 15:14:27 +02:00
* @throws \InvalidArgumentException
2017-11-06 10:18:22 +02:00
* @throws \BadMethodCallException
* @throws \RuntimeException
2015-11-18 15:14:27 +02:00
*/
protected function check(UniformResourceLocator $locator)
2015-11-18 15:14:27 +02:00
{
2018-09-14 15:36:25 +03:00
$streams = $this->items['streams']['schemes'] ?? null;
if (!\is_array($streams)) {
2015-11-18 15:14:27 +02:00
throw new \InvalidArgumentException('Configuration is missing streams.schemes!');
}
$diff = array_keys(array_diff_key($this->streams, $streams));
if ($diff) {
throw new \InvalidArgumentException(
sprintf('Configuration is missing keys %s from streams.schemes!', implode(', ', $diff))
);
}
try {
if (!$locator->findResource('environment://config', true)) {
// If environment does not have its own directory, remove it from the lookup.
$this->set('streams.schemes.environment.prefixes', ['config' => []]);
$this->initializeLocator($locator);
}
// Create security.yaml if it doesn't exist.
$filename = $locator->findResource('config://security.yaml', true, true);
$security_file = CompiledYamlFile::instance($filename);
$security_content = (array)$security_file->content();
if (!isset($security_content['salt'])) {
$security_content = array_merge($security_content, ['salt' => Utils::generateRandomString(14)]);
$security_file->content($security_content);
$security_file->save();
$security_file->free();
}
} catch (\RuntimeException $e) {
throw new \RuntimeException(sprintf('Grav failed to initialize: %s', $e->getMessage()), 500, $e);
}
2015-11-18 15:14:27 +02:00
}
}