Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
router.php
1<?php
2
4
8
9class Router
10{
11 const CACHE_ID = 'UrlPreviewRouteCache';
12 const CACHE_TTL = 315360000;
13
17 protected static $routeTable = array();
18
20 protected static $managedCache;
21
23 protected static $initialized = false;
24
44 public static function setRouteHandler($route, $handlerModule, $handlerClass, array $handlerParameters)
45 {
46 static::init();
47
48 if(!is_string($route) || $route == '')
49 throw new ArgumentException('Route could not be empty', '$route');
50 if(!is_string($handlerModule) || $handlerModule == '')
51 throw new ArgumentException('Handler module could not be empty', '$handler');
52 if(!is_string($handlerClass) || $handlerClass == '')
53 throw new ArgumentException('Handler class could not be empty', '$handler');
54
55 $newRoute = true;
56 if(isset(static::$routeTable[$route]))
57 {
58 if ( $handlerModule === static::$routeTable[$route]['MODULE']
59 && $handlerClass === static::$routeTable[$route]['CLASS']
60 && $handlerParameters == static::$routeTable[$route]['PARAMETERS']
61 )
62 {
63 return;
64 }
65 $newRoute = false;
66 }
67
68 $allowSlashes = ($handlerParameters['allowSlashes'] ?? 'N') === 'Y';
69 static::$routeTable[$route]['ROUTE'] = $route;
70 static::$routeTable[$route]['REGEXP'] = static::convertRouteToRegexp($route, $allowSlashes);
71 static::$routeTable[$route]['MODULE'] = $handlerModule;
72 static::$routeTable[$route]['CLASS'] = $handlerClass;
73 static::$routeTable[$route]['PARAMETERS'] = $handlerParameters;
74
75 static::persistRoute($route, $newRoute);
76 }
77
84 public static function dispatch(Uri $uri)
85 {
86 static::init();
87
88 $urlPath = $uri->getPath();
89 //todo: replace cycle with compiled regexp for all routes
90 foreach(static::$routeTable as $routeRecord)
91 {
92 if(preg_match($routeRecord['REGEXP'], $urlPath, $matches))
93 {
94 $result = $routeRecord;
95 //replace parameters variables with values
96 foreach($result['PARAMETERS'] as $parameterName => &$parameterValue)
97 {
98 if(mb_strpos($parameterValue, '$') === 0)
99 {
100 $variableName = mb_substr($parameterValue, 1);
101 if(isset($matches[$variableName]))
102 {
103 $parameterValue = $matches[$variableName];
104 }
105 }
106 }
107 unset($parameterValue);
108
109 $uriQuery = $uri->getQuery();
110 if (mb_strlen($uriQuery) > 0)
111 {
112 $uriQueryParams = static::parseQueryParams($uriQuery);
113 foreach ($result['PARAMETERS'] as $parameterName => &$parameterValue)
114 {
115 if (mb_strpos($parameterValue, '$') === 0)
116 {
117 $variableName = mb_substr($parameterValue, 1);
118 if (isset($uriQueryParams[$variableName]))
119 {
120 $parameterValue = $uriQueryParams[$variableName];
121 }
122 }
123 }
124 unset($parameterValue);
125 }
126
127 return $result;
128 }
129 }
130
131 return false;
132 }
133
134 protected static function parseQueryParams($uriQuery): array
135 {
136 $data = preg_replace_callback(
137 '/(?:^|(?<=&))[^=[]+/',
138 function($match)
139 {
140 return bin2hex(urldecode($match[0]));
141 },
142 $uriQuery
143 );
144
145 parse_str($data, $values);
146
147 return array_combine(array_map('hex2bin', array_keys($values)), $values);
148 }
149
154 protected static function init()
155 {
156 if(static::$initialized)
157 return;
158
159 static::$managedCache = Application::getInstance()->getManagedCache();
160
161 if(static::$managedCache->read(static::CACHE_TTL, static::CACHE_ID))
162 {
163 static::$routeTable = (array)static::$managedCache->get(static::CACHE_ID);
164 }
165 else
166 {
167 $queryResult = RouteTable::getList(array(
168 'select' => array('*')
169 ));
170
171 while($routeRecord = $queryResult->fetch())
172 {
173 $allowSlashes = ($routeRecord['PARAMETERS']['allowSlashes'] ?? 'N') === 'Y';
174 $routeRecord['REGEXP'] = static::convertRouteToRegexp($routeRecord['ROUTE'], $allowSlashes);
175 static::$routeTable[$routeRecord['ROUTE']] = $routeRecord;
176 }
177
178 uksort(static::$routeTable, function($a, $b)
179 {
180 $lengthOfA = mb_strlen($a);
181 $lengthOfB = mb_strlen($b);
182 if($lengthOfA > $lengthOfB)
183 return -1;
184 else if($lengthOfA == $lengthOfB)
185 return 0;
186 else
187 return 1;
188 });
189
190 static::$managedCache->set(static::CACHE_ID, static::$routeTable);
191 }
192
193 static::$initialized = true;
194 }
195
203 protected static function persistRoute($route, $isNew)
204 {
205 static::invalidateRouteCache();
206 //Oracle does not support 'merge ... returning field into :field' clause, thus we can't merge clob fields into the table.
207 $routeData = array(
208 'ROUTE' => static::$routeTable[$route]['ROUTE'],
209 'MODULE' => static::$routeTable[$route]['MODULE'],
210 'CLASS' => static::$routeTable[$route]['CLASS'],
211 );
212
213 if($isNew)
214 {
215 $addResult = RouteTable::merge($routeData);
216 if($addResult->isSuccess())
217 {
218 static::$routeTable[$route]['ID'] = $addResult->getId();
219 RouteTable::update(
220 static::$routeTable[$route]['ID'],
221 array(
222 'PARAMETERS' => static::$routeTable[$route]['PARAMETERS']
223 )
224 );
225 }
226 $result = $addResult->isSuccess();
227 }
228 else
229 {
230 $routeData['PARAMETERS'] = static::$routeTable[$route]['PARAMETERS'];
231 $updateResult = RouteTable::update(static::$routeTable[$route]['ID'], $routeData);
232 $result = $updateResult->isSuccess();
233 }
234 return $result;
235 }
236
243 protected static function convertRouteToRegexp(string $route, bool $allowSlashes = false): string
244 {
245 $result = preg_replace(
246 "/#(\w+)#/",
247 $allowSlashes ? "(?'\\1'.*?)" : "(?'\\1'[^/]+)",
248 $route
249 );
250 $result = str_replace('/', '\/', $result);
251 $result = '/^'.$result.'$/';
252
253 return $result;
254 }
255
260 public static function invalidateRouteCache()
261 {
262 Application::getInstance()->getManagedCache()->clean(static::CACHE_ID);
263 }
264}
static convertRouteToRegexp(string $route, bool $allowSlashes=false)
Definition router.php:243
static parseQueryParams($uriQuery)
Definition router.php:134
static persistRoute($route, $isNew)
Definition router.php:203
static dispatch(Uri $uri)
Definition router.php:84
static setRouteHandler($route, $handlerModule, $handlerClass, array $handlerParameters)
Definition router.php:44