[TASK] CGL: Fix a series of minor indentation issues
[Packages/TYPO3.CMS.git] / typo3 / sysext / frontend / Classes / Controller / TypoScriptFrontendController.php
index 1aa5aee..06e40ce 100644 (file)
@@ -40,6 +40,7 @@ use TYPO3\CMS\Core\Page\PageRenderer;
 use TYPO3\CMS\Core\Resource\StorageRepository;
 use TYPO3\CMS\Core\Service\DependencyOrderingService;
 use TYPO3\CMS\Core\TimeTracker\TimeTracker;
 use TYPO3\CMS\Core\Resource\StorageRepository;
 use TYPO3\CMS\Core\Service\DependencyOrderingService;
 use TYPO3\CMS\Core\TimeTracker\TimeTracker;
+use TYPO3\CMS\Core\Type\Bitmask\Permission;
 use TYPO3\CMS\Core\TypoScript\Parser\TypoScriptParser;
 use TYPO3\CMS\Core\TypoScript\TemplateService;
 use TYPO3\CMS\Core\Utility\ArrayUtility;
 use TYPO3\CMS\Core\TypoScript\Parser\TypoScriptParser;
 use TYPO3\CMS\Core\TypoScript\TemplateService;
 use TYPO3\CMS\Core\Utility\ArrayUtility;
@@ -483,12 +484,6 @@ class TypoScriptFrontendController implements LoggerAwareInterface
     public $absRefPrefix = '';
 
     /**
     public $absRefPrefix = '';
 
     /**
-     * Lock file path
-     * @var string
-     */
-    public $lockFilePath = '';
-
-    /**
      * <A>-tag parameters
      * @var string
      */
      * <A>-tag parameters
      * @var string
      */
@@ -1293,14 +1288,6 @@ class TypoScriptFrontendController implements LoggerAwareInterface
         $this->initUserGroups();
         // Sets sys_page where-clause
         $this->setSysPageWhereClause();
         $this->initUserGroups();
         // Sets sys_page where-clause
         $this->setSysPageWhereClause();
-        // Splitting $this->id by a period (.).
-        // First part is 'id' and second part (if exists) will overrule the &type param
-        $idParts = explode('.', $this->id, 2);
-        $this->id = $idParts[0];
-        if (isset($idParts[1])) {
-            $this->type = $idParts[1];
-        }
-
         // If $this->id is a string, it's an alias
         $this->checkAndSetAlias();
         // The id and type is set to the integer-value - just to be sure...
         // If $this->id is a string, it's an alias
         $this->checkAndSetAlias();
         // The id and type is set to the integer-value - just to be sure...
@@ -1606,20 +1593,36 @@ class TypoScriptFrontendController implements LoggerAwareInterface
     }
 
     /**
     }
 
     /**
-     * Checks the current rootline for defined sections.
+     * Checks if visibility of the page is blocked upwards in the root line.
+     *
+     * If any page in the root line is blocking visibility, true is returend.
+     *
+     * All pages from the blocking page downwards are removed from the root
+     * line, so that the remaning pages can be used to relocate the page up
+     * to lowest visible page.
+     *
+     * The blocking feature of a page must be turned on by setting the page
+     * record field 'extendToSubpages' to 1.
+     *
+     * The following fields are evaluated then:
+     *
+     *      hidden, starttime, endtime, fe_group
+     *
+     * @todo Find a better name, i.e. checkVisibilityByRootLine
+     * @todo Invert boolean return value. Return true if visible.
      *
      * @return bool
      * @access private
      */
      *
      * @return bool
      * @access private
      */
