<commit_before><?php
/**
 * Copyright (c) 2012 <NAME> <<EMAIL>>
 * This file is licensed under the Affero General Public License version 3 or
 * later.
 * See the COPYING-README file.
 */

namespace OC\Route;

use OCP\Route\IRouter;
use Symfony\Component\Routing\Matcher\UrlMatcher;
use Symfony\Component\Routing\Generator\UrlGenerator;
use Symfony\Component\Routing\RequestContext;
use Symfony\Component\Routing\RouteCollection;

class Router implements IRouter {
	/**
	 * @var \Symfony\Component\Routing\RouteCollection[]
	 */
	protected $collections = array();

	/**
	 * @var \Symfony\Component\Routing\RouteCollection
	 */
	protected $collection = null;

	/**
	 * @var \Symfony\Component\Routing\RouteCollection
	 */
	protected $root = null;

	/**
	 * @var \Symfony\Component\Routing\Generator\UrlGenerator
	 */
	protected $generator = null;

	/**
	 * @var string[]
	 */
	protected $routingFiles;

	/**
	 * @var string
	 */
	protected $cacheKey;

	protected $loaded = false;

	protected $loadedApps = array();

	public function __construct() {
		$baseUrl = \OC_Helper::linkTo('', 'index.php');
		if (!\OC::$CLI) {
			$method = $_SERVER['REQUEST_METHOD'];
		} else {
			$method = 'GET';
		}
		$host = \OC_Request::serverHost();
		$schema = \OC_Request::serverProtocol();
		$this->context = new RequestContext($baseUrl, $method, $host, $schema);
		// TODO cache
		$this->root = $this->getCollection('root');
	}

	/**
	 * Get the files to load the routes from
	 *
	 * @return string[]
	 */
	public function getRoutingFiles() {
		if (!isset($this->routingFiles)) {
			$this->routingFiles = array();
			foreach (\OC_APP::getEnabledApps() as $app) {
				$file = \OC_App::getAppPath($app) . '/appinfo/routes.php';
				if (file_exists($file)) {
					$this->routingFiles[$app] = $file;
				}
			}
		}
		return $this->routingFiles;
	}

	public function getCacheKey() {
		if (!isset($this->cacheKey)) {
			$files = $this->getRoutingFiles();
			$files[] = 'settings/routes.php';
			$files[] = 'core/routes.php';
			$files[] = 'ocs/routes.php';
			$this->cacheKey = \OC_Cache::generateCacheKeyFromFiles($files);
		}
		return $this->cacheKey;
	}

	/**
	 * loads the api routes
	 */
	public function loadRoutes($app = null) {
		if ($this->loaded) {
			return;
		}
		if (is_null($app)) {
			$this->loaded = true;
			$routingFiles = $this->getRoutingFiles();
		} else {
			if (isset($this->loadedApps[$app])) {
				return;
			}
			$file = \OC_App::getAppPath($app) . '/appinfo/routes.php';
			if (file_exists($file)) {
				$routingFiles = array($app => $file);
			} else {
				$routingFiles = array();
			}
		}
		foreach ($routingFiles as $app => $file) {
			$this->loadedApps[$app] = true;
			$this->useCollection($app);
			require_once $file;
			$collection = $this->getCollection($app);
			$collection->addPrefix('/apps/' . $app);
			$this->root->addCollection($collection);
		}
		if (!isset($this->loadedApps['core'])) {
			$this->loadedApps['core'] = true;
			$this->useCollection('root');
			require_once 'settings/routes.php';
			require_once 'core/routes.php';

			// include ocs routes
			require_once 'ocs/routes.php';
			$collection = $this->getCollection('ocs');
			$collection->addPrefix('/ocs');
			$this->root->addCollection($collection);
		}
	}

	/**
	 * @param string $name
	 * @return \Symfony\Component\Routing\RouteCollection
	 */
	protected function getCollection($name) {
		if (!isset($this->collections[$name])) {
			$this->collections[$name] = new RouteCollection();
		}
		return $this->collections[$name];
	}

