require_once 'Net/URL/Mapper.php';
-class StatusNet_URL_Mapper extends Net_URL_Mapper {
+class StatusNet_URL_Mapper extends Net_URL_Mapper
+{
private static $_singleton = null;
+ private $_actionToPath = array();
private function __construct()
{
}
-
+
public static function getInstance($id = '__default__')
{
if (empty(self::$_singleton)) {
$result = null;
if (Event::handle('StartConnectPath', array(&$path, &$defaults, &$rules, &$result))) {
$result = parent::connect($path, $defaults, $rules);
+ if (array_key_exists('action', $defaults)) {
+ $action = $defaults['action'];
+ } elseif (array_key_exists('action', $rules)) {
+ $action = $rules['action'];
+ } else {
+ $action = null;
+ }
+ $this->_mapAction($action, $result);
Event::handle('EndConnectPath', array($path, $defaults, $rules, $result));
}
return $result;
}
+
+ protected function _mapAction($action, $path)
+ {
+ if (!array_key_exists($action, $this->_actionToPath)) {
+ $this->_actionToPath[$action] = array();
+ }
+ $this->_actionToPath[$action][] = $path;
+ return;
+ }
+
+ public function generate($values = array(), $qstring = array(), $anchor = '')
+ {
+ if (!array_key_exists('action', $values)) {
+ return parent::generate($values, $qstring, $anchor);
+ }
+
+ $action = $values['action'];
+
+ if (!array_key_exists($action, $this->_actionToPath)) {
+ return parent::generate($values, $qstring, $anchor);
+ }
+
+ $oldPaths = $this->paths;
+ $this->paths = $this->_actionToPath[$action];
+ $result = parent::generate($values, $qstring, $anchor);
+ $this->paths = $oldPaths;
+
+ return $result;
+ }
}
/**
function __construct()
{
- if (!$this->m) {
- $this->m = $this->initialize();
+ if (empty($this->m)) {
+ if (!common_config('router', 'cache')) {
+ $this->m = $this->initialize();
+ } else {
+ $k = self::cacheKey();
+ $c = Cache::instance();
+ $m = $c->get($k);
+ if (!empty($m)) {
+ $this->m = $m;
+ } else {
+ $this->m = $this->initialize();
+ $c->set($k, $this->m);
+ }
+ }
}
}
+ /**
+ * Create a unique hashkey for the router.
+ *
+ * The router's url map can change based on the version of the software
+ * you're running and the plugins that are enabled. To avoid having bad routes
+ * get stuck in the cache, the key includes a list of plugins and the software
+ * version.
+ *
+ * There can still be problems with a) differences in versions of the plugins and
+ * b) people running code between official versions, but these tend to be more
+ * sophisticated users who can grok what's going on and clear their caches.
+ *
+ * @return string cache key string that should uniquely identify a router
+ */
+
+ static function cacheKey()
+ {
+ return Cache::codeKey('router');
+ }
+
function initialize()
{
$m = StatusNet_URL_Mapper::getInstance();
'deleteuser',
'geocode',
'version',
- );
+ );
foreach ($main as $a) {
$m->connect('main/'.$a, array('action' => $a));
array('action' => 'publicxrds'));
$m->connect('.well-known/host-meta',
array('action' => 'hostmeta'));
- $m->connect('main/xrd',
- array('action' => 'userxrd'));
+ $m->connect('main/xrd',
+ array('action' => 'userxrd'));
// these take a code
}
$m->connect('settings/oauthapps/show/:id',
- array('action' => 'showapplication'),
- array('id' => '[0-9]+')
+ array('action' => 'showapplication'),
+ array('id' => '[0-9]+')
);
$m->connect('settings/oauthapps/new',
- array('action' => 'newapplication')
+ array('action' => 'newapplication')
);
$m->connect('settings/oauthapps/edit/:id',
- array('action' => 'editapplication'),
- array('id' => '[0-9]+')
+ array('action' => 'editapplication'),
+ array('id' => '[0-9]+')
);
$m->connect('settings/oauthapps/delete/:id',
- array('action' => 'deleteapplication'),
- array('id' => '[0-9]+')
+ array('action' => 'deleteapplication'),
+ array('id' => '[0-9]+')
);
// search
$m->connect('api/oauth/authorize',
array('action' => 'ApiOauthAuthorize'));
- $m->connect('api/statusnet/app/service/:id.xml',
- array('action' => 'ApiAtomService',
- 'id' => Nickname::DISPLAY_FMT));
-
- $m->connect('api/statusnet/app/service.xml',
- array('action' => 'ApiAtomService'));
-
// Admin
$m->connect('admin/site', array('action' => 'siteadminpanel'));
if (common_config('singleuser', 'enabled')) {
- $user = User::singleUser();
- $nickname = $user->nickname;
+ $nickname = User::singleUserNickname();
foreach (array('subscriptions', 'subscribers',
'all', 'foaf', 'xrds',
array('nickname' => Nickname::DISPLAY_FMT));
}
+ // AtomPub API
+
+ $m->connect('api/statusnet/app/service/:id.xml',
+ array('action' => 'ApiAtomService',
+ 'id' => Nickname::DISPLAY_FMT));
+
+ $m->connect('api/statusnet/app/service.xml',
+ array('action' => 'ApiAtomService'));
+
+ $m->connect('api/statusnet/app/subscriptions/:subscriber/:subscribed.atom',
+ array('action' => 'AtomPubShowSubscription'),
+ array('subscriber' => '[0-9]+',
+ 'subscribed' => '[0-9]+'));
+
+ $m->connect('api/statusnet/app/subscriptions/:subscriber.atom',
+ array('action' => 'AtomPubSubscriptionFeed'),
+ array('subscriber' => '[0-9]+'));
+
// user stuff
Event::handle('RouterInitialized', array($m));
$qpos = strpos($url, '?');
if ($qpos !== false) {
$url = substr($url, 0, $qpos+1) .
- str_replace('?', '&', substr($url, $qpos+1));
+ str_replace('?', '&', substr($url, $qpos+1));
// @fixme this is a hacky workaround for http_build_query in the
// lower-level code and bad configs that set the default separator
// to & instead of &. Encoded &s in parameters will not be
// affected.
$url = substr($url, 0, $qpos+1) .
- str_replace('&', '&', substr($url, $qpos+1));
+ str_replace('&', '&', substr($url, $qpos+1));
}