示例#1
0
 /**
  * @param array|NULL $backendUser
  * @param int $size
  * @param bool $showIcon
  * @return string
  */
 public function render(array $backendUser = NULL, $size = 32, $showIcon = FALSE)
 {
     $size = (int) $size;
     if (!is_array($backendUser)) {
         $backendUser = $this->getBackendUser()->user;
     }
     $image = parent::render($backendUser, $size, $showIcon);
     if (!StringUtility::beginsWith($image, '<span class="avatar"><span class="avatar-image"></span>') || empty($backendUser['email'])) {
         return $image;
     }
     $cachedFilePath = PATH_site . 'typo3temp/t3gravatar/';
     $cachedFileName = sha1($backendUser['email'] . $size) . '.jpg';
     if (!file_exists($cachedFilePath . $cachedFileName)) {
         $gravatar = 'https://www.gravatar.com/avatar/' . md5(strtolower($backendUser['email'])) . '?s=' . $size . '&d=404';
         $gravatarImage = GeneralUtility::getUrl($gravatar);
         if (empty($gravatarImage)) {
             return $image;
         }
         GeneralUtility::writeFileToTypo3tempDir($cachedFileName, $gravatarImage);
     }
     // Icon
     $icon = '';
     if ($showIcon) {
         $icon = '<span class="avatar-icon">' . IconUtility::getSpriteIconForRecord('be_users', $backendUser) . '</span>';
     }
     $relativeFilePath = PathUtility::getRelativePath(PATH_typo3, $cachedFilePath);
     return '<span class="avatar"><span class="avatar-image">' . '<img src="' . $relativeFilePath . $cachedFileName . '" width="' . $size . '" height="' . $size . '" /></span>' . $icon . '</span>';
 }
示例#2
0
 /**
  * Unset all additional properties of test classes to help PHP
  * garbage collection. This reduces memory footprint with lots
  * of tests.
  *
  * If owerwriting tearDown() in test classes, please call
  * parent::tearDown() at the end. Unsetting of own properties
  * is not needed this way.
  *
  * @throws \RuntimeException
  * @return void
  */
 protected function tearDown()
 {
     // Unset properties of test classes to safe memory
     $reflection = new \ReflectionObject($this);
     foreach ($reflection->getProperties() as $property) {
         $declaringClass = $property->getDeclaringClass()->getName();
         if (!$property->isStatic() && $declaringClass !== \TYPO3\CMS\Core\Tests\UnitTestCase::class && $declaringClass !== \TYPO3\CMS\Core\Tests\BaseTestCase::class && strpos($property->getDeclaringClass()->getName(), 'PHPUnit_') !== 0) {
             $propertyName = $property->getName();
             unset($this->{$propertyName});
         }
     }
     unset($reflection);
     // Delete registered test files and directories
     foreach ($this->testFilesToDelete as $absoluteFileName) {
         $absoluteFileName = GeneralUtility::fixWindowsFilePath(PathUtility::getCanonicalPath($absoluteFileName));
         if (!GeneralUtility::validPathStr($absoluteFileName)) {
             throw new \RuntimeException('tearDown() cleanup: Filename contains illegal characters', 1410633087);
         }
         if (!StringUtility::beginsWith($absoluteFileName, PATH_site . 'typo3temp/')) {
             throw new \RuntimeException('tearDown() cleanup:  Files to delete must be within typo3temp/', 1410633412);
         }
         // file_exists returns false for links pointing to not existing targets, so handle links before next check.
         if (@is_link($absoluteFileName) || @is_file($absoluteFileName)) {
             unlink($absoluteFileName);
         } elseif (@is_dir($absoluteFileName)) {
             GeneralUtility::rmdir($absoluteFileName, true);
         } else {
             throw new \RuntimeException('tearDown() cleanup: File, link or directory does not exist', 1410633510);
         }
     }
     $this->testFilesToDelete = array();
 }
 /**
  * Resolve placeholders for input/text fields. Placeholders that are simple
  * strings will be returned unmodified. Placeholders beginning with __row are
  * being resolved, possibly traversing multiple tables.
  *
  * @param array $result
  * @return array
  */
 public function addData(array $result)
 {
     foreach ($result['processedTca']['columns'] as $fieldName => $fieldConfig) {
         // Placeholders are only valid for input and text type fields
         if ($fieldConfig['config']['type'] !== 'input' && $fieldConfig['config']['type'] !== 'text' || !isset($fieldConfig['config']['placeholder'])) {
             continue;
         }
         // Resolve __row|field type placeholders
         if (StringUtility::beginsWith($fieldConfig['config']['placeholder'], '__row|')) {
             // split field names into array and remove the __row indicator
             $fieldNameArray = array_slice(GeneralUtility::trimExplode('|', $fieldConfig['config']['placeholder'], true), 1);
             $result['processedTca']['columns'][$fieldName]['config']['placeholder'] = $this->getPlaceholderValue($fieldNameArray, $result);
         }
         // Resolve placeholders from language files
         if (StringUtility::beginsWith($fieldConfig['config']['placeholder'], 'LLL:')) {
             $result['processedTca']['columns'][$fieldName]['config']['placeholder'] = $this->getLanguageService()->sl($fieldConfig['config']['placeholder']);
         }
         // Remove empty placeholders
         if (empty($fieldConfig['config']['placeholder'])) {
             unset($result['processedTca']['columns'][$fieldName]['config']['placeholder']);
             continue;
         }
     }
     return $result;
 }
 /**
  * Type fetching method, based on the type that softRefParserObj returns
  *
  * @param array $value Reference properties
  * @param string $type Current type
  * @param string $key Validator hook name
  * @return string fetched type
  */
 public function fetchType($value, $type, $key)
 {
     if (StringUtility::beginsWith(strtolower($value['tokenValue']), 'file:')) {
         $type = 'file';
     }
     return $type;
 }
示例#5
0
 /**
  * @param Icon $icon
  * @param array $options
  * @return string
  * @throws \InvalidArgumentException
  */
 protected function generateInlineMarkup(Icon $icon, array $options)
 {
     if (empty($options['source'])) {
         throw new \InvalidArgumentException('The option "source" is required and must not be empty', 1440754980);
     }
     $source = $options['source'];
     if (StringUtility::beginsWith($source, 'EXT:') || !StringUtility::beginsWith($source, '/')) {
         $source = GeneralUtility::getFileAbsFileName($source);
     }
     return $this->getInlineSvg($source);
 }
 /**
  * @param Icon $icon
  * @param array $options
  * @return string
  * @throws \InvalidArgumentException
  */
 protected function generateMarkup(Icon $icon, array $options)
 {
     if (empty($options['source'])) {
         throw new \InvalidArgumentException('[' . $icon->getIdentifier() . '] The option "source" is required and must not be empty', 1440754980);
     }
     $source = $options['source'];
     if (StringUtility::beginsWith($source, 'EXT:') || !StringUtility::beginsWith($source, '/')) {
         $source = GeneralUtility::getFileAbsFileName($source);
     }
     $source = PathUtility::getAbsoluteWebPath($source);
     return '<img src="' . htmlspecialchars($source) . '" width="' . $icon->getDimension()->getWidth() . '" height="' . $icon->getDimension()->getHeight() . '" />';
 }
 /**
  * Return the default value of a field formatted to match the native MySQL SQL dialect
  *
  * @param array $fieldDefinition
  * @return mixed
  */
 protected function getNativeDefaultValue($fieldDefinition)
 {
     if (!$fieldDefinition['has_default']) {
         $returnValue = null;
     } elseif ($fieldDefinition['type'] === 'SERIAL' && substr($fieldDefinition['default_value'], 0, 7) === 'nextval') {
         $returnValue = null;
     } elseif ($fieldDefinition['type'] === 'varchar') {
         // Strip character class and unquote string
         if (StringUtility::beginsWith($fieldDefinition['default_value'], 'NULL::')) {
             $returnValue = null;
         } else {
             $returnValue = str_replace("\\'", "'", preg_replace('/\'(.*)\'(::(?:character\\svarying|varchar|character|char|text)(?:\\(\\d+\\))?)?\\z/', '\\1', $fieldDefinition['default_value']));
         }
     } elseif (substr($fieldDefinition['type'], 0, 3) === 'int') {
         $returnValue = (int) preg_replace('/^\\(?(\\-?\\d+)\\)?$/', '\\1', $fieldDefinition['default_value']);
     } else {
         $returnValue = $fieldDefinition['default_value'];
     }
     return $returnValue;
 }
 /**
  * @param array $data
  * @return array
  */
 protected function decryptDataArray(array $data)
 {
     foreach ($data as $key => $value) {
         if (empty($value)) {
             continue;
         }
         if (is_array($value)) {
             $data[$key] = $this->decryptDataArray($value);
             continue;
         }
         if (!StringUtility::beginsWith($value, 'rsa:')) {
             continue;
         }
         $decryptedValue = $this->getBackend()->decrypt($this->getKey(), substr($value, 4));
         if ($decryptedValue !== null) {
             $data[$key] = $decryptedValue;
         }
     }
     return $data;
 }
 /**
  * Determine which fields are required to render the placeholders and
  * add those to the list of columns that must be processed by the next
  * data providers.
  *
  * @param array $result
  * @return array
  */
 public function addData(array $result)
 {
     foreach ($result['processedTca']['columns'] as $fieldName => $fieldConfig) {
         // Placeholders are only valid for input and text type fields
         if ($fieldConfig['config']['type'] !== 'input' && $fieldConfig['config']['type'] !== 'text' || !isset($fieldConfig['config']['placeholder'])) {
             continue;
         }
         // Process __row|field type placeholders
         if (StringUtility::beginsWith($fieldConfig['config']['placeholder'], '__row|')) {
             // split field names into array and remove the __row indicator
             $fieldNameArray = array_slice(GeneralUtility::trimExplode('|', $fieldConfig['config']['placeholder'], true), 1);
             // only the first field is required to be processed as it's the one referring to
             // the current record. All other columns will be resolved in a later pass through
             // the related records.
             if (!empty($fieldNameArray[0])) {
                 $result['columnsToProcess'][] = $fieldNameArray[0];
             }
         }
     }
     return $result;
 }
