Something went wrong. Try again.
@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
Something went wrong. Try again.
PHP
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167<?php
/** * Collection of routes on a site for an application. * * @task info Map Information * @task routing Routing */final class AphrontRoutingMap extends Phobject {
private $site; private $application; private $routes = array();
/* -( Map Info )----------------------------------------------------------- */
public function setSite(AphrontSite $site) { $this->site = $site; return $this; }
/** * @return AphrontSite */ public function getSite() { return $this->site; }
public function setApplication(PhabricatorApplication $application) { $this->application = $application; return $this; }
/** * @return PhabricatorApplication */ public function getApplication() { return $this->application; }
public function setRoutes(array $routes) { $this->routes = $routes; return $this; }
public function getRoutes() { return $this->routes; }
/* -( Routing )------------------------------------------------------------ */
/** * Find the route matching a path, if one exists. * * @param string $path Path to route. * @return AphrontRoutingResult|null Routing result, if path matches map. * @task routing */ public function routePath($path) { $map = $this->getRoutes();
foreach ($map as $route => $value) { $match = $this->tryRoute($route, $value, $path); if (!$match) { continue; }
$result = $this->newRoutingResult(); $application = $result->getApplication();
$controller_class = $match['class']; $controller = newv($controller_class, array()); $controller->setCurrentApplication($application);
$result ->setController($controller) ->setURIData($match['data']);
return $result; }
return null; }
/** * Test a sub-map to see if any routes match a path. * * @param string $route Pattern from the map. * @param string $value Value from the map. * @param string $path Path to route. * @return array<string, array<string>|string>|null Match details, if path * matches sub-map. * @task routing */ private function tryRoute($route, $value, $path) { $has_submap = is_array($value);
if (!$has_submap) { // If the value is a controller rather than a sub-map, any matching // route must completely consume the path. $pattern = '(^'.$route.'\z)'; } else { $pattern = '(^'.$route.')'; }
$data = null; $ok = preg_match($pattern, $path, $data); if ($ok === false) { throw new Exception( pht( 'Routing fragment "%s" is not a valid regular expression.', $route)); }
if (!$ok) { return null; }
$path_match = $data[0];
// Clean up the data. We only want to retain named capturing groups, not // the duplicated numeric captures. foreach ($data as $k => $v) { if (is_numeric($k)) { unset($data[$k]); } }
if (!$has_submap) { return array( 'class' => $value, 'data' => $data, ); }
$sub_path = substr($path, strlen($path_match)); foreach ($value as $sub_route => $sub_value) { $result = $this->tryRoute($sub_route, $sub_value, $sub_path); if ($result) { $result['data'] += $data; return $result; } }
return null; }
/** * Build a new routing result for this map. * * @return AphrontRoutingResult New, empty routing result. * @task routing */ private function newRoutingResult() { return id(new AphrontRoutingResult()) ->setSite($this->getSite()) ->setApplication($this->getApplication()); }
}