-    public function checkRootlineForIncludeSection()
+    public function checkRootlineForIncludeSection(): bool
     {
         $c = count($this->rootLine);
     {
         $c = count($this->rootLine);
-        $removeTheRestFlag = 0;
+        $removeTheRestFlag = false;
         for ($a = 0; $a < $c; $a++) {
             if (!$this->checkPagerecordForIncludeSection($this->rootLine[$a])) {
                 // Add to page access failure history:
                 $this->pageAccessFailureHistory['sub_section'][] = $this->rootLine[$a];
         for ($a = 0; $a < $c; $a++) {
             if (!$this->checkPagerecordForIncludeSection($this->rootLine[$a])) {
                 // Add to page access failure history:
                 $this->pageAccessFailureHistory['sub_section'][] = $this->rootLine[$a];
-                $removeTheRestFlag = 1;
+                $removeTheRestFlag = true;
             }
 
             if ($this->rootLine[$a]['doktype'] == PageRepository::DOKTYPE_BE_USER_SECTION) {
             }
 
             if ($this->rootLine[$a]['doktype'] == PageRepository::DOKTYPE_BE_USER_SECTION) {
@@ -1640,7 +1643,7 @@ class TypoScriptFrontendController implements LoggerAwareInterface
                                 'uid',
                                 $queryBuilder->createNamedParameter($this->id, \PDO::PARAM_INT)
                             ),
                                 'uid',
                                 $queryBuilder->createNamedParameter($this->id, \PDO::PARAM_INT)
                             ),
-                            $this->getBackendUser()->getPagePermsClause(1)
+                            $this->getBackendUser()->getPagePermsClause(Permission::PAGE_SHOW)
                         )
                         ->execute()
                         ->fetch();
                         )
                         ->execute()
                         ->fetch();
@@ -1648,17 +1651,18 @@ class TypoScriptFrontendController implements LoggerAwareInterface
                     // versionOL()?
                     if (!$row) {
                         // If there was no page selected, the user apparently did not have read access to the current PAGE (not position in rootline) and we set the remove-flag...
                     // versionOL()?
                     if (!$row) {
                         // If there was no page selected, the user apparently did not have read access to the current PAGE (not position in rootline) and we set the remove-flag...
-                        $removeTheRestFlag = 1;
+                        $removeTheRestFlag = true;
                     }
                 } else {
                     // Don't go here, if there is no backend user logged in.
                     }
                 } else {
                     // Don't go here, if there is no backend user logged in.
-                    $removeTheRestFlag = 1;
+                    $removeTheRestFlag = true;
                 }
             }
             if ($removeTheRestFlag) {
                 // Page is 'not found' in case a subsection was found and not accessible, code 2
                 $this->pageNotFound = 2;
                 unset($this->rootLine[$a]);
                 }
             }
             if ($removeTheRestFlag) {
                 // Page is 'not found' in case a subsection was found and not accessible, code 2
                 $this->pageNotFound = 2;
                 unset($this->rootLine[$a]);
+                break;
             }
         }
         return $removeTheRestFlag;
             }
         }
         return $removeTheRestFlag;
@@ -1711,16 +1715,23 @@ class TypoScriptFrontendController implements LoggerAwareInterface
     }
 
     /**
     }
 
     /**
-     * Checks page record for include section
+     * Checks if the current page of the root line is visible.
+     *
+     * If the field extendToSubpages is 0, access is granted,
+     * else the fields hidden, starttime, endtime, fe_group are evaluated.
+     *
+     * @todo Find a better name, i.e. isVisibleRecord()
      *
      *
-     * @param array $row The page record to evaluate (needs fields: extendToSubpages + hidden, starttime, endtime, fe_group)
-     * @return bool Returns TRUE if either extendToSubpages is not checked or if the enableFields does not disable the page record.
+     * @param array $row The page record
+     * @return bool true if visible
      * @access private
      * @access private
-     * @see checkEnableFields(), \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer::getTreeList(), checkRootlineForIncludeSection()
+     * @see checkEnableFields()
+     * @see \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer::getTreeList()
+     * @see checkRootlineForIncludeSection()
      */
      */
