/** * Get role name depending on structure * * @param NodeInterface $node * @param Context $context * * @return string */ protected function getRoleName(NodeInterface $node, Context $context) { if ($node->hasChild('name')) { $value = $node->getChild('name')->getValue(); if (!is_string($value)) { $context->getLogger()->logCritical(sprintf("%s: name attribute is not a string", $node->getPath())); } return $value; } return $node->getName(); }
/** * Internal recursive visit() function the depth-first search topological * sort algorithm * * Topoligical sort, with depth-first search algorithm * https://en.wikipedia.org/wiki/Topological_sorting * * L ← Empty list that will contain the sorted nodes * while there are unmarked nodes do * select an unmarked node n * visit(n) * * function visit(node n) * if n has a temporary mark then stop (not a DAG) * if n is not marked (i.e. has not been visited yet) then * mark n temporarily * for each node m with an edge from n to m do * visit(m) * mark n permanently * unmark n temporarily * add n to head of L */ private function visitDependencies($node, $map, &$stack, &$sorted, &$missing, Context $context) { if ($node->done) { return; } if ($node->marked) { $context->getLogger()->logCritical(sprintf("'%s': circular dependency", $node->path)); return; } $node->marked = true; foreach ($node->vertices as $key) { if (!isset($map[$key])) { $context->getLogger()->logWarning(sprintf("'%s': unmet dependency: '%s'", $node->path, $key)); $missing[] = $key; continue; } $this->visitDependencies($map[$key], $map, $stack, $sorted, $missing, $context); } // Mark n permanently, unmark temporarily unset($stack[$node->path]); $node->marked = false; $node->done = true; $sorted[] = $node->path; }