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:
Hamish Friedlander 2012-08-27 16:08:10 +12:00
parent e0b8f15171
commit 6009cfadc2
2 changed files with 87 additions and 3 deletions

View File

@ -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;
}
}

View File

@ -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;
}
}
/**