mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
NEW Added a dev view to output the current config from dev/config (#9542)
* #3236 Added dev/config view * Refactored use of echo to * Added config/audit for matching missing property definitions in the current config * Minor enhancements to dev/config implementation
This commit is contained in:
parent
9aa2642d03
commit
699913406b
@ -13,3 +13,7 @@ SilverStripe\Dev\DevelopmentAdmin:
|
|||||||
tasks: 'See a list of build tasks to run'
|
tasks: 'See a list of build tasks to run'
|
||||||
confirm:
|
confirm:
|
||||||
controller: SilverStripe\Dev\DevConfirmationController
|
controller: SilverStripe\Dev\DevConfirmationController
|
||||||
|
config:
|
||||||
|
controller: Silverstripe\Dev\DevConfigController
|
||||||
|
links:
|
||||||
|
config: 'View the current config, useful for debugging'
|
||||||
|
@ -58,7 +58,7 @@ Redirections](/developer_guides/controllers/redirection) for more information an
|
|||||||
| ------------ | ------ | ----------- |
|
| ------------ | ------ | ----------- |
|
||||||
| BackURL | URL | Set to a relative URL string to use once Security Action is complete |
|
| BackURL | URL | Set to a relative URL string to use once Security Action is complete |
|
||||||
|
|
||||||
## Building and Publishing URLS
|
## Building and Publishing URLs
|
||||||
|
|
||||||
| Site URL | Action |
|
| Site URL | Action |
|
||||||
| --------------------------------------------- | ------ |
|
| --------------------------------------------- | ------ |
|
||||||
@ -72,3 +72,9 @@ Redirections](/developer_guides/controllers/redirection) for more information an
|
|||||||
| quiet | 1 | Don't show messages during build |
|
| quiet | 1 | Don't show messages during build |
|
||||||
| dont_populate | 1 | Don't run **requireDefaultRecords()** on the models when building. This will build the table but not insert any records |
|
| dont_populate | 1 | Don't run **requireDefaultRecords()** on the models when building. This will build the table but not insert any records |
|
||||||
|
|
||||||
|
## Config diagnostic URLs
|
||||||
|
|
||||||
|
| Site URL | Action |
|
||||||
|
| --------------------------------------------- | ------ |
|
||||||
|
| http://localhost**/dev/config** | Output a simplified representation properties in the `Config` manifest |
|
||||||
|
| http://localhost**/dev/config/audit** | Audit `Config` properties and display any with missing PHP definitions |
|
||||||
|
158
src/Dev/DevConfigController.php
Normal file
158
src/Dev/DevConfigController.php
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
<?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;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user