Exception:
Array
(
    [message] => syntax error, unexpected identifier "stringRegex", expecting "="
    [file] => /home/oldschooloval/oldschooloval.com/system/routes.php
    [line_no] => 25
    [line] => 	public const string stringRegex = '{(\w+)}';	 // <==

    [lines] => Array
        (
            [0] =>  * along with this program.  If not, see .

            [1] =>  *

            [2] =>  */

            [3] => 

            [4] => namespace Vvveb\System;

            [5] => 

            [6] => class Routes {

            [7] => 	public const string stringRegex = '{(\w+)}';	 // <==

            [8] => 

            [9] => 	public const string varRegex = '[{#]([a-zA-Z]\w+)({([\d,]+)})?[#}]';

            [10] => 

            [11] => 	public const string stringLimitRegex = '{([a-zA-Z]\w+){([\d,]+)}}';

            [12] => 

            [13] => 	public const string numericRegex = '#([a-zA-Z]\w+)#';

        )

    [trace] => #0 /home/oldschooloval/oldschooloval.com/plugins/csp-manager/plugin.php(81): Vvveb\System\Core\autoload('Vvveb\\System\\Ro...')
#1 /home/oldschooloval/oldschooloval.com/plugins/csp-manager/plugin.php(174): CspManager->app()
#2 /home/oldschooloval/oldschooloval.com/plugins/csp-manager/plugin.php(179): CspManager->__construct()
#3 /home/oldschooloval/oldschooloval.com/system/extensions/plugins.php(354): include('/home/oldschool...')
#4 /home/oldschooloval/oldschooloval.com/system/core/startup.php(519): Vvveb\System\Extensions\Plugins::loadPlugins(1)
#5 /home/oldschooloval/oldschooloval.com/index.php(172): Vvveb\System\Core\start()
#6 /home/oldschooloval/oldschooloval.com/public/index.php(28): include('/home/oldschool...')
#7 {main}
    [code] => Array
        (
            [0] =>  

            [2] => /**

            [3] =>  * Vvveb

            [4] =>  *

            [5] =>  * Copyright (C) 2022  Ziadin Givan

            [6] =>  *

            [7] =>  * This program is free software: you can redistribute it and/or modify

            [8] =>  * it under the terms of the GNU Affero General Public License as

            [9] =>  * published by the Free Software Foundation, either version 3 of the

            [10] =>  * License, or (at your option) any later version.

            [11] =>  *

            [12] =>  * This program is distributed in the hope that it will be useful,

            [13] =>  * but WITHOUT ANY WARRANTY; without even the implied warranty of

            [14] =>  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the

            [15] =>  * GNU Affero General Public License for more details.

            [16] =>  *

            [17] =>  * You should have received a copy of the GNU Affero General Public License

            [18] =>  * along with this program.  If not, see .

            [19] =>  *

            [20] =>  */

            [21] => 

            [22] => namespace Vvveb\System;

            [23] => 

            [24] => class Routes {

            [25] => 	public const string stringRegex = '{(\w+)}';	 // <==

            [26] => 

            [27] => 	public const string varRegex = '[{#]([a-zA-Z]\w+)({([\d,]+)})?[#}]';

            [28] => 

            [29] => 	public const string stringLimitRegex = '{([a-zA-Z]\w+){([\d,]+)}}';

            [30] => 

            [31] => 	public const string numericRegex = '#([a-zA-Z]\w+)#';

            [32] => 

            [33] => 	public const string numericLimitRegex = '#([a-zA-Z]\w+){([\d,]+)}#';

            [34] => 

            [35] => 	public const string wildcardRegex = '\*';

            [36] => 

            [37] => 	/** @var array> */

            [38] => 	private static array $routes = [];

            [39] => 

            [40] => 	/** @var array */

            [41] => 	private static array $urls = [];

            [42] => 

            [43] => 	/** @var array, count: int}> >|null */

            [44] => 	private static ?array $modules = null;

            [45] => 

            [46] => 	private static bool $init = false;

            [47] => 

            [48] => 	/**

            [49] => 	 * Process a route pattern into regex and store module data.

            [50] => 	 *

            [51] => 	 * @param string                $url  The route URL pattern.

            [52] => 	 * @param array $data Route configuration data.

            [53] => 	 *

            [54] => 	 * @return string The compiled regex pattern.

            [55] => 	 */

            [56] => 	private static function processRoute(string $url, array $data): string {

            [57] => 		$module = $data['module'];

            [58] => 		unset($data['edit'], $data['module']);

            [59] => 

            [60] => 		$parameters = [];

            [61] => 

            [62] => 		if (preg_match_all('/' . self :: varRegex . '/', $url, $matches)) {

            [63] => 			$parameters = $matches[1];

            [64] => 		}

            [65] => 

            [66] => 		if ($data) {

            [67] => 			$parameters = array_merge($parameters, array_keys($data));

            [68] => 		}

            [69] => 

            [70] => 		self :: $modules[$module][] = ['url' => $url, 'parameters' => $parameters, 'count' => count($parameters)];

            [71] => 		uasort(self :: $modules[$module], fn (array $a, array $b): int => $b['count'] <=> $a['count']);

            [72] => 

            [73] => 		$route = $url;

            [74] => 		$url   = str_replace('/', '\/', $url);

            [75] => 		$url   = preg_replace('/' . self :: numericLimitRegex . '/', '(?<$1>\d{$2})', $url);

            [76] => 		$url   = preg_replace('/' . self :: numericRegex . '/', '(?<$1>\d+)', $url);

            [77] => 		$url   = preg_replace('/' . self :: stringLimitRegex . '/', '(?<$1>[^$\/]{$2})', $url);

            [78] => 		$url   = preg_replace('/' . self :: stringRegex . '/', '(?<$1>[^$\/]+)', $url);

            [79] => 		$url   = preg_replace('/' . self :: wildcardRegex . '/', '.*?', $url);

            [80] => 

            [81] => 		self :: $urls[$route] = [$url, $module];

            [82] => 

            [83] => 		return $url;

            [84] => 	}

            [85] => 

            [86] => 	/**

            [87] => 	 * Add a route with its URL pattern and configuration data.

            [88] => 	 *

            [89] => 	 * @param string                $url  The route URL pattern.

            [90] => 	 * @param array $data Route configuration data.

            [91] => 	 */

            [92] => 	public static function addRoute(string $url, array $data): void {

            [93] => 		self :: $routes[$url] = $data;

            [94] => 		self :: processRoute($url, $data);

            [95] => 	}

            [96] => 

            [97] => 	/**

            [98] => 	 * Remove one or more routes by URL pattern.

            [99] => 	 *

            [100] => 	 * @param string|array $url A single URL pattern or array of URL patterns to remove.

            [101] => 	 */

            [102] => 	public static function removeRoute(string|array $url): void {

            [103] => 		if (is_array($url)) {

            [104] => 			foreach ($url as $route) {

            [105] => 				$entry = self :: $urls[$route] ?? false;

            [106] => 

            [107] => 				if ($entry) {

            [108] => 					unset(self :: $modules[$entry[1]]);

            [109] => 				}

            [110] => 				unset(self :: $urls[$route]);

            [111] => 			}

            [112] => 		} else {

            [113] => 			$entry = self :: $urls[$url] ?? false;

            [114] => 

            [115] => 			if ($entry) {

            [116] => 				unset(self :: $modules[$entry[1]]);

            [117] => 			}

            [118] => 			unset(self :: $urls[$url]);

            [119] => 		}

            [120] => 	}

            [121] => 

            [122] => 	/**

            [123] => 	 * Initialize routes from cache or config files.

            [124] => 	 *

            [125] => 	 * @param string   $app     Application name.

            [126] => 	 * @param int|null $site_id Optional site ID for site-specific routes.

            [127] => 	 *

            [128] => 	 * @return bool Always returns true.

            [129] => 	 */

            [130] => 	public static function init(string $app = 'app', ?int $site_id = null): bool {

            [131] => 		$cacheDriver = Cache :: getInstance();

            [132] => 		if ($site_id) {

            [133] => 			$cacheKey = $site_id;

            [134] => 		} else {

            [135] => 			$cacheKey = $app;

            [136] => 		}

            [137] => 

            [138] => 		if ($result = $cacheDriver->get('routes', $cacheKey)) {

            [139] => 			self::$routes  = $result['routes'];

            [140] => 			self::$urls    = $result['urls'];

            [141] => 			self::$modules = $result['modules'];

            [142] => 		} else {

            [143] => 			$routesConfig = DIR_ROOT . '/config/';

            [144] => 			if ($site_id) {

            [145] => 				$routesConfig .= "site-$site_id-routes.php";

            [146] => 			} else {

            [147] => 				$routesConfig .= "$app-routes.php";

            [148] => 			}

            [149] => 

            [150] => 			if (file_exists($routesConfig)) {

            [151] => 				self :: $routes += include $routesConfig;

            [152] => 			}

            [153] => 			

            [154] => 			[self :: $routes] = Event::trigger(__CLASS__, __FUNCTION__, self :: $routes);

            [155] => 

            [156] => 			foreach (self :: $routes as $url => $data) {

            [157] => 				self :: processRoute($url, $data);

            [158] => 			}

            [159] => 

            [160] => 			$result            = [];

            [161] => 			$result['routes']  = self::$routes;

            [162] => 			$result['modules'] = self::$modules;

            [163] => 			$result['urls']    = self::$urls;

            [164] => 

            [165] => 			$cacheDriver->set('routes', $cacheKey, $result);

            [166] => 		}

            [167] => 

            [168] => 		self :: $init = true;

            [169] => 

            [170] => 		return true;

            [171] => 	}

            [172] => 

            [173] => 	/**

            [174] => 	 * Match a URL against registered route patterns and return extracted parameters.

            [175] => 	 *

            [176] => 	 * @param string $url The URL to match.

            [177] => 	 *

            [178] => 	 * @return array|false Matched parameters or false.

            [179] => 	 */

            [180] => 	public static function match(string $url): array|false {

            [181] => 		if (!self :: $init) {

            [182] => 			self :: init();

            [183] => 		}

            [184] => 		$url = preg_replace('/\?.*$/', '', str_replace('//', '/', $url));

            [185] => 

            [186] => 		foreach (self :: $urls as $route => $data) {

            [187] => 			$matches                = [];

            [188] => 			$params                 = self::$routes[$route] ?? '';

            [189] => 			[$pattern, $module]     = $data;

            [190] => 

            [191] => 			if ($url == $pattern || preg_match('/^' . $pattern . '$/', $url, $matches)) {

            [192] => 				$parameters = array_filter($matches, 'is_string', ARRAY_FILTER_USE_KEY);

            [193] => 

            [194] => 				$parameters['route']   = $route;

            [195] => 				$parameters['module']  = $module;

            [196] => 				$parameters['pattern'] = $pattern;

            [197] => 

            [198] => 				$parameters += $params;

            [199] => 

            [200] => 				return $parameters;

            [201] => 			}

            [202] => 		}

            [203] => 

            [204] => 		return false;

            [205] => 	}

            [206] => 

            [207] => 	/**

            [208] => 	 * Get the configuration data for a route by its pattern key.

            [209] => 	 *

            [210] => 	 * @param string $route The route pattern key.

            [211] => 	 *

            [212] => 	 * @return array{module: string, edit?: string} Route data or empty array.

            [213] => 	 */

            [214] => 	public static function get(string $route): array {

            [215] => 		return self :: $routes[$route] ?? [];

            [216] => 	}

            [217] => 

            [218] => 	/**

            [219] => 	 * Get all registered routes.

            [220] => 	 *

            [221] => 	 * @return array> All routes.

            [222] => 	 */

            [223] => 	public static function getRoutes(): array {

            [224] => 		return self :: $routes;

            [225] => 	}

            [226] => 

            [227] => 	/**

            [228] => 	 * Replace variable placeholders in a URL with parameter values.

            [229] => 	 *

            [230] => 	 * @param string                $url        URL pattern with placeholders.

            [231] => 	 * @param array $parameters Key-value pairs for replacement.

            [232] => 	 *

            [233] => 	 * @return string The URL with placeholders replaced.

            [234] => 	 */

            [235] => 	public static function varReplace(string $url, array $parameters): string {

            [236] => 		return preg_replace_callback(

            [237] => 			'/' . self :: stringRegex . '|' . self :: numericRegex . '/',

            [238] => 			function(array $matches) use ($parameters): string {

            [239] => 				$var = $matches[1];

            [240] => 

            [241] => 				if (isset($parameters[$var])) {

            [242] => 					return $parameters[$var];

            [243] => 				}

            [244] => 

            [245] => 				return '';

            [246] => 			},

            [247] => 			$url

            [248] => 		);

            [249] => 	}

            [250] => 

            [251] => 	/**

            [252] => 	 * Get route data for a module name.

            [253] => 	 *

            [254] => 	 * @param string $module The module name.

            [255] => 	 *

            [256] => 	 * @return array, count: int}> Route data for the module.

            [257] => 	 */

            [258] => 	public static function getRouteData(string $module): array {

            [259] => 		if (!self :: $init) {

            [260] => 			self :: init();

            [261] => 		}

            [262] => 

            [263] => 		return self :: $modules[$module] ?? [];

            [264] => 	}

            [265] => 

            [266] => 	/**

            [267] => 	 * Get URL data by matching against registered routes.

            [268] => 	 *

            [269] => 	 * @param string|false $url The URL to resolve, or false to use current URL.

            [270] => 	 *

            [271] => 	 * @return array|false Matched route parameters with route metadata, or false on no match.

            [272] => 	 */

            [273] => 	public static function getUrlData(string|false $url = false): array|false {

            [274] => 		if (!$url) {

            [275] => 			$url = \Vvveb\getCurrentUrl();

            [276] => 		}

            [277] => 

            [278] => 		$parameters = self :: match($url);

            [279] => 		$route      = stripslashes($parameters['route'] ?? '');

            [280] => 

            [281] => 		if ($parameters) {

            [282] => 			$parameters += self :: $routes[$route];

            [283] => 

            [284] => 			if (isset($parameters['edit'])) {

            [285] => 				$parameters['edit'] = self :: varReplace($parameters['edit'], $parameters);

            [286] => 			}

            [287] => 		}

            [288] => 

            [289] => 		return $parameters;

            [290] => 	}

            [291] => 

            [292] => 	/**

            [293] => 	 * Generate a URL from a module route name and parameters.

            [294] => 	 *

            [295] => 	 * @param string                      $route      The module/route name.

            [296] => 	 * @param array|false $parameters Query parameters or false for no parameters.

            [297] => 	 *

            [298] => 	 * @return string|null The resolved URL, or null if the route is not found.

            [299] => 	 */

            [300] => 	public static function url(string $route, array|false $parameters = false): ?string {

            [301] => 		if (!self :: $init) {

            [302] => 			self :: init();

            [303] => 		}

            [304] => 

            [305] => 		if (isset(self :: $modules[$route])) {

            [306] => 			$pattern    = self :: $modules[$route][0]['url'] ?? '';

            [307] => 

            [308] => 			if ($parameters && isset($parameters['route'])) {

            [309] => 				unset($parameters['route']);

            [310] => 			}

            [311] => 

            [312] => 			$parameters_count = is_array($parameters) ? count($parameters) : 0;

            [313] => 			$param_keys       = is_array($parameters) ? array_keys($parameters) : [];

            [314] => 			$no_parameters    = $pattern;

            [315] => 

            [316] => 			foreach (self :: $modules[$route] as $value) {

            [317] => 				if ($value['parameters'] && $parameters_count) {

            [318] => 					if (count(array_intersect($value['parameters'], $param_keys)) === count($value['parameters'])) {

            [319] => 						$pattern  = $value['url'];

            [320] => 

            [321] => 						break;

            [322] => 					}

            [323] => 				} else {

            [324] => 					$no_parameters = $value['url'];

            [325] => 				}

            [326] => 			}

            [327] => 

            [328] => 			if (!$parameters) {

            [329] => 				$pattern = $no_parameters;

            [330] => 			}

            [331] => 

            [332] => 			$missing = false;

            [333] => 			$url     = preg_replace_callback(

            [334] => 				'/' . self :: varRegex . '/',

            [335] => 				function(array $matches) use ($parameters, &$missing): string {

            [336] => 					$var = $matches[1];

            [337] => 

            [338] => 					if (isset($parameters[$var])) {

            [339] => 						return $parameters[$var];

            [340] => 					} else {

            [341] => 						$missing = true;

            [342] => 					}

            [343] => 

            [344] => 					return '';

            [345] => 				},

            [346] => 				$pattern

            [347] => 			);

            [348] => 

            [349] => 			if ($missing) {

            [350] => 				return '/?route=' . $route . '&' . (is_array($parameters) ? http_build_query($parameters) : '');

            [351] => 			} else {

            [352] => 				return $url;

            [353] => 			}

            [354] => 		}

            [355] => 

            [356] => 		return null;

            [357] => 	}

            [358] => }

        )

)