Exemple #1
0
 /**
  * Returns the URL of a view.
  *
  * @param Site $site
  * @param string $view_id The identifier of the view.
  * @param array|null $args The arguments to format the URL, if the URL uses a pattern.
  *
  * @return string
  * @throws \Exception
  */
 public static function resolve_view_url(Site $site, $view_id, $args = null)
 {
     if (isset(self::$view_url_cache[$view_id])) {
         return self::$view_url_cache[$view_id];
     }
     $target = $site->resolve_view_target($view_id);
     if (!$target) {
         return '#unknown-target-for-view-' . $view_id;
     }
     $url_pattern = $target->url_pattern;
     if (!Pattern::is_pattern($url_pattern)) {
         return self::$view_url_cache[$view_id] = $target->url;
     }
     return Pattern::from($url_pattern)->format($args);
 }
 /**
  * Search for a route matching the specified pathname and method.
  *
  * @param string $uri The URI to match. If the URI includes a query string it is removed
  * before searching for a matching route.
  * @param array|null $captured The parameters captured from the URI. If the URI included a
  * query string, its parsed params are stored under the `__query__` key.
  * @param string $method One of HTTP\Request::METHOD_* methods.
  *
  * @return Route|false|null
  */
 public function find($uri, &$captured = null, $method = Request::METHOD_ANY)
 {
     $captured = [];
     $parsed = (array) parse_url($uri) + ['path' => null, 'query' => null];
     $path = $parsed['path'];
     if (!$path) {
         return false;
     }
     #
     # Determine if a route matches prerequisites.
     #
     $matchable = function ($via) use($method) {
         if ($method != Request::METHOD_ANY) {
             if (is_array($via)) {
                 if (!in_array($method, $via)) {
                     return false;
                 }
             } else {
                 if ($via !== Request::METHOD_ANY && $via !== $method) {
                     return false;
                 }
             }
         }
         return true;
     };
     #
     # Search for a matching static route.
     #
     $map_static = function ($definitions) use($path, &$matchable) {
         foreach ($definitions as $id => $definition) {
             $pattern = $definition[RouteDefinition::PATTERN];
             $via = $definition[RouteDefinition::VIA];
             if (!$matchable($via) || $pattern != $path) {
                 continue;
             }
             return $id;
         }
         return null;
     };
     #
     # Search for a matching dynamic route.
     #
     $map_dynamic = function ($definitions) use($path, &$matchable, &$captured) {
         foreach ($definitions as $id => $definition) {
             $pattern = $definition[RouteDefinition::PATTERN];
             $via = $definition[RouteDefinition::VIA];
             if (!$matchable($via) || !Pattern::from($pattern)->match($path, $captured)) {
                 continue;
             }
             return $id;
         }
         return null;
     };
     list($static, $dynamic) = $this->sort_routes();
     $id = null;
     if ($static) {
         $id = $map_static($static);
     }
     if (!$id && $dynamic) {
         $id = $map_dynamic($dynamic);
     }
     if (!$id) {
         return null;
     }
     $query = $parsed['query'];
     if ($query) {
         parse_str($query, $parsed_query_string);
         $captured['__query__'] = $parsed_query_string;
     }
     return $this[$id];
 }
Exemple #3
0
 /**
  * Finds a page using its path.
  *
  * @param string $path
  *
  * @return Page
  */
 public function find_by_path($path)
 {
     global $core;
     $pos = strrpos($path, '.');
     $extension = null;
     if ($pos && $pos > strrpos($path, '/')) {
         $extension = substr($path, $pos);
         $path = substr($path, 0, $pos);
     }
     $l = strlen($path);
     if ($l && $path[$l - 1] == '/') {
         $path = substr($path, 0, -1);
     }
     #
     # matching site
     #
     $site = $core->site;
     $siteid = $site->siteid;
     $site_path = $site->path;
     if ($site_path) {
         if (strpos($path, $site_path) !== 0) {
             return;
         }
         $path = substr($path, strlen($site_path));
     }
     if (!$path) {
         #
         # The home page is requested, we load the first parentless online page of the site.
         #
         $page = $this->find_home($siteid);
         if (!$page) {
             return;
         }
         if (!$this->retrieve($page->nid)) {
             $this->store($page);
         }
         return $page;
     }
     $parts = explode('/', $path);
     array_shift($parts);
     $parts_n = count($parts);
     $vars = array();
     #
     # We load from all the pages just what we need to find a matching path, and create a tree
     # with it.
     #
     $tries = $this->select('nid, parentid, slug, pattern')->filter_by_siteid($siteid)->ordered->all(\PDO::FETCH_OBJ);
     $tries = self::nestNodes($tries);
     $try = null;
     $pages_by_ids = array();
     for ($i = 0; $i < $parts_n; $i++) {
         if ($try) {
             $tries = $try->children;
         }
         $part = $path_part = $parts[$i];
         #
         # first we search for a matching slug
         #
         foreach ($tries as $try) {
             $pattern = $try->pattern;
             if ($pattern) {
                 $stripped = preg_replace('#<[^>]+>#', '', $pattern);
                 $nparts = substr_count($stripped, '/') + 1;
                 $path_part = implode('/', array_slice($parts, $i, $nparts));
                 $pattern = Pattern::from($pattern);
                 if (!$pattern->match($path_part, $path_captured)) {
                     $try = null;
                     continue;
                 }
                 #
                 # found matching pattern !
                 # we skip parts ate by the pattern
                 #
                 $i += $nparts - 1;
                 #
                 # even if the pattern matched, $match is not guaranteed to be an array,
                 # 'feed.xml' is a valid pattern. // FIXME-20110327: is it still ?
                 #
                 if (is_array($path_captured)) {
                     $vars = $path_captured + $vars;
                 }
                 break;
             } else {
                 if ($part == $try->slug) {
                     break;
                 }
             }
             $try = null;
         }
         #
         # If `try` is null at this point it's that the path could not be matched.
         #
         if (!$try) {
             return;
         }
         #
         # otherwise, we continue
         #
         $pages_by_ids[$try->nid] = array('url_part' => $path_part, 'url_variables' => $vars);
     }
     #
     # append the extension (if any) to the last page of the branch
     #
     $pages_by_ids[$try->nid]['url_part'] .= $extension;
     #
     # All page objects have been loaded, we need to set up some additionnal properties, link
     # each page to its parent and propagate the online status.
     #
     $parent = null;
     $pages = $this->find(array_keys($pages_by_ids));
     foreach ($pages as $page) {
         $page->url_part = $pages_by_ids[$page->nid]['url_part'];
         $page->url_variables = $pages_by_ids[$page->nid]['url_variables'];
         if ($parent) {
             // 				$page->parent = $parent;
             if (!$parent->is_online) {
                 $page->is_online = false;
             }
         }
         $parent = $page;
     }
     return $page;
 }
