Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
publicaction.php
1<?php
2namespace Bitrix\Landing;
3
8
9Loc::loadMessages(__FILE__);
10
12{
16 const REST_SCOPE_DEFAULT = 'landing';
17
21 const REST_SCOPE_CLOUD = 'landing_cloud';
22
26 public const REST_USAGE_TYPE_BLOCK = 'blocks';
27
31 public const REST_USAGE_TYPE_PAGE = 'pages';
32
37 protected static $restApp = null;
38
43 protected static $rawData = null;
44
49 protected static function getNamespacePublicClasses()
50 {
51 return __NAMESPACE__ . '\\PublicAction';
52 }
53
61 protected static function getMethodInfo($action, $data = array())
62 {
63 $info = array();
64
65 // if action exist and is callable
66 if ($action && mb_strpos($action, '::'))
67 {
68 $actionOriginal = $action;
69 $action = self::getNamespacePublicClasses() . '\\' . $action;
70 if (is_callable(explode('::', $action)))
71 {
72 [$class, $method] = explode('::', $action);
73 $info = array(
74 'action' => $actionOriginal,
75 'class' => $class,
76 'method' => $method,
77 'params_init' => array(),
78 'params_missing' => array()
79 );
80 // parse func params
81 $reflection = new \ReflectionMethod($class, $method);
82 $static = $reflection->getStaticVariables();
83 $mixedParams = isset($static['mixedParams'])
84 ? $static['mixedParams']
85 : [];
86 foreach ($reflection->getParameters() as $param)
87 {
88 $name = $param->getName();
89 if (isset($data[$name]))
90 {
91 if (!in_array($name, $mixedParams))
92 {
93 if (
94 $param->isArray() &&
95 !is_array($data[$name])
96 ||
97 !$param->isArray() &&
98 is_array($data[$name])
99
100 )
101 {
102 throw new \Bitrix\Main\ArgumentTypeException(
103 $name
104 );
105 }
106 }
107 $info['params_init'][$name] = $data[$name];
108 }
109 elseif ($param->isDefaultValueAvailable())
110 {
111 $info['params_init'][$name] = $param->getDefaultValue();
112 }
113 else
114 {
115 $info['params_missing'][] = $name;
116 }
117 }
118 }
119 }
120
121 return $info;
122 }
123
130 protected static function checkForExtranet(): bool
131 {
133 {
134 return true;
135 }
136
137 if (Type::getCurrentScopeId() === Type::SCOPE_CODE_GROUP)
138 {
139 return true;
140 }
141
142 if (\Bitrix\Main\Loader::includeModule('extranet'))
143 {
144 return \CExtranet::isIntranetUser(
145 \CExtranet::getExtranetSiteID(),
147 );
148 }
149
150 return true;
151 }
152
161 protected static function actionProcessing($action, $data, $isRest = false)
162 {
163 if (!is_array($data))
164 {
165 $data = array();
166 }
167
168 if (isset($data['scope']))
169 {
170 Type::setScope($data['scope']);
171 }
172
173 if (!$isRest && (!defined('BX_UTF') || BX_UTF !== true))
174 {
175 $data = Manager::getApplication()->convertCharsetArray(
176 $data, 'UTF-8', SITE_CHARSET
177 );
178 }
179
180 $error = new Error;
181
182 // not for guest
183 if (!Manager::getUserId() || !self::checkForExtranet())
184 {
185 $error->addError(
186 'ACCESS_DENIED',
187 Loc::getMessage('LANDING_ACCESS_DENIED2')
188 );
189 }
190 // tmp flag for compatibility
191 else if (
192 ModuleManager::isModuleInstalled('bitrix24') &&
193 Manager::getOption('temp_permission_admin_only') &&
194 !\CBitrix24::isPortalAdmin(Manager::getUserId())
195 )
196 {
197 $error->addError(
198 'ACCESS_DENIED',
199 Loc::getMessage('LANDING_ACCESS_DENIED2')
200 );
201 }
202 // check common permission
203 else if (
206 null,
207 true
208 )
209 )
210 {
211 $error->addError(
212 'ACCESS_DENIED',
213 Loc::getMessage('LANDING_ACCESS_DENIED2')
214 );
215 }
216 else if (!Manager::isB24() && Manager::getApplication()->getGroupRight('landing') < 'W')
217 {
218 $error->addError(
219 'ACCESS_DENIED',
220 Loc::getMessage('LANDING_ACCESS_DENIED2')
221 );
222 }
223 // if method::action exist in PublicAction, call it
224 elseif (($action = self::getMethodInfo($action, $data)))
225 {
226 if (!$isRest && !check_bitrix_sessid())
227 {
228 $error->addError(
229 'SESSION_EXPIRED',
230 Loc::getMessage('LANDING_SESSION_EXPIRED')
231 );
232 }
233 if (!empty($action['params_missing']))
234 {
235 $error->addError(
236 'MISSING_PARAMS',
237 Loc::getMessage('LANDING_MISSING_PARAMS', array(
238 '#MISSING#' => implode(', ', $action['params_missing'])
239 ))
240 );
241 }
242 if (method_exists($action['class'], 'init'))
243 {
244 $result = call_user_func_array(
245 array($action['class'], 'init'),
246 []
247 );
248 if (!$result->isSuccess())
249 {
250 $error->copyError($result->getError());
251 }
252 }
253 // all right - execute
254 if ($error->isEmpty())
255 {
256 try
257 {
258 $result = call_user_func_array(
259 array($action['class'], $action['method']),
260 $action['params_init']
261 );
262 // answer
263 if ($result === null)// void is accepted as success
264 {
265 return array(
266 'type' => 'success',
267 'result' => true
268 );
269 }
270 else if ($result->isSuccess())
271 {
272 $restResult = $result->getResult();
273 $event = new \Bitrix\Main\Event('landing', 'onSuccessRest', [
274 'result' => $restResult,
275 'action' => $action
276 ]);
277 $event->send();
278 foreach ($event->getResults() as $eventResult)
279 {
280 if (($modified = $eventResult->getModified()))
281 {
282 if (isset($modified['result']))
283 {
284 $restResult = $modified['result'];
285 }
286 }
287 }
288 return array(
289 'type' => 'success',
290 'result' => $restResult
291 );
292 }
293 else
294 {
295 $error->copyError($result->getError());
296 }
297 }
298 catch (\TypeError $e)
299 {
300 $error->addError(
301 'TYPE_ERROR',
302 $e->getMessage()
303 );
304 }
305 catch (\Exception $e)
306 {
307 $error->addError(
308 'SYSTEM_ERROR',
309 $e->getMessage()
310 );
311 }
312 }
313 }
314 // error
315 $errors = array();
316 foreach ($error->getErrors() as $error)
317 {
318 $errors[] = array(
319 'error' => $error->getCode(),
320 'error_description' => $error->getMessage()
321 );
322 }
323 if (!$isRest)
324 {
325 return [
326 'sessid' => bitrix_sessid(),
327 'type' => 'error',
328 'result' => $errors
329 ];
330 }
331 else
332 {
333 return [
334 'type' => 'error',
335 'result' => $errors
336 ];
337 }
338 }
339
344 public static function getRawData()
345 {
346 return self::$rawData;
347 }
348
354 public static function ajaxProcessing()
355 {
356 $context = \Bitrix\Main\Application::getInstance()->getContext();
357 $request = $context->getRequest();
358 $files = $request->getFileList();
359 $postlist = $context->getRequest()->getPostList();
360
361 Type::setScope($request->get('type'));
362
363 // multiple commands
364 if (
365 $request->offsetExists('batch') &&
366 is_array($request->get('batch'))
367 )
368 {
369 $result = array();
370 // additional site id detect
371 if ($request->offsetExists('site_id'))
372 {
373 $siteId = $request->get('site_id');
374 }
375 foreach ($request->get('batch') as $key => $batchItem)
376 {
377 if (
378 isset($batchItem['action']) &&
379 isset($batchItem['data'])
380 )
381 {
382 $batchItem['data'] = (array)$batchItem['data'];
383 if (isset($siteId))
384 {
385 $batchItem['data']['siteId'] = $siteId;
386 }
387 if ($files)
388 {
389 foreach ($files as $code => $file)
390 {
391 $batchItem['data'][$code] = $file;
392 }
393 }
394 $rawData = $postlist->getRaw('batch');
395 if (isset($rawData[$key]['data']))
396 {
397 self::$rawData = $rawData[$key]['data'];
398 }
399 $result[$key] = self::actionProcessing(
400 $batchItem['action'],
401 $batchItem['data']
402 );
403 }
404 }
405
406 return $result;
407 }
408 // or single command
409 else if (
410 $request->offsetExists('action') &&
411 $request->offsetExists('data') &&
412 is_array($request->get('data'))
413 )
414 {
415 $data = $request->get('data');
416 // additional site id detect
417 if ($request->offsetExists('site_id'))
418 {
419 $data['siteId'] = $request->get('site_id');
420 }
421 if ($files)
422 {
423 foreach ($files as $code => $file)
424 {
425 $data[$code] = $file;
426 }
427 }
428 $rawData = $postlist->getRaw('data');
429 if (isset($rawData['data']))
430 {
431 self::$rawData = $rawData['data'];
432 }
433 return self::actionProcessing(
434 $request->get('action'),
435 $data
436 );
437 }
438
439 return null;
440 }
441
447 public static function restBase()
448 {
449 static $restMethods = array();
450
451 if (empty($restMethods))
452 {
453 $restMethods[self::REST_SCOPE_DEFAULT] = array();
454 $restMethods[self::REST_SCOPE_CLOUD] = array();
455
456 $classes = array(
457 self::REST_SCOPE_DEFAULT => array(
458 'block', 'site', 'landing', 'repo', 'template',
459 'demos', 'role', 'syspage', 'chat'
460 ),
461 self::REST_SCOPE_CLOUD => array(
462 'cloud'
463 )
464 );
465
466 // then methods list for each class
467 foreach ($classes as $scope => $classList)
468 {
469 foreach ($classList as $className)
470 {
471 $fullClassName = self::getNamespacePublicClasses() . '\\' . $className;
472 $class = new \ReflectionClass($fullClassName);
473 $methods = $class->getMethods(\ReflectionMethod::IS_PUBLIC);
474 foreach ($methods as $method)
475 {
476 $static = $method->getStaticVariables();
477 if (!isset($static['internal']) || !$static['internal'])
478 {
479 $command = $scope.'.'.
480 mb_strtolower($className).'.'.
481 mb_strtolower($method->getName());
482 $restMethods[$scope][$command] = array(
483 __CLASS__, 'restGateway'
484 );
485 }
486 }
487 }
488 }
489 }
490
491 return array(
492 self::REST_SCOPE_DEFAULT => $restMethods[self::REST_SCOPE_DEFAULT],
493 self::REST_SCOPE_CLOUD => $restMethods[self::REST_SCOPE_CLOUD]
494 );
495 }
496
505 public static function restGateway($fields, $t, $server)
506 {
507 // get context app
508 self::$restApp = AppTable::getByClientId($server->getClientId());
509 // prepare method and call action
510 $method = $server->getMethod();
511 $method = mb_substr($method, mb_strpos($method, '.') + 1);// delete module-prefix
512 $method = preg_replace('/\./', '\\', $method, substr_count($method, '.') - 1);
513 $method = str_replace('.', '::', $method);
514 $result = self::actionProcessing(
515 $method,
516 $fields,
517 true
518 );
519 // prepare answer
520 if ($result['type'] == 'error')
521 {
522 foreach ($result['result'] as $error)
523 {
524 throw new \Bitrix\Rest\RestException(
525 $error['error_description'],
526 $error['error']
527 );
528 }
529 }
530 else
531 {
532 return $result['result'];
533 }
534 }
535
540 public static function restApplication()
541 {
542 return self::$restApp;
543 }
544
550 public static function restApplicationDelete($app)
551 {
552 if (isset($app['APP_ID']) && $app['APP_ID'])
553 {
554 if (($app = AppTable::getByClientId($app['APP_ID'])))
555 {
557 Repo::deleteByAppCode($app['CODE']);
558 Placement::deleteByAppId($app['ID']);
559 Demos::deleteByAppCode($app['CODE']);
561 }
562 }
563 }
564
570 public static function beforeRestApplicationDelete(\Bitrix\Main\Event $event)
571 {
572 $parameters = $event->getParameters();
573
574 if ($app = AppTable::getByClientId($parameters['ID']))
575 {
576 $stat = self::getRestStat(true);
577 if (isset($stat[self::REST_USAGE_TYPE_BLOCK][$app['CODE']]))
578 {
579 $eventResult = new \Bitrix\Main\EventResult(
580 \Bitrix\Main\EventResult::ERROR,
581 new \Bitrix\Main\Error(
582 Loc::getMessage('LANDING_REST_DELETE_EXIST_BLOCKS'),
583 'LANDING_EXISTS_BLOCKS'
584 )
585 );
586
587 return $eventResult;
588 }
589 else if (isset($stat[self::REST_USAGE_TYPE_PAGE][$app['CODE']]))
590 {
591 $eventResult = new \Bitrix\Main\EventResult(
592 \Bitrix\Main\EventResult::ERROR,
593 new \Bitrix\Main\Error(
594 Loc::getMessage('LANDING_REST_DELETE_EXIST_PAGES'),
595 'LANDING_EXISTS_PAGES'
596 )
597 );
598
599 return $eventResult;
600 }
601 }
602 }
603
611 public static function getRestStat(bool $humanFormat = false, bool $onlyActive = true, array $additionalFilter = []): array
612 {
613 $blockCnt = [];
614 $fullStat = [
615 self::REST_USAGE_TYPE_BLOCK => [],
616 self::REST_USAGE_TYPE_PAGE => []
617 ];
618 $activeValues = $onlyActive ? 'Y' : ['Y', 'N'];
619 $filter = [
620 'CODE' => 'repo_%',
621 '=DELETED' => 'N',
622 '=PUBLIC' => $activeValues,
623 '=LANDING.ACTIVE' => $activeValues,
624 '=LANDING.SITE.ACTIVE' => $activeValues
625 ];
626
627 if (isset($additionalFilter['SITE_ID']))
628 {
629 $filter['LANDING.SITE_ID'] = $additionalFilter['SITE_ID'];
630 }
631
633
634 // gets all partners active block, placed on pages
635 $res = Internals\BlockTable::getList([
636 'select' => [
637 'CODE', 'CNT'
638 ],
639 'filter' => $filter,
640 'group' => [
641 'CODE'
642 ],
643 'runtime' => [
644 new \Bitrix\Main\Entity\ExpressionField('CNT', 'COUNT(*)')
645 ]
646 ]);
647 while ($row = $res->fetch())
648 {
649 $blockCnt[mb_substr($row['CODE'], 5)] = $row['CNT'];
650 }
651
652 // gets apps for this blocks
653 $res = Repo::getList([
654 'select' => [
655 'ID', 'APP_CODE'
656 ],
657 'filter' => [
658 'ID' => array_keys($blockCnt)
659 ]
660 ]);
661 while ($row = $res->fetch())
662 {
663 if (!$row['APP_CODE'])
664 {
665 continue;
666 }
667 if (!isset($fullStat[self::REST_USAGE_TYPE_BLOCK][$row['APP_CODE']]))
668 {
669 $fullStat[self::REST_USAGE_TYPE_BLOCK][$row['APP_CODE']] = 0;
670 }
671 $fullStat[self::REST_USAGE_TYPE_BLOCK][$row['APP_CODE']] += $blockCnt[$row['ID']];
672 }
673 unset($blockCnt);
674
675 // gets additional partners active block with not empty INITIATOR_APP_CODE, placed on pages
676 $filter['!CODE'] = $filter['CODE'];
677 unset($filter['CODE']);
678 $filter['!=INITIATOR_APP_CODE'] = null;
679 $res = Internals\BlockTable::getList([
680 'select' => [
681 'INITIATOR_APP_CODE', 'CNT'
682 ],
683 'filter' => $filter,
684 'group' => [
685 'INITIATOR_APP_CODE'
686 ],
687 'runtime' => [
688 new \Bitrix\Main\Entity\ExpressionField('CNT', 'COUNT(*)')
689 ]
690 ]);
691 while ($row = $res->fetch())
692 {
693 $appCode = $row['INITIATOR_APP_CODE'];
694 if (!isset($fullStat[self::REST_USAGE_TYPE_BLOCK][$appCode]))
695 {
696 $fullStat[self::REST_USAGE_TYPE_BLOCK][$appCode] = 0;
697 }
698 $fullStat[self::REST_USAGE_TYPE_BLOCK][$appCode] += $row['CNT'];
699 }
700
701 // gets all partners active pages
702 $filter = [
703 '=DELETED' => 'N',
704 '=ACTIVE' => $activeValues,
705 '=SITE.ACTIVE' => $activeValues,
706 '!=INITIATOR_APP_CODE' => null
707 ];
708 if (isset($additionalFilter['SITE_ID']))
709 {
710 $filter['SITE_ID'] = $additionalFilter['SITE_ID'];
711 }
712 $res = Landing::getList([
713 'select' => [
714 'INITIATOR_APP_CODE', 'CNT'
715 ],
716 'filter' => $filter,
717 'group' => [
718 'INITIATOR_APP_CODE'
719 ],
720 'runtime' => [
721 new \Bitrix\Main\Entity\ExpressionField('CNT', 'COUNT(*)')
722 ]
723 ]);
724 while ($row = $res->fetch())
725 {
726 $appCode = $row['INITIATOR_APP_CODE'];
727 if (!isset($fullStat[self::REST_USAGE_TYPE_PAGE][$appCode]))
728 {
729 $fullStat[self::REST_USAGE_TYPE_PAGE][$appCode] = 0;
730 }
731 $fullStat[self::REST_USAGE_TYPE_PAGE][$appCode] += $row['CNT'];
732 }
733
734 // get client id for apps
735 if (!$humanFormat && \Bitrix\Main\Loader::includeModule('rest'))
736 {
737 $appsCode = array_merge(
738 array_keys($fullStat[self::REST_USAGE_TYPE_BLOCK]),
739 array_keys($fullStat[self::REST_USAGE_TYPE_PAGE])
740 );
741 $fullStatNew = [
742 self::REST_USAGE_TYPE_BLOCK => [],
743 self::REST_USAGE_TYPE_PAGE => []
744 ];
745 if ($appsCode)
746 {
747 $appsCode = array_unique($appsCode);
748 $res = AppTable::getList([
749 'select' => [
750 'CLIENT_ID', 'CODE'
751 ],
752 'filter' => [
753 '=CODE' => $appsCode
754 ]
755 ]);
756 while ($row = $res->fetch())
757 {
758 foreach ($fullStat as $code => $stat)
759 {
760 if (isset($stat[$row['CODE']]))
761 {
762 $fullStatNew[$code][$row['CLIENT_ID']] = $stat[$row['CODE']];
763 }
764 }
765 }
766 }
767
768 return $fullStatNew;
769 }
770
772
773 return $fullStat;
774 }
775}
static deleteByAppCode($code)
Definition demos.php:27
addError($code, $message='')
Definition error.php:18
static getOption($code, $default=null)
Definition manager.php:160
static getApplication()
Definition manager.php:71
static deleteByAppId($id)
Definition placement.php:17
static getList(array $params=[])
Definition landing.php:584
static getList(array $params=array())
Definition repo.php:533
static beforeRestApplicationDelete(\Bitrix\Main\Event $event)
static getRestStat(bool $humanFormat=false, bool $onlyActive=true, array $additionalFilter=[])
static restGateway($fields, $t, $server)
static actionProcessing($action, $data, $isRest=false)
static getMethodInfo($action, $data=array())
static deleteByAppCode($code)
Definition repo.php:207
static hasAdditionalRight($code, $type=null, bool $checkExtraRights=false, bool $strict=false)
Definition rights.php:1025
static loadMessages($file)
Definition loc.php:64
static getMessage($code, $replace=null, $language=null)
Definition loc.php:29