| <?php |
| /** |
| * File containing the ezcMvcRailsRoute class |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 |
| * @version //autogentag// |
| * @filesource |
| * @package MvcTools |
| */ |
| |
| /** |
| * Router class that uses rails style expressions for matching routes. |
| * |
| * The routes are matched against the uri property of the request object. The |
| * matching algorithm works as follows: |
| * |
| * - The pattern and URI as returned by getUriString() are split on the / |
| * character. |
| * - If the first part of the split *pattern* contains a "." (dot) then the |
| * first part of the pattern and the URI are split by ".". The return of |
| * this, together with the rest of the original split-by-slash string are |
| * concatenated. |
| * - Each of the two arrays are compared with each other with the delimiters |
| * being ignored. |
| * - A special case are elements in the pattern that start with a ":". In this |
| * case the pattern element and uri element do not need to match. Instead the |
| * pattern element creates a named variable with as value the element from |
| * the URI array with the same index. |
| * - If not every element matches, the route does not match and |
| * false is returned. If everything matches, true is returned. |
| * |
| * @package MvcTools |
| * @version //autogentag// |
| * @mainclass |
| */ |
| class ezcMvcRailsRoute implements ezcMvcRoute, ezcMvcReversibleRoute |
| { |
| /** |
| * This property contains the pattern |
| * |
| * @var string |
| */ |
| protected $pattern; |
| |
| /** |
| * This is the name of the controller class that will be instantiated with |
| * the request variables obtained from the route, as well as the default |
| * values belonging to a route. |
| * |
| * @var string |
| */ |
| protected $controllerClassName; |
| |
| /** |
| * Contains the action that the controller should execute. |
| * |
| * @var string |
| */ |
| protected $action; |
| |
| /** |
| * The default values for the variables that are send to the controller. |
| * The route matchers can override those default values |
| * |
| * @var array(string) |
| */ |
| protected $defaultValues; |
| |
| /** |
| * Constructs a new ezcMvcRailsRoute with $pattern. |
| * |
| * When the route is matched (with the match() method), the route |
| * instantiates an object of the class $controllerClassName. |
| * |
| * @param string $pattern |
| * @param string $controllerClassName |
| * @param string $action |
| * @param array(string) $defaultValues |
| */ |
| public function __construct( $pattern, $controllerClassName, $action = null, array $defaultValues = array() ) |
| { |
| $this->pattern = $pattern; |
| $this->controllerClassName = $controllerClassName; |
| $this->action = $action; |
| $this->defaultValues = $defaultValues; |
| } |
| |
| /** |
| * Returns the request information that the matches() method will match the |
| * pattern against. |
| * |
| * @param ezcMvcRequest $request |
| * @return string |
| */ |
| protected function getUriString( ezcMvcRequest $request ) |
| { |
| return $request->uri; |
| } |
| |
| /** |
| * Evaluates the URI against this route. |
| * |
| * The method first runs the match. If the pattern matches, it then creates |
| * an object containing routing information and returns it. If the route's |
| * pattern did not match it returns null. |
| * |
| * @param ezcMvcRequest $request |
| * @return null|ezcMvcRoutingInformation |
| */ |
| public function matches( ezcMvcRequest $request ) |
| { |
| if ( $this->match( $request, $matches ) ) |
| { |
| $request->variables = array_merge( $this->defaultValues, $request->variables, $matches ); |
| |
| return new ezcMvcRoutingInformation( $this->pattern, $this->controllerClassName, $this->action ); |
| } |
| return null; |
| } |
| |
| /** |
| * This method performs the actual pattern match against the $request's |
| * URI. |
| * |
| * @param ezcMvcRequest $request |
| * @param array(string) $matches |
| * @return bool |
| */ |
| protected function match( $request, &$matches ) |
| { |
| $matches = array(); |
| |
| // first we split the pattern and request ID per / |
| $patternParts = preg_split( '@(/)@', $this->pattern, null, PREG_SPLIT_DELIM_CAPTURE ); |
| $requestParts = preg_split( '@(/)@', $this->getUriString( $request ), null, PREG_SPLIT_DELIM_CAPTURE ); |
| |
| if ( strpos( $patternParts[0], '.' ) !== false ) |
| { |
| $subPatternParts = preg_split( '@([.])@', $patternParts[0], null, PREG_SPLIT_DELIM_CAPTURE ); |
| $subRequestParts = preg_split( '@([.])@', $requestParts[0], null, PREG_SPLIT_DELIM_CAPTURE ); |
| |
| $patternParts = array_merge( $subPatternParts, array_slice( $patternParts, 1 ) ); |
| $requestParts = array_merge( $subRequestParts, array_slice( $requestParts, 1 ) ); |
| } |
| |
| // if the number of / is not the same, it can not match |
| if ( count( $patternParts ) != count( $requestParts ) ) |
| { |
| return false; |
| } |
| |
| // now loop over all parts of the pattern, and see if it matches with |
| // the request URI |
| foreach ( $patternParts as $id => $patternPart ) |
| { |
| if ( $patternPart == '' || $patternPart[0] != ':' ) |
| { |
| if ( $patternPart !== $requestParts[$id] ) |
| { |
| return false; |
| } |
| } |
| else |
| { |
| if ( $requestParts[$id] == '' ) |
| { |
| return false; |
| } |
| $matches[substr( $patternPart, 1 )] = $requestParts[$id]; |
| } |
| } |
| return true; |
| } |
| |
| /** |
| * Adds the $prefix to the route's pattern. |
| * |
| * It's up to the developer to provide a meaningfull prefix. In this case, |
| * it needs to be a pattern just like the normal pattern. |
| * |
| * @param mixed $prefix |
| */ |
| public function prefix( $prefix ) |
| { |
| $this->pattern = $prefix . $this->pattern; |
| } |
| |
| /** |
| * Generates an URL back out of a route, including possible arguments |
| * |
| * @param array $arguments |
| */ |
| public function generateUrl( array $arguments = null ) |
| { |
| $patternParts = explode( '/', $this->pattern ); |
| foreach ( $patternParts as &$part ) |
| { |
| if ( strlen( $part ) > 1 && $part[0] === ':' ) |
| { |
| $paramName = substr( $part, 1 ); |
| if ( !isset( $arguments[$paramName] ) ) |
| { |
| throw new ezcMvcMissingRouteArgumentException( $this->pattern, $paramName ); |
| } |
| else |
| { |
| $part = $arguments[$paramName]; |
| } |
| } |
| } |
| return join( '/', $patternParts ); |
| } |
| } |
| ?> |