179 lines
5.2 KiB
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);
|
|
});
|
|
}
|
|
}
|