<commit_before><?php
namespace wcf\system\request;
use wcf\system\application\ApplicationHandler;
use wcf\system\exception\SystemException;
use wcf\system\menu\page\PageMenu;
use wcf\system\WCF;

/**
 * Route implementation to resolve HTTP requests.
 * 
 * Inspired by routing mechanism used by ASP.NET MVC and released under the terms of
 * the Microsoft Public License (MS-PL) http://www.opensource.org/licenses/ms-pl.html
 * 
 * @author	<NAME>
 * @copyright	2001-2015 WoltLab GmbH
 * @license	GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
 * @package	com.woltlab.wcf
 * @subpackage	system.request
 * @category	Community Framework
 */
class Route implements IRoute {
	/**
	 * route controller if controller is no part of the route schema
	 * @var	string
	 */
	protected $controller = null;
	
	/**
	 * route is restricted to ACP
	 * @var	boolean
	 */
	protected $isACP = false;
	
	/**
	 * schema component options
	 * @var	array
	 */
	protected $parameterOptions = array();
	
	/**
	 * route name
	 * @var	string
	 */
	protected $routeName = '';
	
	/**
	 * route schema data
	 * @var	array
	 */
	protected $routeSchema = array();
	
	/**
	 * parsed route data
	 * @var	array
	 */
	protected $routeData = null;
	
	/**
	 * cached list of transformed controller names
	 * @var	array<string>
	 */
	protected static $controllerNames = array();
	
	/**
	 * list of application abbreviation and default controller name
	 * @var	array<string>
	 */
	protected static $defaultControllers = null;
	
	/**
	 * Creates a new route.
	 * 
	 * @param	string		$routeName
	 * @param	boolean		$isACP
	 */
	public function __construct($routeName, $isACP = false) {
		$this->isACP = $isACP;
		$this->routeName = $routeName;
	}
	
	/**
	 * Sets route schema, e.g. /{controller}/{id}.
	 * 
	 * @param	string		$routeSchema
	 * @param	string		$controller
	 */
	public function setSchema($routeSchema, $controller = null) {
		$schemaParts = $this->getParts($routeSchema);
		$hasController = false;
		$pattern = '~^{[a-zA-Z]+}$~';
		
		if ($controller !== null) {
			$this->controller = $controller;
			$hasController = true;
		}
		
		foreach ($schemaParts as &$part) {
			if (!preg_match($pattern, $part)) {
				throw new SystemException("Placeholder expected, but invalid string '" . $part . "' given.");
			}
			
			$part = str_replace(array('{', '}'), '', $part);
			if ($part == 'controller') {
				if ($this->controller !== null) {
					throw new SystemException('Controller may not be part of the scheme if a route controller is given.');
				}
				
				$hasController = true;
			}
		}
		
		// each route must define a controller
		if (!$hasController) {
			throw new SystemException('Route schema does not provide a valid placeholder for controller.');
		}
		
		$this->routeSchema = $schemaParts;
	}
	
	/**
	 * Sets options for a route parameter.
	 * 
	 * @param	string		$key
	 * @param	string		$default
	 * @param	string		$regexPattern
	 * @param	boolean		$isOptional
	 */
	public function setParameterOption($key, $default = null, $regexPattern = null, $isOptional = false) {
		$this->parameterOptions[$key] = array(
			'default' => $default,
			'isOptional' => $isOptional,
			'regexPattern' => $regexPattern
		);
	}
	
