public function path($aco)
{
$aco = $this->resolve($aco);
$path = [];
$level = 0;
$root = $this->_tree;
$stack = [[$root, 0]];
while (!empty($stack)) {
list($root, $level) = array_pop($stack);
if (empty($path[$level])) {
$path[$level] = [];
}
foreach ($root as $node => $elements) {
$pattern = '/^' . str_replace(array_keys(static::$modifiers), array_values(static::$modifiers), $node) . '$/';
if ($node == $aco[$level] || preg_match($pattern, $aco[$level])) {
// merge allow/denies with $path of current level
foreach (['allow', 'deny'] as $policy) {
if (!empty($elements[$policy])) {
if (empty($path[$level][$policy])) {
$path[$level][$policy] = [];
}
$path[$level][$policy] = array_merge($path[$level][$policy], $elements[$policy]);
}
}
// traverse
if (!empty($elements['children']) && isset($aco[$level + 1])) {
array_push($stack, [$elements['children'], $level + 1]);
}
}
}
}
return $path;
}