/** * Cuts off the path to the Ableron root directory in case the given path * is an Ableron path. * * Additionally normalizes the given path. * * @param string $path The path to get relative representation for * @return string */ public static function getRelativeAbleronPath(string $path) { // normalize path $path = self::normalizePath($path); // check whether we have an Ableron path if (StringUtil::startsWith($path, ABLERON_ROOT_DIR . '/')) { return StringUtil::getSubstring($path, StringUtil::getLength(ABLERON_ROOT_DIR)); } // given path is not an Ableron path so simply return given path return $path; }
/** * Initializes the request handler. */ public function __construct() { // set request object $this->setRequest(new HttpRequest($this->getRequestUri(), EnvironmentUtil::getEnvironmentVariable('REQUEST_METHOD'), $this->getRequestHttpVersion(), $this->getRequestHeaders(), $_GET, $_POST, $this->getRequestCookies())); // get the URLs we need $frontendBaseUrl = new Uri(rtrim(rtrim(EnvironmentUtil::getSiteUrl()->toString(), '/') . Application::getConfig()->get('frontend.basePath'), '/')); $backendBaseUrl = new Uri(rtrim(rtrim(EnvironmentUtil::getSiteUrl()->toString(), '/') . Application::getConfig()->get('backend.basePath'), '/')); $requestPath = $this->getRequest()->getUri()->getPath(); // set whether we have a frontend request $this->isFrontendRequest = $this->checkIsFrontendRequest($frontendBaseUrl, $backendBaseUrl, $this->getRequest()->getUri()->getHost(), $requestPath); // determine module base path $this->moduleBasePath = '/' . explode('/', trim(StringUtil::getSubstring($requestPath, StringUtil::getLength($this->isFrontendRequest ? $frontendBaseUrl->getPath() : $backendBaseUrl->getPath())), '/'), 2)[0]; // get requested module $this->requestedModule = Application::getModuleManager()->findModuleByBasePath($this->moduleBasePath, $this->isFrontendRequest); // make sure module base path points to an existing module if ($this->requestedModule === null || !$this->requestedModule->isActive()) { $this->moduleBasePath = '/'; $this->requestedModule = Application::getModuleManager()->findModuleByBasePath($this->moduleBasePath, $this->isFrontendRequest); } // set module request URI $this->setModuleRequestUri(new Uri('/' . ltrim(StringUtil::getSubstring($requestPath, StringUtil::getLength($this->isFrontendRequest ? $frontendBaseUrl->getPath() : $backendBaseUrl->getPath()) + StringUtil::getLength($this->moduleBasePath)), '/'))); $this->getModuleRequestUri()->setQuery($this->getRequest()->getUri()->getQuery()); }
/** * Returns the site path. * * Site path is the path from the document root to the script root directory. * * @return string */ public static function getSitePath() { return CacheUtil::getFromCache(self::getCache(), __FUNCTION__, function () { return ABLERON_ROOT_DIR === self::getDocumentRoot() ? '/' : StringUtil::getSubstring(ABLERON_ROOT_DIR, -(StringUtil::getLength(ABLERON_ROOT_DIR) - StringUtil::getLength(self::getDocumentRoot()))); }); }
/** * Parses the given parameter string. * * This method does not take care of comments. Comments have to be stripped * before calling this method using self::stripComments(). * * Returns an array containing the parameters as key-value pairs. * * @param string $parameterString The parameter string to parse * @throws \Ableron\Core\Exception\SystemException * @return array */ private static function parseParameterString($parameterString) { // prepare required variables $returnValue = array(); $currentParameter = array('name' => '', 'value' => ''); // name/value of the current parameter $isParameterName = true; // indicates whether the current character belongs to the parameter name $isEscaped = false; // indicates whether the current character is escaped $inQuotes = false; // indicates whether the current character is located within a quoted string // process the given string, character by character for ($i = 0, $parameterStringLength = StringUtil::getLength($parameterString); $i < $parameterStringLength; $i++) { // get current character $currentCharacter = StringUtil::getSubstring($parameterString, $i, 1); // check if current character is escaped if ($isEscaped) { // add character to return value $currentParameter[$isParameterName ? 'name' : 'value'] .= '\\' . $currentCharacter; // next character is not escaped $isEscaped = false; // check if we have a backslash escaping the next character } elseif ($currentCharacter == '\\') { $isEscaped = true; // check if current character starts/ends a quoted string } elseif ($currentCharacter == '"') { // add character to return value $currentParameter[$isParameterName ? 'name' : 'value'] .= $currentCharacter; $inQuotes = !$inQuotes; // check whether we have the parameter value now } elseif ($currentCharacter == '=' && $isParameterName) { $isParameterName = false; // check if we have a new parameter } elseif ($currentCharacter == ';' && !$inQuotes && !$isParameterName) { // add current parameter to the parameter list $returnValue[$currentParameter['name']] = $currentParameter['value']; // reset name/value for the next parameter $currentParameter = array('name' => '', 'value' => ''); $isParameterName = true; // not a special character. simply add to the return value } else { $currentParameter[$isParameterName ? 'name' : 'value'] .= $currentCharacter; } } // check for valid syntax if ($inQuotes) { throw new SystemException(sprintf('Unable to parse parameter string "%s" - String contains invalid quotation mark!', $parameterString), 0, E_USER_NOTICE, __FILE__, __LINE__); } // add last processed parameter to return value if (!empty($currentParameter['name'])) { $returnValue[$currentParameter['name']] = $currentParameter['value']; } // return parameters return $returnValue; }
/** * Removes dot segments (/./, /../) from the given path. * * @param string $path The path to remove the dot-segments from * @return string */ public static function removeDotSegments($path) { // check whether path may contain dot segments if (!preg_match('#(^\\.\\.?$|/\\.|\\./)#', $path)) { return $path; } $pathParts = array(); $removeLastSegment = false; while ($path !== '') { switch (true) { case $path === '.' || $path === '..': break 2; case $path === '/.': $path = '/'; break; case $path === '/..': $path = '/'; $removeLastSegment = true; break; case StringUtil::startsWith($path, '/../'): $path = StringUtil::getSubstring($path, 3); $removeLastSegment = true; break; case StringUtil::startsWith($path, './') || StringUtil::startsWith($path, '/./'): $path = StringUtil::getSubstring($path, 2); break; case StringUtil::startsWith($path, '../'): $path = StringUtil::getSubstring($path, 3); break; default: $isLastSegment = ($nextSegmentStart = StringUtil::getFirstIndexOf($path, '/', 1)) === -1; $currentSegment = $isLastSegment ? $path : StringUtil::getSubstring($path, 0, $nextSegmentStart); array_push($pathParts, $currentSegment); $path = $isLastSegment ? '' : StringUtil::getSubstring($path, StringUtil::getLength($currentSegment)); } if ($removeLastSegment) { $removeLastSegment = false; if (!empty($pathParts)) { array_pop($pathParts); } } } return implode('', $pathParts); }
/** * Initializes this template tag using the given template tag string. * * Throws an exception in case the given string is not a valid template tag string. * * @param string $templateTagString The template tag string to parse * @throws \Ableron\Core\Exception\SystemException * @return void */ private function initFromTemplateTagString($templateTagString) { // extract information from given template tag if (!preg_match('#^(?<tagDeclaration>/?\\w+)(\\s+(?<argumentString>.*))?$#s', $templateTagString, $tagParts)) { throw new SystemException(sprintf('Unable to init TemplateTag from string "%s" - Given string is not a valid template tag string!', $templateTagString), 0, E_USER_ERROR, __FILE__, __LINE__); } $this->fullTag = $templateTagString; $this->isClosingTag = StringUtil::startsWith($tagParts['tagDeclaration'], '/'); $this->tagName = $this->isClosingTag ? StringUtil::getSubstring($tagParts['tagDeclaration'], 1) : $tagParts['tagDeclaration']; $this->argumentString = isset($tagParts['argumentString']) ? $tagParts['argumentString'] : null; $this->arguments = $this->parseArgumentString($this->argumentString); }
/** * Removes the given enclosing characters from the start and the end of the given input string * in case the string is enclosed by the given characters. * * E.g. removeEnclosingCharacter('{{foo}}', '{{', '}}') will return 'foo'; * * Returns the input string without any modification in case the given input string * is not enclosed by the given characters. * * @param string $inputString The input string to remove the enclosing characters from * @param string $enclosingStartCharactersToRemove The start characters to remove from the start of the string if string is enclosed by the given characters * @param string $enclosingEndCharactersToRemove The end characters to remove from the end of the string if string is enclosed by the given characters * @return string */ public static function removeEnclosingCharacters(string $inputString, string $enclosingStartCharactersToRemove, string $enclosingEndCharactersToRemove) { // return input string with removed given enclosing characters if (StringUtil::startsWith($inputString, $enclosingStartCharactersToRemove) && StringUtil::endsWith($inputString, $enclosingEndCharactersToRemove)) { return StringUtil::getSubstring($inputString, self::getLength($enclosingStartCharactersToRemove), -self::getLength($enclosingEndCharactersToRemove)); } // return unmodified input string if not enclosed by the given characters return $inputString; }
/** * Extracts all blocks from the given template and returns them. * * @param string $template The template to extract the blocks from * @return array */ private function extractBlocks($template) { // init required variables $blocks = array(); $insideFirstLevelBlock = false; $firstLevelBlockTag = null; $firstLevelBlockContentStartIndex = 0; // parse given template for ($i = 0, $templateLength = StringUtil::getLength($template); $i < $templateLength; $i++) { // check whether current character is the left tag delimiter if (StringUtil::getSubstring($template, $i, 1) == '{') { // get remaining template $remainingTemplate = StringUtil::getSubstring($template, $i); // check whether very first element in the remaining template is an opening or closing block tag $isOpeningBlockTag = preg_match('#^{(block\\s[^}]+)}#', $remainingTemplate, $openingBlockTagMatch); $isClosingBlockTag = StringUtil::startsWith($remainingTemplate, '{/block}'); if ($isOpeningBlockTag && !$insideFirstLevelBlock) { $insideFirstLevelBlock = true; $firstLevelBlockTag = new TemplateTag($openingBlockTagMatch[1]); $firstLevelBlockContentStartIndex = $i + StringUtil::getLength($openingBlockTagMatch[0]); $blocks[$this->getBlockName($firstLevelBlockTag)]['childBlocks'] = array(); } elseif ($isOpeningBlockTag && $insideFirstLevelBlock) { preg_match('#^{(block\\s[^}]+)}(.*?){/block}#s', $remainingTemplate, $blockMatch); $i += StringUtil::getLength($blockMatch[0]) - 1; $secondLevelBlockTag = new TemplateTag($blockMatch[1]); $blocks[$this->getBlockName($firstLevelBlockTag)]['childBlocks'][$this->getBlockName($secondLevelBlockTag)] = array('blockTag' => $secondLevelBlockTag, 'blockContent' => trim($blockMatch[2])); } elseif ($isClosingBlockTag && $insideFirstLevelBlock) { $insideFirstLevelBlock = false; $blocks[$this->getBlockName($firstLevelBlockTag)]['blockTag'] = $firstLevelBlockTag; $blocks[$this->getBlockName($firstLevelBlockTag)]['blockContent'] = trim(StringUtil::getSubstring($template, $firstLevelBlockContentStartIndex, $i - $firstLevelBlockContentStartIndex)); } } } // return extracted blocks return $blocks; }