示例#10
0
 /**
  * Generates the JumpURL for the given parameters.
  *
  * @see \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer::processUrlModifiers()
  * @param string $context The context in which the URL is generated (e.g. "typolink").
  * @param string $url The URL that should be processed.
  * @param array $configuration The link configuration.
  * @param \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer $contentObjectRenderer The calling content object renderer.
  * @param bool $keepProcessing If this is set to FALSE no further hooks will be processed after the current one.
  * @return string
  */
 public function process($context, $url, array $configuration, ContentObjectRenderer $contentObjectRenderer, &$keepProcessing)
 {
     if (!$this->isEnabled($context, $configuration)) {
         return $url;
     }
     $this->contentObjectRenderer = $contentObjectRenderer;
     // Strip the absRefPrefix from the URLs.
     $urlPrefix = (string) $this->getTypoScriptFrontendController()->absRefPrefix;
     if ($urlPrefix !== '' && StringUtility::beginsWith($url, $urlPrefix)) {
         $url = substr($url, strlen($urlPrefix));
     }
     // Make sure the slashes in the file URL are not encoded.
     if ($context === UrlProcessorInterface::CONTEXT_FILE) {
         $url = str_replace('%2F', '/', rawurlencode(rawurldecode($url)));
     }
     $url = $this->build($url, isset($configuration['jumpurl.']) ? $configuration['jumpurl.'] : array());
     // Now add the prefix again if it was not added by a typolink call already.
     if ($urlPrefix !== '' && !StringUtility::beginsWith($url, $urlPrefix)) {
         $url = $urlPrefix . $url;
     }
     return $url;
 }
 /**
  * @param string $status
  * @param string $table
  * @param int $id
  * @param array $fieldArray
  * @param DataHandler $parentObject
  */
 public function processDatamap_afterDatabaseOperations($status, $table, $id, $fieldArray, $parentObject)
 {
     if ($table !== 'be_groups' || $GLOBALS['TYPO3_CONF_VARS']['BE']['explicitADmode'] !== 'explicitAllow') {
         return;
     }
     $backendUserGroup = BackendUtility::getRecord($table, $id, 'explicit_allowdeny');
     $explicitAllowDenyFields = GeneralUtility::trimExplode(',', $backendUserGroup['explicit_allowdeny']);
     foreach ($explicitAllowDenyFields as $value) {
         if (StringUtility::beginsWith($value, 'tt_content:list_type:')) {
             if (!in_array('tt_content:CType:list:ALLOW', $explicitAllowDenyFields, true)) {
                 /** @var $flashMessage FlashMessage */
                 $flashMessage = GeneralUtility::makeInstance(FlashMessage::class, $this->getLanguageService()->sl('LLL:EXT:lang/locallang_core.xlf:error.backendUserGroupListTypeError.message'), $this->getLanguageService()->sl('LLL:EXT:lang/locallang_core.xlf:error.backendUserGroupListTypeError.header'), FlashMessage::WARNING, true);
                 /** @var $flashMessageService FlashMessageService */
                 $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class);
                 /** @var $defaultFlashMessageQueue FlashMessageQueue */
                 $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
                 $defaultFlashMessageQueue->enqueue($flashMessage);
             }
             return;
         }
     }
 }
 /**
  * Checks if this is the handler for the given link
  *
  * The handler may store this information locally for later usage.
  *
  * @param array $linkParts Link parts as returned from TypoLinkCodecService
  *
  * @return bool
  */
 public function canHandleLink(array $linkParts)
 {
     if (!$linkParts['url']) {
         return false;
     }
     $url = rawurldecode($linkParts['url']);
     if (StringUtility::beginsWith($url, 'file:') && !StringUtility::beginsWith($url, 'file://')) {
         $rel = substr($url, 5);
         try {
             // resolve FAL-api "file:UID-of-sys_file-record" and "file:combined-identifier"
             $fileOrFolderObject = ResourceFactory::getInstance()->retrieveFileOrFolderObject($rel);
             if (is_a($fileOrFolderObject, $this->expectedClass)) {
                 $this->linkParts = $linkParts;
                 $this->linkParts['url'] = $rel;
                 $this->linkParts['name'] = $fileOrFolderObject->getName();
                 return true;
             }
         } catch (FileDoesNotExistException $e) {
         }
     }
     return false;
 }
 /**
  * Determines whether the URL is on the current host and belongs to the
  * current TYPO3 installation. The scheme part is ignored in the comparison.
  *
  * @param string $url URL to be checked
  * @return bool Whether the URL belongs to the current TYPO3 installation
  */
 protected function isInCurrentDomain($url)
 {
     $urlWithoutSchema = preg_replace('#^https?://#', '', $url);
     $siteUrlWithoutSchema = preg_replace('#^https?://#', '', GeneralUtility::getIndpEnv('TYPO3_SITE_URL'));
     return StringUtility::beginsWith($urlWithoutSchema . '/', GeneralUtility::getIndpEnv('HTTP_HOST') . '/') && StringUtility::beginsWith($urlWithoutSchema, $siteUrlWithoutSchema);
 }
示例#14
0
 /**
  * called from the typoLink() function
  *
  * does the magic to split the full "typolink" string like "15,13 _blank myclass &more=1"
  * into separate parts
  *
  * @param string $linkText The string (text) to link
  * @param string $mixedLinkParameter destination data like "15,13 _blank myclass &more=1" used to create the link
  * @param array $configuration TypoScript configuration
  * @return array | string
  * @see typoLink()
  */
 protected function resolveMixedLinkParameter($linkText, $mixedLinkParameter, &$configuration = array())
 {
     $linkParameter = null;
     // Link parameter value = first part
     $linkParameterParts = GeneralUtility::makeInstance(TypoLinkCodecService::class)->decode($mixedLinkParameter);
     // Check for link-handler keyword:
     list($linkHandlerKeyword, $linkHandlerValue) = explode(':', $linkParameterParts['url'], 2);
     if ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['typolinkLinkHandler'][$linkHandlerKeyword] && (string) $linkHandlerValue !== '') {
         $linkHandlerObj = GeneralUtility::getUserObj($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['typolinkLinkHandler'][$linkHandlerKeyword]);
         if (method_exists($linkHandlerObj, 'main')) {
             return $linkHandlerObj->main($linkText, $configuration, $linkHandlerKeyword, $linkHandlerValue, $mixedLinkParameter, $this);
         }
     }
     // Resolve FAL-api "file:UID-of-sys_file-record" and "file:combined-identifier"
     if ($linkHandlerKeyword === 'file' && !StringUtility::beginsWith($linkParameterParts['url'], 'file://')) {
         try {
             $fileOrFolderObject = $this->getResourceFactory()->retrieveFileOrFolderObject($linkHandlerValue);
             // Link to a folder or file
             if ($fileOrFolderObject instanceof File || $fileOrFolderObject instanceof Folder) {
                 $linkParameter = $fileOrFolderObject->getPublicUrl();
             } else {
                 $linkParameter = null;
             }
         } catch (\RuntimeException $e) {
             // Element wasn't found
             $linkParameter = null;
         } catch (ResourceDoesNotExistException $e) {
             // Resource was not found
             return $linkText;
         }
         // Disallow direct javascript: links
     } elseif (strtolower(trim($linkHandlerKeyword)) === 'javascript') {
         return $linkText;
     } else {
         $linkParameter = $linkParameterParts['url'];
     }
     // additional parameters that need to be set
     if ($linkParameterParts['additionalParams'] !== '') {
         $forceParams = $linkParameterParts['additionalParams'];
         // params value
         $configuration['additionalParams'] .= $forceParams[0] === '&' ? $forceParams : '&' . $forceParams;
     }
     return array('href' => $linkParameter, 'target' => $linkParameterParts['target'], 'class' => $linkParameterParts['class'], 'title' => $linkParameterParts['title']);
 }
 /**
  * Detects if a control button (up/down/around/delete) has been pressed for an item and accordingly it will
  * manipulate the internal TABLECFG array
  *
  * @return void
  * @internal
  */
 public function changeFunc()
 {
     if ($this->TABLECFG['col_remove']) {
         $kk = key($this->TABLECFG['col_remove']);
         $cmd = 'col_remove';
     } elseif ($this->TABLECFG['col_add']) {
         $kk = key($this->TABLECFG['col_add']);
         $cmd = 'col_add';
     } elseif ($this->TABLECFG['col_start']) {
         $kk = key($this->TABLECFG['col_start']);
         $cmd = 'col_start';
     } elseif ($this->TABLECFG['col_end']) {
         $kk = key($this->TABLECFG['col_end']);
         $cmd = 'col_end';
     } elseif ($this->TABLECFG['col_left']) {
         $kk = key($this->TABLECFG['col_left']);
         $cmd = 'col_left';
     } elseif ($this->TABLECFG['col_right']) {
         $kk = key($this->TABLECFG['col_right']);
         $cmd = 'col_right';
     } elseif ($this->TABLECFG['row_remove']) {
         $kk = key($this->TABLECFG['row_remove']);
         $cmd = 'row_remove';
     } elseif ($this->TABLECFG['row_add']) {
         $kk = key($this->TABLECFG['row_add']);
         $cmd = 'row_add';
     } elseif ($this->TABLECFG['row_top']) {
         $kk = key($this->TABLECFG['row_top']);
         $cmd = 'row_top';
     } elseif ($this->TABLECFG['row_bottom']) {
         $kk = key($this->TABLECFG['row_bottom']);
         $cmd = 'row_bottom';
     } elseif ($this->TABLECFG['row_up']) {
         $kk = key($this->TABLECFG['row_up']);
         $cmd = 'row_up';
     } elseif ($this->TABLECFG['row_down']) {
         $kk = key($this->TABLECFG['row_down']);
         $cmd = 'row_down';
     } else {
         $kk = '';
         $cmd = '';
     }
     if ($cmd && MathUtility::canBeInterpretedAsInteger($kk)) {
         if (StringUtility::beginsWith($cmd, 'row_')) {
             switch ($cmd) {
                 case 'row_remove':
                     unset($this->TABLECFG['c'][$kk]);
                     break;
                 case 'row_add':
                     for ($a = 1; $a <= $this->numNewRows; $a++) {
                         // Checking if set: The point is that any new row between existing rows
                         // will be TRUE after one row is added while if rows are added in the bottom
                         // of the table there will be no existing rows to stop the addition of new rows
                         // which means it will add up to $this->numNewRows rows then.
                         if (!isset($this->TABLECFG['c'][$kk + $a])) {
                             $this->TABLECFG['c'][$kk + $a] = array();
                         } else {
                             break;
                         }
                     }
                     break;
                 case 'row_top':
                     $this->TABLECFG['c'][1] = $this->TABLECFG['c'][$kk];
                     unset($this->TABLECFG['c'][$kk]);
                     break;
                 case 'row_bottom':
                     $this->TABLECFG['c'][10000000] = $this->TABLECFG['c'][$kk];
                     unset($this->TABLECFG['c'][$kk]);
                     break;
                 case 'row_up':
                     $this->TABLECFG['c'][$kk - 3] = $this->TABLECFG['c'][$kk];
                     unset($this->TABLECFG['c'][$kk]);
                     break;
                 case 'row_down':
                     $this->TABLECFG['c'][$kk + 3] = $this->TABLECFG['c'][$kk];
                     unset($this->TABLECFG['c'][$kk]);
                     break;
             }
             ksort($this->TABLECFG['c']);
         }
         if (StringUtility::beginsWith($cmd, 'col_')) {
             foreach ($this->TABLECFG['c'] as $cAK => $value) {
                 switch ($cmd) {
                     case 'col_remove':
                         unset($this->TABLECFG['c'][$cAK][$kk]);
                         break;
                     case 'col_add':
                         $this->TABLECFG['c'][$cAK][$kk + 1] = '';
                         break;
                     case 'col_start':
                         $this->TABLECFG['c'][$cAK][1] = $this->TABLECFG['c'][$cAK][$kk];
                         unset($this->TABLECFG['c'][$cAK][$kk]);
                         break;
                     case 'col_end':
                         $this->TABLECFG['c'][$cAK][1000000] = $this->TABLECFG['c'][$cAK][$kk];
                         unset($this->TABLECFG['c'][$cAK][$kk]);
                         break;
                     case 'col_left':
                         $this->TABLECFG['c'][$cAK][$kk - 3] = $this->TABLECFG['c'][$cAK][$kk];
                         unset($this->TABLECFG['c'][$cAK][$kk]);
                         break;
                     case 'col_right':
                         $this->TABLECFG['c'][$cAK][$kk + 3] = $this->TABLECFG['c'][$cAK][$kk];
                         unset($this->TABLECFG['c'][$cAK][$kk]);
                         break;
                 }
                 ksort($this->TABLECFG['c'][$cAK]);
             }
         }
     }
     // Convert line breaks to <br /> tags:
     foreach ($this->TABLECFG['c'] as $a => $value) {
         foreach ($this->TABLECFG['c'][$a] as $b => $value2) {
             $this->TABLECFG['c'][$a][$b] = str_replace(LF, '<br />', str_replace(CR, '', $this->TABLECFG['c'][$a][$b]));
         }
     }
 }
