Your IP : 18.220.66.3
<?php
namespace Bitrix\Main\Engine;
use Bitrix\Main\Config\Configuration;
use Bitrix\Main\ObjectException;
final class Resolver
{
const DEFAULT_VENDOR = 'bitrix';
/**
* Returns list instance of controller and action in this controller.
*
* @param string $vendor
* @param string $module
* @param string $action
* @param string $scope
*
* @return array|null
*/
public static function getControllerAndAction($vendor, $module, $action, $scope = Controller::SCOPE_AJAX)
{
$parts = explode('.', $action);
$actionName = array_pop($parts);
$controllerClass = self::buildControllerClassName($vendor, $module, $parts);
if (!$controllerClass)
{
return null;
}
try
{
$controller = ControllerBuilder::build($controllerClass, [
'scope' => $scope,
'currentUser' => CurrentUser::get(),
]);
return [$controller, $actionName];
}
catch (ObjectException $exception)
{}
return null;
}
private static function buildControllerClassName($vendor, $module, array $actionParts)
{
$controllerName = array_pop($actionParts);
if (self::isOldFullQualifiedName($vendor, $module, $actionParts))
{
$actionParts[] = $controllerName;
$className = implode('\\', $actionParts);
if (!self::checkClassUnderAllowedNamespaces($module, $className))
{
return null;
}
return $className;
}
$namespaces = self::listAllowedNamespaces($module);
$aliases = array_change_key_case($namespaces, CASE_LOWER);
$probablyPrefix = mb_strtolower(reset($actionParts));
if (isset($aliases[$probablyPrefix]))
{
$alias = $aliases[$probablyPrefix];
array_shift($actionParts); //drop prefix
array_push($actionParts, $controllerName);
return $alias . '\\' . implode('\\', $actionParts);
}
$furtherControllerClassName = self::buildClassNameByAction(
$vendor,
$module,
array_merge($actionParts, [$controllerName])
);
if (self::checkClassUnderAllowedNamespaces($module, $furtherControllerClassName))
{
return $furtherControllerClassName;
}
$defaultNamespaceByModule = self::getDefaultNamespaceByModule($module);
if (!$defaultNamespaceByModule)
{
return null;
}
$defaultPath = strtr($defaultNamespaceByModule, ['\\' => '.']);
// do not lower if probably psr4
$firstLetter = mb_substr($controllerName, 0, 1);
if ($firstLetter === mb_strtolower($firstLetter))
{
$defaultPath = mb_strtolower($defaultPath);
}
array_unshift($actionParts, ...explode('.', $defaultPath));
array_push($actionParts, $controllerName);
return implode('\\', $actionParts);
}
/**
* Returns default namespace by module.
* @param string $module Module id.
*
* @return null|string
*/
public static function getDefaultNamespaceByModule($module)
{
$controllersConfig = Configuration::getInstance($module);
if (!$controllersConfig['controllers'] || !isset($controllersConfig['controllers']['defaultNamespace']))
{
return null;
}
return $controllersConfig['controllers']['defaultNamespace'];
}
/**
* Checks if the name of action is old full qualified name.
* For example: disk.bitrix.disk.controller.file.get.
* @param $vendor
* @param $module
* @param array $actionParts
*
* @return bool
*/
private static function isOldFullQualifiedName($vendor, $module, array $actionParts)
{
if ($vendor !== self::DEFAULT_VENDOR)
{
return false;
}
if (!isset($actionParts[0]) || !isset($actionParts[1]))
{
return false;
}
return $actionParts[0] === $vendor && $actionParts[1] === $module;
}
private static function listAllowedNamespaces($module)
{
$controllersConfig = Configuration::getInstance($module);
if (!$controllersConfig['controllers'])
{
return [];
}
$namespaces = [];
if (isset($controllersConfig['controllers']['namespaces']))
{
foreach ($controllersConfig['controllers']['namespaces'] as $key => $namespace)
{
if (is_int($key))
{
$namespaces[] = $namespace;
}
else
{
$namespaces[$namespace] = $key;
}
}
}
if (isset($controllersConfig['controllers']['defaultNamespace']))
{
$namespaces[] = $controllersConfig['controllers']['defaultNamespace'];
}
return $namespaces;
}
private static function checkClassUnderAllowedNamespaces($module, $class)
{
$namespaces = self::listAllowedNamespaces($module);
foreach ($namespaces as $namespace)
{
if (mb_stripos(trim($class, '\\'), trim($namespace, '\\') . '\\') === 0)
{
return true;
}
}
return false;
}
/**
* Builds class name by vendor and module.
* @param $vendor
* @param $module
* @param array $actionParts
*
* @return string
*/
private static function buildClassNameByAction($vendor, $module, array $actionParts)
{
if($vendor === self::DEFAULT_VENDOR)
{
$namespace = "\\Bitrix\\$module";
}
else
{
$namespace = "\\" . strtr($module, ['.' => '\\']);
}
if (!$actionParts)
{
return $namespace;
}
return "{$namespace}\\" . trim(implode('\\', $actionParts), '\\');
}
/**
* Returns name of controller for using in routing.
* The name is built by rules: fully qualified name contains delimiters by dot.
* Example: vendor:module.controller.action.
*
* @param Controller $controller Controller.
*
* @return string
*/
public static function getNameByController(Controller $controller)
{
$parts = explode('\\', get_class($controller));
$vendor = mb_strtolower(array_shift($parts));
//lower case for module name
$parts[0] = mb_strtolower($parts[0]);
return $vendor . ':' . implode('.', $parts);
}
}