      1: <?php
      2: /*************************************************************************************/
      3: /*                                                                                   */
      4: /*      Thelia                                                                       */
      5: /*                                                                                   */
      6: /*      Copyright (c) OpenStudio                                                     */
      7: /*  email : info@thelia.net                                                      */
      8: /*      web : http://www.thelia.net                                                  */
      9: /*                                                                                   */
     10: /*      This program is free software; you can redistribute it and/or modify         */
     11: /*      it under the terms of the GNU General Public License as published by         */
     12: /*      the Free Software Foundation; either version 3 of the License                */
     13: /*                                                                                   */
     14: /*      This program is distributed in the hope that it will be useful,              */
     15: /*      but WITHOUT ANY WARRANTY; without even the implied warranty of               */
     16: /*      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                */
     17: /*      GNU General Public License for more details.                                 */
     18: /*                                                                                   */
     19: /*      You should have received a copy of the GNU General Public License            */
     20: /*      along with this program. If not, see <http://www.gnu.org/licenses/>.     */
     21: /*                                                                                   */
     22: /*************************************************************************************/
     23: namespace Thelia\Routing;
     24:
     25: use Symfony\Component\Routing\Matcher\RequestMatcherInterface;
     26: use Symfony\Component\Routing\Exception\ResourceNotFoundException;
     27: use Symfony\Component\Routing\Exception\MethodNotAllowedException;
     28: use Symfony\Component\Routing\RequestContextAwareInterface;
     29: use Symfony\Component\Routing\RequestContext;
     30: use Symfony\Component\HttpFoundation\Request;
     31:
     32: /**
     33:  *
     34:  * Collection of Matcher.
     35:  *
     36:  * Matcher resolve request into controller::method
     37:  * exemple of Matcher : UrlMatcher of HttpKernel component (but it implements UrlMatcherInterface and not RequestMatcherInterface.
     38:  *
     39:  * @author Manuel Raynaud <mraynaud@openstudio.fr>
     40:  */
     41:
     42: class TheliaMatcherCollection implements RequestMatcherInterface, RequestContextAwareInterface
     43: {
     44:     protected $context;
     45:     protected $matchers = array();
     46:     protected $defaultMatcher;
     47:
     48:     protected $sortedMatchers = array();
     49:
     50:     /**
     51:      * Constructor
     52:      *
     53:      * Check if this constructor is needed (is RequestContext needed ? )
     54:      */
     55:     public function __construct()
     56:     {
     57:         $this->context = new RequestContext();
     58:     }
     59:
     60:     /**
     61:      * allow to add a matcher routing class to the matchers collection
     62:      * matcher must implement RequestMatcherInterface
     63:      *
     64:      * priority can be fixed with $priority parameter
     65:      *
     66:      * @param RequestMatcherInterface $matcher
     67:      * @param int                     $priority set the priority of the added matcher
     68:      *
     69:      */
     70:     public function add(RequestMatcherInterface $matcher, $priority = 0)
     71:     {
     72:         if (!is_object($matcher)) {
     73:             $matcher = new $matcher();
     74:         }
     75:
     76:         if (!isset($this->matchers[$priority])) {
     77:             $this->matchers[$priority] = array();
     78:         }
     79:
     80:         $this->matchers[$priority][] = $matcher;
     81:         $this->sortedMatchers = array();
     82:     }
     83:
     84:     /**
     85:      *
     86:      * Sort Matchers by priority
     87:      *
     88:      * @return array Array of matchers sorted by priority.
     89:      */
     90:     public function getSortedMatchers()
     91:     {
     92:         if (empty($this->sortedMatchers)) {
     93:             $this->sortedMatchers = $this->sortMatchers();
     94:         }
     95:
     96:         return $this->sortedMatchers;
     97:     }
     98:
     99:     /**
    100:      *
    101:      * Sort the matcher by priority
    102:      *
    103:      * @return array Array of matchers sorted by priority.
    104:      */
    105:     public function sortMatchers()
    106:     {
    107:         $sortedMatchers = array();
    108:         krsort($this->matchers);
    109:
    110:         foreach ($this->matchers as $matcher) {
    111:             $sortedMatchers = array_merge($sortedMatchers,$matcher);
    112:         }
    113:
    114:         return $sortedMatchers;
    115:     }
    116:
    117:     /**
    118:      * Tries to match a request with a set of routes.
    119:      *
    120:      * If the matcher can not find information, it must throw one of the exceptions documented
    121:      * below.
    122:      *
    123:      * @param Request $request The request to match
    124:      *
    125:      * @return array An array of parameters
    126:      *
    127:      * @throws ResourceNotFoundException If no matching resource could be found
    128:      * @throws MethodNotAllowedException If a matching resource was found but the request method is not allowed
    129:      */
    130:     public function matchRequest(Request $request)
    131:     {
    132:         if (empty($this->matchers)) {
    133:             throw new \InvalidArgumentException('there is no matcher added to the TheliaMatcherCollection');
    134:         }
    135:
    136:         foreach ($this->getSortedMatchers() as $matcher) {
    137:             try {
    138:                 return $matcher->matchRequest($request);
    139:             } catch (ResourceNotFoundException $e) {
    140:                 //no action, wait for next matcher
    141:             } catch (MethodNotAllowedException $e) {
    142:                 /**
    143:                  * @todo what todo with a MethodNotAllowedException ?
    144:                  */
    145:             }
    146:         }
    147:
    148:         throw new ResourceNotFoundException('No one matcher in this collection matched the current request');
    149:     }
    150:
    151:     /**
    152:      * Sets the request context.
    153:      *
    154:      * @param RequestContext $context The context
    155:      *
    156:      */
    157:     public function setContext(RequestContext $context)
    158:     {
    159:         $this->context = $context;
    160:
    161:     }
    162:
    163:     /**
    164:      * Gets the request context.
    165:      *
    166:      * @return RequestContext The context
    167:      *
    168:      */
    169:     public function getContext()
    170:     {
    171:         return $this->context;
    172:     }
    173: }
    174: