[ 'type' => 'ReadOnlyStream', 'prefixes' => [ '' => ['system'], ] ], 'user' => [ 'type' => 'ReadOnlyStream', 'force' => true, 'prefixes' => [ '' => ['user'], ] ], 'environment' => [ 'type' => 'ReadOnlyStream' // If not defined, environment will be set up in the constructor. ], 'asset' => [ 'type' => 'ReadOnlyStream', 'prefixes' => [ '' => ['assets'], ] ], 'blueprints' => [ 'type' => 'ReadOnlyStream', 'prefixes' => [ '' => ['environment://blueprints', 'user://blueprints', 'system/blueprints'], ] ], 'config' => [ 'type' => 'ReadOnlyStream', 'prefixes' => [ '' => ['environment://config', 'user://config', 'system/config'], ] ], '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'], ] ], 'cache' => [ 'type' => 'Stream', 'force' => true, 'prefixes' => [ '' => ['cache'], 'images' => ['images'] ] ], 'log' => [ 'type' => 'Stream', 'force' => true, 'prefixes' => [ '' => ['logs'] ] ], 'backup' => [ 'type' => 'Stream', 'force' => true, 'prefixes' => [ '' => ['backup'] ] ], 'tmp' => [ 'type' => 'Stream', 'force' => true, 'prefixes' => [ '' => ['tmp'] ] ], 'image' => [ 'type' => 'ReadOnlyStream', 'prefixes' => [ '' => ['user://images', 'system://images'] ] ], 'page' => [ 'type' => 'ReadOnlyStream', 'prefixes' => [ '' => ['user://pages'] ] ], 'account' => [ 'type' => 'ReadOnlyStream', 'prefixes' => [ '' => ['user://accounts'] ] ], ]; /** * @param Container|array $container */ public function __construct($container) { $environment = null !== static::$environment ? static::$environment : ($container['uri']->environment() ?: 'localhost'); // Pre-load setup.php which contains our initial configuration. // Configuration may contain dynamic parts, which is why we need to always load it. // If "GRAVE_SETUP_PATH" has been defined, use it, otherwise use defaults. $file = defined('GRAV_SETUP_PATH') ? GRAV_SETUP_PATH : GRAV_ROOT . '/setup.php'; $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 ?: 'cli'); $this->def('streams.schemes.environment.prefixes', ['' => $environment ? ["user://{$this->environment}"] : []]); } /** * @return $this * @throws \RuntimeException * @throws \InvalidArgumentException */ 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. foreach (array_reverse($files) as $path) { $file = CompiledYamlFile::instance($path); $content = (array)$file->content(); 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); return $this; } /** * Initialize resource locator by using the configuration. * * @param UniformResourceLocator $locator * @throws \BadMethodCallException */ 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']); } $override = isset($config['override']) ? $config['override'] : false; $force = isset($config['force']) ? $config['force'] : false; if (isset($config['prefixes'])) { foreach ((array)$config['prefixes'] as $prefix => $paths) { $locator->addPath($scheme, $prefix, $paths, $override, $force); } } } } /** * Get available streams and their types from the configuration. * * @return array */ public function getStreams() { $schemes = []; foreach ((array) $this->get('streams.schemes') as $scheme => $config) { $type = !empty($config['type']) ? $config['type'] : 'ReadOnlyStream'; if ($type[0] !== '\\') { $type = '\\RocketTheme\\Toolbox\\StreamWrapper\\' . $type; } $schemes[$scheme] = $type; } return $schemes; } /** * @param UniformResourceLocator $locator * @throws \InvalidArgumentException * @throws \BadMethodCallException * @throws \RuntimeException */ protected function check(UniformResourceLocator $locator) { $streams = isset($this->items['streams']['schemes']) ? $this->items['streams']['schemes'] : null; if (!is_array($streams)) { 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); $file = YamlFile::instance($filename); if (!$file->exists()) { $file->save(['salt' => Utils::generateRandomString(14)]); $file->free(); } } catch (\RuntimeException $e) { throw new \RuntimeException(sprintf('Grav failed to initialize: %s', $e->getMessage()), 500, $e); } } }