3namespace Bitrix\Main\Engine;
5use Bitrix\Main\Application;
6use Bitrix\Main\Component\ParameterSigner;
7use Bitrix\Main\Config\Configuration;
8use Bitrix\Main\Diag\ExceptionHandlerFormatter;
9use Bitrix\Main\Engine\ActionFilter\FilterType;
10use Bitrix\Main\Engine\AutoWire\BinderArgumentException;
11use Bitrix\Main\Engine\AutoWire\Parameter;
12use Bitrix\Main\Engine\Contract\Controllerable;
13use Bitrix\Main\Engine\Response\Converter;
15use Bitrix\Main\ErrorCollection;
16use Bitrix\Main\Errorable;
17use Bitrix\Main\ArgumentNullException;
18use Bitrix\Main\ArgumentTypeException;
19use Bitrix\Main\Context;
20use Bitrix\Main\Engine\Response\Render\Component;
21use Bitrix\Main\Engine\Response\Render\Extension;
22use Bitrix\Main\Engine\Response\Render\View;
23use Bitrix\Main\Engine\View\ViewPathResolver;
25use Bitrix\Main\EventManager;
26use Bitrix\Main\EventResult;
27use Bitrix\Main\HttpResponse;
28use Bitrix\Main\Request;
29use Bitrix\Main\Response;
30use Bitrix\Main\Security\Sign\BadSignatureException;
31use Bitrix\Main\SystemException;
32use Bitrix\Main\Validation\ValidationException;
33use Bitrix\Main\Web\Uri;
55 private Action $currentAction;
56 private array $eventHandlersIds = [
61 private $configurationOfActions =
null;
63 private string $scope;
71 private $sourceParametersList;
72 private $unsignedParameters;
90 $this->scope = self::SCOPE_AJAX;
92 $this->request =
$request?: Context::getCurrent()->getRequest();
94 $this->converter = Converter::toJson();
107 public function forward($controller,
string $actionName,
array $parameters =
null)
109 if (is_string($controller))
111 $controller =
new $controller;
119 $controller->setScope($this->
getScope());
122 $currentAction = $this->getCurrentAction();
131 $this->attachFilters($currentAction);
132 $this->
addErrors($controller->getErrors());
144 $this->buildConfigurationOfActions();
152 return $this->configurationOfActions;
166 private function getCurrentAction():
Action
181 $firstLetter = mb_substr(basename($this->
getFilePath()), 0, 1);
183 return $firstLetter !== mb_strtolower($firstLetter);
188 if (!$this->filePath)
190 $reflector = new \ReflectionClass($this);
191 $this->filePath = preg_replace(
'#[\\\/]+#',
'/', $reflector->getFileName());
194 return $this->filePath;
209 if (!str_contains($this->
getFilePath(),
'/components/'))
222 return $this->unsignedParameters;
229 $signedParameters = $source[
'signedParameters'] ??
null;
230 if (is_string($signedParameters))
234 $this->unsignedParameters = ParameterSigner::unsignParameters(
256 if (isset($source[
'c']) && is_string($source[
'c']))
270 return $this->currentUser;
278 $this->currentUser = $currentUser;
290 return $this->converter->process(
$data);
300 $lengthSuffix = mb_strlen(self::METHOD_ACTION_SUFFIX);
302 $class = new \ReflectionClass($this);
303 foreach ($class->getMethods(\ReflectionMethod::IS_PUBLIC) as
$method)
305 $probablySuffix = mb_substr(
$method->getName(), -$lengthSuffix);
306 if ($probablySuffix === self::METHOD_ACTION_SUFFIX)
308 $actions[] = mb_strtolower(mb_substr(
$method->getName(), 0, -$lengthSuffix));
312 return array_unique($actions);
347 private function buildConfigurationOfActions(): void
349 $this->configurationOfActions = $this->configurator->getConfigurationByController($this);
375 $this->scope = $scope;
385 return $this->sourceParametersList;
395 $this->sourceParametersList = $sourceParametersList;
407 final public function run($actionName,
array $sourceParametersList)
421 throw new SystemException(
"Could not create action by name {$actionName}");
423 $this->setCurrentAction(
$action);
436 $this->errorCollection->add(
$action->getErrors());
442 if ($probablyResult !==
null)
447 catch (\Throwable $e)
450 $this->processExceptionInDebug($e);
467 return $action->runWithSourceParametersList();
473 $exceptionHandler->writeToLog($e);
476 private function processExceptionInDebug(\Throwable $e): void
478 if ($this->shouldWriteToLogException($e))
480 $this->writeToLogException($e);
483 $exceptionHandling = Configuration::getValue(
'exception_handling');
484 if (!empty($exceptionHandling[
'debug']))
487 if ($e->getPrevious())
494 private function shouldWriteToLogException(\Throwable $e): bool
496 if ($e instanceof BinderArgumentException)
501 if ($e instanceof SystemException && ($e->getCode() === self::EXCEPTION_UNKNOWN_ACTION))
511 return static::class .
'::' . $eventName;
563 static::getFullEventName(static::EVENT_ON_BEFORE_ACTION),
566 'controller' => $this,
572 foreach (
$event->getResults() as $eventResult)
574 if ($eventResult->getType() != EventResult::SUCCESS)
576 $handler = $eventResult->getHandler();
579 $this->errorCollection->add($handler->getErrors());
618 static::getFullEventName(static::EVENT_ON_AFTER_ACTION),
622 'controller' => $this,
629 return $event->getParameter(
'result');
634 return $action . self::METHOD_ACTION_SUFFIX;
643 if (method_exists($this, $methodName))
645 $method = new \ReflectionMethod($this, $methodName);
646 if (
$method->isPublic() && mb_strtolower(
$method->getName()) === mb_strtolower($methodName))
660 "Could not find description of $actionName in {$this::className()}",
661 self::EXCEPTION_UNKNOWN_ACTION
673 if (isset(
$config[
'callable']))
675 $callable =
$config[
'callable'];
676 if (!is_callable($callable))
687 "Could not find class in description of {$actionName} in {$this::className()} to create instance",
688 self::EXCEPTION_UNKNOWN_ACTION
704 if ($e->getCode() !== Controller::EXCEPTION_UNKNOWN_ACTION)
754 if (!isset(
$config[FilterType::Prefilter->value]))
756 $config[FilterType::Prefilter->value] = $this->configurator->wrapFiltersClosure(
760 if (!isset(
$config[FilterType::Postfilter->value]))
762 $config[FilterType::Postfilter->value] = $this->configurator->wrapFiltersClosure(
767 $hasPostMethod = $hasCsrfCheck =
false;
772 $hasPostMethod =
true;
776 $hasCsrfCheck =
true;
780 if ($hasPostMethod && !$hasCsrfCheck && $this->request->isPost())
785 if (!empty(
$config[FilterType::DisablePrefilter->value]))
787 $config[FilterType::Prefilter->value] =
791 if (!empty(
$config[FilterType::DisablePostfilter->value]))
793 $config[FilterType::Postfilter->value] =
797 if (!empty(
$config[FilterType::EnablePrefilter->value]))
799 $config[FilterType::Prefilter->value] =
803 if (!empty(
$config[FilterType::EnablePostfilter->value]))
805 $config[FilterType::Postfilter->value] =
814 return array_merge($filters, $filtersToAppend);
819 $cleanedFilters = [];
823 foreach ($filtersToRemove as $filterToRemove)
825 if (is_a(
$filter, $filterToRemove))
838 return $cleanedFilters;
843 $modifiedConfig = $this->buildFilters(
844 $this->getActionConfig(
$action->getName())
848 foreach ($modifiedConfig[FilterType::Prefilter->value] as
$filter)
851 if (!in_array($this->getScope(),
$filter->listAllowedScopes(),
true))
858 $this->eventHandlersIds[FilterType::Prefilter->value][] =
$eventManager->addEventHandler(
860 static::getFullEventName(static::EVENT_ON_BEFORE_ACTION),
865 foreach ($modifiedConfig[FilterType::Postfilter->value] as
$filter)
868 if (!in_array($this->getScope(),
$filter->listAllowedScopes(),
true))
876 $this->eventHandlersIds[FilterType::Postfilter->value][] =
$eventManager->addEventHandler(
878 static::getFullEventName(static::EVENT_ON_AFTER_ACTION),
893 foreach ($this->eventHandlersIds[FilterType::Prefilter->value] as $handlerId)
897 static::getFullEventName(static::EVENT_ON_BEFORE_ACTION),
902 $this->eventHandlersIds[FilterType::Prefilter->value] = [];
908 foreach ($this->eventHandlersIds[FilterType::Postfilter->value] as $handlerId)
912 static::getFullEventName(static::EVENT_ON_AFTER_ACTION),
917 $this->eventHandlersIds[FilterType::Postfilter->value] = [];
922 $listOfActions = array_change_key_case($this->configurationOfActions, CASE_LOWER);
923 $actionName = mb_strtolower($actionName);
925 if (!isset($listOfActions[$actionName]))
930 return $listOfActions[$actionName];
935 $this->configurationOfActions[$actionName] =
$config;
979 $currentControllerErrors = $this->
getErrors();
985 if (in_array(
$error, $currentControllerErrors,
true))
1002 if (empty($validationErrors))
1009 foreach ($validationErrors as $validationError)
1019 return new Error($e->getMessage(), self::ERROR_REQUIRED_PARAMETER);
1022 return new Error($e->getMessage(), $e->getCode());
1072 $this->errorCollection[] =
$error;
1085 $this->errorCollection->add(
$errors);
1096 return $this->errorCollection->toArray();
1101 return !$this->errorCollection->isEmpty();
1111 return $this->errorCollection->getErrorByCode(
$code);
1199 $resolver->resolve(),
if(!Loader::includeModule('catalog')) if(!AccessController::getCurrent() ->check(ActionDictionary::ACTION_PRICE_EDIT)) if(!check_bitrix_sessid()) $request
static format($exception, $htmlMode=false, $level=0)
buildFilters(array $config=null)
runProcessingThrowable(\Throwable $throwable)
runProcessingIfUserNotAuthorized()
processAfterAction(Action $action, $result)
buildActionInstance($actionName, array $config)
const EVENT_ON_BEFORE_ACTION
convertKeysToCamelCase($data)
const ERROR_REQUIRED_PARAMETER
processUnsignedParameters()
setSourceParametersList($sourceParametersList)
renderComponent(string $name, string $template='', array $params=[], bool $withSiteTemplate=true)
runProcessingValidationException(ValidationException $e)
const ERROR_UNKNOWN_ACTION
runProcessingException(\Exception $e)
getPrimaryAutoWiredParameter()
appendFilters(array $filters, array $filtersToAppend)
const EXCEPTION_UNKNOWN_ACTION
detachFilters(Action $action)
__construct(Request $request=null)
processBeforeAction(Action $action)
getActionConfig($actionName)
renderExtension(string $extension, array $params=[], bool $withSiteTemplate=true)
getActionResponse(Action $action)
finalizeResponse(Response $response)
triggerOnBeforeAction(Action $action)
renderView(string $viewPath, array $params=[], bool $withSiteTemplate=true)
runProcessingBinderThrowable(BinderArgumentException $e)
runProcessingIfInvalidCsrfToken()
generateActionMethodName($action)
const EVENT_ON_AFTER_ACTION
buildErrorFromPhpError(\Error $error)
getSourceParametersList()
detachPreFilters(Action $action)
forward($controller, string $actionName, array $parameters=null)
runProcessingError(\Error $error)
static getFullEventName($eventName)
getActionUri(string $actionName, array $params=[], bool $absolute=false)
getDefaultAutoWiredParameters()
run($actionName, array $sourceParametersList)
getConfigurationOfActions()
setActionConfig($actionName, array $config=null)
buildErrorFromException(\Exception $e)
triggerOnAfterAction(Action $action, $result)
existsAction($actionName)
setCurrentUser(CurrentUser $currentUser)
detachPostFilters(Action $action)
removeFilters(array $filters, array $filtersToRemove)
Configurator $configurator
writeToLogException(\Throwable $e)
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
if(!is_null($config))($config as $configItem)(! $configItem->isVisible()) $code
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)
if($inWords) echo htmlspecialcharsbx(Number2Word_Rus(roundEx($totalVatSum $params['CURRENCY']