%PDF- %PDF-
Direktori : /home/vacivi36/intranet.vacivitta.com.br/protected/humhub/components/ |
Current File : /home/vacivi36/intranet.vacivitta.com.br/protected/humhub/components/ContentContainerUrlRule.php |
<?php /** * @link https://www.humhub.org/ * @copyright Copyright (c) 2021 HumHub GmbH & Co. KG * @license https://www.humhub.com/licences */ namespace humhub\components; use humhub\modules\content\components\ContentContainerActiveRecord; use yii\web\UrlRule; use yii\web\UrlRuleInterface; use yii\base\BaseObject; /** * Content Container URL Rule * * @author luke * @since 1.9 */ abstract class ContentContainerUrlRule extends BaseObject implements UrlRuleInterface { /** * @var string default route to content container home */ protected $defaultRoute; /** * @var string Prefix of the container URLs */ protected $urlPrefix; /** * @var string[] Possible prefixes for route */ protected $routePrefixes = ['<contentContainer>']; /** * @var array map with Content Container guid/url pairs */ public static $containerUrlMap; /** * Get Content Container by URL * * @param string $url * @return ContentContainerActiveRecord */ abstract static protected function getContentContainerByUrl(string $url): ?ContentContainerActiveRecord; /** * Get Content Container by guid * * @param string $guid * @return ContentContainerActiveRecord */ abstract protected static function getContentContainerByGuid(string $guid): ?ContentContainerActiveRecord; /** * Get URL map data from Content Container * * @param ContentContainerActiveRecord $contentContainer * @return string|null */ abstract protected static function getUrlMapFromContentContainer(ContentContainerActiveRecord $contentContainer): ?string; /** * Check if the object is of proper instance * * @param ContentContainerActiveRecord $contentContainer * @return bool */ abstract protected static function isContentContainerInstance(ContentContainerActiveRecord $contentContainer): bool; /** * @inheritdoc */ public function createUrl($manager, $route, $params) { if (!isset($params['cguid'])) { return false; } $urlPart = static::getUrlByContentContainerGuid($params['cguid']); if ($urlPart === null) { return false; } $url = $this->urlPrefix . '/' . urlencode(mb_strtolower($urlPart)); unset($params['cguid']); if ($route == $this->defaultRoute) { $route = ''; } foreach ($manager->rules as $rule) { if ($result = $this->createUrlByClass($rule, $manager, $url, $route, $params)) { return $result; } if ($result = $this->createUrlByRule($rule, $route, $params)) { list($route, $params) = $result; } } $url .= '/' . $route; if (!empty($params) && ($query = http_build_query($params)) !== '') { $url .= '?' . $query; } return $url; } /** * Try to create URL by class rule * * @param UrlRule $rule * @param UrlManager $manager the URL manager * @param string $containerUrlPath Current relative URL path to the Content Container * @param string $route the route. It should not have slashes at the beginning or the end. * @param array $params the parameters * @return string|bool the created URL, or false if this rule cannot be used for creating this URL. */ private function createUrlByClass($rule, UrlManager $manager, string $containerUrlPath, string $route, array $params) { if (!($rule instanceof ContentContainerUrlRuleInterface)) { return false; } return $rule->createContentContainerUrl($manager, $containerUrlPath, $route, $params); } /** * Try to create URL by simple rule * * @param UrlRule $rule * @param string $route the route. It should not have slashes at the beginning or the end. * @param array $params the parameters * @return array|false */ private function createUrlByRule($rule, string $route, array $params) { if (!($rule instanceof UrlRule)) { return false; } if ($rule->route !== $route) { return false; } if (!($ruleParts = $this->getRuleParts($rule))) { return false; } $ruleRoute = []; foreach ($ruleParts as $r => $rulePart) { if (preg_match( '/^<([a-zA-Z0-9_-]+)>$/', $rulePart, $ruleParamMatch)) { if (!isset($params[$ruleParamMatch[1]])) { return false; } $ruleRoute[] = urlencode($params[$ruleParamMatch[1]]); unset($params[$ruleParamMatch[1]]); } else { $ruleRoute[] = $rulePart; } } return [implode('/', $ruleRoute), $params]; } /** * @inheritdoc */ public function parseRequest($manager, $request) { $pathInfo = $request->getPathInfo(); if (strpos($pathInfo, $this->urlPrefix . '/') !== 0) { return false; } $parts = explode('/', $pathInfo, 3); if (!isset($parts[1])) { return false; } $contentContainer = static::getContentContainerByUrl($parts[1]); if (!$contentContainer) { return false; } if (!isset($parts[2]) || $parts[2] == '') { $parts[2] = $this->defaultRoute; } $params = $request->get(); $params['cguid'] = $contentContainer->guid; foreach ($manager->rules as $rule) { if ($result = $this->parseRequestByClass($rule, $contentContainer, $manager, $parts[2], $params)) { return $result; } if ($result = $this->parseRequestByRule($rule, $parts[2], $params)) { return $result; } } return [$parts[2], $params]; } /** * Try to parse by class rule * * @param UrlRule $rule * @param ContentContainerActiveRecord $container Content Container (Space/User) * @param UrlManager $manager the URL manager * @param string $containerUrlPath Current relative URL path to the Content Container * @param array $urlParams Additional GET params of the current request * @return array|bool the parsing result. The route and the parameters are returned as an array. */ private function parseRequestByClass($rule, ContentContainerActiveRecord $contentContainer, UrlManager $manager, string $containerUrlPath, array $urlParams) { if (!($rule instanceof ContentContainerUrlRuleInterface)) { return false; } return $rule->parseContentContainerRequest($contentContainer, $manager, $containerUrlPath, $urlParams); } /** * Try to parse by simple rule * * @param UrlRule $rule * @param string $containerUrlPath * @param array $urlParams * @return array|false */ private function parseRequestByRule($rule, string $containerUrlPath, array $urlParams) { if (!($rule instanceof UrlRule)) { return false; } if (!($ruleParts = $this->getRuleParts($rule))) { return false; } $requestParts = explode('/', $containerUrlPath); if (count($ruleParts) !== count($requestParts)) { // Skip the rule is not matched to current request return false; } $ruleParams = []; foreach ($ruleParts as $r => $rulePart) { if (preg_match( '/^<([a-zA-Z0-9_-]+)>$/', $rulePart, $ruleParamMatch)) { $ruleParams[$ruleParamMatch[1]] = $requestParts[$r]; } elseif ($rulePart !== $requestParts[$r]) { // Skip the rule if at least one part is different return false; } } return [$rule->route, array_merge($urlParams, $ruleParams)]; } /** * Gets Content Container url name by given guid * * @param string $guid * @return string|null the Content Container url part */ public static function getUrlByContentContainerGuid(string $guid): ?string { if (array_key_exists($guid, static::$containerUrlMap)) { return static::$containerUrlMap[$guid]; } $contentContainer = null; if (UrlManager::$cachedLastContainerRecord !== null && UrlManager::$cachedLastContainerRecord->guid === $guid) { if (static::isContentContainerInstance(UrlManager::$cachedLastContainerRecord)) { $contentContainer = UrlManager::$cachedLastContainerRecord; } } else { $contentContainer = static::getContentContainerByGuid($guid); } static::$containerUrlMap[$guid] = $contentContainer ? static::getUrlMapFromContentContainer($contentContainer) : null; return static::$containerUrlMap[$guid]; } /** * Get parts of rule * * @param UrlRule $rule * @return string[]|false */ private function getRuleParts($rule) { foreach ($this->routePrefixes as $routePrefix) { if (strpos($rule->name, $routePrefix . '/') === 0) { return explode('/', substr($rule->name, strlen($routePrefix . '/'))); } } return false; } }