Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

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
  • Loading branch information...
commit 6009cfadc2e310b723a8c091cd9d94db968fe07e 1 parent e0b8f15
@hafriedlander hafriedlander authored
Showing with 87 additions and 3 deletions.
  1. +63 −2 core/DAG.php
  2. +24 −1 core/manifest/ConfigManifest.php
View
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 @@ function sort() {
$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
25 core/manifest/ConfigManifest.php
@@ -268,7 +268,30 @@ protected function sortYamlFragments() {
}
}
- $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;
+ }
+
}
/**
Please sign in to comment.
Something went wrong with that request. Please try again.