	/**
	 * @see	\wcf\system\request\IRoute::matches()
	 */
	public function matches($requestURL) {
		$urlParts = $this->getParts($requestURL);
		$data = array();
		
		// handle each route schema component
		for ($i = 0, $size = count($this->routeSchema); $i < $size; $i++) {
			$schemaPart = $this->routeSchema[$i];
			
			if (isset($urlParts[$i])) {
				if (isset($this->parameterOptions[$schemaPart])) {
					// validate parameter against a regex pattern
					if ($this->parameterOptions[$schemaPart]['regexPattern'] !== null) {
						$pattern = '~^' . $this->parameterOptions[$schemaPart]['regexPattern'] . '$~';
						if (!preg_match($pattern, $urlParts[$i])) {
							return false;
						}
					}
				}
				
				// url component passed previous validation
				$data[$schemaPart] = $urlParts[$i];
			}
			else {
				if (isset($this->parameterOptions[$schemaPart])) {
					// default value is provided
					if ($this->parameterOptions[$schemaPart]['default'] !== null) {
						if ($schemaPart == 'controller') {
							$data['isDefaultController'] = true;
						}
						
						$data[$schemaPart] = $this->parameterOptions[$schemaPart]['default'];
						continue;
					}
					
					// required parameter is missing
					if (!$this->parameterOptions[$schemaPart]['isOptional']) {
						return false;<commit_msg>Work-around for case-sensitive controller patterns<commit_after><?php
namespace wcf\system\request;
use wcf\system\application\ApplicationHandler;
use wcf\system\exception\SystemException;
use wcf\system\menu\page\PageMenu;
use wcf\system\WCF;

/**
 * Route implementation to resolve HTTP requests.
 * 
 * Inspired by routing mechanism used by ASP.NET MVC and released under the terms of
 * the Microsoft Public License (MS-PL) http://www.opensource.org/licenses/ms-pl.html
 * 
 * @author	<NAME>
 * @copyright	2001-2015 WoltLab GmbH
 * @license	GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
 * @package	com.woltlab.wcf
 * @subpackage	system.request
 * @category	Community Framework
 */
class Route implements IRoute {
	/**
	 * route controller if controller is no part of the route schema
	 * @var	string
	 */
	protected $controller = null;
	
	/**
	 * route is restricted to ACP
	 * @var	boolean
	 */
	protected $isACP = false;
	
	/**
	 * schema component options
	 * @var	array
	 */
	protected $parameterOptions = array();
	
	/**
	 * route name
	 * @var	string
	 */
	protected $routeName = '';
	
	/**
	 * route schema data
	 * @var	array
	 */
	protected $routeSchema = array();
	
	/**
	 * parsed route data
	 * @var	array
	 */
	protected $routeData = null;
	
	/**
	 * cached list of transformed controller names
	 * @var	array<string>
	 */
	protected static $controllerNames = array();
	
	/**
	 * list of application abbreviation and default controller name
	 * @var	array<string>
	 */
	protected static $defaultControllers = null;
	
	/**
	 * Creates a new route.
	 * 
	 * @param	string		$routeName
	 * @param	boolean		$isACP
	 */
	public function __construct($routeName, $isACP = false) {
		$this->isACP = $isACP;
		$this->routeName = $routeName;
	}
	
	/**
	 * Sets route schema, e.g. /{controller}/{id}.
	 * 
	 * @param	string		$routeSchema
	 * @param	string		$controller
	 */
	public function setSchema($routeSchema, $controller = null) {
		$schemaParts = $this->getParts($routeSchema);
		$hasController = false;
		$pattern = '~^{[a-zA-Z]+}$~';
		
		if ($controller !== null) {
			$this->controller = $controller;
			$hasController = true;
		}
		
		foreach ($schemaParts as &$part) {
			if (!preg_match($pattern, $part)) {
				throw new SystemException("Placeholder expected, but invalid string '" . $part . "' given.");
			}
			
			$part = str_replace(array('{', '}'), '', $part);
			if ($part == 'controller') {
				if ($this->controller !== null) {
					throw new SystemException('Controller may not be part of the scheme if a route controller is given.');
				}
				
				$hasController = true;
			}
		}
		
		// each route must define a controller
		if (!$hasController) {
			throw new SystemException('Route schema does not provide a valid placeholder for controller.');
		}
		
		$this->routeSchema = $schemaParts;
	}
	
	/**
	 * Sets options for a route parameter.
	 * 
	 * @param	string		$key
	 * @param	string		$default
	 * @param	string		$regexPattern
	 * @param	boolean		$isOptional
	 */
	public function setParameterOption($key, $default = null, $regexPattern = null, $isOptional = false) {
		$this->parameterOptions[$key] = array(
			'default' => $default,
			'isOptional' => $isOptional,
			'regexPattern' => $regexPattern
		);
	}
	
	/**
	 * @see	\wcf\system\request\IRoute::matches()
	 */
	public function matches($requestURL) {
		$urlParts = $this->getParts($requestURL);
		$data = array();
		
		// handle each route schema component
		for ($i = 0, $size = count($this->routeSchema); $i < $size; $i++) {
			$schemaPart = $this->routeSchema[$i];
			
			if (isset($urlParts[$i])) {
				if (isset($this->parameterOptions[$schemaPart])) {
					// validate parameter against a regex pattern
					if ($this->parameterOptions[$schemaPart]['regexPattern'] !== null) {
						$pattern = '~^' . $this->parameterOptions[$schemaPart]['regexPattern'] . '$~';
						if (!URL_LEGACY_MODE && $schemaPart == 'controller') $pattern .= 'i';
						
						if (!preg_match($pattern, $urlParts[$i])) {
							return false;
						}
					}
				}
				
				// url component passed previous validation
				$data[$schemaPart] = $urlParts[$i];
			}
			else {
				if (isset($this->parameterOptions[$schemaPart])) {
					// default value is provided
					if ($this->parameterOptions[$schemaPart]['default'] !== null) {
						if ($schemaPart == 'controller') {
							$data['isDefaultController'] = true;
						}
						
						$data[$schemaPart] = $this->parameterOptions[$schemaPart]['default'];
						continue;
					}
					
					// required parameter is missing
					if (!$this->parameterOptions[$schemaPart]['isOptional']) {
						return false;
{'fraction_non_alphanumeric': 0.14998914695029303, 'fraction_numerical': 0.0019535489472541786, 'mean_word_length': 3.2231897341888174, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 51, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5626122', 'n_tokens_mistral': 3334, 'n_tokens_neox': 2731, 'n_words': 745}