	/**
	 * Sets the collection to use for adding routes
	 *
	 * @param string $name Name of the collection to use.
	 */
	public function useCollection($name) {
		$this->collection = $this->getCollection($name);
	}

	/**
	 * Create a \OC\Route\Route.
	 *
	 * @param string $name Name of the route to create.
	 * @param string $pattern The pattern to match
	 * @param array $defaults An array of default parameter values
	 * @param array $requirements An array of requirements for parameters (regexes)
	 * @return \OC\Route\Route
	 */
	public function create($name, $pattern, array $defaults = array(), array $requirements = array()) {
		$route = new Route($pattern, $defaults, $requirements);
		$this->collection->add($name, $route);
		return $route;
	}

	/**
	 * Find the route matching $url
	 *
	 * @param string $url The url to find
	 * @throws \Exception
	 */
	public function match($url) {
		if (substr($url, 0, 6) === '/apps/') {
			// empty string / 'apps' / $app / rest of the route
			list(, , $app,) = explode('/', $url, 4);
			$this->loadRoutes($app);
		} else if(substr($url, 0, 6) === '/core/' or substr($url, 0, 5) === '/ocs/' or substr($url, 0, 10) === '/settings/') {
			$this->loadRoutes('core');
		} else {
			$this->loadRoutes();
		}
		$matcher = new UrlMatcher($this->root, $this->context);
		$parameters = $matcher->match($url);
		if (isset($parameters['action'])) {
			$action = $parameters['action'];
			if (!is_callable($action)) {
				var_dump($action);
				throw new \Exception('not a callable action');
			}
			unset($parameters['action']);
			call_user_func($action, $parameters);
		} elseif (isset($parameters['file'])) {
			include $parameters['file'];
		} else {
			throw new \Exception('no action available');
		}
	}

	/**
	 * Get the url generator
	 *<commit_msg>Fix routes getting lost when loading app routes twice<commit_after><?php
/**
 * Copyright (c) 2012 <NAME> <<EMAIL>>
 * This file is licensed under the Affero General Public License version 3 or
 * later.
 * See the COPYING-README file.
 */

namespace OC\Route;

use OCP\Route\IRouter;
use Symfony\Component\Routing\Matcher\UrlMatcher;
use Symfony\Component\Routing\Generator\UrlGenerator;
use Symfony\Component\Routing\RequestContext;
use Symfony\Component\Routing\RouteCollection;

class Router implements IRouter {
	/**
	 * @var \Symfony\Component\Routing\RouteCollection[]
	 */
	protected $collections = array();

	/**
	 * @var \Symfony\Component\Routing\RouteCollection
	 */
	protected $collection = null;

	/**
	 * @var \Symfony\Component\Routing\RouteCollection
	 */
	protected $root = null;

	/**
	 * @var \Symfony\Component\Routing\Generator\UrlGenerator
	 */
	protected $generator = null;

	/**
	 * @var string[]
	 */
	protected $routingFiles;

	/**
	 * @var string
	 */
	protected $cacheKey;

	protected $loaded = false;

	protected $loadedApps = array();

	public function __construct() {
		$baseUrl = \OC_Helper::linkTo('', 'index.php');
		if (!\OC::$CLI) {
			$method = $_SERVER['REQUEST_METHOD'];
		} else {
			$method = 'GET';
		}
		$host = \OC_Request::serverHost();
		$schema = \OC_Request::serverProtocol();
		$this->context = new RequestContext($baseUrl, $method, $host, $schema);
		// TODO cache
		$this->root = $this->getCollection('root');
	}

	/**
	 * Get the files to load the routes from
	 *
	 * @return string[]
	 */
	public function getRoutingFiles() {
		if (!isset($this->routingFiles)) {
			$this->routingFiles = array();
			foreach (\OC_APP::getEnabledApps() as $app) {
				$file = \OC_App::getAppPath($app) . '/appinfo/routes.php';
				if (file_exists($file)) {
					$this->routingFiles[$app] = $file;
				}
			}
		}
		return $this->routingFiles;
	}

