/** * @see \Ableron\Core\Template\Plugins\Interfaces\CompilerPluginInterface::compileOpeningTag() */ public function compileOpeningTag(TemplateCompiler $templateCompiler) { // get translation $translation = Application::getI18nHandler()->getTranslator()->translate($this->getArgument('key')); // return translation return $this->getArgument('htmlEncode') ? StringUtil::encodeHtml($translation) : $translation; }
/** * Returns the absolute path for the given template file path based on the given base directory. * * In case the given template file path starts with a slash ("/"), the template file is considered * to be relative to the module directory. * Otherwise the given template file path is considered to be relative to the given base path. * * @param string $templateFilePath Path of the template file to return the absolute path for * @param string $basePath Base path used to determine the absolute path for the given template file * @return string */ public static function getAbsoluteTemplateFilePath($templateFilePath, $basePath) { // determine template directory $templateDirectory = StringUtil::startsWith($templateFilePath, '/') ? ABLERON_MODULE_DIR : FileUtil::normalizePath($basePath) . '/'; // return absolute template file path return $templateDirectory . $templateFilePath; }
/** * Tests whether writeFile() creates parent directories. * * @return void */ public function testWriteFileCreatesParentDirectories() { $filePath = ABLERON_TEMP_DIR . '/FileUtilTest/writeFile/testWriteFileCreatesParentDirectories-' . StringUtil::getRandomString(12); $this->assertTrue(FileUtil::writeFile($filePath)); $this->assertTrue(is_file($filePath)); $this->assertTrue(is_writable(dirname($filePath))); unlink($filePath); }
/** * Sets the value of the header field. * * Accepts either strings or objects of type \Ableron\Lib\Net\Uri. * * @param string|\Ableron\Lib\Net\Uri $fieldValue The field value to set * @throws \Ableron\Core\Exception\SystemException * @return void */ public function setFieldValue($fieldValue) { if (is_string($fieldValue)) { $this->fieldValue = new Uri($fieldValue); } elseif ($fieldValue instanceof Uri) { $this->fieldValue = $fieldValue; } else { throw new SystemException(sprintf('Unable to set header field value to %s - Field value must be a string or an object of type \\Ableron\\Lib\\Net\\Uri. Given: %s', StringUtil::toString($fieldValue), gettype($fieldValue)), 0, E_USER_WARNING, __FILE__, __LINE__); } }
/** * @see \Ableron\Core\Template\Plugins\Interfaces\CompilerPluginInterface::compileOpeningTag() */ public function compileOpeningTag(TemplateCompiler $templateCompiler) { // build base URL $actionUrl = new Uri(parent::compileOpeningTag($templateCompiler)); // add URL of current request as action source URL $actionUrl->addQueryParameter(ABLERON_PARAM_ACTION_SOURCE_URL, StringUtil::base64UrlEncode(Application::getRequestHandler()->getRequest()->getUri()->toString())); // add CSRF token query parameter to URL $actionUrl->addQueryParameter(ABLERON_PARAM_CSRF_TOKEN, self::$actionUrlCsrfTokenPlaceholder); // return final URL return str_replace(self::$actionUrlCsrfTokenPlaceholder, '<?php echo $application::getSecurityHandler()->getCsrfProtector()->getCurrentToken(); ?>', $actionUrl->toString()); }
/** * Initializes the entity. * * @param \Ableron\Modules\Core\Model\Entities\UserEntity $user The user belonging to the session */ public function __construct(UserEntity $user = null) { $this->id = StringUtil::getRandomString(24); $this->setCreationTime(DateUtil::getCurrentUtcDateTime()); $this->setLastActivityTime($this->getCreationTime()); $this->data = array(); // TODO if ($user !== null) { $this->setUser($user); } }
/** * Builds the log file entry for the given log message. * * TODO: Use localized time in local log files * * @param string $logLevel Log level of the message to log * @param string $message The message to log * @param \Exception|null $exception Exception belonging to the log entry * @return string */ private function buildLogEntry(string $logLevel, string $message, Exception $exception = null) { // build base log entry $logEntry = sprintf('%s %s %s', DateUtil::getCurrentUtcDateTime()->format('Y-m-d H:i:s'), StringUtil::toUpperCase($logLevel), $message); // add exception information if present if ($exception !== null) { $logEntry .= StringUtil::CHAR_LINE_FEED . sprintf('Exception: %s in file %s on line %s', $exception->getMessage(), $exception->getFile(), $exception->getLine()) . StringUtil::CHAR_LINE_FEED . ExceptionUtil::getFullTrace($exception); } // return log entry return $logEntry; }
/** * @see \Ableron\Core\Template\Plugins\Interfaces\FunctionPluginInterface::execute() */ public function execute(TemplateRenderer $templateRenderer, $tagArguments) { // read arguments $templateFile = isset($tagArguments['templateFile']) ? $tagArguments['templateFile'] : $tagArguments[0]; $variables = isset($tagArguments['variables']) ? $tagArguments['variables'] : array(); $sandboxMode = isset($tagArguments['sandboxMode']) ? $tagArguments['sandboxMode'] : false; // check for argument "templateFile" if (StringUtil::isNullOrEmpty($templateFile)) { throw new SystemException('Missing argument "templateFile" in tag {include}', 0, E_USER_ERROR, __FILE__, __LINE__); } // return output of the rendered template return $templateRenderer->getTemplateHandler()->render(TemplateHelper::getAbsoluteTemplateFilePath($templateFile, $templateRenderer->getCurrentTemplatePath()), $sandboxMode ? $variables : array_merge($templateRenderer->getCurrentVariables(), $variables), true, $templateRenderer); }
/** * @see \Ableron\Lib\Collections\Interfaces\SetInterface::add() * @throws \Ableron\Core\Exception\SystemException In case the given element does not fit the element type of this set */ public function add($element) { // check whether given element is an object if (!is_object($element)) { throw new SystemException(sprintf('Unable to add non-object to object set: %s', StringUtil::toString($element)), 0, E_USER_WARNING, __FILE__, __LINE__); } // check whether given element has the correct type if ($this->elementType !== null && !$element instanceof $this->elementType) { throw new SystemException(sprintf('Unable to add object of type %s to object set of type %s', get_class($element), $this->elementType), 0, E_USER_WARNING, __FILE__, __LINE__); } // add given element to set parent::add($element); }
/** * @see \Ableron\Lib\Stdlib\Interfaces\HeaderFieldInterface::addFieldValue() */ public function addFieldValue($fieldValue) { // get current field value $currentFieldValue = $this->fieldValue; // try to set field value try { // check whether field value is valid $this->setFieldValue($fieldValue); // combine old and new field value if ($currentFieldValue !== null) { $this->fieldValue = sprintf('%s, %s', $currentFieldValue, $this->fieldValue); } } catch (SystemException $e) { throw new SystemException(sprintf('Unable to add header field value %s', StringUtil::toString($fieldValue)), 0, E_USER_WARNING, __FILE__, __LINE__, $e); } }
/** * @see \Ableron\Core\Router\Route\RouteInterface::match() */ public function match(Uri $moduleRequestUri, HttpRequest $request) { // prepare module request URI $moduleRequestUriNormalized = $this->routeParameters['isCaseSensitive'] ? $moduleRequestUri->getPath() : StringUtil::toLowerCase($moduleRequestUri->getPath()); // handle "exactMath" if ($this->routeParameters['exactMatch'] !== null) { $exactMatchPattern = $this->routeParameters['isCaseSensitive'] ? $this->routeParameters['exactMatch'] : StringUtil::toLowerCase($this->routeParameters['exactMatch']); return $exactMatchPattern === $moduleRequestUriNormalized ? $this : null; } // handle "startsWith" if ($this->routeParameters['startsWith'] !== null) { $startsWithPattern = $this->routeParameters['isCaseSensitive'] ? $this->routeParameters['startsWith'] : StringUtil::toLowerCase($this->routeParameters['startsWith']); return StringUtil::startsWith($moduleRequestUriNormalized, $startsWithPattern) ? $this : null; } // no match return null; }
/** * Returns the name of the web server. * * Returns 'n/a' in case the web server could not be determined. * * @return string */ public static function getWebServer() { // get server information as array $serverSoftware = StringUtil::split('/', strip_tags(EnvironmentUtil::getEnvironmentVariable('SERVER_SOFTWARE')), 2); // check for web server name if (isset($serverSoftware[0])) { // try to get web server version if (isset($serverSoftware[1])) { // get web server version $webServerVersion = StringUtil::split(' ', $serverSoftware[1], 2)[0]; // append web server version to web server name if ($webServerVersion !== '') { return $serverSoftware[0] . ' ' . $webServerVersion; } } // return web server return $serverSoftware[0]; } // unable to determine web server return 'n/a'; }
/** * @see \Ableron\Core\Controller\AbstractController::run() */ protected function run() { // check for valid CSRF token before executing action if ($this->checkCsrfToken()) { try { $this->readParameters(); $this->readData(); $this->execute(); $this->onExecuteSuccessful(); } catch (ExecutionFailedException $e) { $this->onExecuteFailed(); } } else { $this->setFlashMessage(Application::getI18nHandler()->getTranslator()->translate('core.security.csrf.actionNotExecuted'), null, ControllerInterface::MESSAGE_TYPE_ERROR); } // if we are here, no redirect has been sent during execution; so redirect to action source URL if (($encodedActionSourceUrl = $this->getQueryParameter(ABLERON_PARAM_ACTION_SOURCE_URL, false)) !== false && ($actionSourceUrl = StringUtil::base64UrlDecode($encodedActionSourceUrl)) !== false) { $this->redirectTo(new Uri($actionSourceUrl)); } else { $this->redirectTo(EnvironmentUtil::getInternalUrl('/')); } }
/** * Takes care of possible CSRF attacks. * * Logs the possible attack and changes the current CSRF token. * * @return void */ private function handlePossibleCsrfAttack() { // log possible attack Application::getPersistenceManager()->getEntityManager()->persist(new CsrfAttemptEntity()); // invalidate session token by setting a new one Application::getSession()->setData($this->csrfTokensSessionKey, StringUtil::getRandomString($this->tokenLength)); }
/** * Returns the headers of the active request as an array of key-value pairs * extracted from the $_SERVER superglobal. * * @return array */ private function parseRequestHeaders() { $headers = array(); foreach ($_SERVER as $key => $value) { if (StringUtil::startsWith($key, 'HTTP_')) { $headers[str_replace(' ', '-', ucwords(str_replace('_', ' ', strtolower(substr($key, 5)))))] = $value; } } return $headers; }
/** * Returns whether the given file name ends with the file extension * configured for the storage. * * @param string $fileName The file name to check * @return bool TRUE if the given file name matches the file extension configured for the storage, FALSE otherwise */ private function hasStorageFileExtension(string $fileName) { return $this->fileExtension === '' || StringUtil::endsWith($fileName, $this->fileExtension); }
/** * 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()))); }); }
/** * Returns the file where to save the compiled version of the given source template. * * @param string $sourceTemplateFile The source template file for which to get the file of the compiled version * @throws \Ableron\Core\Exception\SystemException * @return string */ public function getCompiledTemplateFile($sourceTemplateFile) { // make sure "./" and "../" are handled correctly $sourceTemplateFile = StringUtil::contains($sourceTemplateFile, './') ? FileUtil::normalizePath(realpath($sourceTemplateFile)) : $sourceTemplateFile; // extract template information from path (module, area and template name) if (!preg_match('#/Modules/(?<module>[^/]+)(?<path>(/[^/]+)+?)/(?<name>[^/]+)\\.tpl$#', $sourceTemplateFile, $templateInfo)) { throw new SystemException(sprintf('Template file has invalid path: %s (Pattern of valid template file: .../<module>/**/<name>.tpl, e.g. **/app/Modules/Core/Pages/Backend/Templates/IndexPage.tpl)', $sourceTemplateFile), 0, E_USER_ERROR, __FILE__, __LINE__); } // build and return file name of the compiled template return FileUtil::getTempFileName(sprintf('tpl/%s/%s/%s', $templateInfo['module'], $templateInfo['path'], Application::getI18nHandler()->getLocale()->getLocaleCode()), '', $templateInfo['name'], 'php'); }
/** * 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; }
/** * Compiles the given template tags. * * Throws an exception in case there are unclosed tags remaining. * * @param array $templateTags The template tags to compile * @param array $textBlocks Text blocks outside of template-tags * @throws \Ableron\Core\Exception\SystemException * @return array */ private function compileTemplateTags($templateTags, $textBlocks) { // prepare return value and get number of template tags to compile $compiledTags = array(); $templateTagsCount = count($templateTags); // compile template tags, one by one for ($currentTagIndex = 0; $currentTagIndex < $templateTagsCount; $currentTagIndex++) { $this->currentLineNumber += StringUtil::getSubstringCount($textBlocks[$currentTagIndex], StringUtil::CHAR_LINE_FEED); $compiledTags[] = $this->compileTemplateTag($templateTags[$currentTagIndex]); $this->currentLineNumber += StringUtil::getSubstringCount($templateTags[$currentTagIndex], StringUtil::CHAR_LINE_FEED); } // check for unclosed tags if (!$this->compilerPluginTagStack->isEmpty()) { throw new SystemException(sprintf('Unclosed tag {%s} in template "%s" on line %s', $this->getLastCompilerPluginTagParameter('tagName'), $this->getCurrentTemplateName(), $this->getLastCompilerPluginTagParameter('lineNumber')), 0, E_USER_ERROR, __FILE__, __LINE__); } // return compiled tags return $compiledTags; }
/** * 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; }
/** * @see \Ableron\Lib\Collections\Abstracts\AbstractMap::__construct() */ public function __construct(array $elements = array()) { parent::__construct(function ($key) { return StringUtil::toLowerCase($key); }, null, $elements); }
/** * Converts the given argument value to its real PHP value. * * Takes care of boolean TRUE/FALSE and NULL. * * @param string $argumentValue The argument value to convert * @return mixed */ private function argumentValueToPhpValue($argumentValue) { // handle boolean TRUE if (StringUtil::equalsIgnoreCase($argumentValue, 'true')) { return true; } // handle boolean FALSE if (StringUtil::equalsIgnoreCase($argumentValue, 'false')) { return false; } // handle NULL if (StringUtil::equalsIgnoreCase($argumentValue, 'null')) { return null; } // return argument value without any changes return $argumentValue; }
/** * Returns a string representation of the given stack trace. * * @param array $trace The stack trace to format * @return string */ public static function getTraceAsString(array $trace) { $currentTracePosition = count($trace); $formattedTrace = array(); foreach ($trace as $tracePoint) { $formattedTrace[] = sprintf('#%d %s: %s%s(%s)', $currentTracePosition--, isset($tracePoint['file']) ? sprintf('%s(%d)', FileUtil::getRelativeAbleronPath($tracePoint['file']), $tracePoint['line']) : '[internal function]', isset($tracePoint['class']) ? $tracePoint['class'] . $tracePoint['type'] : '', $tracePoint['function'], !empty($tracePoint['args']) ? StringUtil::buildPhpArgumentString($tracePoint['args']) : ''); } return implode(StringUtil::CHAR_LINE_FEED, $formattedTrace); }
/** * Returns the absolute path of a temporary file. * * @param string $subDirectory Sub directory of the temp directory the file shall be located in * @param string $filePrefix Prefix of the temp file * @param string $fileName Name of the temp file * @param string $fileExtension File extension of the temp file * @return string */ public static function getTempFileName(string $subDirectory = '', string $filePrefix = '', string $fileName = '', string $fileExtension = 'tmp') { // get temp directory $tempDirectory = self::normalizePath(ABLERON_TEMP_DIR . '/' . $subDirectory); // get temp file name $tempFileName = sprintf('%s%s%s', $filePrefix, $fileName === '' ? StringUtil::getRandomString(32) : $fileName, ltrim($fileExtension, '.') === '' ? '' : '.' . ltrim($fileExtension, '.')); // return absolute path return sprintf('%s/%s', $tempDirectory, $tempFileName); }
/** * 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; }
/** * Validates the given last name. * * @param string $lastName The last name to validate * @throws \Ableron\Install\Exception\InputException * @return void */ private function validateLastName($lastName) { // check whether last name is set if ($lastName === '') { throw new InputException(null, 'stepCreateAdminAccount.adminLastName.error.empty', array('#adminLastName')); } // check maximum length if (StringUtil::getLength($lastName) > 255) { throw new InputException(null, 'stepCreateAdminAccount.adminLastName.error.maxLengthExceeded', array('#adminLastName')); } }
/** * @see \Ableron\Core\Controller\Page\PageInterface::assignVariables() */ public function assignVariables() { parent::assignVariables(); Application::getTemplateHandler()->getVariables()->setAll(array('documentTitle' => Application::getI18nHandler()->getTranslator()->translate('sysInfo.systemInfo.title'), 'ableronCoreVersion' => Application::getVersion(), 'ableronInstallationTime' => StringUtil::formatDateTime(Application::getInstallationTime()), 'databaseManagementSystem' => SystemInformation::getDatabaseManagementSystem(), 'operatingSystem' => SystemInformation::getOperatingSystem(), 'phpVersion' => SystemInformation::getPhpVersion(), 'phpServerApi' => SystemInformation::getPhpServerApi(), 'webServer' => SystemInformation::getWebServer(), 'zendEngineVersion' => SystemInformation::getZendEngineVersion())); }
/** * @see \Ableron\Core\Form\FormInterface::getOpenTag() */ public function getOpenTag() { // get form attributes $formAttributes = $this->attributes->toArray(); // if name is set but and id is not, treat element name as id if (!$this->attributes->containsKey('id') && $this->attributes->containsKey(self::ATTR_NAME)) { $formAttributes['id'] = $this->attributes->get([self::ATTR_NAME]); } // declare attribute strings $attributeStrings = array(); // build attribute string foreach ($formAttributes as $formAttributeName => $formAttributeValue) { // make key lower case $formAttributeName = StringUtil::toLowerCase($formAttributeName); // skip boolean attributes which values are "false" (false = default) if ($formAttributeValue === false) { continue; } // compose attribute $attributeStrings[] = sprintf('%s="%s"', StringUtil::encodeHtml($formAttributeName), StringUtil::encodeHtml($formAttributeValue)); } // build final HTML tag return sprintf('<form %s>', implode(' ', $attributeStrings)); }
/** * Sets up this object by parsing the given string representation of a URI. * * Throws an exception in case the given string could not be parsed correctly. * * @param string $uri The URI to parse * @throws \Ableron\Core\Exception\SystemException * @return void */ private function parseUri($uri) { if (($uriComponents = parse_url(StringUtil::startsWith($uri, '//') ? 'http:' . $uri : $uri)) !== false) { // set scheme if (isset($uriComponents['scheme']) && !StringUtil::startsWith($uri, '//')) { $this->setScheme($uriComponents['scheme']); } // set user info $isUsernameSet = isset($uriComponents['user']) && $uriComponents['user'] !== ''; $isPasswordSet = isset($uriComponents['pass']) && $uriComponents['pass'] !== ''; if ($isUsernameSet || $isPasswordSet) { $this->setUserInfo(($isUsernameSet ? $uriComponents['user'] : '') . ($isPasswordSet ? ':' . $uriComponents['pass'] : '')); } // set host if (isset($uriComponents['host'])) { $this->setHost($uriComponents['host']); } // set port if (isset($uriComponents['port'])) { $this->setPort($uriComponents['port']); } // set path if (isset($uriComponents['path'])) { $this->setPath($uriComponents['path']); } // set fragment if (isset($uriComponents['fragment'])) { $this->setFragment($uriComponents['fragment']); } elseif (StringUtil::endsWith($uri, '#')) { $this->setFragment('', true); } // set query (it is necessary to set the query after the fragment as we need the fragment part here) if (isset($uriComponents['query'])) { $this->setQuery($uriComponents['query']); } elseif (StringUtil::endsWith($uri, '?' . ($this->fragment !== null ? '#' . $this->fragment : ''))) { $this->setQuery('', true); } } else { throw new SystemException(sprintf('Unable to parse URI: %s', $uri), 0, E_USER_NOTICE, __FILE__, __LINE__); } }