示例#16
0
    /**
     * Checks the input string (un-parsed TypoScript) for include-commands ("<INCLUDE_TYPOSCRIPT: ....")
     * Use: \TYPO3\CMS\Core\TypoScript\Parser\TypoScriptParser::checkIncludeLines()
     *
     * @param string $string Unparsed TypoScript
     * @param int $cycle_counter Counter for detecting endless loops
     * @param bool $returnFiles When set an array containing the resulting typoscript and all included files will get returned
     * @param string $parentFilenameOrPath The parent file (with absolute path) or path for relative includes
     * @return string Complete TypoScript with includes added.
     * @static
     */
    public static function checkIncludeLines($string, $cycle_counter = 1, $returnFiles = FALSE, $parentFilenameOrPath = '')
    {
        $includedFiles = array();
        if ($cycle_counter > 100) {
            GeneralUtility::sysLog('It appears like TypoScript code is looping over itself. Check your templates for "&lt;INCLUDE_TYPOSCRIPT: ..." tags', 'Core', GeneralUtility::SYSLOG_SEVERITY_WARNING);
            if ($returnFiles) {
                return array('typoscript' => '', 'files' => $includedFiles);
            }
            return '
###
### ERROR: Recursion!
###
';
        }
        // If no tags found, no need to do slower preg_split
        if (strpos($string, '<INCLUDE_TYPOSCRIPT:') !== FALSE) {
            $splitRegEx = '/\\r?\\n\\s*<INCLUDE_TYPOSCRIPT:\\s*(?i)source\\s*=\\s*"((?i)file|dir):\\s*([^"]*)"(.*)>[\\ \\t]*/';
            $parts = preg_split($splitRegEx, LF . $string . LF, -1, PREG_SPLIT_DELIM_CAPTURE);
            // First text part goes through
            $newString = $parts[0] . LF;
            $partCount = count($parts);
            for ($i = 1; $i + 3 < $partCount; $i += 4) {
                // $parts[$i] contains 'FILE' or 'DIR'
                // $parts[$i+1] contains relative file or directory path to be included
                // $parts[$i+2] optional properties of the INCLUDE statement
                // $parts[$i+3] next part of the typoscript string (part in between include-tags)
                $includeType = $parts[$i];
                $filename = $parts[$i + 1];
                $originalFilename = $filename;
                $optionalProperties = $parts[$i + 2];
                $tsContentsTillNextInclude = $parts[$i + 3];
                // Resolve a possible relative paths if a parent file is given
                if ($parentFilenameOrPath !== '' && $filename[0] === '.') {
                    $filename = PathUtility::getAbsolutePathOfRelativeReferencedFileOrPath($parentFilenameOrPath, $filename);
                }
                // There must be a line-break char after - not sure why this check is necessary, kept it for being 100% backwards compatible
                // An empty string is also ok (means that the next line is also a valid include_typoscript tag)
                if (!preg_match('/(^\\s*\\r?\\n|^$)/', $tsContentsTillNextInclude)) {
                    $newString .= self::typoscriptIncludeError('Invalid characters after <INCLUDE_TYPOSCRIPT: source="' . $includeType . ':' . $filename . '">-tag (rest of line must be empty).');
                } elseif (strpos('..', $filename) !== FALSE) {
                    $newString .= self::typoscriptIncludeError('Invalid filepath "' . $filename . '" (containing "..").');
                } else {
                    switch (strtolower($includeType)) {
                        case 'file':
                            self::includeFile($originalFilename, $cycle_counter, $returnFiles, $newString, $includedFiles, $optionalProperties, $parentFilenameOrPath);
                            break;
                        case 'dir':
                            self::includeDirectory($originalFilename, $cycle_counter, $returnFiles, $newString, $includedFiles, $optionalProperties, $parentFilenameOrPath);
                            break;
                        default:
                            $newString .= self::typoscriptIncludeError('No valid option for INCLUDE_TYPOSCRIPT source property (valid options are FILE or DIR)');
                    }
                }
                // Prepend next normal (not file) part to output string
                $newString .= $tsContentsTillNextInclude . LF;
                // load default TypoScript for content rendering templates like
                // css_styled_content if those have been included through f.e.
                // <INCLUDE_TYPOSCRIPT: source="FILE:EXT:css_styled_content/static/setup.txt">
                $filePointer = strtolower($filename);
                if (StringUtility::beginsWith($filePointer, 'ext:')) {
                    $filePointerPathParts = explode('/', substr($filePointer, 4));
                    // remove file part, determine whether to load setup or constants
                    list($includeType, ) = explode('.', array_pop($filePointerPathParts));
                    if (in_array($includeType, array('setup', 'constants'))) {
                        // adapt extension key to required format (no underscores)
                        $filePointerPathParts[0] = str_replace('_', '', $filePointerPathParts[0]);
                        // load default TypoScript
                        $defaultTypoScriptKey = implode('/', $filePointerPathParts) . '/';
                        if (in_array($defaultTypoScriptKey, $GLOBALS['TYPO3_CONF_VARS']['FE']['contentRenderingTemplates'], TRUE)) {
                            $newString .= $GLOBALS['TYPO3_CONF_VARS']['FE']['defaultTypoScript_' . $includeType . '.']['defaultContentRendering'];
                        }
                    }
                }
            }
            // Add a line break before and after the included code in order to make sure that the parser always has a LF.
            $string = LF . trim($newString) . LF;
        }
        // When all included files should get returned, simply return an compound array containing
        // the TypoScript with all "includes" processed and the files which got included
        if ($returnFiles) {
            return array('typoscript' => $string, 'files' => $includedFiles);
        }
        return $string;
    }
示例#17
0
 /**
  * Migrate "iconfile" references which starts with ../ to EXT: and consisting of filename only to absolute paths in EXT:t3skin
  *
  * @param array $tca Incoming TCA
  * @return array Migrated TCA
  */
 protected function migrateIconfileRelativePathOrFilenameOnlyToExtReference(array $tca)
 {
     foreach ($tca as $table => &$tableDefinition) {
         if (!isset($tableDefinition['ctrl']) || !is_array($tableDefinition['ctrl'])) {
             continue;
         }
         if (!isset($tableDefinition['ctrl']['iconfile'])) {
             continue;
         }
         if (StringUtility::beginsWith($tableDefinition['ctrl']['iconfile'], '../typo3conf/ext/')) {
             $tableDefinition['ctrl']['iconfile'] = str_replace('../typo3conf/ext/', 'EXT:', $tableDefinition['ctrl']['iconfile']);
             $tcaPath = implode('.', [$table, 'ctrl', 'iconfile']);
             $this->messages[] = '[' . $tcaPath . '] relative path to ../typo3conf/ext/ is deprecated, use EXT: instead';
         } elseif (strpos($tableDefinition['ctrl']['iconfile'], '/') === false) {
             $tableDefinition['ctrl']['iconfile'] = 'EXT:t3skin/icons/gfx/i/' . $tableDefinition['ctrl']['iconfile'];
             $tcaPath = implode('.', [$table, 'ctrl', 'iconfile']);
             $this->messages[] = '[' . $tcaPath . '] filename only is deprecated, use EXT: or absolute reference instead';
         }
     }
     return $tca;
 }
 /**
  * If the backend script is in CLI mode, it will try to load a backend user named by the CLI module name (in lowercase)
  *
  * @param string $commandLineName the name of the module registered inside $TYPO3_CONF_VARS[SC_OPTIONS][GLOBAL][cliKeys] as second parameter
  * @throws \RuntimeException if a non-admin Backend user could not be loaded
  */
 protected function loadCommandLineBackendUser($commandLineName)
 {
     if ($GLOBALS['BE_USER']->user['uid']) {
         throw new \RuntimeException('Another user was already loaded which is impossible in CLI mode!', 3);
     }
     if (!StringUtility::beginsWith($commandLineName, '_CLI_')) {
         throw new \RuntimeException('Module name, "' . $commandLineName . '", was not prefixed with "_CLI_"', 3);
     }
     $userName = strtolower($commandLineName);
     $GLOBALS['BE_USER']->setBeUserByName($userName);
     if (!$GLOBALS['BE_USER']->user['uid']) {
         throw new \RuntimeException('No backend user named "' . $userName . '" was found!', 3);
     }
     if ($GLOBALS['BE_USER']->isAdmin()) {
         throw new \RuntimeException('CLI backend user "' . $userName . '" was ADMIN which is not allowed!', 3);
     }
 }
示例#19
0
 /**
  * Transformation handler: 'ts_links' / direction: "rte"
  * Converting <link tags> to <A>-tags
  *
  * @param string $value Content input
  * @return string Content output
  * @see TS_links_rte()
  */
 public function TS_links_rte($value)
 {
     $conf = array();
     $value = $this->TS_AtagToAbs($value);
     // Split content by the TYPO3 pseudo tag "<link>":
     $blockSplit = $this->splitIntoBlock('link', $value, 1);
     $siteUrl = $this->siteUrl();
     foreach ($blockSplit as $k => $v) {
         $error = '';
         $external = false;
         // Block
         if ($k % 2) {
             // split away the first "<link" part
             $typolink = explode(' ', substr($this->getFirstTag($v), 0, -1), 2)[1];
             $tagCode = GeneralUtility::makeInstance(TypoLinkCodecService::class)->decode($typolink);
             $link_param = $tagCode['url'];
             // Parsing the typolink data. This parsing is roughly done like in \TYPO3\CMS\Frontend\ContentObject->typoLink()
             // Parse URL:
             $pU = parse_url($link_param);
             if (strstr($link_param, '@') && (!$pU['scheme'] || $pU['scheme'] == 'mailto')) {
                 // mailadr
                 $href = 'mailto:' . preg_replace('/^mailto:/i', '', $link_param);
             } elseif ($link_param[0] === '#') {
                 // check if anchor
                 $href = $siteUrl . $link_param;
             } else {
                 // Check for FAL link-handler keyword:
                 list($linkHandlerKeyword, $linkHandlerValue) = explode(':', trim($link_param), 2);
                 if ($linkHandlerKeyword === 'file' && !StringUtility::beginsWith($link_param, 'file://')) {
                     $href = $siteUrl . '?' . $linkHandlerKeyword . ':' . rawurlencode($linkHandlerValue);
                 } else {
                     $fileChar = (int) strpos($link_param, '/');
                     $urlChar = (int) strpos($link_param, '.');
                     // Detects if a file is found in site-root.
                     list($rootFileDat) = explode('?', $link_param);
                     $rFD_fI = pathinfo($rootFileDat);
                     if (trim($rootFileDat) && !strstr($link_param, '/') && (@is_file(PATH_site . $rootFileDat) || GeneralUtility::inList('php,html,htm', strtolower($rFD_fI['extension'])))) {
                         $href = $siteUrl . $link_param;
                     } elseif ($pU['scheme'] && !isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['typolinkLinkHandler'][$pU['scheme']]) || $urlChar && (!$fileChar || $urlChar < $fileChar)) {
                         // url (external): if has scheme or if a '.' comes before a '/'.
                         $href = $link_param;
                         if (!$pU['scheme']) {
                             $href = 'http://' . $href;
                         }
                         $external = true;
                     } elseif ($fileChar) {
                         // It is an internal file or folder
                         // Try to transform the href into a FAL reference
                         try {
                             $fileOrFolderObject = \TYPO3\CMS\Core\Resource\ResourceFactory::getInstance()->retrieveFileOrFolderObject($link_param);
                         } catch (\TYPO3\CMS\Core\Resource\Exception $exception) {
                             // Nothing to be done if file/folder not found or path invalid
                             $fileOrFolderObject = null;
                         }
                         if ($fileOrFolderObject instanceof \TYPO3\CMS\Core\Resource\Folder) {
                             // It's a folder
                             $folderIdentifier = $fileOrFolderObject->getIdentifier();
                             $href = $siteUrl . '?file:' . rawurlencode($folderIdentifier);
                         } elseif ($fileOrFolderObject instanceof \TYPO3\CMS\Core\Resource\FileInterface) {
                             // It's a file
                             $fileIdentifier = $fileOrFolderObject->getIdentifier();
                             $fileObject = $fileOrFolderObject->getStorage()->getFile($fileIdentifier);
                             $href = $siteUrl . '?file:' . $fileObject->getUid();
                         } else {
                             $href = $siteUrl . $link_param;
                         }
                     } else {
                         // integer or alias (alias is without slashes or periods or commas, that is 'nospace,alphanum_x,lower,unique' according to tables.php!!)
                         // Splitting the parameter by ',' and if the array counts more than 1 element it's an id/type/parameters triplet
                         $pairParts = GeneralUtility::trimExplode(',', $link_param, true);
                         $idPart = $pairParts[0];
                         $link_params_parts = explode('#', $idPart);
                         $idPart = trim($link_params_parts[0]);
                         $sectionMark = trim($link_params_parts[1]);
                         if ((string) $idPart === '') {
                             $idPart = $this->recPid;
                         }
                         // If no id or alias is given, set it to class record pid
                         // Checking if the id-parameter is an alias.
                         if (!\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($idPart)) {
                             list($idPartR) = BackendUtility::getRecordsByField('pages', 'alias', $idPart);
                             $idPart = (int) $idPartR['uid'];
                         }
                         $page = BackendUtility::getRecord('pages', $idPart);
                         if (is_array($page)) {
                             // Page must exist...
                             $href = $siteUrl . '?id=' . $idPart . ($pairParts[2] ? $pairParts[2] : '') . ($sectionMark ? '#' . $sectionMark : '');
                         } elseif (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['typolinkLinkHandler'][array_shift(explode(':', $link_param))])) {
                             $href = $link_param;
                         } else {
                             $href = $siteUrl . '?id=' . $link_param;
                             $error = 'No page found: ' . $idPart;
                         }
                     }
                 }
             }
             // Setting the A-tag:
             $bTag = '<a href="' . htmlspecialchars($href) . '"' . ($tagCode['target'] ? ' target="' . htmlspecialchars($tagCode['target']) . '"' : '') . ($tagCode['class'] ? ' class="' . htmlspecialchars($tagCode['class']) . '"' : '') . ($tagCode['title'] ? ' title="' . htmlspecialchars($tagCode['title']) . '"' : '') . ($external ? ' data-htmlarea-external="1"' : '') . ($error ? ' rteerror="' . htmlspecialchars($error) . '" style="background-color: yellow; border:2px red solid; color: black;"' : '') . '>';
             $eTag = '</a>';
             // Modify parameters
             if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_parsehtml_proc.php']['modifyParams_LinksRte_PostProc']) && is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_parsehtml_proc.php']['modifyParams_LinksRte_PostProc'])) {
                 $parameters = array('conf' => &$conf, 'currentBlock' => $v, 'url' => $href, 'tagCode' => $tagCode, 'external' => $external, 'error' => $error);
                 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_parsehtml_proc.php']['modifyParams_LinksRte_PostProc'] as $objRef) {
                     $processor = GeneralUtility::getUserObj($objRef);
                     $blockSplit[$k] = $processor->modifyParamsLinksRte($parameters, $this);
                 }
             } else {
                 $blockSplit[$k] = $bTag . $this->TS_links_rte($this->removeFirstAndLastTag($blockSplit[$k])) . $eTag;
             }
         }
     }
     // Return content:
     return implode('', $blockSplit);
 }
