Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

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
Hamish Friedlander hafriedlander authored
Showing with 87 additions and 3 deletions.
  1. +63 −2 core/DAG.php
  2. +24 −1 core/manifest/ConfigManifest.php
65 core/DAG.php
View
@@ -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;
+ }
}
25 core/manifest/ConfigManifest.php
View
@@ -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.