[BUGFIX] Fix several typos in php comments
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Page / PageRenderer.php
index 75dca76..249344c 100644 (file)
@@ -16,24 +16,24 @@ namespace TYPO3\CMS\Core\Page;
 
 use TYPO3\CMS\Backend\Routing\Router;
 use TYPO3\CMS\Backend\Routing\UriBuilder;
-use TYPO3\CMS\Backend\Template\DocumentTemplate;
 use TYPO3\CMS\Core\Cache\CacheManager;
-use TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException;
 use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface;
 use TYPO3\CMS\Core\Core\Environment;
+use TYPO3\CMS\Core\Localization\Locales;
 use TYPO3\CMS\Core\Localization\LocalizationFactory;
 use TYPO3\CMS\Core\MetaTag\MetaTagManagerRegistry;
+use TYPO3\CMS\Core\Package\PackageManager;
+use TYPO3\CMS\Core\Resource\ResourceCompressor;
 use TYPO3\CMS\Core\Service\MarkerBasedTemplateService;
-use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
+use TYPO3\CMS\Core\SingletonInterface;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Core\Utility\PathUtility;
-use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
 
 /**
  * TYPO3 pageRender class
  * This class render the HTML of a webpage, usable for BE and FE
  */
-class PageRenderer implements \TYPO3\CMS\Core\SingletonInterface
+class PageRenderer implements SingletonInterface
 {
     // Constants for the part to be rendered
     const PART_COMPLETE = 0;
@@ -74,7 +74,7 @@ class PageRenderer implements \TYPO3\CMS\Core\SingletonInterface
     protected $moveJsFromHeaderToFooter = false;
 
     /**
-     * @var \TYPO3\CMS\Core\Localization\Locales
+     * @var Locales
      */
     protected $locales;
 
@@ -95,7 +95,7 @@ class PageRenderer implements \TYPO3\CMS\Core\SingletonInterface
     protected $languageDependencies = [];
 
     /**
-     * @var \TYPO3\CMS\Core\Resource\ResourceCompressor
+     * @var ResourceCompressor
      */
     protected $compressor;
 
@@ -171,13 +171,6 @@ class PageRenderer implements \TYPO3\CMS\Core\SingletonInterface
     protected $metaTags = [];
 
     /**
-     * META Tags added via the API
-     *
-     * @var array
-     */
-    protected $metaTagsByAPI = [];
-
-    /**
      * @var array
      */
     protected $inlineComments = [];
@@ -341,7 +334,7 @@ class PageRenderer implements \TYPO3\CMS\Core\SingletonInterface
     public function __construct($templateFile = '')
     {
         $this->reset();
-        $this->locales = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Localization\Locales::class);
+        $this->locales = GeneralUtility::makeInstance(Locales::class);
         if ($templateFile !== '') {
             $this->templateFile = $templateFile;
         }
@@ -359,6 +352,15 @@ class PageRenderer implements \TYPO3\CMS\Core\SingletonInterface
     }
 
     /**
+     * Set restored meta tag managers as singletons
+     * so that uncached plugins can use them to add or remove meta tags
+     */
+    public function __wakeup()
+    {
+        GeneralUtility::setSingletonInstance(get_class($this->metaTagRegistry), $this->metaTagRegistry);
+    }
+
+    /**
      * @param FrontendInterface $cache
      */
     public static function setCache(FrontendInterface $cache)
@@ -918,7 +920,6 @@ class PageRenderer implements \TYPO3\CMS\Core\SingletonInterface
                 1496402460
             );
         }
-
         $manager = $this->metaTagRegistry->getManagerForProperty($name);
         $manager->addProperty($name, $content, $subProperties, $replace, $type);
     }
@@ -1018,11 +1019,8 @@ class PageRenderer implements \TYPO3\CMS\Core\SingletonInterface
      * @param bool $defer Flag if property 'defer="defer"' should be added to JavaScript tags
      * @param string $crossorigin CORS settings attribute
      */
