Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
router.php
1<?php
2
3namespace Bitrix\Main\Engine;
4
5
15
16final class Router
17{
18 public const COMPONENT_MODE_AJAX = 'ajax';
19 public const COMPONENT_MODE_CLASS = 'class';
20
22 public const EXCEPTION_INVALID_COMPONENT = 2210202;
23 public const EXCEPTION_INVALID_AJAX_MODE = 2210203;
24 public const EXCEPTION_NO_CONFIGURATION = 2210204;
25 public const EXCEPTION_NO_MODULE = 2210205;
26 public const EXCEPTION_INVALID_MODULE_NAME = 22102051;
27 public const EXCEPTION_INVALID_COMPONENT_NAME = 2210206;
28 public const EXCEPTION_NO_COMPONENT = 2210207;
29 public const EXCEPTION_NO_COMPONENT_AJAX_CLASS = 2210208;
30
32 protected $module = 'main';
33 protected $action = 'index';
34 protected $component;
35 protected $mode;
36
40 private $request;
41
46 public function __construct(HttpRequest $request)
47 {
48 $this->request = $request;
49
50 $this->component = $this->request->getQuery('c') ?: null;
51 $this->mode = $this->request->getQuery('mode') ?: null;
52
53 $this->action = $this->request->getQuery('action');
54 if ($this->action && is_string($this->action) && !$this->component)
55 {
56 list($this->vendor, $this->action) = $this->resolveVendor($this->action);
57 list($module, $this->action) = $this->resolveModuleAndAction($this->action);
58
59 $this->module = $this->refineModuleName($this->vendor, $module);
60 }
61 }
62
63 private function resolveModuleAndAction($action)
64 {
65 $actionParts = explode('.', $action);
66 $module = array_shift($actionParts);
67 $action = implode('.', $actionParts);
68
69 return [
71 ];
72 }
73
74 private function resolveVendor($action)
75 {
76 list($vendor, $action) = explode(':', $action) + [null, null];
77 if (!$action)
78 {
81 }
82
83 return [
85 ];
86 }
87
88 protected function refineModuleName($vendor, $module)
89 {
91 {
92 return $module;
93 }
94
95 return $vendor . '.' . $module;
96 }
97
110 protected function buildComponent($componentName, $signedParameters = null, $template = null)
111 {
112 $class = \CBitrixComponent::includeComponentClass($componentName);
113 if (!is_subclass_of($class, 'CBitrixComponent'))
114 {
115 return null;
116 }
117
118 $parameters = array();
119 if ($signedParameters)
120 {
121 $parameters = ParameterSigner::unsignParameters($componentName, $signedParameters);
122 }
123
125 $component = new $class();
126
127 if (!($component instanceof Controllerable))
128 {
129 throw new SystemException(
130 "The component {$this->component} must be implement interface \Bitrix\Main\Engine\Contract\Controllerable",
131 self::EXCEPTION_INVALID_COMPONENT_INTERFACE
132 );
133 }
134
135 $component->initComponent($componentName, $template);
136 $component->onIncludeComponentLang();
137 $component->arParams = $component->onPrepareComponentParams($parameters);
138 $component->__prepareComponentParams($component->arParams);
139
140 return $component;
141 }
142
146 public function getControllerAndAction()
147 {
148 if ($this->component)
149 {
150 return $this->getComponentControllerAndAction();
151 }
152
153 $this->includeModule($this->module);
154 $controllerAndAction = Resolver::getControllerAndAction($this->vendor, $this->module, $this->action);
155 if ($controllerAndAction)
156 {
157 return $controllerAndAction;
158 }
159 //default ajax class
160 $ajaxClass = DefaultController::className();
161
163 return array(new $ajaxClass, $this->action);
164 }
165
166 private function getComponentControllerAndAction()
167 {
168 $componentAsString = var_export($this->component, true);
169 if ($this->mode === self::COMPONENT_MODE_CLASS)
170 {
171 $component = $this->buildComponent($this->component, $this->request->getPost('signedParameters'));
172 if (!$component)
173 {
174 throw new SystemException(
175 "Could not build component instance {$componentAsString}",
176 self::EXCEPTION_INVALID_COMPONENT
177 );
178 }
179
180 return array(new ComponentController($component), $this->action);
181 }
182 elseif ($this->mode === self::COMPONENT_MODE_AJAX)
183 {
184 $ajaxClass = $this->includeComponentAjaxClass($this->component);
185
186 $controller = ControllerBuilder::build($ajaxClass, [
187 'scope' => Controller::SCOPE_AJAX,
188 'currentUser' => CurrentUser::get(),
189 ]);
190
191 return [$controller, $this->action];
192 }
193 else
194 {
195 $modeAsString = var_export($this->mode, true);
196 throw new SystemException(
197 "Unknown ajax mode ({$modeAsString}) to work {$componentAsString}",
198 self::EXCEPTION_INVALID_AJAX_MODE
199 );
200 }
201 }
202
203 private function includeModule($module)
204 {
206 {
207 throw new SystemException(
208 "Invalid module name {$module}",
209 self::EXCEPTION_INVALID_MODULE_NAME
210 );
211 }
212
213 if (!Configuration::getInstance($module)->get('controllers'))
214 {
215 throw new SystemException(
216 "There is no configuration in {$module} with 'controllers' value.",
217 self::EXCEPTION_NO_CONFIGURATION
218 );
219 }
220
222 {
223 throw new SystemException("Could not find module {$module}", self::EXCEPTION_NO_MODULE);
224 }
225 }
226
227 private function includeComponentAjaxClass($name)
228 {
229 $path2Comp = \CComponentEngine::makeComponentPath($name);
230 if ($path2Comp === '')
231 {
232 throw new SystemException("{$name} is not a valid component name", self::EXCEPTION_INVALID_COMPONENT_NAME);
233 }
234
235 $componentPath = getLocalPath("components" . $path2Comp);
236 if ($componentPath === false)
237 {
238 throw new SystemException("Could not find component by name {$name}", self::EXCEPTION_NO_COMPONENT);
239 }
240
241 $ajaxClass = $this->getAjaxClassForPath($componentPath);
242 if (!$ajaxClass)
243 {
244 throw new SystemException("Could not find ajax class {$componentPath}", self::EXCEPTION_NO_COMPONENT_AJAX_CLASS);
245 }
246
247 return $ajaxClass;
248 }
249
250 private function getAjaxClassForPath($componentPath)
251 {
252 $filename = \Bitrix\Main\Application::getDocumentRoot() . $componentPath . '/ajax.php';
253 if (!file_exists($filename) || !is_file($filename))
254 {
255 return null;
256 }
257
258 $beforeClasses = get_declared_classes();
259 $beforeClassesCount = count($beforeClasses);
260 include_once($filename);
261 $afterClasses = get_declared_classes();
262 $afterClassesCount = count($afterClasses);
263 $furthestClass = null;
264 for ($i = $afterClassesCount - 1; $i >= $beforeClassesCount; $i--)
265 {
266 if (
267 is_subclass_of($afterClasses[$i], Controller::class) ||
268 ($furthestClass && is_subclass_of($afterClasses[$i], $furthestClass))
269 )
270 {
271 $furthestClass = $afterClasses[$i];
272 }
273 }
274
275 return $furthestClass;
276 }
277
282 public function setRequest(HttpRequest $request)
283 {
284 $this->request = $request;
285
286 return $this;
287 }
288
292 public function getVendor()
293 {
294 return $this->vendor;
295 }
296
300 public function getModule()
301 {
302 return $this->module;
303 }
304
308 public function getAction()
309 {
310 return $this->action;
311 }
312
316 public function getComponent()
317 {
318 return $this->component;
319 }
320
324 public function getMode()
325 {
326 return $this->mode;
327 }
328}
static unsignParameters($componentName, $signedParameters)
static getControllerAndAction($vendor, $module, $action, $scope=Controller::SCOPE_AJAX)
Definition resolver.php:23
setRequest(HttpRequest $request)
Definition router.php:282
const EXCEPTION_INVALID_COMPONENT_INTERFACE
Definition router.php:21
const EXCEPTION_NO_COMPONENT_AJAX_CLASS
Definition router.php:29
const EXCEPTION_INVALID_MODULE_NAME
Definition router.php:26
const EXCEPTION_INVALID_COMPONENT
Definition router.php:22
__construct(HttpRequest $request)
Definition router.php:46
refineModuleName($vendor, $module)
Definition router.php:88
const EXCEPTION_INVALID_COMPONENT_NAME
Definition router.php:27
const EXCEPTION_INVALID_AJAX_MODE
Definition router.php:23
static includeModule($moduleName)
Definition loader.php:69
static isValidModule(string $moduleName)