114 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			114 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| 
 | |
| require_once "website.php";
 | |
| 
 | |
| class RuleEngine
 | |
| {
 | |
| 	/**
 | |
| 	 * @param Website $site
 | |
| 	 * @param array $urlConfig
 | |
| 	 * @return URLRoute
 | |
| 	 */
 | |
| 	public static function findRoute(Website $site, array $urlConfig): URLRoute
 | |
| 	{
 | |
| 		if ($site->isProd())
 | |
| 			$requri = $_SERVER['REQUEST_URI'];
 | |
| 		else
 | |
| 			$requri = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : 'localhost:80/';
 | |
| 
 | |
| 		$parse = parse_url($requri);
 | |
| 
 | |
| 		$path      = isset($parse['path']) ? $parse['path'] : '';
 | |
| 		$pathparts = preg_split('@/@', $path, NULL, PREG_SPLIT_NO_EMPTY);
 | |
| 		$partcount = count($pathparts);
 | |
| 
 | |
| 		foreach ($urlConfig as $rule)
 | |
| 		{
 | |
| 			$route = self::testRule($site, $rule, $requri, $pathparts, $partcount);
 | |
| 			if ($route === null) continue;
 | |
| 
 | |
| 			if ($route->needsAdminLogin && !$site->isLoggedInByCookie()) return URLRoute::getLoginRoute($route, $requri);
 | |
| 
 | |
| 			return $route;
 | |
| 		}
 | |
| 
 | |
| 		return URLRoute::getNotFoundRoute($requri);
 | |
| 	}
 | |
| 
 | |
| 	private static function testRule(Website $site, array $rule, string $requri, array $pathparts, int $partcount)
 | |
| 	{
 | |
| 		if ($partcount !== count($rule['url'])) return null;
 | |
| 
 | |
| 		$urlparams = [];
 | |
| 
 | |
| 		$match = true;
 | |
| 		for($i = 0; $i < $partcount; $i++)
 | |
| 		{
 | |
| 			$comp = $rule['url'][$i];
 | |
| 			if (startsWith($comp, '?{') && endsWith($comp, '}'))
 | |
| 			{
 | |
| 				$ident = substr($comp, 2, strlen($comp)-3);
 | |
| 				$urlparams[$ident] = $pathparts[$i];
 | |
| 			}
 | |
| 			else if ($comp === '*')
 | |
| 			{
 | |
| 				if (!isset($urlparams['*'])) $urlparams['*'] = [];
 | |
| 				$urlparams['*'] []= $pathparts[$i];
 | |
| 			}
 | |
| 			else
 | |
| 			{
 | |
| 				if (strtolower($comp) !== strtolower($pathparts[$i])) { $match = false; break; }
 | |
| 			}
 | |
| 		}
 | |
| 		if (!$match) return null;
 | |
| 
 | |
| 		$route = new URLRoute($rule['target'], $requri);
 | |
| 
 | |
| 		foreach($rule['parameter'] as $optname => $optvalue)
 | |
| 		{
 | |
| 			$value = $optvalue;
 | |
| 
 | |
| 			if ($value === '%GET%')
 | |
| 			{
 | |
| 				if (!isset($_GET[$optname])) { $match = false; break; }
 | |
| 				$value = $_GET[$optname];
 | |
| 			}
 | |
| 			else if ($value === '%POST%')
 | |
| 			{
 | |
| 				if (!isset($_POST[$optname])) { $match = false; break; }
 | |
| 				$value = $_POST[$optname];
 | |
| 			}
 | |
| 			else if ($value === '%URL%')
 | |
| 			{
 | |
| 				if (!isset($urlparams[$optname])) { $match = false; break; }
 | |
| 				$value = urldecode($urlparams[$optname]);
 | |
| 			}
 | |
| 
 | |
| 			$route->parameter[strtolower($optname)] = $value;
 | |
| 		}
 | |
| 		if (!$match) return null;
 | |
| 
 | |
| 		$route->urlParameter = $urlparams;
 | |
| 
 | |
| 		$ctrlOpt = $rule['options'];
 | |
| 
 | |
| 		if (in_array('disabled', $ctrlOpt)) return null;
 | |
| 		if (in_array('api', $ctrlOpt)) $route->isAPI = true;
 | |
| 
 | |
| 		if (isset($ctrlOpt['method']) && $_SERVER["REQUEST_METHOD"] !== $ctrlOpt['method']) return null;
 | |
| 
 | |
| 		$route->needsAdminLogin = in_array('password', $ctrlOpt);
 | |
| 
 | |
| 		if ($site->isProd() && isHTTPRequest() && !in_array('http', $ctrlOpt))
 | |
| 		{
 | |
| 			// enforce https
 | |
| 			$redirect = 'https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
 | |
| 			header('HTTP/1.1 301 Moved Permanently');
 | |
| 			header('Location: ' . $redirect);
 | |
| 			exit();
 | |
| 		}
 | |
| 
 | |
| 		return $route;
 | |
| 	}
 | |
| }
 |