-    public function checkPagerecordForIncludeSection($row)
+    public function checkPagerecordForIncludeSection(array $row): bool
     {
     {
-        return !$row['extendToSubpages'] || $this->checkEnableFields($row) ? 1 : 0;
+        return !$row['extendToSubpages'] || $this->checkEnableFields($row);
     }
 
     /**
     }
 
     /**
@@ -2147,7 +2158,7 @@ class TypoScriptFrontendController implements LoggerAwareInterface
             $GET['id'] = $this->id;
             $this->cHash_array = $this->cacheHash->getRelevantParameters(GeneralUtility::implodeArrayForUrl('', $GET));
             $cHash_calc = $this->cacheHash->calculateCacheHash($this->cHash_array);
             $GET['id'] = $this->id;
             $this->cHash_array = $this->cacheHash->getRelevantParameters(GeneralUtility::implodeArrayForUrl('', $GET));
             $cHash_calc = $this->cacheHash->calculateCacheHash($this->cHash_array);
-            if ($cHash_calc != $this->cHash) {
+            if (!hash_equals($cHash_calc, $this->cHash)) {
                 if ($GLOBALS['TYPO3_CONF_VARS']['FE']['pageNotFoundOnCHashError']) {
                     $this->pageNotFoundAndExit('Request parameters could not be validated (&cHash comparison failed)');
                 } else {
                 if ($GLOBALS['TYPO3_CONF_VARS']['FE']['pageNotFoundOnCHashError']) {
                     $this->pageNotFoundAndExit('Request parameters could not be validated (&cHash comparison failed)');
                 } else {
@@ -2830,7 +2841,7 @@ class TypoScriptFrontendController implements LoggerAwareInterface
                 }
                 if (!is_array($value)) {
                     $temp = rawurlencode($value);
                 }
                 if (!is_array($value)) {
                     $temp = rawurlencode($value);
-                    if ($test !== '' && !PageGenerator::isAllowedLinkVarValue($temp, $test)) {
+                    if ($test !== '' && !$this->isAllowedLinkVarValue($temp, $test)) {
                         // Error: This value was not allowed for this key
                         continue;
                     }
                         // Error: This value was not allowed for this key
                         continue;
                     }
@@ -2870,6 +2881,49 @@ class TypoScriptFrontendController implements LoggerAwareInterface
     }
 
     /**
     }
 
     /**
+     * Checks if the value defined in "config.linkVars" contains an allowed value.
+     * Otherwise, return FALSE which means the value will not be added to any links.
+     *
+     * @param string $haystack The string in which to find $needle
+     * @param string $needle The string to find in $haystack
+     * @return bool Returns TRUE if $needle matches or is found in $haystack
+     */
+    protected function isAllowedLinkVarValue(string $haystack, string $needle): bool
+    {
+        $isAllowed = false;
+        // Integer
+        if ($needle === 'int' || $needle === 'integer') {
+            if (MathUtility::canBeInterpretedAsInteger($haystack)) {
+                $isAllowed = true;
+            }
+        } elseif (preg_match('/^\\/.+\\/[imsxeADSUXu]*$/', $needle)) {
+            // Regular expression, only "//" is allowed as delimiter
+            if (@preg_match($needle, $haystack)) {
+                $isAllowed = true;
+            }
+        } elseif (strstr($needle, '-')) {
+            // Range
+            if (MathUtility::canBeInterpretedAsInteger($haystack)) {
+                $range = explode('-', $needle);
+                if ($range[0] <= $haystack && $range[1] >= $haystack) {
+                    $isAllowed = true;
+                }
+            }
+        } elseif (strstr($needle, '|')) {
+            // List
+            // Trim the input
+            $haystack = str_replace(' ', '', $haystack);
+            if (strstr('|' . $needle . '|', '|' . $haystack . '|')) {
+                $isAllowed = true;
+            }
+        } elseif ((string)$needle === (string)$haystack) {
+            // String comparison
+            $isAllowed = true;
+        }
+        return $isAllowed;
+    }
+
+    /**
      * Redirect to target page if the current page is an overlaid mountpoint.
      *
      * If the current page is of type mountpoint and should be overlaid with the contents of the mountpoint page
      * Redirect to target page if the current page is an overlaid mountpoint.
      *
      * If the current page is of type mountpoint and should be overlaid with the contents of the mountpoint page
@@ -2945,7 +2999,7 @@ class TypoScriptFrontendController implements LoggerAwareInterface
         $this->tempContent = false;
         if (!$this->no_cache) {
             $seconds = 30;
         $this->tempContent = false;
         if (!$this->no_cache) {
             $seconds = 30;
-            $title = htmlspecialchars($this->tmpl->printTitle($this->page['title']));
+            $title = htmlspecialchars($this->printTitle($this->page['title']));
             $request_uri = htmlspecialchars(GeneralUtility::getIndpEnv('REQUEST_URI'));
             $stdMsg = '
                <strong>Page is being generated.</strong><br />
             $request_uri = htmlspecialchars(GeneralUtility::getIndpEnv('REQUEST_URI'));
             $stdMsg = '
                <strong>Page is being generated.</strong><br />
@@ -3208,8 +3262,6 @@ class TypoScriptFrontendController implements LoggerAwareInterface
         } else {
             $this->absRefPrefix = '';
         }
         } else {
             $this->absRefPrefix = '';
         }
-        $this->lockFilePath = '' . $this->config['config']['lockFilePath'];
-        $this->lockFilePath = $this->lockFilePath ?: $GLOBALS['TYPO3_CONF_VARS']['BE']['fileadminDir'];
         $this->ATagParams = trim($this->config['config']['ATagParams']) ? ' ' . trim($this->config['config']['ATagParams']) : '';
         $this->initializeSearchWordDataInTsfe();
         // linkVars
         $this->ATagParams = trim($this->config['config']['ATagParams']) ? ' ' . trim($this->config['config']['ATagParams']) : '';
         $this->initializeSearchWordDataInTsfe();
         // linkVars
@@ -3314,11 +3366,82 @@ class TypoScriptFrontendController implements LoggerAwareInterface
     }
 
     /**
     }
 
     /**
-     * Generate the page title again as TSFE->altPageTitle might have been modified by an inc script
+     * Generate the page title, can be called multiple times,
+     * as $this->altPageTitle might have been modified by an uncached plugin etc.
+     *
+     * @return string the generated page title
+     */
+    public function generatePageTitle(): string
+    {
+        $pageTitleSeparator = '';
+
+        // Check for a custom pageTitleSeparator, and perform stdWrap on it
+        if (isset($this->config['config']['pageTitleSeparator']) && $this->config['config']['pageTitleSeparator'] !== '') {
+            $pageTitleSeparator = $this->config['config']['pageTitleSeparator'];
+
+            if (isset($this->config['config']['pageTitleSeparator.']) && is_array($this->config['config']['pageTitleSeparator.'])) {
+                $pageTitleSeparator = $this->cObj->stdWrap($pageTitleSeparator, $this->config['config']['pageTitleSeparator.']);
+            } else {
+                $pageTitleSeparator .= ' ';
+            }
+        }
+
+        $pageTitle = $this->altPageTitle ?: $this->page['title'] ?? '';
+        $titleTagContent = $this->printTitle(
+            $pageTitle,
+            (bool)$this->config['config']['noPageTitle'],
+            (bool)$this->config['config']['pageTitleFirst'],
+            $pageTitleSeparator
+        );
+        if ($this->config['config']['titleTagFunction']) {
+            $titleTagContent = $this->cObj->callUserFunction(
+                $this->config['config']['titleTagFunction'],
+                [],
+                $titleTagContent
+            );
+        }
+        // stdWrap around the title tag
+        if (isset($this->config['config']['pageTitle.']) && is_array($this->config['config']['pageTitle.'])) {
+            $titleTagContent = $this->cObj->stdWrap($titleTagContent, $this->config['config']['pageTitle.']);
+        }
+
+        // config.noPageTitle = 2 - means do not render the page title
+        if ($this->config['config']['noPageTitle'] === 2) {
+            $titleTagContent = '';
+        }
+        if ($titleTagContent !== '') {
+            $this->pageRenderer->setTitle($titleTagContent);
+        }
+        return (string)$titleTagContent;
+    }
+
+    /**
+     * Compiles the content for the page <title> tag.
+     *
+     * @param string $pageTitle The input title string, typically the "title" field of a page's record.
+     * @param bool $noTitle If set, then only the site title is outputted (from $this->setup['sitetitle'])
+     * @param bool $showTitleFirst If set, then "sitetitle" and $title is swapped
+     * @param string $pageTitleSeparator an alternative to the ": " as the separator between site title and page title
+     * @return string The page title on the form "[sitetitle]: [input-title]". Not htmlspecialchar()'ed.
+     * @see tempPageCacheContent(), generatePageTitle()
      */
      */
-    protected function regeneratePageTitle()
+    protected function printTitle(string $pageTitle, bool $noTitle = false, bool $showTitleFirst = false, string $pageTitleSeparator = ''): string
     {
     {
-        PageGenerator::generatePageTitle();
+        $siteTitle = trim($this->tmpl->setup['sitetitle'] ?? '');
+        $pageTitle = $noTitle ? '' : $pageTitle;
+        if ($showTitleFirst) {
+            $temp = $siteTitle;
+            $siteTitle = $pageTitle;
+            $pageTitle = $temp;
+        }
+        // only show a separator if there are both site title and page title
+        if ($pageTitle === '' || $siteTitle === '') {
+            $pageTitleSeparator = '';
+        } elseif (empty($pageTitleSeparator)) {
+            // use the default separator if non given
+            $pageTitleSeparator = ': ';
+        }
+        return $siteTitle . $pageTitleSeparator . $pageTitle;
     }
 
     /**
     }
 
     /**
@@ -3345,7 +3468,7 @@ class TypoScriptFrontendController implements LoggerAwareInterface
         $this->recursivelyReplaceIntPlaceholdersInContent();
         $this->getTimeTracker()->push('Substitute header section');
         $this->INTincScript_loadJSCode();
         $this->recursivelyReplaceIntPlaceholdersInContent();
         $this->getTimeTracker()->push('Substitute header section');
         $this->INTincScript_loadJSCode();
-        $this->regeneratePageTitle();
+        $this->generatePageTitle();
 
         $this->content = str_replace(
             [
 
         $this->content = str_replace(
             [
@@ -4390,7 +4513,7 @@ class TypoScriptFrontendController implements LoggerAwareInterface
      *
      * @param int $targetPid Target page id
      * @return mixed Return domain data or NULL
      *
      * @param int $targetPid Target page id
      * @return mixed Return domain data or NULL
-    */
+     */
     public function getDomainDataForPid($targetPid)
     {
         // Using array_key_exists() here, nice $result can be NULL
     public function getDomainDataForPid($targetPid)
     {
         // Using array_key_exists() here, nice $result can be NULL