mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
159 lines
4.6 KiB
PHP
159 lines
4.6 KiB
PHP
|
<?php
|
||
|
|
||
|
namespace SilverStripe\Dev;
|
||
|
|
||
|
use SilverStripe\Control\Controller;
|
||
|
use SilverStripe\Control\Director;
|
||
|
use SilverStripe\Control\HTTPResponse;
|
||
|
use SilverStripe\Core\ClassInfo;
|
||
|
use SilverStripe\Core\Config\Config;
|
||
|
use Symfony\Component\Yaml\Yaml;
|
||
|
use SilverStripe\Core\Injector\Injector;
|
||
|
|
||
|
/**
|
||
|
* Outputs the full configuration.
|
||
|
*/
|
||
|
class DevConfigController extends Controller
|
||
|
{
|
||
|
|
||
|
/**
|
||
|
* @var array
|
||
|
*/
|
||
|
private static $url_handlers = [
|
||
|
'audit' => 'audit',
|
||
|
'' => 'index'
|
||
|
];
|
||
|
|
||
|
/**
|
||
|
* @var array
|
||
|
*/
|
||
|
private static $allowed_actions = [
|
||
|
'index',
|
||
|
'audit',
|
||
|
];
|
||
|
|
||
|
/**
|
||
|
* Note: config() method is already defined, so let's just use index()
|
||
|
*
|
||
|
* @return string|HTTPResponse
|
||
|
*/
|
||
|
public function index()
|
||
|
{
|
||
|
$body = '';
|
||
|
$subtitle = "Config manifest";
|
||
|
|
||
|
if (Director::is_cli()) {
|
||
|
$body .= sprintf("\n%s\n\n", strtoupper($subtitle));
|
||
|
$body .= Yaml::dump(Config::inst()->getAll(), 99, 2, Yaml::DUMP_EMPTY_ARRAY_AS_SEQUENCE);
|
||
|
} else {
|
||
|
$renderer = DebugView::create();
|
||
|
$body .= $renderer->renderHeader();
|
||
|
$body .= $renderer->renderInfo("Configuration", Director::absoluteBaseURL());
|
||
|
$body .= "<div class=\"options\">";
|
||
|
$body .= sprintf("<h2>%s</h2>", $subtitle);
|
||
|
$body .= "<pre>";
|
||
|
$body .= Yaml::dump(Config::inst()->getAll(), 99, 2, Yaml::DUMP_EMPTY_ARRAY_AS_SEQUENCE);
|
||
|
$body .= "</pre>";
|
||
|
$body .= "</div>";
|
||
|
$body .= $renderer->renderFooter();
|
||
|
}
|
||
|
|
||
|
return $this->getResponse()->setBody($body);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Output the extraneous config properties which are defined in .yaml but not in a corresponding class
|
||
|
*
|
||
|
* @return string|HTTPResponse
|
||
|
*/
|
||
|
public function audit()
|
||
|
{
|
||
|
$body = '';
|
||
|
$missing = [];
|
||
|
$subtitle = "Missing Config property definitions";
|
||
|
|
||
|
foreach ($this->array_keys_recursive(Config::inst()->getAll(), 2) as $className => $props) {
|
||
|
$props = array_keys($props);
|
||
|
|
||
|
if (!count($props)) {
|
||
|
// We can skip this entry
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if ($className == strtolower(Injector::class)) {
|
||
|
// We don't want to check the injector config
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
foreach ($props as $prop) {
|
||
|
$defined = false;
|
||
|
// Check ancestry (private properties don't inherit natively)
|
||
|
foreach (ClassInfo::ancestry($className) as $cn) {
|
||
|
if (property_exists($cn, $prop)) {
|
||
|
$defined = true;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ($defined) {
|
||
|
// No need to record this property
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
$missing[] = sprintf("%s::$%s\n", $className, $prop);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
$output = count($missing)
|
||
|
? implode("\n", $missing)
|
||
|
: "All configured properties are defined\n";
|
||
|
|
||
|
if (Director::is_cli()) {
|
||
|
$body .= sprintf("\n%s\n\n", strtoupper($subtitle));
|
||
|
$body .= $output;
|
||
|
} else {
|
||
|
$renderer = DebugView::create();
|
||
|
$body .= $renderer->renderHeader();
|
||
|
$body .= $renderer->renderInfo(
|
||
|
"Configuration",
|
||
|
Director::absoluteBaseURL(),
|
||
|
"Config properties that are not defined (or inherited) by their respective classes"
|
||
|
);
|
||
|
$body .= "<div class=\"options\">";
|
||
|
$body .= sprintf("<h2>%s</h2>", $subtitle);
|
||
|
$body .= sprintf("<pre>%s</pre>", $output);
|
||
|
$body .= "</div>";
|
||
|
$body .= $renderer->renderFooter();
|
||
|
}
|
||
|
|
||
|
return $this->getResponse()->setBody($body);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns all the keys of a multi-dimensional array while maintining any nested structure
|
||
|
*
|
||
|
* @param array $array
|
||
|
* @param int $maxdepth
|
||
|
* @param int $depth
|
||
|
* @param array $arrayKeys
|
||
|
* @return array
|
||
|
*/
|
||
|
private function array_keys_recursive($array, $maxdepth = 20, $depth = 0, $arrayKeys = [])
|
||
|
{
|
||
|
if ($depth < $maxdepth) {
|
||
|
$depth++;
|
||
|
$keys = array_keys($array);
|
||
|
|
||
|
foreach ($keys as $key) {
|
||
|
if (!is_array($array[$key])) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
$arrayKeys[$key] = $this->array_keys_recursive($array[$key], $maxdepth, $depth);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return $arrayKeys;
|
||
|
}
|
||
|
}
|