<commit_before><?php
namespace Drest\Route;

use DrestCommon\Request\Request;


/**
 * Class Matcher takes a request object and finds matching routes
 * @package Drest\Route
 */
class Matcher
{

    /**
     * The route meta data this matcher should operate on
     * @var \Drest\Mapping\RouteMetaData $routeMetaData
     */
    protected $routeMetaData;

    /**
     * Key-value array of URL parameter names
     * @var array $param_names
     */
    protected $param_names = array();

    /**
     * Key-value array of URL parameters with + at the end
     * @var array $param_names_path
     */
    protected $param_names_path = array();

    /**
     * Key-value array of URL parameters populated after a match has been successful
     * - or directly by using available setter
     * @var array $route_params
     */
    protected $route_params;

    /**
     * An index array of URL parameters that exist but didn't match a route pattern parameter
     * Eg: pattern: /user/:id+  with url: /user/1/some/additional/params.
     * The value id => 1 will go into $route_params
     * All the rest will go in here.
     * @var array $unmapped_route_params
     */
    protected $unmapped_route_params;

    /**
     * Route meta data to test a match on
     * @param \Drest\Mapping\RouteMetaData|null $routeMetaData
     */
    public function __construct(\Drest\Mapping\RouteMetaData $routeMetaData = null)
    {
        $this->setRouteMetaData($routeMetaData);
    }

    /**
     * Set the route meta data
     * @param \Drest\Mapping\RouteMetaData $routeMetaData
     */
    public function setRouteMetaData(\Drest\Mapping\RouteMetaData $routeMetaData)
    {
        $this->routeMetaData = $routeMetaData;
    }

    /**
     * Does this request match the route pattern
     * @param  Request $request
     * @param  boolean $matchVerb - Whether you want to match the route using the request HTTP verb
     *                            - useful for OPTIONS requests to provide route info
     * @param  string  $basePath  - add a base path to the route pattern
     * @return boolean $result
     */
    public function matches(Request $request, $matchVerb = true, $basePath = null)
    {
        // If we're matching the verb and we've defined them, ensure the method used is in our list of registered verbs
        if ($matchVerb &&
            $this->routeMetaData->usesHttpVerbs() &&
            !$this->methodIsInOurListOfAllowedVerbs($request->getHttpMethod())) {
            return false;
        }

        $patternAsRegex = $this->getMatchRegexPattern($basePath);

        //Cache URL params' names and values if this route matches the current HTTP request
        if (!preg_match('#^' . $patternAsRegex . '$#', $request->getPath(), $paramValues)) {
            return false;
        }

        // Process the param names and save them on the route params
        $this->processRouteParams($paramValues);

        // Check the route conditions
        if (!$this->routeConditionsAreValid())
        {
            return false;
        }

        return true;
    }

    /**
     * Get the determined route parameters
     * @return array
     */
    public function getRouteParams()
    {
        return $this->route_params;
    }


    /**
     * Get the param names
     * @return array
     */
    public function getParamNames()
    {
        return $this->param_names;
    }

    /**
     * Get the params names path
     * @return array
     */
    public function getParamNamesPath()
    {
        return $this->param_names_path;
    }

    /**
     * Inject unmapped route params onto this object without performing a match.
     * Useful when calling a named route directly
     * @param array $params - should be a keyed array. associative values are ignored
     */
    public function setUnmappedRouteParams(array $params = array())
    {
        $this->unmapped_route_params = array_flip(
            array_filter(
                array_flip($params),
                function ($entry) {
                    return !is_string($entry);
                }
            )
        );
    }

    /**
     * Get any unmapped route parameters
     * @return array $params
     */
    public function getUnmappedRouteParams()
    {
        return $this->unmapped_route_params;
    }

