public function acquire($name) { return \arc\tree::dive($this->tree, function ($node) use($name) { return $this->getValueIfRoot($name, $node->nodeValue); }, function ($node, $result) use($name) { return $this->mergeValue($result, $this->getValue($name, $node->nodeValue)); }); }
/** * Calls the first callback method on each successive parent until a non-null value is returned. Then * calls all the parents from that point back to this node with the second callback in reverse order. * The first callback (dive) must accept one parameter, the node. * The second callback (rise) must accept two parameters, the nde and the result up to that point. * @param \arc\tree\Node $node A tree node, must have traversable childNodes property and a parentNode property * @param callable $diveCallback The callback for the dive phase. * @param callable $riseCallback The callback for the rise phase. * @return mixed */ public static function dive($node, $diveCallback = null, $riseCallback = null) { $result = null; if (is_callable($diveCallback)) { $result = call_user_func($diveCallback, $node); } if (!isset($result) && $node->parentNode) { $result = \arc\tree::dive($node->parentNode, $diveCallback, $riseCallback); } if (is_callable($riseCallback)) { return call_user_func($riseCallback, $node, $result); } else { return $result; } }
/** * Matches a path or url to a list of routes and calls the best matching route handler. * @param string $path * @param mixed $routes A tree of routes with handlers as nodeValue. * @return array|bool */ public static function match($path, $routes) { $routes = \arc\tree::expand($routes); $controller = \arc\tree::dive($routes->cd($path), function ($node) { if (isset($node->nodeValue)) { return $node; } }); if ($controller) { $remainder = substr($path, strlen($controller->getPath())); if (is_callable($controller->nodeValue)) { $result = call_user_func($controller->nodeValue, $remainder); } else { $result = $controller->nodeValue; } return ['path' => $controller->getPath(), 'remainder' => $remainder, 'result' => $result]; } return false; }
/** * @return string */ private function fetchGrants() { $user = $this->user; $groups = array_fill_keys($this->groups, 1); $grants = (string) \arc\tree::dive($this->tree, function ($node) use($user) { if (isset($node->nodeValue['users'][$user])) { return $node->nodeValue['users'][$user]; } }, function ($node, $grants) use(&$user, $groups) { if (!$user) { // don't do this for user grants the first time $grants = preg_replace(array('/\\=[^ ]*/', '/\\>([^ ]*)/'), array('', '$1'), $grants); } $user = false; foreach ($groups as $group) { if (isset($node->nodeValue['groups'][$group])) { $grants .= $node->nodeValue['groups'][$group]; } } return $grants; }); return $grants; }
/** * Returns the root node object of this tree. * @return \arc\tree\Node the root node */ public function getRootNode() { $result = \arc\tree::dive($this, function ($node) { return isset($node->parentNode) ? null : $node; }); return $result; }
/** * Calls each listener with the given event untill a listener returns false. */ private function walkListeners($event) { $callListeners = function ($listeners) use($event) { foreach ((array) $listeners as $listener) { $result = call_user_func($listener['method'], $event); if ($result === false) { return false; // this will stop \arc\path::walk, so other event handlers won't be called } } }; $result = \arc\tree::parents($this->tree, function ($node, $result) use($callListeners, $event) { if ($result !== false && isset($node->nodeValue['capture.' . $event->name])) { return call_user_func($callListeners, $node->nodeValue['capture.' . $event->name]); } }); if (!isset($result)) { $result = \arc\tree::dive($this->tree, function ($node) use($callListeners, $event) { if (isset($node->nodeValue['listen.' . $event->name])) { return call_user_func($callListeners, $node->nodeValue['listen.' . $event->name]); } }); } return !isset($result) ? true : false; }