示例#20
0
 /**
  * Here we check for the module.
  *
  * Return values:
  * 'notFound':	If the module was not found in the path (no "conf.php" file)
  * FALSE:		If no access to the module (access check failed)
  * array():	    Configuration array, in case a valid module where access IS granted exists.
  *
  * @param string $name Module name
  * @param string $fullPath Absolute path to module
  * @return string|bool|array See description of function
  */
 public function checkMod($name, $fullPath)
 {
     if ($name === 'user_ws' && !ExtensionManagementUtility::isLoaded('version')) {
         return false;
     }
     // Check for own way of configuring module
     if (is_array($GLOBALS['TBE_MODULES']['_configuration'][$name]['configureModuleFunction'])) {
         $obj = $GLOBALS['TBE_MODULES']['_configuration'][$name]['configureModuleFunction'];
         if (is_callable($obj)) {
             $MCONF = call_user_func($obj, $name, $fullPath);
             if ($this->checkModAccess($name, $MCONF) !== true) {
                 return false;
             }
             return $MCONF;
         }
     }
     // merges $MCONF and $MLANG from conf.php and the additional configuration of the module
     $setupInformation = $this->getModuleSetupInformation($name, $fullPath);
     // Because 'path/../path' does not work
     // clean up the configuration part
     if (empty($setupInformation['configuration'])) {
         return 'notFound';
     }
     if ($setupInformation['configuration']['shy'] || !$this->checkModAccess($name, $setupInformation['configuration']) || !$this->checkModWorkspace($name, $setupInformation['configuration'])) {
         return false;
     }
     $finalModuleConfiguration = $setupInformation['configuration'];
     $finalModuleConfiguration['name'] = $name;
     // Language processing. This will add module labels and image reference to the internal ->moduleLabels array of the LANG object.
     $lang = $this->getLanguageService();
     if (is_object($lang)) {
         // $setupInformation['labels']['default']['tabs_images']['tab'] is for modules the reference
         // to the module icon.
         $defaultLabels = $setupInformation['labels']['default'];
         // Here the path is transformed to an absolute reference.
         if ($defaultLabels['tabs_images']['tab']) {
             // Initializing search for alternative icon:
             // Alternative icon key (might have an alternative set in $TBE_STYLES['skinImg']
             $altIconKey = 'MOD:' . $name . '/' . $defaultLabels['tabs_images']['tab'];
             $altIconAbsPath = is_array($GLOBALS['TBE_STYLES']['skinImg'][$altIconKey]) ? GeneralUtility::resolveBackPath(PATH_typo3 . $GLOBALS['TBE_STYLES']['skinImg'][$altIconKey][0]) : '';
             // Setting icon, either default or alternative:
             if ($altIconAbsPath && @is_file($altIconAbsPath)) {
                 $defaultLabels['tabs_images']['tab'] = $altIconAbsPath;
             } else {
                 if (\TYPO3\CMS\Core\Utility\StringUtility::beginsWith($defaultLabels['tabs_images']['tab'], 'EXT:')) {
                     list($extensionKey, $relativePath) = explode('/', substr($defaultLabels['tabs_images']['tab'], 4), 2);
                     $defaultLabels['tabs_images']['tab'] = ExtensionManagementUtility::extPath($extensionKey) . $relativePath;
                 } else {
                     $defaultLabels['tabs_images']['tab'] = $fullPath . '/' . $defaultLabels['tabs_images']['tab'];
                 }
             }
             $defaultLabels['tabs_images']['tab'] = $this->getRelativePath(PATH_typo3, $defaultLabels['tabs_images']['tab']);
             // Finally, setting the icon with correct path:
             if (substr($defaultLabels['tabs_images']['tab'], 0, 3) === '../') {
                 $defaultLabels['tabs_images']['tab'] = PATH_site . substr($defaultLabels['tabs_images']['tab'], 3);
             } else {
                 $defaultLabels['tabs_images']['tab'] = PATH_typo3 . $defaultLabels['tabs_images']['tab'];
             }
         }
         // If LOCAL_LANG references are used for labels of the module:
         if ($defaultLabels['ll_ref']) {
             // Now the 'default' key is loaded with the CURRENT language - not the english translation...
             $defaultLabels['labels']['tablabel'] = $lang->sL($defaultLabels['ll_ref'] . ':mlang_labels_tablabel');
             $defaultLabels['labels']['tabdescr'] = $lang->sL($defaultLabels['ll_ref'] . ':mlang_labels_tabdescr');
             $defaultLabels['tabs']['tab'] = $lang->sL($defaultLabels['ll_ref'] . ':mlang_tabs_tab');
             $lang->addModuleLabels($defaultLabels, $name . '_');
         } else {
             // ... otherwise use the old way:
             $lang->addModuleLabels($defaultLabels, $name . '_');
             $lang->addModuleLabels($setupInformation['labels'][$lang->lang], $name . '_');
         }
     }
     // Default script setup
     if ($setupInformation['configuration']['script'] === '_DISPATCH' || isset($setupInformation['configuration']['routeTarget'])) {
         if ($setupInformation['configuration']['extbase']) {
             $finalModuleConfiguration['script'] = BackendUtility::getModuleUrl('Tx_' . $name);
         } else {
             // just go through BackendModuleRequestHandler where the routeTarget is resolved
             $finalModuleConfiguration['script'] = BackendUtility::getModuleUrl($name);
         }
     } elseif ($setupInformation['configuration']['script'] && file_exists($setupInformation['path'] . '/' . $setupInformation['configuration']['script'])) {
         $finalModuleConfiguration['script'] = $this->getRelativePath(PATH_typo3, $fullPath . '/' . $setupInformation['configuration']['script']);
     } else {
         $finalModuleConfiguration['script'] = BackendUtility::getModuleUrl('dummy');
     }
     if (!empty($setupInformation['configuration']['navigationFrameModule'])) {
         $finalModuleConfiguration['navFrameScript'] = BackendUtility::getModuleUrl($setupInformation['configuration']['navigationFrameModule'], !empty($setupInformation['configuration']['navigationFrameModuleParameters']) ? $setupInformation['configuration']['navigationFrameModuleParameters'] : array());
     } elseif (!empty($setupInformation['configuration']['navFrameScript'])) {
         // Navigation Frame Script (GET params could be added)
         $navFrameScript = explode('?', $setupInformation['configuration']['navFrameScript']);
         $navFrameScript = $navFrameScript[0];
         if (file_exists($setupInformation['path'] . '/' . $navFrameScript)) {
             $finalModuleConfiguration['navFrameScript'] = $this->getRelativePath(PATH_typo3, $fullPath . '/' . $setupInformation['configuration']['navFrameScript']);
         }
         // Additional params for Navigation Frame Script: "&anyParam=value&moreParam=1"
         if ($setupInformation['configuration']['navFrameScriptParam']) {
             $finalModuleConfiguration['navFrameScriptParam'] = $setupInformation['configuration']['navFrameScriptParam'];
         }
     }
     // Check if this is a submodule
     $mainModule = '';
     if (strpos($name, '_') !== false) {
         list($mainModule, ) = explode('_', $name, 2);
     }
     // check if there is a navigation component (like the pagetree)
     if (is_array($this->navigationComponents[$name])) {
         $finalModuleConfiguration['navigationComponentId'] = $this->navigationComponents[$name]['componentId'];
         // navigation component can be overriden by the main module component
     } elseif ($mainModule && is_array($this->navigationComponents[$mainModule]) && $setupInformation['configuration']['inheritNavigationComponentFromMainModule'] !== false) {
         $finalModuleConfiguration['navigationComponentId'] = $this->navigationComponents[$mainModule]['componentId'];
     }
     return $finalModuleConfiguration;
 }
示例#21
0
 /**
  * @test
  * @dataProvider beginsWithReturnsInvalidArgumentDataProvider
  * @expectedException \InvalidArgumentException
  */
 public function beginsWithReturnsThrowsExceptionWithInvalidArguments($string, $part)
 {
     StringUtility::beginsWith($string, $part);
 }
