mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
NEW Allow debugging of config cyclic errors
It is possible to specify before and after rules on config fragments that conflict - A before B and B before A isnt possible to solve. This used to just throw an error with no way to debug. Now if you specify debug as a GET parameter and the site is not in live mode youll get a basic dump of the remaining DAG graph
This commit is contained in:
parent
e0b8f15171
commit
6009cfadc2
65
core/DAG.php
65
core/DAG.php
@ -4,7 +4,7 @@
|
||||
* A Directed Acyclic Graph - used for doing topological sorts on dependencies, such as the before/after conditions
|
||||
* in config yaml fragments
|
||||
*/
|
||||
class SS_DAG {
|
||||
class SS_DAG implements IteratorAggregate {
|
||||
/** @var array|null - The nodes/vertices in the graph. Should be a numeric sequence of items (no string keys, no gaps). */
|
||||
protected $data;
|
||||
|
||||
@ -68,7 +68,68 @@ class SS_DAG {
|
||||
$dag = $withedges;
|
||||
}
|
||||
|
||||
if ($dag) throw new Exception("DAG has cyclic requirements");
|
||||
if ($dag) {
|
||||
$remainder = new SS_DAG($data); $remainder->dag = $dag;
|
||||
throw new SS_DAG_CyclicException("DAG has cyclic requirements", $remainder);
|
||||
}
|
||||
return $sorted;
|
||||
}
|
||||
|
||||
function getIterator() {
|
||||
return new SS_DAG_Iterator($this->data, $this->dag);
|
||||
}
|
||||
}
|
||||
|
||||
class SS_DAG_CyclicException extends Exception {
|
||||
|
||||
public $dag;
|
||||
|
||||
function __construct($message, $dag) {
|
||||
$this->dag = $dag;
|
||||
parent::__construct($message);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class SS_DAG_Iterator implements Iterator {
|
||||
|
||||
protected $data;
|
||||
protected $dag;
|
||||
|
||||
protected $dagkeys;
|
||||
protected $i;
|
||||
|
||||
function __construct($data, $dag) {
|
||||
$this->data = $data;
|
||||
$this->dag = $dag;
|
||||
$this->rewind();
|
||||
}
|
||||
|
||||
function key() {
|
||||
return $this->i;
|
||||
}
|
||||
|
||||
function current() {
|
||||
$res = array();
|
||||
|
||||
$res['from'] = $this->data[$this->i];
|
||||
|
||||
$res['to'] = array();
|
||||
foreach ($this->dag[$this->i] as $to) $res['to'][] = $this->data[$to];
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
function next() {
|
||||
$this->i = array_shift($this->dagkeys);
|
||||
}
|
||||
|
||||
function rewind() {
|
||||
$this->dagkeys = array_keys($this->dag);
|
||||
$this->next();
|
||||
}
|
||||
|
||||
function valid() {
|
||||
return $this->i !== null;
|
||||
}
|
||||
}
|
||||
|
@ -268,7 +268,30 @@ class SS_ConfigManifest {
|
||||
}
|
||||
}
|
||||
|
||||
$this->yamlConfigFragments = $dag->sort();
|
||||
try {
|
||||
$this->yamlConfigFragments = $dag->sort();
|
||||
}
|
||||
catch (SS_DAG_CyclicException $e) {
|
||||
|
||||
if (!Director::isLive() && isset($_REQUEST['debug'])) {
|
||||
$res = '<h1>Remaining config fragment graph</h1>';
|
||||
$res .= '<dl>';
|
||||
|
||||
foreach ($e->dag as $node) {
|
||||
$res .= "<dt>{$node['from']['module']}/{$node['from']['file']}#{$node['from']['name']} marked to come after</dt><dd><ul>";
|
||||
foreach ($node['to'] as $to) {
|
||||
$res .= "<li>{$to['module']}/{$to['file']}#{$to['name']}</li>";
|
||||
}
|
||||
$res .= "</ul></dd>";
|
||||
}
|
||||
|
||||
$res .= '</dl>';
|
||||
echo $res;
|
||||
}
|
||||
|
||||
throw $e;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user