silverstripe-framework/src/Core/Config/CoreConfigFactory.php

179 lines
5.2 KiB
PHP

<?php
namespace SilverStripe\Core\Config;
use Psr\SimpleCache\CacheInterface;
use SilverStripe\Config\Collections\CachedConfigCollection;
use SilverStripe\Config\Collections\MemoryConfigCollection;
use SilverStripe\Config\Transformer\PrivateStaticTransformer;
use SilverStripe\Config\Transformer\YamlTransformer;
use SilverStripe\Core\Cache\CacheFactory;
use SilverStripe\Core\Config\Middleware\ExtensionMiddleware;
use SilverStripe\Core\Config\Middleware\InheritanceMiddleware;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\Core\Kernel;
use SilverStripe\Core\Manifest\ClassLoader;
use SilverStripe\Core\Manifest\ModuleLoader;
use Symfony\Component\Finder\Finder;
/**
* Factory for silverstripe configs
*/
class CoreConfigFactory
{
/**
* @var CacheFactory
*/
protected $cacheFactory = null;
/**
* Create factory
*
* @param CacheFactory $cacheFactory
*/
public function __construct(CacheFactory $cacheFactory = null)
{
$this->cacheFactory = $cacheFactory;
}
/**
* Create root application config.
* This will be an immutable cached config,
* which conditionally generates a nested "core" config.
*
* @return CachedConfigCollection
*/
public function createRoot()
{
$instance = new CachedConfigCollection();
// Create config cache
if ($this->cacheFactory) {
$cache = $this->cacheFactory->create(CacheInterface::class . '.configcache', [
'namespace' => 'configcache'
]);
$instance->setCache($cache);
}
// Set collection creator
$instance->setCollectionCreator(function () {
return $this->createCore();
});
return $instance;
}
/**
* Rebuild new uncached config, which is mutable
*
* @return MemoryConfigCollection
*/
public function createCore()
{
$config = new MemoryConfigCollection();
// Set default middleware
$config->setMiddlewares([
new InheritanceMiddleware(Config::UNINHERITED),
new ExtensionMiddleware(Config::EXCLUDE_EXTRA_SOURCES),
]);
// Transform
$config->transform([
$this->buildStaticTransformer(),
$this->buildYamlTransformer()
]);
return $config;
}
/**
* @return YamlTransformer
*/
protected function buildYamlTransformer()
{
// Get all module dirs
$modules = ModuleLoader::inst()->getManifest()->getModules();
$dirs = [];
foreach ($modules as $module) {
// Load from _config dirs
$path = $module->getPath() . '/_config';
if (is_dir($path)) {
$dirs[] = $path;
}
}
return $this->buildYamlTransformerForPath($dirs);
}
/**
* @return PrivateStaticTransformer
*/
public function buildStaticTransformer()
{
return new PrivateStaticTransformer(function () {
$classes = ClassLoader::inst()->getManifest()->getClasses();
return array_keys($classes);
});
}
/**
* @param array|string $dirs Base dir to load from
* @return YamlTransformer
*/
public function buildYamlTransformerForPath($dirs)
{
// Construct
$transformer = YamlTransformer::create(
BASE_PATH,
Finder::create()
->in($dirs)
->files()
->name('/\.(yml|yaml)$/')
);
// Add default rules
$envvarset = function ($var, $value = null) {
if (getenv($var) === false) {
return false;
}
if ($value) {
return getenv($var) === $value;
}
return true;
};
$constantdefined = function ($const, $value = null) {
if (!defined($const)) {
return false;
}
if ($value) {
return constant($const) === $value;
}
return true;
};
return $transformer
->addRule('classexists', function ($class) {
return class_exists($class);
})
->addRule('envvarset', $envvarset)
->addRule('constantdefined', $constantdefined)
->addRule(
'envorconstant',
// Composite rule
function ($name, $value = null) use ($envvarset, $constantdefined) {
return $envvarset($name, $value) || $constantdefined($name, $value);
}
)
->addRule('environment', function ($env) {
// Note: The below relies on direct assignment of kernel to injector instance,
// and will fail if failing back to config service locator
/** @var Kernel $kernel */
$kernel = Injector::inst()->get(Kernel::class);
return strtolower($kernel->getEnvironment()) === strtolower($env);
})
->addRule('moduleexists', function ($module) {
return ModuleLoader::inst()->getManifest()->moduleExists($module);
});
}
}