示例#22
0
 /**
  * Renders the $icon, supports a filename for skinImg or sprite-icon-name
  *
  * @param string $icon The icon passed, could be a file-reference or a sprite Icon name
  * @param string $alt Alt attribute of the icon returned
  * @param string $title Title attribute of the icon return
  * @return string A tag representing to show the asked icon
  * @internal
  */
 public static function getIconHtml($icon, $alt = '', $title = '')
 {
     $icon = (string) $icon;
     $iconFile = '';
     $iconInfo = false;
     if (StringUtility::beginsWith($icon, 'EXT:')) {
         $absoluteFilePath = GeneralUtility::getFileAbsFileName($icon);
         if (!empty($absoluteFilePath)) {
             $iconFile = '../' . PathUtility::stripPathSitePrefix($absoluteFilePath);
             $iconInfo = StringUtility::endsWith($absoluteFilePath, '.svg') ? true : getimagesize($absoluteFilePath);
         }
     } elseif (StringUtility::beginsWith($icon, '../')) {
         // @TODO: this is special modList, files from folders and selicon
         $iconFile = GeneralUtility::resolveBackPath($icon);
         if (is_file(PATH_site . GeneralUtility::resolveBackPath(substr($icon, 3)))) {
             $iconInfo = StringUtility::endsWith($icon, '.svg') ? true : getimagesize(PATH_site . GeneralUtility::resolveBackPath(substr($icon, 3)));
         }
     }
     if ($iconInfo !== false && is_file(GeneralUtility::resolveBackPath(PATH_typo3 . $iconFile))) {
         return '<img' . ' src="' . htmlspecialchars($iconFile) . '"' . ' alt="' . htmlspecialchars($alt) . '" ' . ($title ? 'title="' . htmlspecialchars($title) . '"' : '') . ' />';
     }
     $iconFactory = GeneralUtility::makeInstance(IconFactory::class);
     return '<span alt="' . htmlspecialchars($alt) . '" title="' . htmlspecialchars($title) . '">' . $iconFactory->getIcon($icon, Icon::SIZE_SMALL)->render() . '</span>';
 }
 /**
  * Sets the cache-flag to 1. Could be called from user-included php-files in order to ensure that a page is not cached.
  *
  * @param string $reason An optional reason to be written to the syslog.
  * @param bool $internal Whether the call is done from core itself (should only be used by core).
  * @return void
  */
 public function set_no_cache($reason = '', $internal = false)
 {
     if ($internal && isset($GLOBALS['BE_USER'])) {
         $severity = GeneralUtility::SYSLOG_SEVERITY_NOTICE;
     } else {
         $severity = GeneralUtility::SYSLOG_SEVERITY_WARNING;
     }
     if ($reason !== '') {
         $warning = '$TSFE->set_no_cache() was triggered. Reason: ' . $reason . '.';
     } else {
         $trace = debug_backtrace();
         // This is a hack to work around ___FILE___ resolving symbolic links
         $PATH_site_real = dirname(realpath(PATH_site . 'typo3')) . '/';
         $file = $trace[0]['file'];
         if (StringUtility::beginsWith($file, $PATH_site_real)) {
             $file = str_replace($PATH_site_real, '', $file);
         } else {
             $file = str_replace(PATH_site, '', $file);
         }
         $line = $trace[0]['line'];
         $trigger = $file . ' on line ' . $line;
         $warning = '$GLOBALS[\'TSFE\']->set_no_cache() was triggered by ' . $trigger . '.';
     }
     if ($this->TYPO3_CONF_VARS['FE']['disableNoCacheParameter']) {
         $warning .= ' However, $TYPO3_CONF_VARS[\'FE\'][\'disableNoCacheParameter\'] is set, so it will be ignored!';
         $this->getTimeTracker()->setTSlogMessage($warning, 2);
     } else {
         $warning .= ' Caching is disabled!';
         $this->disableCache();
     }
     GeneralUtility::sysLog($warning, 'cms', $severity);
 }
示例#24
0
 /**
  * Returns the Page TSconfig for page with id, $id
  *
  * @param int $id Page uid for which to create Page TSconfig
  * @param array $rootLine If $rootLine is an array, that is used as rootline, otherwise rootline is just calculated
  * @param bool $returnPartArray If $returnPartArray is set, then the array with accumulated Page TSconfig is returned non-parsed. Otherwise the output will be parsed by the TypoScript parser.
  * @return array Page TSconfig
  * @see \TYPO3\CMS\Core\TypoScript\Parser\TypoScriptParser
  */
 public static function getPagesTSconfig($id, $rootLine = null, $returnPartArray = false)
 {
     static $pagesTSconfig_cacheReference = array();
     static $combinedTSconfig_cache = array();
     $id = (int) $id;
     if ($returnPartArray === false && $rootLine === null && isset($pagesTSconfig_cacheReference[$id])) {
         return $combinedTSconfig_cache[$pagesTSconfig_cacheReference[$id]];
     } else {
         $TSconfig = array();
         if (!is_array($rootLine)) {
             $useCacheForCurrentPageId = true;
             $rootLine = self::BEgetRootLine($id, '', true);
         } else {
             $useCacheForCurrentPageId = false;
         }
         // Order correctly
         ksort($rootLine);
         $TSdataArray = array();
         // Setting default configuration
         $TSdataArray['defaultPageTSconfig'] = $GLOBALS['TYPO3_CONF_VARS']['BE']['defaultPageTSconfig'];
         foreach ($rootLine as $k => $v) {
             if (trim($v['tsconfig_includes'])) {
                 $includeTsConfigFileList = GeneralUtility::trimExplode(',', $v['tsconfig_includes'], true);
                 // Traversing list
                 foreach ($includeTsConfigFileList as $key => $includeTsConfigFile) {
                     if (StringUtility::beginsWith($includeTsConfigFile, 'EXT:')) {
                         list($includeTsConfigFileExtensionKey, $includeTsConfigFilename) = explode('/', substr($includeTsConfigFile, 4), 2);
                         if ((string) $includeTsConfigFileExtensionKey !== '' && ExtensionManagementUtility::isLoaded($includeTsConfigFileExtensionKey) && (string) $includeTsConfigFilename !== '') {
                             $includeTsConfigFileAndPath = ExtensionManagementUtility::extPath($includeTsConfigFileExtensionKey) . $includeTsConfigFilename;
                             if (file_exists($includeTsConfigFileAndPath)) {
                                 $TSdataArray['uid_' . $v['uid'] . '_static_' . $key] = GeneralUtility::getUrl($includeTsConfigFileAndPath);
                             }
                         }
                     }
                 }
             }
             $TSdataArray['uid_' . $v['uid']] = $v['TSconfig'];
         }
         $TSdataArray = static::emitGetPagesTSconfigPreIncludeSignal($TSdataArray, $id, $rootLine, $returnPartArray);
         $TSdataArray = TypoScriptParser::checkIncludeLines_array($TSdataArray);
         if ($returnPartArray) {
             return $TSdataArray;
         }
         // Parsing the page TS-Config
         $pageTS = implode(LF . '[GLOBAL]' . LF, $TSdataArray);
         /* @var $parseObj \TYPO3\CMS\Backend\Configuration\TsConfigParser */
         $parseObj = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Configuration\TsConfigParser::class);
         $res = $parseObj->parseTSconfig($pageTS, 'PAGES', $id, $rootLine);
         if ($res) {
             $TSconfig = $res['TSconfig'];
         }
         $cacheHash = $res['hash'];
         // Get User TSconfig overlay
         $userTSconfig = static::getBackendUserAuthentication()->userTS['page.'];
         if (is_array($userTSconfig)) {
             ArrayUtility::mergeRecursiveWithOverrule($TSconfig, $userTSconfig);
             $cacheHash .= '_user' . $GLOBALS['BE_USER']->user['uid'];
         }
         if ($useCacheForCurrentPageId) {
             if (!isset($combinedTSconfig_cache[$cacheHash])) {
                 $combinedTSconfig_cache[$cacheHash] = $TSconfig;
             }
             $pagesTSconfig_cacheReference[$id] = $cacheHash;
         }
     }
     return $TSconfig;
 }