    /**
     * Get the regex pattern to match the request path
     * @param $basePath
     * @return string
     */
    protected function getMatchRegexPattern($basePath)
    {
        // Convert URL params into regex patterns, construct a regex for this route, init params
        $routePattern = (is_null($basePath))
            ? (string) $this->routeMetaData->getRoutePattern()
            : '/' . $basePath . '/' . ltrim((string) $this->routeMetaData->getRoutePattern(), '/');
        $patternAsRegex = preg_replace_callback(
            '#:([\w]+)\+?#',<commit_msg>Refactor RouteMetaData to abstract matching logic<commit_after><?php
namespace Drest\Route;

use DrestCommon\Request\Request;


/**
 * Class Matcher takes a request object and finds matching routes
 * @package Drest\Route
 */
class Matcher
{

    /**
     * The route meta data this matcher should operate on
     * @var \Drest\Mapping\RouteMetaData $routeMetaData
     */
    protected $routeMetaData;

    /**
     * Key-value array of URL parameter names
     * @var array $param_names
     */
    protected $param_names = array();

    /**
     * Key-value array of URL parameters with + at the end
     * @var array $param_names_path
     */
    protected $param_names_path = array();

    /**
     * Key-value array of URL parameters populated after a match has been successful
     * - or directly by using available setter
     * @var array $route_params
     */
    protected $route_params;

    /**
     * An index array of URL parameters that exist but didn't match a route pattern parameter
     * Eg: pattern: /user/:id+  with url: /user/1/some/additional/params.
     * The value id => 1 will go into $route_params
     * All the rest will go in here.
     * @var array $unmapped_route_params
     */
    protected $unmapped_route_params;

    /**
     * Route meta data to test a match on
     * @param \Drest\Mapping\RouteMetaData|null $routeMetaData
     */
    public function __construct(\Drest\Mapping\RouteMetaData $routeMetaData = null)
    {
        if (!is_null($routeMetaData))
        {
            $this->setRouteMetaData($routeMetaData);
        }
    }

    /**
     * Set the route meta data
     * @param \Drest\Mapping\RouteMetaData $routeMetaData
     */
    public function setRouteMetaData(\Drest\Mapping\RouteMetaData $routeMetaData)
    {
        $this->routeMetaData = $routeMetaData;
    }

    /**
     * Does this request match the route pattern
     * @param  Request $request
     * @param  boolean $matchVerb - Whether you want to match the route using the request HTTP verb
     *                            - useful for OPTIONS requests to provide route info
     * @param  string  $basePath  - add a base path to the route pattern
     * @return boolean $result
     */
    public function matches(Request $request, $matchVerb = true, $basePath = null)
    {
        // If we're matching the verb and we've defined them, ensure the method used is in our list of registered verbs
        if ($matchVerb &&
            $this->routeMetaData->usesHttpVerbs() &&
            !$this->methodIsInOurListOfAllowedVerbs($request->getHttpMethod())) {
            return false;
        }

        $patternAsRegex = $this->getMatchRegexPattern($basePath);

        //Cache URL params' names and values if this route matches the current HTTP request
        if (!preg_match('#^' . $patternAsRegex . '$#', $request->getPath(), $paramValues)) {
            return false;
        }

        // Process the param names and save them on the route params
        $this->processRouteParams($paramValues);

        // Check the route conditions
        if (!$this->routeConditionsAreValid())
        {
            return false;
        }

        return true;
    }

    /**
     * Get the determined route parameters
     * @return array
     */
    public function getRouteParams()
    {
        return $this->route_params;
    }


    /**
     * Get the param names
     * @return array
     */
    public function getParamNames()
    {
        return $this->param_names;
    }

    /**
     * Get the params names path
     * @return array
     */
    public function getParamNamesPath()
    {
        return $this->param_names_path;
    }

    /**
     * Get any unmapped route parameters
     * @return array $params
     */
    public function getUnmappedRouteParams()
    {
        return $this->unmapped_route_params;
    }

    /**
     * Get the regex pattern to match the request path
     * @param $basePath
     * @return string
     */
    protected function getMatchRegexPattern($basePath)
    {
        // Convert URL params into regex patterns, construct a regex for this route, init params
        $routePattern = (is_null($basePath))
            ? (string) $this->routeMetaData->getRoutePattern()
            : '/' . $basePath . '/' . ltrim((string) $this->routeMetaData->getRoutePattern(), '/');
        $patternAsRegex = preg_replace_callback(
            '#:([\w]+)\+?#',
{'fraction_non_alphanumeric': 0.10027975037658704, 'fraction_numerical': 0.00043038519474930065, 'mean_word_length': 2.198554714384033, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 42, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1179130', 'n_tokens_mistral': 2535, 'n_tokens_neox': 2521, 'n_words': 787}