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(122): Vvveb\System\Core\start()
#6 /home/oldschooloval/oldschooloval.com/index.php(168): Vvveb\saveCache()
#7 /home/oldschooloval/oldschooloval.com/public/index.php(28): include('/home/oldschool...')
#8 {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] => }
)
)