示例#25
0
 /**
  * For RTE/link: Parses the incoming URL and determines if it's a page, file, external or mail address.
  *
  * @param string $href HREF value tp analyse
  * @param string $siteUrl The URL of the current website (frontend)
  * @return array[] Array with URL information stored in assoc. keys: value, act (page, file, spec, mail), pageid, cElement, info
  */
 public function parseCurUrl($href, $siteUrl)
 {
     $href = trim($href);
     $lang = $this->getLanguageService();
     if ($href) {
         $info = array();
         // Default is "url":
         $info['value'] = $href;
         $info['act'] = 'url';
         $specialParts = explode('#_SPECIAL', $href);
         // Special kind (Something RTE specific: User configurable links through: "userLinks." from ->thisConfig)
         if (count($specialParts) == 2) {
             $info['value'] = '#_SPECIAL' . $specialParts[1];
             $info['act'] = 'spec';
         } elseif (!StringUtility::beginsWith($href, 'file://') && strpos($href, 'file:') !== FALSE) {
             $rel = substr($href, strpos($href, 'file:') + 5);
             $rel = rawurldecode($rel);
             // resolve FAL-api "file:UID-of-sys_file-record" and "file:combined-identifier"
             $fileOrFolderObject = ResourceFactory::getInstance()->retrieveFileOrFolderObject($rel);
             if ($fileOrFolderObject instanceof Folder) {
                 $info['act'] = 'folder';
                 $info['value'] = $fileOrFolderObject->getCombinedIdentifier();
             } elseif ($fileOrFolderObject instanceof File) {
                 $info['act'] = 'file';
                 $info['value'] = $fileOrFolderObject->getUid();
             } else {
                 $info['value'] = $rel;
             }
         } elseif (StringUtility::beginsWith($href, $siteUrl)) {
             // If URL is on the current frontend website:
             // URL is a file, which exists:
             if (file_exists(PATH_site . rawurldecode($href))) {
                 $info['value'] = rawurldecode($href);
                 if (@is_dir(PATH_site . $info['value'])) {
                     $info['act'] = 'folder';
                 } else {
                     $info['act'] = 'file';
                 }
             } else {
                 // URL is a page (id parameter)
                 $uP = parse_url($href);
                 $pp = preg_split('/^id=/', $uP['query']);
                 $pp[1] = preg_replace('/&id=[^&]*/', '', $pp[1]);
                 $parameters = explode('&', $pp[1]);
                 $id = array_shift($parameters);
                 if ($id) {
                     // Checking if the id-parameter is an alias.
                     if (!MathUtility::canBeInterpretedAsInteger($id)) {
                         list($idPartR) = BackendUtility::getRecordsByField('pages', 'alias', $id);
                         $id = (int) $idPartR['uid'];
                     }
                     $pageRow = BackendUtility::getRecordWSOL('pages', $id);
                     $titleLen = (int) $this->getBackendUserAuthentication()->uc['titleLen'];
                     $info['value'] = $lang->getLL('page', TRUE) . ' \'' . htmlspecialchars(GeneralUtility::fixed_lgd_cs($pageRow['title'], $titleLen)) . '\' (ID:' . $id . ($uP['fragment'] ? ', #' . $uP['fragment'] : '') . ')';
                     $info['pageid'] = $id;
                     $info['cElement'] = $uP['fragment'];
                     $info['act'] = 'page';
                     $info['query'] = $parameters[0] ? '&' . implode('&', $parameters) : '';
                 }
             }
         } else {
             // Email link:
             if (strtolower(substr($href, 0, 7)) === 'mailto:') {
                 $info['value'] = trim(substr($href, 7));
                 $info['act'] = 'mail';
             }
         }
         $info['info'] = $info['value'];
     } else {
         // NO value input:
         $info = array();
         $info['info'] = $lang->getLL('none');
         $info['value'] = '';
         $info['act'] = 'page';
     }
     // let the hook have a look
     foreach ($this->hookObjects as $hookObject) {
         $info = $hookObject->parseCurrentUrl($href, $siteUrl, $info);
     }
     return $info;
 }
 /**
  * Adds new fields to all palettes that is defined after an existing field.
  * If the field does not have a following palette yet, it's created automatically
  * and gets called "generatedFor-$field".
  *
  * See unit tests for more examples and edge cases.
  *
  * Example:
  *
  * 'aTable' => array(
  * 	'types' => array(
  * 		'aType' => array(
  * 			'showitem' => 'aField, --palette--;;aPalette',
  * 		),
  * 	),
  * 	'palettes' => array(
  * 		'aPallete' => array(
  * 			'showitem' => 'fieldB, fieldC',
  * 		),
  * 	),
  * ),
  *
  * Calling addFieldsToAllPalettesOfField('aTable', 'aField', 'newA', 'before: fieldC') results in:
  *
  * 'aTable' => array(
  * 	'types' => array(
  * 		'aType' => array(
  * 			'showitem' => 'aField, --palette--;;aPalette',
  * 		),
  * 	),
  * 	'palettes' => array(
  * 		'aPallete' => array(
  * 			'showitem' => 'fieldB, newA, fieldC',
  * 		),
  * 	),
  * ),
  *
  * @param string $table Name of the table
  * @param string $field Name of the field that has the palette to be extended
  * @param string $addFields List of fields to be added to the palette
  * @param string $insertionPosition Insert fields before (default) or after one
  * @return void
  */
 public static function addFieldsToAllPalettesOfField($table, $field, $addFields, $insertionPosition = '')
 {
     if (!isset($GLOBALS['TCA'][$table]['columns'][$field])) {
         return;
     }
     if (!is_array($GLOBALS['TCA'][$table]['types'])) {
         return;
     }
     // Iterate through all types and search for the field that defines the palette to be extended
     foreach ($GLOBALS['TCA'][$table]['types'] as $typeName => $typeArray) {
         // Continue if types has no showitem at all or if requested field is not in it
         if (!isset($typeArray['showitem']) || strpos($typeArray['showitem'], $field) === false) {
             continue;
         }
         $fieldArrayWithOptions = GeneralUtility::trimExplode(',', $typeArray['showitem']);
         // Find the field we're handling
         $newFieldStringArray = array();
         foreach ($fieldArrayWithOptions as $fieldNumber => $fieldString) {
             $newFieldStringArray[] = $fieldString;
             $fieldArray = GeneralUtility::trimExplode(';', $fieldString);
             if ($fieldArray[0] !== $field) {
                 continue;
             }
             if (isset($fieldArrayWithOptions[$fieldNumber + 1]) && StringUtility::beginsWith($fieldArrayWithOptions[$fieldNumber + 1], '--palette--')) {
                 // Match for $field and next field is a palette - add fields to this one
                 $paletteName = GeneralUtility::trimExplode(';', $fieldArrayWithOptions[$fieldNumber + 1]);
                 $paletteName = $paletteName[2];
                 self::addFieldsToPalette($table, $paletteName, $addFields, $insertionPosition);
             } else {
                 // Match for $field but next field is no palette - create a new one
                 $newPaletteName = 'generatedFor-' . $field;
                 self::addFieldsToPalette($table, 'generatedFor-' . $field, $addFields, $insertionPosition);
                 $newFieldStringArray[] = '--palette--;;' . $newPaletteName;
             }
         }
         $GLOBALS['TCA'][$table]['types'][$typeName]['showitem'] = implode(', ', $newFieldStringArray);
     }
 }
    /**
     * Creating the module output.
     *
     * @throws \UnexpectedValueException
     * @return void
     */
    public function main()
    {
        $lang = $this->getLanguageService();
        $this->content .= '<form action="" name="editForm" id="NewContentElementController"><input type="hidden" name="defValues" value="" />';
        if ($this->id && $this->access) {
            // Init position map object:
            $posMap = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Tree\View\ContentCreationPagePositionMap::class);
            $posMap->cur_sys_language = $this->sys_language;
            // If a column is pre-set:
            if (isset($this->colPos)) {
                if ($this->uid_pid < 0) {
                    $row = array();
                    $row['uid'] = abs($this->uid_pid);
                } else {
                    $row = '';
                }
                $this->onClickEvent = $posMap->onClickInsertRecord($row, $this->colPos, '', $this->uid_pid, $this->sys_language);
            } else {
                $this->onClickEvent = '';
            }
            // ***************************
            // Creating content
            // ***************************
            $this->content .= '<h1>' . $lang->getLL('newContentElement') . '</h1>';
            // Wizard
            $wizardItems = $this->wizardArray();
            // Wrapper for wizards
            $this->elementWrapper['section'] = array('', '');
            // Hook for manipulating wizardItems, wrapper, onClickEvent etc.
            if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms']['db_new_content_el']['wizardItemsHook'])) {
                foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms']['db_new_content_el']['wizardItemsHook'] as $classData) {
                    $hookObject = GeneralUtility::getUserObj($classData);
                    if (!$hookObject instanceof NewContentElementWizardHookInterface) {
                        throw new \UnexpectedValueException('$hookObject must implement interface ' . NewContentElementWizardHookInterface::class, 1227834741);
                    }
                    $hookObject->manipulateWizardItems($wizardItems, $this);
                }
            }
            // Add document inline javascript
            $this->moduleTemplate->addJavaScriptCode('NewContentElementWizardInlineJavascript', '
				function goToalt_doc() {	//
					' . $this->onClickEvent . '
				}

				if(top.refreshMenu) {
					top.refreshMenu();
				} else {
					top.TYPO3ModuleMenu.refreshMenu();
				}');
            $iconRegistry = GeneralUtility::makeInstance(IconRegistry::class);
            // Traverse items for the wizard.
            // An item is either a header or an item rendered with a radio button and title/description and icon:
            $cc = $key = 0;
            $menuItems = array();
            foreach ($wizardItems as $k => $wInfo) {
                if ($wInfo['header']) {
                    $menuItems[] = array('label' => htmlspecialchars($wInfo['header']), 'content' => $this->elementWrapper['section'][0]);
                    $key = count($menuItems) - 1;
                } else {
                    $content = '';
                    if (!$this->onClickEvent) {
                        // Radio button:
                        $oC = 'document.editForm.defValues.value=unescape(' . GeneralUtility::quoteJSvalue(rawurlencode($wInfo['params'])) . ');goToalt_doc();' . (!$this->onClickEvent ? 'window.location.hash=\'#sel2\';' : '');
                        $content .= '<div class="media-left"><input type="radio" name="tempB" value="' . htmlspecialchars($k) . '" onclick="' . htmlspecialchars($oC) . '" /></div>';
                        // Onclick action for icon/title:
                        $aOnClick = 'document.getElementsByName(\'tempB\')[' . $cc . '].checked=1;' . $oC . 'return false;';
                    } else {
                        $aOnClick = "document.editForm.defValues.value=unescape('" . rawurlencode($wInfo['params']) . "');goToalt_doc();" . (!$this->onClickEvent ? "window.location.hash='#sel2';" : '');
                    }
                    if (isset($wInfo['icon'])) {
                        GeneralUtility::deprecationLog('The PageTS-Config: mod.wizards.newContentElement.wizardItems.*.elements.*.icon' . ' is deprecated since TYPO3 CMS 7, will be removed in TYPO3 CMS 8.' . ' Register your icon in IconRegistry::registerIcon and use the new setting:' . ' mod.wizards.newContentElement.wizardItems.*.elements.*.iconIdentifier');
                        $wInfo['iconIdentifier'] = 'content-' . $k;
                        $icon = $wInfo['icon'];
                        if (StringUtility::beginsWith($icon, '../typo3conf/ext/')) {
                            $icon = str_replace('../typo3conf/ext/', 'EXT:', $icon);
                        }
                        if (!StringUtility::beginsWith($icon, 'EXT:') && strpos($icon, '/') !== false) {
                            $icon = TYPO3_mainDir . GeneralUtility::resolveBackPath($wInfo['icon']);
                        }
                        $iconRegistry->registerIcon($wInfo['iconIdentifier'], BitmapIconProvider::class, array('source' => $icon));
                    }
                    $icon = $this->moduleTemplate->getIconFactory()->getIcon($wInfo['iconIdentifier'])->render();
                    $menuItems[$key]['content'] .= '
						<div class="media">
							<a href="#" onclick="' . htmlspecialchars($aOnClick) . '">
								' . $content . '
								<div class="media-left">
									' . $icon . '
								</div>
								<div class="media-body">
									<strong>' . htmlspecialchars($wInfo['title']) . '</strong>' . '<br />' . nl2br(htmlspecialchars(trim($wInfo['description']))) . '</div>
							</a>
						</div>';
                    $cc++;
                }
            }
            // Add closing section-tag
            foreach ($menuItems as $key => $val) {
                $menuItems[$key]['content'] .= $this->elementWrapper['section'][1];
            }
            // Add the wizard table to the content, wrapped in tabs
            $code = '<p>' . $lang->getLL('sel1', 1) . '</p>' . $this->moduleTemplate->getDynamicTabMenu($menuItems, 'new-content-element-wizard');
            $this->content .= !$this->onClickEvent ? '<h2>' . $lang->getLL('1_selectType', true) . '</h2>' : '';
            $this->content .= '<div>' . $code . '</div>';
            // If the user must also select a column:
            if (!$this->onClickEvent) {
                // Add anchor "sel2"
                $this->content .= '<div><a name="sel2"></a></div>';
                // Select position
                $code = '<p>' . $lang->getLL('sel2', 1) . '</p>';
                // Load SHARED page-TSconfig settings and retrieve column list from there, if applicable:
                $colPosArray = GeneralUtility::callUserFunction(BackendLayoutView::class . '->getColPosListItemsParsed', $this->id, $this);
                $colPosIds = array_column($colPosArray, 1);
                // Removing duplicates, if any
                $colPosList = implode(',', array_unique(array_map('intval', $colPosIds)));
                // Finally, add the content of the column selector to the content:
                $code .= $posMap->printContentElementColumns($this->id, 0, $colPosList, 1, $this->R_URI);
                $this->content .= '<h2>' . $lang->getLL('2_selectPosition', true) . '</h2><div>' . $code . '</div>';
            }
        } else {
            // In case of no access:
            $this->content = '';
            $this->content .= '<h1>' . $lang->getLL('newContentElement') . '</h1>';
        }
        $this->content .= '</form>';
        // Setting up the buttons and markers for docheader
        $this->getButtons();
    }
