1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
eventmanager.php
См. документацию.
1<?php
2
9
10namespace Bitrix\Main;
11
13{
14 protected const CACHE_ID = 'b_module_to_module';
15
19 protected static $instance;
20 protected $handlers = [];
21 protected $isHandlersLoaded = false;
22
23 protected function __construct()
24 {
25 }
26
31 public static function getInstance()
32 {
33 if (!isset(self::$instance))
34 {
35 $c = __CLASS__;
36 self::$instance = new $c;
37 }
38
39 return self::$instance;
40 }
41
46 public static function setInstance($instance)
47 {
48 $c = __CLASS__;
49 if ($instance instanceof $c)
50 {
51 self::$instance = $instance;
52 }
53 }
54
55 protected function addEventHandlerInternal($fromModuleId, $eventType, $callback, $includeFile, $sort, $version)
56 {
57 $event = [
58 'FROM_MODULE_ID' => $fromModuleId,
59 'MESSAGE_ID' => $eventType,
60 'CALLBACK' => $callback,
61 'SORT' => (int)$sort,
62 'FULL_PATH' => $includeFile,
63 'VERSION' => $version,
64 'TO_NAME' => $this->formatEventName(['CALLBACK' => $callback]),
65 ];
66
67 $fromModuleId = strtoupper($fromModuleId);
68 $eventType = strtoupper($eventType);
69
70 if (!isset($this->handlers[$fromModuleId]) || !is_array($this->handlers[$fromModuleId]))
71 {
72 $this->handlers[$fromModuleId] = [];
73 }
74
75 $events = &$this->handlers[$fromModuleId];
76
77 if (empty($events[$eventType]) || !is_array($events[$eventType]))
78 {
79 $events[$eventType] = [$event];
80 $eventHandlerKey = 0;
81 }
82 else
83 {
84 $newEvents = [];
85 $eventHandlerKey = max(array_keys($events[$eventType])) + 1;
86
87 foreach ($events[$eventType] as $key => $value)
88 {
89 if ($value['SORT'] > $event['SORT'])
90 {
91 $newEvents[$eventHandlerKey] = $event;
92 }
93
94 $newEvents[$key] = $value;
95 }
96 $newEvents[$eventHandlerKey] = $event;
97 $events[$eventType] = $newEvents;
98 }
99
100 return $eventHandlerKey;
101 }
102
103 public function addEventHandler($fromModuleId, $eventType, $callback, $includeFile = false, $sort = 100)
104 {
105 return $this->addEventHandlerInternal($fromModuleId, $eventType, $callback, $includeFile, $sort, 2);
106 }
107
116 public function addEventHandlerCompatible($fromModuleId, $eventType, $callback, $includeFile = false, $sort = 100)
117 {
118 return $this->addEventHandlerInternal($fromModuleId, $eventType, $callback, $includeFile, $sort, 1);
119 }
120
121 public function removeEventHandler($fromModuleId, $eventType, $iEventHandlerKey)
122 {
123 $fromModuleId = strtoupper($fromModuleId);
124 $eventType = strtoupper($eventType);
125
126 if (isset($this->handlers[$fromModuleId][$eventType][$iEventHandlerKey]))
127 {
128 unset($this->handlers[$fromModuleId][$eventType][$iEventHandlerKey]);
129 return true;
130 }
131
132 return false;
133 }
134
135 public function unRegisterEventHandler($fromModuleId, $eventType, $toModuleId, $toClass = '', $toMethod = '', $toPath = '', $toMethodArg = [])
136 {
137 $toMethodArg = (!is_array($toMethodArg) || empty($toMethodArg) ? '' : serialize($toMethodArg));
138
140 $sqlHelper = $connection->getSqlHelper();
141
142 $sql =
143 "DELETE FROM b_module_to_module " .
144 "WHERE FROM_MODULE_ID='" . $sqlHelper->forSql($fromModuleId) . "'" .
145 " AND MESSAGE_ID='" . $sqlHelper->forSql($eventType) . "' " .
146 " AND TO_MODULE_ID='" . $sqlHelper->forSql($toModuleId) . "' " .
147 (($toClass != '') ? " AND TO_CLASS='" . $sqlHelper->forSql($toClass) . "' " : " AND (TO_CLASS='' OR TO_CLASS IS NULL) ") .
148 (($toMethod != '') ? " AND TO_METHOD='" . $sqlHelper->forSql($toMethod) . "'" : " AND (TO_METHOD='' OR TO_METHOD IS NULL) ") .
149 (($toPath != '' && $toPath !== 1/*controller disconnect correction*/) ? " AND TO_PATH='" . $sqlHelper->forSql($toPath) . "'" : " AND (TO_PATH='' OR TO_PATH IS NULL) ") .
150 (($toMethodArg != '') ? " AND TO_METHOD_ARG='" . $sqlHelper->forSql($toMethodArg) . "'" : " AND (TO_METHOD_ARG='' OR TO_METHOD_ARG IS NULL) ");
151
152 $connection->queryExecute($sql);
153
154 if ($connection->getAffectedRowsCount() > 0)
155 {
156 $this->clearLoadedHandlers();
157 }
158 }
159
160 public function registerEventHandler($fromModuleId, $eventType, $toModuleId, $toClass = '', $toMethod = '', $sort = 100, $toPath = '', $toMethodArg = [])
161 {
162 $this->registerEventHandlerInternal($fromModuleId, $eventType, $toModuleId, $toClass, $toMethod, $sort, $toPath, $toMethodArg, 2);
163 }
164
165 public function registerEventHandlerCompatible($fromModuleId, $eventType, $toModuleId, $toClass = '', $toMethod = '', $sort = 100, $toPath = '', $toMethodArg = [])
166 {
167 $this->registerEventHandlerInternal($fromModuleId, $eventType, $toModuleId, $toClass, $toMethod, $sort, $toPath, $toMethodArg, 1);
168 }
169
170 protected function registerEventHandlerInternal($fromModuleId, $eventType, $toModuleId, $toClass, $toMethod, $sort, $toPath, $toMethodArg, $version)
171 {
172 $toMethodArg = (!is_array($toMethodArg) || empty($toMethodArg) ? '' : serialize($toMethodArg));
173 $sort = intval($sort);
174 $version = intval($version);
175
176 $uniqueID = md5(mb_strtolower($fromModuleId . '.' . $eventType . '.' . $toModuleId . '.' . $toPath . '.' . $toClass . '.' . $toMethod . '.' . $toMethodArg . '.' . $version));
177
179 $sqlHelper = $connection->getSqlHelper();
180
181 $fromModuleId = $sqlHelper->forSql($fromModuleId);
182 $eventType = $sqlHelper->forSql($eventType);
183 $toModuleId = $sqlHelper->forSql($toModuleId);
184 $toClass = $sqlHelper->forSql($toClass);
185 $toMethod = $sqlHelper->forSql($toMethod);
186 $toPath = $sqlHelper->forSql($toPath);
187 $toMethodArg = $sqlHelper->forSql($toMethodArg);
188
189 $fields = '(SORT, FROM_MODULE_ID, MESSAGE_ID, TO_MODULE_ID, TO_CLASS, TO_METHOD, TO_PATH, TO_METHOD_ARG, VERSION, UNIQUE_ID)';
190 $values = "(" . $sort . ", '" . $fromModuleId . "', '" . $eventType . "', '" . $toModuleId . "', " . " '" . $toClass . "', '" . $toMethod . "', '" . $toPath . "', '" . $toMethodArg . "', " . $version . ", '" . $uniqueID . "')";
191 $sql = $sqlHelper->getInsertIgnore('b_module_to_module', $fields, 'VALUES ' . $values);
192
193 $connection->queryExecute($sql);
194
195 if ($connection->getAffectedRowsCount() > 0)
196 {
197 $this->clearLoadedHandlers();
198 }
199 }
200
201 protected function formatEventName($event)
202 {
203 $name = '';
204 if (isset($event['CALLBACK']))
205 {
206 if (is_array($event['CALLBACK']))
207 {
208 $name .= (is_object($event['CALLBACK'][0]) ? get_class($event['CALLBACK'][0]) : $event['CALLBACK'][0]) . '::' . $event['CALLBACK'][1];
209 }
210 elseif (is_callable($event['CALLBACK']))
211 {
212 $name .= 'callable';
213 }
214 else
215 {
216 $name .= $event['CALLBACK'];
217 }
218 }
219 else
220 {
221 $name .= $event['TO_CLASS'] . '::' . $event['TO_METHOD'];
222 }
223 if (!empty($event['TO_MODULE_ID']))
224 {
225 $name .= ' (' . $event['TO_MODULE_ID'] . ')';
226 }
227 return $name;
228 }
229
230 protected function loadEventHandlers()
231 {
232 $cache = Application::getInstance()->getManagedCache();
233
234 if ($cache->read(3600, self::CACHE_ID, self::CACHE_ID))
235 {
236 $rawEvents = $cache->get(self::CACHE_ID);
237
238 if (!is_array($rawEvents))
239 {
240 $rawEvents = [];
241 }
242 }
243 else
244 {
246
247 $rs = $con->query("
248 SELECT FROM_MODULE_ID, MESSAGE_ID, SORT, TO_MODULE_ID, TO_PATH,
249 TO_CLASS, TO_METHOD, TO_METHOD_ARG, VERSION
250 FROM b_module_to_module m2m
251 INNER JOIN b_module m ON (m2m.TO_MODULE_ID = m.ID)
252 ORDER BY SORT
253 ");
254
255 $rawEvents = $rs->fetchAll();
256
257 $cache->set(self::CACHE_ID, $rawEvents);
258 }
259
261 $hasHandlers = !empty($this->handlers);
262
263 foreach ($rawEvents as $ar)
264 {
265 $ar['TO_NAME'] = $this->formatEventName([
266 'TO_MODULE_ID' => $ar['TO_MODULE_ID'],
267 'TO_CLASS' => $ar['TO_CLASS'],
268 'TO_METHOD' => $ar['TO_METHOD'],
269 ]);
270 $ar['FROM_MODULE_ID'] = strtoupper($ar['FROM_MODULE_ID']);
271 $ar['MESSAGE_ID'] = strtoupper($ar['MESSAGE_ID']);
272 if ($ar['TO_METHOD_ARG'] != '')
273 {
274 $ar['TO_METHOD_ARG'] = unserialize($ar['TO_METHOD_ARG'], ['allowed_classes' => false]);
275 }
276 else
277 {
278 $ar['TO_METHOD_ARG'] = [];
279 }
280
281 $this->handlers[$ar['FROM_MODULE_ID']][$ar['MESSAGE_ID']][] = [
282 'SORT' => (int)$ar['SORT'],
283 'TO_MODULE_ID' => $ar['TO_MODULE_ID'],
284 'TO_PATH' => $ar['TO_PATH'],
285 'TO_CLASS' => $ar['TO_CLASS'],
286 'TO_METHOD' => $ar['TO_METHOD'],
287 'TO_METHOD_ARG' => $ar['TO_METHOD_ARG'],
288 'VERSION' => $ar['VERSION'],
289 'TO_NAME' => $ar['TO_NAME'],
290 'FROM_DB' => true,
291 ];
292 }
293
294 if ($hasHandlers)
295 {
296 // need to re-sort because of AddEventHandler() calls (before loadEventHandlers)
297 foreach (array_keys($handlers) as $moduleId)
298 {
299 foreach (array_keys($handlers[$moduleId]) as $event)
300 {
301 uasort(
302 $this->handlers[$moduleId][$event],
303 function ($a, $b) {
304 if ($a['SORT'] == $b['SORT'])
305 {
306 return 0;
307 }
308 return ($a['SORT'] < $b['SORT'] ? -1 : 1);
309 }
310 );
311 }
312 }
313 }
314
315 $this->isHandlersLoaded = true;
316 }
317
318 public function clearLoadedHandlers()
319 {
320 $managedCache = Application::getInstance()->getManagedCache();
321 $managedCache->clean(self::CACHE_ID, self::CACHE_ID);
322
323 foreach ($this->handlers as $module => $types)
324 {
325 foreach ($types as $type => $events)
326 {
327 foreach ($events as $i => $event)
328 {
329 if (isset($event['FROM_DB']) && $event['FROM_DB'])
330 {
331 unset($this->handlers[$module][$type][$i]);
332 }
333 }
334 }
335 }
336 $this->isHandlersLoaded = false;
337 }
338
339 public function findEventHandlers($eventModuleId, $eventType, array $filter = null)
340 {
341 if (!$this->isHandlersLoaded)
342 {
343 $this->loadEventHandlers();
344 }
345
346 $eventModuleId = strtoupper($eventModuleId);
347 $eventType = strtoupper($eventType);
348
349 if (!isset($this->handlers[$eventModuleId]) || !isset($this->handlers[$eventModuleId][$eventType]))
350 {
351 return [];
352 }
353
354 $handlers = $this->handlers[$eventModuleId][$eventType];
355 if (!is_array($handlers))
356 {
357 return [];
358 }
359
360 if (is_array($filter) && !empty($filter))
361 {
362 $handlersTmp = $handlers;
363 $handlers = [];
364 foreach ($handlersTmp as $handler)
365 {
366 if (isset($handler['TO_MODULE_ID']) && in_array($handler['TO_MODULE_ID'], $filter))
367 {
368 $handlers[] = $handler;
369 }
370 }
371 }
372
373 return $handlers;
374 }
375
376 public function send(Event $event)
377 {
378 $handlers = $this->findEventHandlers($event->getModuleId(), $event->getEventType(), $event->getFilter());
379 foreach ($handlers as $handler)
380 {
381 $this->sendToEventHandler($handler, $event);
382 }
383 }
384
385 protected function sendToEventHandler(array $handler, Event $event)
386 {
387 try
388 {
389 $result = true;
390 $includeResult = true;
391
392 $event->addDebugInfo($handler);
393
394 if (!empty($handler['TO_MODULE_ID']) && ($handler['TO_MODULE_ID'] != 'main'))
395 {
396 $result = Loader::includeModule($handler['TO_MODULE_ID']);
397 }
398 elseif (!empty($handler['TO_PATH']))
399 {
400 $path = ltrim($handler['TO_PATH'], '/');
401 if (($path = Loader::getLocal($path)) !== false)
402 {
403 $includeResult = include_once($path);
404 }
405 }
406 elseif (!empty($handler['FULL_PATH']) && IO\File::isFileExists($handler['FULL_PATH']))
407 {
408 $includeResult = include_once($handler['FULL_PATH']);
409 }
410
411 $event->addDebugInfo($result);
412
413 if ($result)
414 {
415 if (!empty($handler['TO_METHOD_ARG']) && is_array($handler['TO_METHOD_ARG']))
416 {
417 $args = $handler['TO_METHOD_ARG'];
418 }
419 else
420 {
421 $args = [];
422 }
423
424 if ($handler['VERSION'] > 1)
425 {
426 $args[] = $event;
427 }
428 else
429 {
430 $args = array_merge($args, array_values($event->getParameters()));
431 }
432
433 $callback = null;
434 if (isset($handler['CALLBACK']))
435 {
436 $callback = $handler['CALLBACK'];
437 }
438 elseif (!empty($handler['TO_CLASS']) && !empty($handler['TO_METHOD']) && class_exists($handler['TO_CLASS']))
439 {
440 $callback = [$handler['TO_CLASS'], $handler['TO_METHOD']];
441 }
442
443 if ($callback != null)
444 {
445 $result = call_user_func_array($callback, $args);
446 }
447 else
448 {
449 $result = $includeResult;
450 }
451
452 if (($result != null) && !($result instanceof EventResult))
453 {
454 $result = new EventResult(EventResult::UNDEFINED, $result, $handler['TO_MODULE_ID'] ?? null);
455 }
456
457 $event->addDebugInfo($result);
458
459 if ($result != null)
460 {
461 $event->addResult($result);
462 }
463 }
464 }
465 catch (\Exception $ex)
466 {
467 if ($event->isDebugOn())
468 {
469 $event->addException($ex);
470 }
471 else
472 {
473 throw $ex;
474 }
475 }
476 }
477}
$path
Определения access_edit.php:21
$connection
Определения actionsdefinitions.php:38
$con
Определения admin_tab.php:7
$type
Определения options.php:106
static getInstance()
Определения application.php:98
static getConnection($name="")
Определения application.php:638
Определения event.php:5
getModuleId()
Определения event.php:39
registerEventHandler($fromModuleId, $eventType, $toModuleId, $toClass='', $toMethod='', $sort=100, $toPath='', $toMethodArg=[])
Определения eventmanager.php:160
addEventHandlerInternal($fromModuleId, $eventType, $callback, $includeFile, $sort, $version)
Определения eventmanager.php:55
registerEventHandlerCompatible($fromModuleId, $eventType, $toModuleId, $toClass='', $toMethod='', $sort=100, $toPath='', $toMethodArg=[])
Определения eventmanager.php:165
addEventHandlerCompatible($fromModuleId, $eventType, $callback, $includeFile=false, $sort=100)
Определения eventmanager.php:116
const CACHE_ID
Определения eventmanager.php:14
removeEventHandler($fromModuleId, $eventType, $iEventHandlerKey)
Определения eventmanager.php:121
send(Event $event)
Определения eventmanager.php:376
clearLoadedHandlers()
Определения eventmanager.php:318
loadEventHandlers()
Определения eventmanager.php:230
sendToEventHandler(array $handler, Event $event)
Определения eventmanager.php:385
static getInstance()
Определения eventmanager.php:31
addEventHandler($fromModuleId, $eventType, $callback, $includeFile=false, $sort=100)
Определения eventmanager.php:103
formatEventName($event)
Определения eventmanager.php:201
unRegisterEventHandler($fromModuleId, $eventType, $toModuleId, $toClass='', $toMethod='', $toPath='', $toMethodArg=[])
Определения eventmanager.php:135
static $instance
Определения eventmanager.php:19
registerEventHandlerInternal($fromModuleId, $eventType, $toModuleId, $toClass, $toMethod, $sort, $toPath, $toMethodArg, $version)
Определения eventmanager.php:170
static setInstance($instance)
Определения eventmanager.php:46
findEventHandlers($eventModuleId, $eventType, array $filter=null)
Определения eventmanager.php:339
static includeModule($moduleName)
Определения loader.php:67
static getLocal($path, $root=null)
Определения loader.php:572
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
Определения file_new.php:804
$result
Определения get_property_values.php:14
$moduleId
$filter
Определения iblock_catalog_list.php:54
$name
Определения menu_edit.php:35
Определения directory.php:3
$event
Определения prolog_after.php:141
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)
Определения prolog_main_admin.php:393
$ar
Определения options.php:199
if(empty($signedUserToken)) $key
Определения quickway.php:257
$i
Определения factura.php:643
else $a
Определения template.php:137
$rs
Определения action.php:82
$fields
Определения yandex_run.php:501