	public function getCacheKey() {
		if (!isset($this->cacheKey)) {
			$files = $this->getRoutingFiles();
			$files[] = 'settings/routes.php';
			$files[] = 'core/routes.php';
			$files[] = 'ocs/routes.php';
			$this->cacheKey = \OC_Cache::generateCacheKeyFromFiles($files);
		}
		return $this->cacheKey;
	}

	/**
	 * loads the api routes
	 */
	public function loadRoutes($app = null) {
		if ($this->loaded) {
			return;
		}
		if (is_null($app)) {
			$this->loaded = true;
			$routingFiles = $this->getRoutingFiles();
		} else {
			if (isset($this->loadedApps[$app])) {
				return;
			}
			$file = \OC_App::getAppPath($app) . '/appinfo/routes.php';
			if (file_exists($file)) {
				$routingFiles = array($app => $file);
			} else {
				$routingFiles = array();
			}
		}
		foreach ($routingFiles as $app => $file) {
			if (!$this->loadedApps[$app]) {
				$this->loadedApps[$app] = true;
				$this->useCollection($app);
				require_once $file;
				$collection = $this->getCollection($app);
				$collection->addPrefix('/apps/' . $app);
				$this->root->addCollection($collection);
			}
		}
		if (!isset($this->loadedApps['core'])) {
			$this->loadedApps['core'] = true;
			$this->useCollection('root');
			require_once 'settings/routes.php';
			require_once 'core/routes.php';

			// include ocs routes
			require_once 'ocs/routes.php';
			$collection = $this->getCollection('ocs');
			$collection->addPrefix('/ocs');
			$this->root->addCollection($collection);
		}
	}

	/**
	 * @param string $name
	 * @return \Symfony\Component\Routing\RouteCollection
	 */
	protected function getCollection($name) {
		if (!isset($this->collections[$name])) {
			$this->collections[$name] = new RouteCollection();
		}
		return $this->collections[$name];
	}

	/**
	 * Sets the collection to use for adding routes
	 *
	 * @param string $name Name of the collection to use.
	 */
	public function useCollection($name) {
		$this->collection = $this->getCollection($name);
	}

	/**
	 * Create a \OC\Route\Route.
	 *
	 * @param string $name Name of the route to create.
	 * @param string $pattern The pattern to match
	 * @param array $defaults An array of default parameter values
	 * @param array $requirements An array of requirements for parameters (regexes)
	 * @return \OC\Route\Route
	 */
	public function create($name, $pattern, array $defaults = array(), array $requirements = array()) {
		$route = new Route($pattern, $defaults, $requirements);
		$this->collection->add($name, $route);
		return $route;
	}

	/**
	 * Find the route matching $url
	 *
	 * @param string $url The url to find
	 * @throws \Exception
	 */
	public function match($url) {
		if (substr($url, 0, 6) === '/apps/') {
			// empty string / 'apps' / $app / rest of the route
			list(, , $app,) = explode('/', $url, 4);
			$this->loadRoutes($app);
		} else if (substr($url, 0, 6) === '/core/' or substr($url, 0, 5) === '/ocs/' or substr($url, 0, 10) === '/settings/') {
			$this->loadRoutes('core');
		} else {
			$this->loadRoutes();
		}
		$matcher = new UrlMatcher($this->root, $this->context);
		$parameters = $matcher->match($url);
		if (isset($parameters['action'])) {
			$action = $parameters['action'];
			if (!is_callable($action)) {
				var_dump($action);
				throw new \Exception('not a callable action');
			}
			unset($parameters['action']);
			call_user_func($action, $parameters);
		} elseif (isset($parameters['file'])) {
			include $parameters['file'];
		} else {
			throw new \Exception('no action available');
		}
	}

	/**
	 * Get the url generator
	 *
{'fraction_non_alphanumeric': 0.18036764019781656, 'fraction_numerical': 0.0027992908463189323, 'mean_word_length': 3.613861386138614, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 96, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, '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': '1334517', 'n_tokens_mistral': 3929, 'n_tokens_neox': 3497, 'n_words': 809}