示例#28
0
 /**
  * This flattens a hierarchical TypoScript array to $this->flatSetup
  *
  * @param array $setupArray TypoScript array
  * @param string $prefix Prefix to the object path. Used for recursive calls to this function.
  * @return void
  * @see generateConfig()
  */
 public function flattenSetup($setupArray, $prefix)
 {
     if (is_array($setupArray)) {
         foreach ($setupArray as $key => $val) {
             if ($prefix || !StringUtility::beginsWith($key, 'TSConstantEditor')) {
                 // We don't want 'TSConstantEditor' in the flattend setup on the first level (190201)
                 if (is_array($val)) {
                     $this->flattenSetup($val, $prefix . $key);
                 } else {
                     $this->flatSetup[$prefix . $key] = $val;
                 }
             }
         }
     }
 }
 /**
  * Adds a module path to $GLOBALS['TBE_MODULES'] for used with the module dispatcher, index.php
  * Used only for modules that are not placed in the main/sub menu hierarchy by the traditional mechanism of addModule()
  * Examples for this is context menu functionality (like import/export) which runs as an independent module through index.php
  * FOR USE IN ext_tables.php FILES
  * Example:  \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addModulePath('xMOD_tximpexp', \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath($_EXTKEY).'app/');
  *
  * @param string $name The name of the module, refer to conf.php of the module.
  * @param string $path The absolute path to the module directory inside of which "index.php" and "conf.php" is found.
  * @return void
  * @deprecated since TYPO3 CMS 7, will be removed in TYPO3 CMS 8, use routeTarget or dispatched modules instead.
  */
 public static function addModulePath($name, $path)
 {
     GeneralUtility::logDeprecatedFunction();
     if (StringUtility::beginsWith($path, 'EXT:')) {
         list($extensionKey, $relativePath) = explode('/', substr($path, 4), 2);
         $path = ExtensionManagementUtility::extPath($extensionKey) . $relativePath;
     }
     $GLOBALS['TBE_MODULES']['_PATHS'][$name] = $path;
 }
 /**
  * Implements the "typolink" property of stdWrap (and others)
  * Basically the input string, $linktext, is (typically) wrapped in a <a>-tag linking to some page, email address, file or URL based on a parameter defined by the configuration array $conf.
  * This function is best used from internal functions as is. There are some API functions defined after this function which is more suited for general usage in external applications.
  * Generally the concept "typolink" should be used in your own applications as an API for making links to pages with parameters and more. The reason for this is that you will then automatically make links compatible with all the centralized functions for URL simulation and manipulation of parameters into hashes and more.
  * For many more details on the parameters and how they are interpreted, please see the link to TSref below.
  *
  * the FAL API is handled with the namespace/prefix "file:..."
  *
  * @param string $linkText The string (text) to link
  * @param array $conf TypoScript configuration (see link below)
  * @return string A link-wrapped string.
  * @see stdWrap(), \TYPO3\CMS\Frontend\Plugin\AbstractPlugin::pi_linkTP()
  */
 public function typoLink($linkText, $conf)
 {
     $linkText = (string) $linkText;
     $tsfe = $this->getTypoScriptFrontendController();
     $LD = array();
     $finalTagParts = array();
     $finalTagParts['aTagParams'] = $this->getATagParams($conf);
     $linkParameter = trim(isset($conf['parameter.']) ? $this->stdWrap($conf['parameter'], $conf['parameter.']) : $conf['parameter']);
     $this->lastTypoLinkUrl = '';
     $this->lastTypoLinkTarget = '';
     $resolvedLinkParameters = $this->resolveMixedLinkParameter($linkText, $linkParameter, $conf);
     // check if the link handler hook has resolved the link completely already
     if (!is_array($resolvedLinkParameters)) {
         return $resolvedLinkParameters;
     }
     $linkParameter = $resolvedLinkParameters['href'];
     $target = $resolvedLinkParameters['target'];
     $linkClass = $resolvedLinkParameters['class'];
     $forceTitle = $resolvedLinkParameters['title'];
     if (!$linkParameter) {
         return $linkText;
     }
     // Check, if the target is coded as a JS open window link:
     $JSwindowParts = array();
     $JSwindowParams = '';
     if ($target && preg_match('/^([0-9]+)x([0-9]+)(:(.*)|.*)$/', $target, $JSwindowParts)) {
         // Take all pre-configured and inserted parameters and compile parameter list, including width+height:
         $JSwindow_tempParamsArr = GeneralUtility::trimExplode(',', strtolower($conf['JSwindow_params'] . ',' . $JSwindowParts[4]), true);
         $JSwindow_paramsArr = array();
         foreach ($JSwindow_tempParamsArr as $JSv) {
             list($JSp, $JSv) = explode('=', $JSv, 2);
             $JSwindow_paramsArr[$JSp] = $JSp . '=' . $JSv;
         }
         // Add width/height:
         $JSwindow_paramsArr['width'] = 'width=' . $JSwindowParts[1];
         $JSwindow_paramsArr['height'] = 'height=' . $JSwindowParts[2];
         // Imploding into string:
         $JSwindowParams = implode(',', $JSwindow_paramsArr);
         // Resetting the target since we will use onClick.
         $target = '';
     }
     // Title tag
     $title = $conf['title'];
     if ($conf['title.']) {
         $title = $this->stdWrap($title, $conf['title.']);
     }
     $theTypeP = '';
     // Detecting kind of link
     $linkType = $this->detectLinkTypeFromLinkParameter($linkParameter);
     switch ($linkType) {
         // If it's a mail address
         case 'mailto':
             $linkParameter = preg_replace('/^mailto:/i', '', $linkParameter);
             list($this->lastTypoLinkUrl, $linkText) = $this->getMailTo($linkParameter, $linkText);
             $finalTagParts['url'] = $this->lastTypoLinkUrl;
             break;
             // url (external): If doubleSlash or if a '.' comes before a '/'.
         // url (external): If doubleSlash or if a '.' comes before a '/'.
         case 'url':
             if (empty($target)) {
                 if (isset($conf['extTarget'])) {
                     $target = $conf['extTarget'];
                 } elseif ($tsfe->dtdAllowsFrames) {
                     $target = $tsfe->extTarget;
                 }
                 if ($conf['extTarget.']) {
                     $target = $this->stdWrap($target, $conf['extTarget.']);
                 }
             }
             $linkText = $this->parseFallbackLinkTextIfLinkTextIsEmpty($linkText, $linkParameter);
             // Parse URL:
             $urlParts = parse_url($linkParameter);
             if (!$urlParts['scheme']) {
                 $scheme = 'http://';
             } else {
                 $scheme = '';
             }
             $this->lastTypoLinkUrl = $this->processUrl(UrlProcessorInterface::CONTEXT_EXTERNAL, $scheme . $linkParameter, $conf);
             $this->lastTypoLinkTarget = $target;
             $finalTagParts['url'] = $this->lastTypoLinkUrl;
             $finalTagParts['targetParams'] = $target ? ' target="' . $target . '"' : '';
             $finalTagParts['aTagParams'] .= $this->extLinkATagParams($finalTagParts['url'], $linkType);
             break;
             // file (internal)
         // file (internal)
         case 'file':
             $splitLinkParam = explode('?', $linkParameter);
             // check if the file exists or if a / is contained (same check as in detectLinkType)
             if (file_exists(rawurldecode($splitLinkParam[0])) || strpos($linkParameter, '/') !== false) {
                 // Setting title if blank value to link
                 $linkText = $this->parseFallbackLinkTextIfLinkTextIsEmpty($linkText, rawurldecode($linkParameter));
                 $fileUri = (!StringUtility::beginsWith($linkParameter, '/') ? $GLOBALS['TSFE']->absRefPrefix : '') . $linkParameter;
                 $this->lastTypoLinkUrl = $this->processUrl(UrlProcessorInterface::CONTEXT_FILE, $fileUri, $conf);
                 $this->lastTypoLinkUrl = $this->forceAbsoluteUrl($this->lastTypoLinkUrl, $conf);
                 if (empty($target)) {
                     $target = isset($conf['fileTarget']) ? $conf['fileTarget'] : $tsfe->fileTarget;
                     if ($conf['fileTarget.']) {
                         $target = $this->stdWrap($target, $conf['fileTarget.']);
                     }
                 }
                 $this->lastTypoLinkTarget = $target;
                 $finalTagParts['url'] = $this->lastTypoLinkUrl;
                 $finalTagParts['targetParams'] = $target ? ' target="' . $target . '"' : '';
                 $finalTagParts['aTagParams'] .= $this->extLinkATagParams($finalTagParts['url'], $linkType);
             } else {
                 $this->getTimeTracker()->setTSlogMessage('typolink(): File "' . $splitLinkParam[0] . '" did not exist, so "' . $linkText . '" was not linked.', 1);
                 return $linkText;
             }
             break;
             // Integer or alias (alias is without slashes or periods or commas, that is
             // 'nospace,alphanum_x,lower,unique' according to definition in $GLOBALS['TCA']!)
         // Integer or alias (alias is without slashes or periods or commas, that is
         // 'nospace,alphanum_x,lower,unique' according to definition in $GLOBALS['TCA']!)
         case 'page':
             $enableLinksAcrossDomains = $tsfe->config['config']['typolinkEnableLinksAcrossDomains'];
             if ($conf['no_cache.']) {
                 $conf['no_cache'] = $this->stdWrap($conf['no_cache'], $conf['no_cache.']);
             }
             // Splitting the parameter by ',' and if the array counts more than 1 element it's an id/type/parameters triplet
             $pairParts = GeneralUtility::trimExplode(',', $linkParameter, true);
             $linkParameter = $pairParts[0];
             $link_params_parts = explode('#', $linkParameter);
             // Link-data del
             $linkParameter = trim($link_params_parts[0]);
             // If no id or alias is given
             if ($linkParameter === '') {
                 $linkParameter = $tsfe->id;
             }
             $sectionMark = trim(isset($conf['section.']) ? $this->stdWrap($conf['section'], $conf['section.']) : $conf['section']);
             if ($sectionMark !== '') {
                 $sectionMark = '#' . (MathUtility::canBeInterpretedAsInteger($sectionMark) ? 'c' : '') . $sectionMark;
             }
             if ($link_params_parts[1] && $sectionMark === '') {
                 $sectionMark = trim($link_params_parts[1]);
                 $sectionMark = '#' . (MathUtility::canBeInterpretedAsInteger($sectionMark) ? 'c' : '') . $sectionMark;
             }
             if (count($pairParts) > 1) {
                 // Overruling 'type'
                 $theTypeP = isset($pairParts[1]) ? $pairParts[1] : 0;
                 $conf['additionalParams'] .= isset($pairParts[2]) ? $pairParts[2] : '';
             }
             // Checking if the id-parameter is an alias.
             if (!MathUtility::canBeInterpretedAsInteger($linkParameter)) {
                 $linkParameter = $tsfe->sys_page->getPageIdFromAlias($linkParameter);
             }
             // Link to page even if access is missing?
             if (isset($conf['linkAccessRestrictedPages'])) {
                 $disableGroupAccessCheck = (bool) $conf['linkAccessRestrictedPages'];
             } else {
                 $disableGroupAccessCheck = (bool) $tsfe->config['config']['typolinkLinkAccessRestrictedPages'];
             }
             // Looking up the page record to verify its existence:
             $page = $tsfe->sys_page->getPage($linkParameter, $disableGroupAccessCheck);
             if (!empty($page)) {
                 // MointPoints, look for closest MPvar:
                 $MPvarAcc = array();
                 if (!$tsfe->config['config']['MP_disableTypolinkClosestMPvalue']) {
                     $temp_MP = $this->getClosestMPvalueForPage($page['uid'], true);
                     if ($temp_MP) {
                         $MPvarAcc['closest'] = $temp_MP;
                     }
                 }
                 // Look for overlay Mount Point:
                 $mount_info = $tsfe->sys_page->getMountPointInfo($page['uid'], $page);
                 if (is_array($mount_info) && $mount_info['overlay']) {
                     $page = $tsfe->sys_page->getPage($mount_info['mount_pid'], $disableGroupAccessCheck);
                     if (empty($page)) {
                         $this->getTimeTracker()->setTSlogMessage('typolink(): Mount point "' . $mount_info['mount_pid'] . '" was not available, so "' . $linkText . '" was not linked.', 1);
                         return $linkText;
                     }
                     $MPvarAcc['re-map'] = $mount_info['MPvar'];
                 }
                 // Setting title if blank value to link
                 $linkText = $this->parseFallbackLinkTextIfLinkTextIsEmpty($linkText, $page['title']);
                 // Query Params:
                 $addQueryParams = $conf['addQueryString'] ? $this->getQueryArguments($conf['addQueryString.']) : '';
                 $addQueryParams .= isset($conf['additionalParams.']) ? trim($this->stdWrap($conf['additionalParams'], $conf['additionalParams.'])) : trim($conf['additionalParams']);
                 if ($addQueryParams === '&' || $addQueryParams[0] !== '&') {
                     $addQueryParams = '';
                 }
                 if ($conf['useCacheHash']) {
                     // Mind the order below! See http://forge.typo3.org/issues/17070
                     $params = $tsfe->linkVars . $addQueryParams;
                     if (trim($params, '& ') != '') {
                         /** @var $cacheHash CacheHashCalculator */
                         $cacheHash = GeneralUtility::makeInstance(CacheHashCalculator::class);
                         $cHash = $cacheHash->generateForParameters($params);
                         $addQueryParams .= $cHash ? '&cHash=' . $cHash : '';
                     }
                     unset($params);
                 }
                 $targetDomain = '';
                 $currentDomain = (string) $this->getEnvironmentVariable('HTTP_HOST');
                 // Mount pages are always local and never link to another domain
                 if (!empty($MPvarAcc)) {
                     // Add "&MP" var:
                     $addQueryParams .= '&MP=' . rawurlencode(implode(',', $MPvarAcc));
                 } elseif (strpos($addQueryParams, '&MP=') === false && $tsfe->config['config']['typolinkCheckRootline']) {
                     // We do not come here if additionalParams had '&MP='. This happens when typoLink is called from
                     // menu. Mount points always work in the content of the current domain and we must not change
                     // domain if MP variables exist.
                     // If we link across domains and page is free type shortcut, we must resolve the shortcut first!
                     // If we do not do it, TYPO3 will fail to (1) link proper page in RealURL/CoolURI because
                     // they return relative links and (2) show proper page if no RealURL/CoolURI exists when link is clicked
                     if ($enableLinksAcrossDomains && (int) $page['doktype'] === PageRepository::DOKTYPE_SHORTCUT && (int) $page['shortcut_mode'] === PageRepository::SHORTCUT_MODE_NONE) {
                         // Save in case of broken destination or endless loop
                         $page2 = $page;
                         // Same as in RealURL, seems enough
                         $maxLoopCount = 20;
                         while ($maxLoopCount && is_array($page) && (int) $page['doktype'] === PageRepository::DOKTYPE_SHORTCUT && (int) $page['shortcut_mode'] === PageRepository::SHORTCUT_MODE_NONE) {
                             $page = $tsfe->sys_page->getPage($page['shortcut'], $disableGroupAccessCheck);
                             $maxLoopCount--;
                         }
                         if (empty($page) || $maxLoopCount === 0) {
                             // We revert if shortcut is broken or maximum number of loops is exceeded (indicates endless loop)
                             $page = $page2;
                         }
                     }
                     $targetDomain = $tsfe->getDomainNameForPid($page['uid']);
                     // Do not prepend the domain if it is the current hostname
                     if (!$targetDomain || $tsfe->domainNameMatchesCurrentRequest($targetDomain)) {
                         $targetDomain = '';
                     }
                 }
                 $absoluteUrlScheme = 'http';
                 // URL shall be absolute:
                 if (isset($conf['forceAbsoluteUrl']) && $conf['forceAbsoluteUrl'] || $page['url_scheme'] > 0) {
                     // Override scheme:
                     if (isset($conf['forceAbsoluteUrl.']['scheme']) && $conf['forceAbsoluteUrl.']['scheme']) {
                         $absoluteUrlScheme = $conf['forceAbsoluteUrl.']['scheme'];
                     } elseif ($page['url_scheme'] > 0) {
                         $absoluteUrlScheme = (int) $page['url_scheme'] === HttpUtility::SCHEME_HTTP ? 'http' : 'https';
                     } elseif ($this->getEnvironmentVariable('TYPO3_SSL')) {
                         $absoluteUrlScheme = 'https';
                     }
                     // If no domain records are defined, use current domain:
                     $currentUrlScheme = parse_url($this->getEnvironmentVariable('TYPO3_REQUEST_URL'), PHP_URL_SCHEME);
                     if ($targetDomain === '' && ($conf['forceAbsoluteUrl'] || $absoluteUrlScheme !== $currentUrlScheme)) {
                         $targetDomain = $currentDomain;
                     }
                     // If go for an absolute link, add site path if it's not taken care about by absRefPrefix
                     if (!$tsfe->config['config']['absRefPrefix'] && $targetDomain === $currentDomain) {
                         $targetDomain = $currentDomain . rtrim($this->getEnvironmentVariable('TYPO3_SITE_PATH'), '/');
                     }
                 }
                 // If target page has a different domain and the current domain's linking scheme (e.g. RealURL/...) should not be used
                 if ($targetDomain !== '' && $targetDomain !== $currentDomain && !$enableLinksAcrossDomains) {
                     if (empty($target)) {
                         $target = isset($conf['extTarget']) ? $conf['extTarget'] : $tsfe->extTarget;
                         if ($conf['extTarget.']) {
                             $target = $this->stdWrap($target, $conf['extTarget.']);
                         }
                     }
                     $LD['target'] = $target;
                     // Convert IDNA-like domain (if any)
                     if (!preg_match('/^[a-z0-9.\\-]*$/i', $targetDomain)) {
                         $targetDomain = GeneralUtility::idnaEncode($targetDomain);
                     }
                     $this->lastTypoLinkUrl = $this->URLqMark($absoluteUrlScheme . '://' . $targetDomain . '/index.php?id=' . $page['uid'], $addQueryParams) . $sectionMark;
                 } else {
                     // Internal link or current domain's linking scheme should be used
                     // Internal target:
                     if (empty($target)) {
                         if (isset($conf['target'])) {
                             $target = $conf['target'];
                         } elseif ($tsfe->dtdAllowsFrames) {
                             $target = $tsfe->intTarget;
                         }
                         if ($conf['target.']) {
                             $target = $this->stdWrap($target, $conf['target.']);
                         }
                     }
                     $LD = $tsfe->tmpl->linkData($page, $target, $conf['no_cache'], '', '', $addQueryParams, $theTypeP, $targetDomain);
                     if ($targetDomain !== '') {
                         // We will add domain only if URL does not have it already.
                         if ($enableLinksAcrossDomains && $targetDomain !== $currentDomain) {
                             // Get rid of the absRefPrefix if necessary. absRefPrefix is applicable only
                             // to the current web site. If we have domain here it means we link across
                             // domains. absRefPrefix can contain domain name, which will screw up
                             // the link to the external domain.
                             $prefixLength = strlen($tsfe->config['config']['absRefPrefix']);
                             if (substr($LD['totalURL'], 0, $prefixLength) === $tsfe->config['config']['absRefPrefix']) {
                                 $LD['totalURL'] = substr($LD['totalURL'], $prefixLength);
                             }
                         }
                         $urlParts = parse_url($LD['totalURL']);
                         if (empty($urlParts['host'])) {
                             $LD['totalURL'] = $absoluteUrlScheme . '://' . $targetDomain . ($LD['totalURL'][0] === '/' ? '' : '/') . $LD['totalURL'];
                         }
                     }
                     $this->lastTypoLinkUrl = $this->URLqMark($LD['totalURL'], '') . $sectionMark;
                 }
                 $this->lastTypoLinkTarget = $LD['target'];
                 // If sectionMark is set, there is no baseURL AND the current page is the page the link is to, check if there are any additional parameters or addQueryString parameters and if not, drop the url.
                 if ($sectionMark && !$tsfe->config['config']['baseURL'] && (int) $page['uid'] === (int) $tsfe->id && !trim($addQueryParams) && (empty($conf['addQueryString']) || !isset($conf['addQueryString.']))) {
                     $currentQueryParams = $this->getQueryArguments(array());
                     if (!trim($currentQueryParams)) {
                         list(, $URLparams) = explode('?', $this->lastTypoLinkUrl);
                         list($URLparams) = explode('#', $URLparams);
                         parse_str($URLparams . $LD['orig_type'], $URLparamsArray);
                         // Type nums must match as well as page ids
                         if ((int) $URLparamsArray['type'] === (int) $tsfe->type) {
                             unset($URLparamsArray['id']);
                             unset($URLparamsArray['type']);
                             // If there are no parameters left.... set the new url.
                             if (empty($URLparamsArray)) {
                                 $this->lastTypoLinkUrl = $sectionMark;
                             }
                         }
                     }
                 }
                 // If link is to an access restricted page which should be redirected, then find new URL:
                 if (empty($conf['linkAccessRestrictedPages']) && $tsfe->config['config']['typolinkLinkAccessRestrictedPages'] && $tsfe->config['config']['typolinkLinkAccessRestrictedPages'] !== 'NONE' && !$tsfe->checkPageGroupAccess($page)) {
                     $thePage = $tsfe->sys_page->getPage($tsfe->config['config']['typolinkLinkAccessRestrictedPages']);
                     $addParams = str_replace(array('###RETURN_URL###', '###PAGE_ID###'), array(rawurlencode($this->lastTypoLinkUrl), $page['uid']), $tsfe->config['config']['typolinkLinkAccessRestrictedPages_addParams']);
                     $this->lastTypoLinkUrl = $this->getTypoLink_URL($thePage['uid'] . ($theTypeP ? ',' . $theTypeP : ''), $addParams, $target);
                     $this->lastTypoLinkUrl = $this->forceAbsoluteUrl($this->lastTypoLinkUrl, $conf);
                     $this->lastTypoLinkLD['totalUrl'] = $this->lastTypoLinkUrl;
                     $LD = $this->lastTypoLinkLD;
                 }
                 // Rendering the tag.
                 $finalTagParts['url'] = $this->lastTypoLinkUrl;
                 $finalTagParts['targetParams'] = (string) $LD['target'] !== '' ? ' target="' . htmlspecialchars($LD['target']) . '"' : '';
             } else {
                 $this->getTimeTracker()->setTSlogMessage('typolink(): Page id "' . $linkParameter . '" was not found, so "' . $linkText . '" was not linked.', 1);
                 return $linkText;
             }
             break;
     }
     $finalTagParts['TYPE'] = $linkType;
     $this->lastTypoLinkLD = $LD;
     if ($forceTitle) {
         $title = $forceTitle;
     }
     if ($JSwindowParams) {
         // Create TARGET-attribute only if the right doctype is used
         $xhtmlDocType = $tsfe->xhtmlDoctype;
         if ($xhtmlDocType !== 'xhtml_strict' && $xhtmlDocType !== 'xhtml_11') {
             $target = ' target="FEopenLink"';
         } else {
             $target = '';
         }
         $onClick = 'vHWin=window.open(' . GeneralUtility::quoteJSvalue($tsfe->baseUrlWrap($finalTagParts['url'])) . ',\'FEopenLink\',' . GeneralUtility::quoteJSvalue($JSwindowParams) . ');vHWin.focus();return false;';
         $finalAnchorTag = '<a href="' . htmlspecialchars($finalTagParts['url']) . '"' . $target . ' onclick="' . htmlspecialchars($onClick) . '"' . ((string) $title !== '' ? ' title="' . htmlspecialchars($title) . '"' : '') . ($linkClass !== '' ? ' class="' . $linkClass . '"' : '') . $finalTagParts['aTagParams'] . '>';
     } else {
         if ($tsfe->spamProtectEmailAddresses === 'ascii' && $linkType === 'mailto') {
             $finalAnchorTag = '<a href="' . $finalTagParts['url'] . '"';
         } else {
             $finalAnchorTag = '<a href="' . htmlspecialchars($finalTagParts['url']) . '"';
         }
         $finalAnchorTag .= ((string) $title !== '' ? ' title="' . htmlspecialchars($title) . '"' : '') . $finalTagParts['targetParams'] . ($linkClass ? ' class="' . $linkClass . '"' : '') . $finalTagParts['aTagParams'] . '>';
     }
     // Call user function:
     if ($conf['userFunc']) {
         $finalTagParts['TAG'] = $finalAnchorTag;
         $finalAnchorTag = $this->callUserFunction($conf['userFunc'], $conf['userFunc.'], $finalTagParts);
     }
     // Hook: Call post processing function for link rendering:
     if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['typoLink_PostProc']) && is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['typoLink_PostProc'])) {
         $_params = array('conf' => &$conf, 'linktxt' => &$linkText, 'finalTag' => &$finalAnchorTag, 'finalTagParts' => &$finalTagParts);
         foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['typoLink_PostProc'] as $_funcRef) {
             GeneralUtility::callUserFunction($_funcRef, $_params, $this);
         }
     }
     // If flag "returnLastTypoLinkUrl" set, then just return the latest URL made:
     if ($conf['returnLast']) {
         switch ($conf['returnLast']) {
             case 'url':
                 return $this->lastTypoLinkUrl;
                 break;
             case 'target':
                 return $this->lastTypoLinkTarget;
                 break;
         }
     }
     $wrap = isset($conf['wrap.']) ? $this->stdWrap($conf['wrap'], $conf['wrap.']) : $conf['wrap'];
     if ($conf['ATagBeforeWrap']) {
         return $finalAnchorTag . $this->wrap($linkText, $wrap) . '</a>';
     }
     return $this->wrap($finalAnchorTag . $linkText . '</a>', $wrap);
 }