%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;
}
}