-    public function addJsLibrary($name, $file, $type = 'text/javascript', $compress = false, $forceOnTop = false, $allWrap = '', $excludeFromConcatenation = false, $splitChar = '|', $async = false, $integrity = '', $defer = false, $crossorigin = '')
+    public function addJsLibrary($name, $file, $type = '', $compress = false, $forceOnTop = false, $allWrap = '', $excludeFromConcatenation = false, $splitChar = '|', $async = false, $integrity = '', $defer = false, $crossorigin = '')
     {
-        if (!$type) {
-            $type = 'text/javascript';
-        }
         if (!in_array(strtolower($name), $this->jsLibs)) {
             $this->jsLibs[strtolower($name)] = [
                 'file' => $file,
@@ -1057,11 +1055,8 @@ class PageRenderer implements \TYPO3\CMS\Core\SingletonInterface
      * @param bool $defer Flag if property 'defer="defer"' should be added to JavaScript tags
      * @param string $crossorigin CORS settings attribute
      */
-    public function addJsFooterLibrary($name, $file, $type = 'text/javascript', $compress = false, $forceOnTop = false, $allWrap = '', $excludeFromConcatenation = false, $splitChar = '|', $async = false, $integrity = '', $defer = false, $crossorigin = '')
+    public function addJsFooterLibrary($name, $file, $type = '', $compress = false, $forceOnTop = false, $allWrap = '', $excludeFromConcatenation = false, $splitChar = '|', $async = false, $integrity = '', $defer = false, $crossorigin = '')
     {
-        if (!$type) {
-            $type = 'text/javascript';
-        }
         $name .= '_jsFooterLibrary';
         if (!in_array(strtolower($name), $this->jsLibs)) {
             $this->jsLibs[strtolower($name)] = [
@@ -1096,11 +1091,8 @@ class PageRenderer implements \TYPO3\CMS\Core\SingletonInterface
      * @param bool $defer Flag if property 'defer="defer"' should be added to JavaScript tags
      * @param string $crossorigin CORS settings attribute
      */
-    public function addJsFile($file, $type = 'text/javascript', $compress = true, $forceOnTop = false, $allWrap = '', $excludeFromConcatenation = false, $splitChar = '|', $async = false, $integrity = '', $defer = false, $crossorigin = '')
+    public function addJsFile($file, $type = '', $compress = true, $forceOnTop = false, $allWrap = '', $excludeFromConcatenation = false, $splitChar = '|', $async = false, $integrity = '', $defer = false, $crossorigin = '')
     {
-        if (!$type) {
-            $type = 'text/javascript';
-        }
         if (!isset($this->jsFiles[$file])) {
             $this->jsFiles[$file] = [
                 'file' => $file,
@@ -1134,11 +1126,8 @@ class PageRenderer implements \TYPO3\CMS\Core\SingletonInterface
      * @param bool $defer Flag if property 'defer="defer"' should be added to JavaScript tags
      * @param string $crossorigin CORS settings attribute
      */
-    public function addJsFooterFile($file, $type = 'text/javascript', $compress = true, $forceOnTop = false, $allWrap = '', $excludeFromConcatenation = false, $splitChar = '|', $async = false, $integrity = '', $defer = false, $crossorigin = '')
+    public function addJsFooterFile($file, $type = '', $compress = true, $forceOnTop = false, $allWrap = '', $excludeFromConcatenation = false, $splitChar = '|', $async = false, $integrity = '', $defer = false, $crossorigin = '')
     {
-        if (!$type) {
-            $type = 'text/javascript';
-        }
         if (!isset($this->jsFiles[$file])) {
             $this->jsFiles[$file] = [
                 'file' => $file,
@@ -1293,16 +1282,16 @@ class PageRenderer implements \TYPO3\CMS\Core\SingletonInterface
             return;
         }
 
-        $loadedExtensions = ExtensionManagementUtility::getLoadedExtensionListArray();
+        $packages = GeneralUtility::makeInstance(PackageManager::class)->getActivePackages();
         $isDevelopment = GeneralUtility::getApplicationContext()->isDevelopment();
-        $cacheIdentifier = 'requireJS_' . md5(implode(',', $loadedExtensions) . ($isDevelopment ? ':dev' : '') . GeneralUtility::getIndpEnv('TYPO3_REQUEST_SCRIPT'));
+        $cacheIdentifier = 'requireJS_' . md5(implode(',', array_keys($packages)) . ($isDevelopment ? ':dev' : '') . GeneralUtility::getIndpEnv('TYPO3_REQUEST_SCRIPT'));
         /** @var FrontendInterface $cache */
         $cache = static::$cache ?? GeneralUtility::makeInstance(CacheManager::class)->getCache('assets');
         $requireJsConfig = $cache->get($cacheIdentifier);
 
         // if we did not get a configuration from the cache, compute and store it in the cache
         if (!isset($requireJsConfig['internal']) || !isset($requireJsConfig['public'])) {
-            $requireJsConfig = $this->computeRequireJsConfig($isDevelopment, $loadedExtensions);
+            $requireJsConfig = $this->computeRequireJsConfig($isDevelopment, $packages);
             $cache->set($cacheIdentifier, $requireJsConfig);
         }
 
@@ -1316,10 +1305,10 @@ class PageRenderer implements \TYPO3\CMS\Core\SingletonInterface
      * resource folders plus some additional generic configuration.
      *
      * @param bool $isDevelopment
-     * @param array $loadedExtensions
+     * @param array $packages
      * @return array The RequireJS configuration
      */
-    protected function computeRequireJsConfig($isDevelopment, array $loadedExtensions)
+    protected function computeRequireJsConfig($isDevelopment, array $packages)
     {
         // load all paths to map to package names / namespaces
         $requireJsConfig = [
@@ -1328,13 +1317,7 @@ class PageRenderer implements \TYPO3\CMS\Core\SingletonInterface
             'internalNames' => [],
         ];
 
-        // In order to avoid browser caching of JS files, adding a GET parameter to the files loaded via requireJS
-        if ($isDevelopment) {
-            $requireJsConfig['public']['urlArgs'] = 'bust=' . $GLOBALS['EXEC_TIME'];
-        } else {
-            $requireJsConfig['public']['urlArgs'] = 'bust=' . GeneralUtility::hmac(TYPO3_version . Environment::getProjectPath());
-        }
-        $corePath = ExtensionManagementUtility::extPath('core', 'Resources/Public/JavaScript/Contrib/');
+        $corePath = $packages['core']->getPackagePath() . 'Resources/Public/JavaScript/Contrib/';
         $corePath = PathUtility::getAbsoluteWebPath($corePath);
         // first, load all paths for the namespaces, and configure contrib libs.
         $requireJsConfig['public']['paths'] = [
@@ -1353,18 +1336,20 @@ class PageRenderer implements \TYPO3\CMS\Core\SingletonInterface
             'jquery/autocomplete' => $corePath . 'jquery.autocomplete',
             'd3' => $corePath . 'd3/d3',
             'Sortable' => $corePath . 'Sortable.min',
+            'broadcastchannel' => $corePath . '/broadcastchannel-polyfill',
         ];
         $requireJsConfig['public']['waitSeconds'] = 30;
         $requireJsConfig['public']['typo3BaseUrl'] = false;
         $publicPackageNames = ['core', 'frontend', 'backend'];
-        foreach ($loadedExtensions as $packageName) {
-            $jsPath = 'EXT:' . $packageName . '/Resources/Public/JavaScript/';
-            $absoluteJsPath = GeneralUtility::getFileAbsFileName($jsPath);
+        $requireJsExtensionVersions = [];
+        foreach ($packages as $packageName => $package) {
+            $absoluteJsPath = $package->getPackagePath() . 'Resources/Public/JavaScript/';
             $fullJsPath = PathUtility::getAbsoluteWebPath($absoluteJsPath);
             $fullJsPath = rtrim($fullJsPath, '/');
             if (!empty($fullJsPath) && file_exists($absoluteJsPath)) {
                 $type = in_array($packageName, $publicPackageNames, true) ? 'public' : 'internal';
                 $requireJsConfig[$type]['paths']['TYPO3/CMS/' . GeneralUtility::underscoredToUpperCamelCase($packageName)] = $fullJsPath;
+                $requireJsExtensionVersions[] = $package->getPackageKey() . ':' . $package->getPackageMetadata()->getVersion();
             }
         }
         // sanitize module names in internal 'paths'
@@ -1381,6 +1366,15 @@ class PageRenderer implements \TYPO3\CMS\Core\SingletonInterface
             $internalPathModuleNames
         );
 
+        // Add a GET parameter to the files loaded via requireJS in order to avoid browser caching of JS files
+        if ($isDevelopment) {
+            $requireJsConfig['public']['urlArgs'] = 'bust=' . $GLOBALS['EXEC_TIME'];
+        } else {
+            $requireJsConfig['public']['urlArgs'] = 'bust=' . GeneralUtility::hmac(
+                Environment::getProjectPath() . implode('|', $requireJsExtensionVersions)
+            );
+        }
+
         // check if additional AMD modules need to be loaded if a single AMD module is initialized
         if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['RequireJS']['postInitializationModules'] ?? false)) {
             $this->addInlineSettingArray(
@@ -1447,14 +1441,14 @@ class PageRenderer implements \TYPO3\CMS\Core\SingletonInterface
         // directly after that, include the require.js file
         $html .= '<script src="'
             . $this->processJsFile($this->requireJsPath . 'require.js')
-            . '" type="text/javascript"></script>' . LF;
+            . '"></script>' . LF;
 
         if (!empty($requireJsConfig['typo3BaseUrl'])) {
             $html .= '<script src="'
                 . $this->processJsFile(
                     'EXT:core/Resources/Public/JavaScript/requirejs-loader.js'
                 )
-                . '" type="text/javascript"></script>' . LF;
+                . '"></script>' . LF;
         }
 
         return $html;
@@ -1674,33 +1668,11 @@ class PageRenderer implements \TYPO3\CMS\Core\SingletonInterface
     {
         $metaTags = [];
         $metaTagManagers = $this->metaTagRegistry->getAllManagers();
-        try {
-            $cache = GeneralUtility::makeInstance(CacheManager::class)->getCache('pages');
-        } catch (NoSuchCacheException $e) {
-            $cache = null;
-        }
 
         foreach ($metaTagManagers as $manager => $managerObject) {
-            $cacheIdentifier =  $this->getTypoScriptFrontendController()->newHash . '-metatag-' . $manager;
-
-            $existingCacheEntry = false;
-            if ($cache instanceof FrontendInterface && $properties = $cache->get($cacheIdentifier)) {
-                $existingCacheEntry = true;
-            } else {
-                $properties = $managerObject->renderAllProperties();
-            }
-
+            $properties = $managerObject->renderAllProperties();
             if (!empty($properties)) {
                 $metaTags[] = $properties;
-
-                if ($cache instanceof FrontendInterface && !$existingCacheEntry && ($this->getTypoScriptFrontendController()->page['uid'] ?? false)) {
-                    $cache->set(
-                        $cacheIdentifier,
-                        $properties,
-                        ['pageId_' . $this->getTypoScriptFrontendController()->page['uid']],
-                        $this->getTypoScriptFrontendController()->get_cache_timeout()
-                    );
-                }
             }
         }
         return $metaTags;
@@ -1709,7 +1681,7 @@ class PageRenderer implements \TYPO3\CMS\Core\SingletonInterface
     /**
      * Render the page but not the JavaScript and CSS Files
      *
-     * @param string $substituteHash The hash that is used for the placehoder markers
+     * @param string $substituteHash The hash that is used for the placeholder markers
      * @internal
      * @return string Content of rendered section
      */
@@ -1727,7 +1699,7 @@ class PageRenderer implements \TYPO3\CMS\Core\SingletonInterface
      * of uncached content objects (USER_INT, COA_INT)
      *
      * @param string $cachedPageContent
-     * @param string $substituteHash The hash that is used for the placehoder markers
+     * @param string $substituteHash The hash that is used for the variables
      * @internal
      * @return string
      */
@@ -1778,7 +1750,7 @@ class PageRenderer implements \TYPO3\CMS\Core\SingletonInterface
     /**
      * Renders all JavaScript and CSS
      *
-     * @return array<string>
+     * @return array|string[]
      */
     protected function renderJavaScriptAndCss()
     {
@@ -1859,7 +1831,7 @@ class PageRenderer implements \TYPO3\CMS\Core\SingletonInterface
     /**
      * Fills the marker array with the given strings and trims each value
      *
-     * @param string $substituteHash The hash that is used for the placehoder markers
+     * @param string $substituteHash The hash that is used for the placeholder markers
      * @return array Marker array
      */
     protected function getPreparedMarkerArrayForPageWithUncachedObjects($substituteHash)
@@ -2131,9 +2103,9 @@ class PageRenderer implements \TYPO3\CMS\Core\SingletonInterface
     }
 
     /**
-     * Render JavaScipt libraries
+     * Render JavaScript libraries
      *
-     * @return array<string> jsLibs and jsFooterLibs strings
+     * @return array|string[] jsLibs and jsFooterLibs strings
      */
     protected function renderAdditionalJavaScriptLibraries()
     {
@@ -2177,7 +2149,7 @@ class PageRenderer implements \TYPO3\CMS\Core\SingletonInterface
     /**
      * Render JavaScript files
      *
-     * @return array<string> jsFiles and jsFooterFiles strings
+     * @return array|string[] jsFiles and jsFooterFiles strings
      */
     protected function renderJavaScriptFiles()
     {
@@ -2186,11 +2158,12 @@ class PageRenderer implements \TYPO3\CMS\Core\SingletonInterface
         if (!empty($this->jsFiles)) {
             foreach ($this->jsFiles as $file => $properties) {
                 $file = $this->getStreamlinedFileName($file);
+                $type = $properties['type'] ? ' type="' . htmlspecialchars($properties['type']) . '"' : '';
                 $async = $properties['async'] ? ' async="async"' : '';
                 $defer = $properties['defer'] ? ' defer="defer"' : '';
                 $integrity = $properties['integrity'] ? ' integrity="' . htmlspecialchars($properties['integrity']) . '"' : '';
                 $crossorigin = $properties['crossorigin'] ? ' crossorigin="' . htmlspecialchars($properties['crossorigin']) . '"' : '';
-                $tag = '<script src="' . htmlspecialchars($file) . '" type="' . htmlspecialchars($properties['type']) . '"' . $async . $defer . $integrity . $crossorigin . '></script>';
+                $tag = '<script src="' . htmlspecialchars($file) . '"' . $type . $async . $defer . $integrity . $crossorigin . '></script>';
                 if ($properties['allWrap']) {
                     $wrapArr = explode($properties['splitChar'] ?: '|', $properties['allWrap'], 2);
                     $tag = $wrapArr[0] . $tag . $wrapArr[1];
@@ -2221,7 +2194,7 @@ class PageRenderer implements \TYPO3\CMS\Core\SingletonInterface
     /**
      * Render inline JavaScript
      *
-     * @return array<string> jsInline and jsFooterInline string
+     * @return array|string[] jsInline and jsFooterInline string
      */
     protected function renderInlineJavaScript()
     {
@@ -2387,12 +2360,8 @@ class PageRenderer implements \TYPO3\CMS\Core\SingletonInterface
                 ];
                 GeneralUtility::callUserFunction($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['cssConcatenateHandler'], $params, $this);
             } else {
-                $cssOptions = [];
-                if (TYPO3_MODE === 'BE') {
-                    $cssOptions = ['baseDirectories' => GeneralUtility::makeInstance(DocumentTemplate::class)->getSkinStylesheetDirectories()];
-                }
-                $this->cssLibs = $this->getCompressor()->concatenateCssFiles($this->cssLibs, $cssOptions);
-                $this->cssFiles = $this->getCompressor()->concatenateCssFiles($this->cssFiles, $cssOptions);
+                $this->cssLibs = $this->getCompressor()->concatenateCssFiles($this->cssLibs);
+                $this->cssFiles = $this->getCompressor()->concatenateCssFiles($this->cssFiles);
             }
         }
     }
@@ -2470,12 +2439,12 @@ class PageRenderer implements \TYPO3\CMS\Core\SingletonInterface
     /**
      * Returns instance of \TYPO3\CMS\Core\Resource\ResourceCompressor
      *
-     * @return \TYPO3\CMS\Core\Resource\ResourceCompressor
+     * @return ResourceCompressor
      */
     protected function getCompressor()
     {
         if ($this->compressor === null) {
-            $this->compressor = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Resource\ResourceCompressor::class);
+            $this->compressor = GeneralUtility::makeInstance(ResourceCompressor::class);
         }
         return $this->compressor;
     }
@@ -2535,7 +2504,7 @@ class PageRenderer implements \TYPO3\CMS\Core\SingletonInterface
      *
      * @param string $file
      * @return string
-     * @see TypoScriptFrontendController::setAbsRefPrefix()
+     * @see \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController::setAbsRefPrefix()
      */
     protected function getAbsoluteWebPath(string $file): string
     {
@@ -2545,16 +2514,6 @@ class PageRenderer implements \TYPO3\CMS\Core\SingletonInterface
         return PathUtility::getAbsoluteWebPath($file);
     }
 
-    /**
-     * Returns global frontend controller
-     *
-     * @return TypoScriptFrontendController
-     */
-    protected function getTypoScriptFrontendController()
-    {
-        return $GLOBALS['TSFE'];
-    }
-
     /*****************************************************/
     /*                                                   */
     /*  Hooks                                            */
@@ -2667,7 +2626,7 @@ class PageRenderer implements \TYPO3\CMS\Core\SingletonInterface
     }
 
     /**
-     * Creates an CSS inline tag
+     * Creates a CSS inline tag
      *
      * @param string $file the filename to process
      * @param array $properties