Exemple #4
0
 /**
  * Initializes the {@link $pattern} property and the properties provided.
  *
  * @param string $pattern
  * @param array $properties
  */
 public function __construct($pattern, array $properties)
 {
     $this->pattern = Pattern::from($pattern);
     unset($properties['pattern']);
     $this->assert_properties_are_valid($properties, self::$invalid_construct_properties);
     foreach ($properties as $property => $value) {
         $this->{$property} = $value;
     }
 }
Exemple #5
0
 /**
  * Returns the URL of the page.
  *
  * @return string
  */
 protected function get_url()
 {
     global $core;
     if ($this->location) {
         return $this->location->url;
     }
     $url_pattern = $this->url_pattern;
     if ($this->is_home) {
         return $url_pattern;
     }
     $url = null;
     if (Pattern::is_pattern($url_pattern)) {
         if ($this->url_variables) {
             $url = Pattern::from($url_pattern)->format($this->url_variables);
             //				\ICanBoogie\log('URL %pattern rescued using URL variables', array('%pattern' => $pattern));
         } else {
             $page = isset($core->request->context->page) ? $core->request->context->page : null;
             if ($page && $page->url_variables) {
                 $url = Pattern::from($url_pattern)->format($page->url_variables);
                 // 					\ICanBoogie\log("URL pattern %pattern was resolved using current page's variables", array('%pattern' => $pattern));
             } else {
                 $url = '#url-pattern-could-not-be-resolved';
             }
         }
     } else {
         $url = $url_pattern;
     }
     return $url;
 }
Exemple #6
0
 /**
  * Resolves a request into a page.
  *
  * @param Request $request
  *
  * @return Page|Response
  */
 protected function resolve_page(Request $request)
 {
     global $core;
     /* TODO-20130812: Move the following code section in the Sites module. */
     $site = $request->context->site;
     if (!$site->siteid) {
         throw new NotFound('Unable to find matching website.');
     }
     $status = $site->status;
     switch ($status) {
         case Site::STATUS_UNAUTHORIZED:
             throw new AuthenticationRequired();
         case Site::STATUS_NOT_FOUND:
             throw new NotFound(\ICanBoogie\format("The requested URL does not exists: %uri", ['uri' => $request->uri]));
         case Site::STATUS_UNAVAILABLE:
             throw new ServiceUnavailable();
     }
     /* /TODO */
     $path = $request->path;
     $page = $core->models['pages']->find_by_path($request->path);
     if (!$page) {
         return;
     }
     if ($page->location) {
         return new RedirectResponse($page->location->url, 301, ['Icybee-Redirected-By' => __FILE__ . '::' . __LINE__]);
     }
     #
     # We make sure that a normalized URL is used. For instance, "/fr" is redirected to
     # "/fr/".
     #
     $url_pattern = Pattern::from($page->url_pattern);
     if (!$url_pattern->params && $page->url != $path) {
         $query_string = $request->query_string;
         return new RedirectResponse($page->url . ($query_string ? '?' . $query_string : ''), 301, ['Icybee-Redirected-By' => __FILE__ . '::' . __LINE__]);
     }
     if (!$page->is_online || $page->site->status != Site::STATUS_OK) {
         #
         # Offline pages are displayed if the user has ownership, otherwise an HTTP exception
         # with code 401 (Authentication) is thrown. We add the "✎" marker to the title of the
         # page to indicate that the page is offline but displayed as a preview for the user.
         #
         if (!$core->user->has_ownership('pages', $page)) {
             throw new AuthenticationRequired(\ICanBoogie\format('The requested URL %url requires authentication.', ['url' => $path]));
         }
         $page->title .= ' ✎';
     }
     if (isset($page->url_variables)) {
         $request->path_params = array_merge($request->path_params, $page->url_variables);
         $request->params = array_merge($request->params, $page->url_variables);
     }
     return $page;
 }