[!!!][TASK] Streamline ExtensionManagementUtility 23/54523/5
authorBenni Mack <benni@typo3.org>
Thu, 2 Nov 2017 05:54:47 +0000 (06:54 +0100)
committerSusanne Moog <susanne.moog@typo3.org>
Thu, 2 Nov 2017 15:43:52 +0000 (16:43 +0100)
The following functionality within this API class is marked as deprecated:
- siteRelPath()
- getExtensionKeyByPrefix()
- removeCacheFiles()
- second parameter of isLoaded()

Additionally, the following more strict rules apply now:
- addNavigationComponent() always requires an $extensionKey
- First parameter of addLLrefForTCAdescr() must not be empty
- addService() requires $serviceType and $info to be non-empty
- addPlugin() always requires an $extensionKey
- addStaticFile() throws exceptions if no extension key or path is set
- addTypoScript() expects $type to be either "setup" or "constants"

This is meant for extension developers using the current API more properly
than before.

Resolves: #82899
Releases: master
Change-Id: Ie5beddd4787da25f05f76ff37c6ec55a92257001
Reviewed-on: https://review.typo3.org/54523
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Mathias Schreiber <mathias.schreiber@typo3.com>
Tested-by: Mathias Schreiber <mathias.schreiber@typo3.com>
Reviewed-by: Susanne Moog <susanne.moog@typo3.org>
Tested-by: Susanne Moog <susanne.moog@typo3.org>
19 files changed:
typo3/sysext/backend/Classes/Backend/Avatar/Avatar.php
typo3/sysext/backend/Classes/Controller/EditDocumentController.php
typo3/sysext/core/Classes/Utility/ExtensionManagementUtility.php
typo3/sysext/core/Documentation/Changelog/master/Breaking-82899-MoreRestrictingChecksForAPIMethodsInExtensionManagementUtility.rst [new file with mode: 0644]
typo3/sysext/core/Documentation/Changelog/master/Deprecation-82899-ExtensionManagementUtilityMethods.rst [new file with mode: 0644]
typo3/sysext/core/Tests/Unit/Utility/ExtensionManagementUtilityTest.php
typo3/sysext/core/Tests/Unit_Deprecated/Utility/ExtensionManagementUtilityTest.php [new file with mode: 0644]
typo3/sysext/documentation/Classes/Utility/MiscUtility.php
typo3/sysext/feedit/Classes/FrontendEditPanel.php
typo3/sysext/frontend/Classes/ContentObject/ContentObjectRenderer.php
typo3/sysext/frontend/Classes/Imaging/GifBuilder.php
typo3/sysext/frontend/Classes/View/AdminPanelView.php
typo3/sysext/indexed_search/Classes/Controller/SearchController.php
typo3/sysext/install/Classes/Controller/UpgradeController.php
typo3/sysext/install/Classes/UpgradeAnalysis/DocumentationFile.php
typo3/sysext/install/Configuration/ExtensionScanner/Php/MethodArgumentDroppedStaticMatcher.php
typo3/sysext/install/Configuration/ExtensionScanner/Php/MethodCallStaticMatcher.php
typo3/sysext/lang/Classes/Domain/Repository/ExtensionRepository.php
typo3/sysext/rsaauth/Classes/RsaEncryptionEncoder.php

index 4da6f7a..5aacf8a 100644 (file)
@@ -19,8 +19,8 @@ use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
 use TYPO3\CMS\Core\Cache\CacheManager;
 use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface;
 use TYPO3\CMS\Core\Service\DependencyOrderingService;
-use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Core\Utility\PathUtility;
 use TYPO3\CMS\Fluid\View\StandaloneView;
 
 /**
@@ -98,7 +98,7 @@ class Avatar
         if (!$avatarImage) {
             $avatarImage = GeneralUtility::makeInstance(
                 Image::class,
-                ExtensionManagementUtility::siteRelPath('core') . 'Resources/Public/Icons/T3Icons/avatar/avatar-default.svg',
+                PathUtility::stripPathSitePrefix(GeneralUtility::getFileAbsFileName('EXT:core/Resources/Public/Icons/T3Icons/avatar/avatar-default.svg')),
                 $size,
                 $size
             );
index 89f71b6..07dcc08 100644 (file)
@@ -36,7 +36,6 @@ use TYPO3\CMS\Core\Messaging\FlashMessageQueue;
 use TYPO3\CMS\Core\Messaging\FlashMessageService;
 use TYPO3\CMS\Core\Page\PageRenderer;
 use TYPO3\CMS\Core\Type\Bitmask\Permission;
-use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Core\Utility\HttpUtility;
 use TYPO3\CMS\Core\Utility\MathUtility;
@@ -1435,7 +1434,7 @@ class EditDocumentController
      */
     public function shortCutLink()
     {
-        if ($this->returnUrl !== ExtensionManagementUtility::siteRelPath('backend') . 'Resources/Private/Templates/Close.html') {
+        if ($this->returnUrl !== $this->getCloseUrl()) {
             $shortCutButton = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar()->makeShortcutButton();
             $shortCutButton->setModuleName($this->MCONF['name'])
                 ->setGetVariables([
@@ -1455,10 +1454,10 @@ class EditDocumentController
      */
     public function openInNewWindowLink()
     {
-        $closeUrl = ExtensionManagementUtility::siteRelPath('backend') . 'Resources/Private/Templates/Close.html';
+        $closeUrl = $this->getCloseUrl();
         if ($this->returnUrl !== $closeUrl) {
             $aOnClick = 'vHWin=window.open(' . GeneralUtility::quoteJSvalue(GeneralUtility::linkThisScript(
-                ['returnUrl' => PathUtility::getAbsoluteWebPath($closeUrl)]
+                ['returnUrl' => $closeUrl]
             ))
                 . ','
                 . GeneralUtility::quoteJSvalue(md5($this->R_URI))
@@ -1476,6 +1475,18 @@ class EditDocumentController
         }
     }
 
+    /**
+     * Returns the URL (usually for the "returnUrl") which closes the current window.
+     * Used when editing a record in a popup.
+     *
+     * @return string
+     */
+    protected function getCloseUrl(): string
+    {
+        $closeUrl = GeneralUtility::getFileAbsFileName('EXT:backend/Resources/Private/Templates/Close.html');
+        return PathUtility::getAbsoluteWebPath($closeUrl);
+    }
+
     /***************************
      *
      * Localization stuff
index b4989b4..02cfb2e 100644 (file)
@@ -106,19 +106,23 @@ class ExtensionManagementUtility
      * Returns TRUE if the extension with extension key $key is loaded.
      *
      * @param string $key Extension key to test
-     * @param bool $exitOnError If $exitOnError is TRUE and the extension is not loaded the function will die with an error message
+     * @param bool $exitOnError If $exitOnError is TRUE and the extension is not loaded the function will die with an error message, this is deprecated and will be removed in TYPO3 v10
      * @return bool
      * @throws \BadFunctionCallException
      */
-    public static function isLoaded($key, $exitOnError = false)
+    public static function isLoaded($key, $exitOnError = null)
     {
         // safety net for extensions checking for "EXT:version", can be removed in TYPO3 v10.
         if ($key === 'version') {
             trigger_error('EXT:version has been moved into EXT:workspaces, you should check against "workspaces", as this might lead to unexpected behaviour in the future.', E_USER_DEPRECATED);
             $key = 'workspaces';
         }
+        if ($exitOnError !== null) {
+            trigger_error('Calling isLoaded() with a second argument via "exitOnError" will be removed in TYPO3 v10, handle an unloaded package yourself in the future.', E_USER_DEPRECATED);
+        }
         $isLoaded = static::$packageManager->isPackageActive($key);
         if ($exitOnError && !$isLoaded) {
+            // @deprecated, once $existOnError is gone, this check can be removed.
             throw new \BadFunctionCallException('TYPO3 Fatal Error: Extension "' . $key . '" is not loaded!', 1270853910);
         }
         return $isLoaded;
@@ -147,9 +151,11 @@ class ExtensionManagementUtility
      *
      * @param string $key Extension key
      * @return string
+     * @deprecated use extPath() or GeneralUtility::getFileAbsFileName() together with PathUtility::getAbsoluteWebPath() instead.
      */
     public static function siteRelPath($key)
     {
+        trigger_error('Calling siteRelPath() is deprecated. This method will be removed in TYPO3 v10, use extPath() in conjunction with PathUtility::getAbsoluteWebPath() instead.', E_USER_DEPRECATED);
         return PathUtility::stripPathSitePrefix(self::extPath($key));
     }
 
@@ -170,9 +176,11 @@ class ExtensionManagementUtility
      *
      * @param string $prefix The extension prefix (e.g. 'tx_ttnews')
      * @return mixed Real extension key (string)or FALSE (bool) if something went wrong
+     * @deprecated since TYPO3 v9, just use the proper extension key directly
      */
     public static function getExtensionKeyByPrefix($prefix)
     {
+        trigger_error('Calling getExtensionKeyByPrefix() is deprecated and will be removed in TYPO3 v10. Use extension keys directly', E_USER_DEPRECATED);
         $result = false;
         // Build map of short keys referencing to real keys:
         if (!isset(self::$extensionKeyMap)) {
@@ -961,20 +969,21 @@ class ExtensionManagementUtility
      * FOR USE IN ext_tables.php FILES
      * eg. \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addLLrefForTCAdescr('pages', 'EXT:lang/Resources/Private/Language/locallang_csh_pages.xlf'); for the pages table or \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addLLrefForTCAdescr('_MOD_web_layout', 'EXT:frontend/Resources/Private/Language/locallang_csh_weblayout.xlf'); for the Web > Page module.
      *
-     * @param string $tca_descr_key Description key. Typically a database table (like "pages") but for applications can be other strings, but prefixed with "_MOD_")
-     * @param string $file_ref File reference to locallang file, eg. "EXT:lang/Resources/Private/Language/locallang_csh_pages.xlf" (or ".xml")
+     * @param string $key Description key. Typically a database table (like "pages") but for applications can be other strings, but prefixed with "_MOD_")
+     * @param string $file File reference to locallang file, eg. "EXT:lang/Resources/Private/Language/locallang_csh_pages.xlf" (or ".xml")
      */
-    public static function addLLrefForTCAdescr($tca_descr_key, $file_ref)
+    public static function addLLrefForTCAdescr($key, $file)
     {
-        if ($tca_descr_key) {
-            if (!is_array($GLOBALS['TCA_DESCR'][$tca_descr_key])) {
-                $GLOBALS['TCA_DESCR'][$tca_descr_key] = [];
-            }
-            if (!is_array($GLOBALS['TCA_DESCR'][$tca_descr_key]['refs'])) {
-                $GLOBALS['TCA_DESCR'][$tca_descr_key]['refs'] = [];
-            }
-            $GLOBALS['TCA_DESCR'][$tca_descr_key]['refs'][] = $file_ref;
+        if (empty($key)) {
+            throw new \RuntimeException('No extension key set in addLLrefForTCAdescr(). Provide it as third parameter', 1507321596);
+        }
+        if (!is_array($GLOBALS['TCA_DESCR'][$key])) {
+            $GLOBALS['TCA_DESCR'][$key] = [];
+        }
+        if (!is_array($GLOBALS['TCA_DESCR'][$key]['refs'])) {
+            $GLOBALS['TCA_DESCR'][$key]['refs'] = [];
         }
+        $GLOBALS['TCA_DESCR'][$key]['refs'][] = $file;
     }
 
     /**
@@ -985,11 +994,10 @@ class ExtensionManagementUtility
      * @param string $extensionKey
      * @throws \RuntimeException
      */
-    public static function addNavigationComponent($module, $componentId, $extensionKey = null)
+    public static function addNavigationComponent($module, $componentId, $extensionKey)
     {
-        $extensionKey = $extensionKey ?: $GLOBALS['_EXTKEY'];
-        if (!isset($extensionKey)) {
-            throw new \RuntimeException('No extensionKey set in addNavigationComponent(). Provide it as third Parameter', 1404068039);
+        if (empty($extensionKey)) {
+            throw new \RuntimeException('No extensionKey set in addNavigationComponent(). Provide it as third parameter', 1404068039);
         }
         $GLOBALS['TBE_MODULES']['_navigationComponents'][$module] = [
             'componentId' => $componentId,
@@ -1006,7 +1014,7 @@ class ExtensionManagementUtility
      */
     public static function addCoreNavigationComponent($module, $componentId)
     {
-        self::addNavigationComponent($module, $componentId);
+        self::addNavigationComponent($module, $componentId, 'core');
         $GLOBALS['TBE_MODULES']['_navigationComponents'][$module]['isCoreComponent'] = true;
     }
 
@@ -1025,36 +1033,40 @@ class ExtensionManagementUtility
      */
     public static function addService($extKey, $serviceType, $serviceKey, $info)
     {
-        if ($serviceType && is_array($info)) {
-            $info['priority'] = max(0, min(100, $info['priority']));
-            $GLOBALS['T3_SERVICES'][$serviceType][$serviceKey] = $info;
-            $GLOBALS['T3_SERVICES'][$serviceType][$serviceKey]['extKey'] = $extKey;
-            $GLOBALS['T3_SERVICES'][$serviceType][$serviceKey]['serviceKey'] = $serviceKey;
-            $GLOBALS['T3_SERVICES'][$serviceType][$serviceKey]['serviceType'] = $serviceType;
-            // Change the priority (and other values) from $GLOBALS['TYPO3_CONF_VARS']
-            // $GLOBALS['TYPO3_CONF_VARS']['T3_SERVICES'][$serviceType][$serviceKey]['priority']
-            // even the activation is possible (a unix service might be possible on windows for some reasons)
-            if (is_array($GLOBALS['TYPO3_CONF_VARS']['T3_SERVICES'][$serviceType][$serviceKey])) {
-                // No check is done here - there might be configuration values only the service type knows about, so
-                // we pass everything
-                $GLOBALS['T3_SERVICES'][$serviceType][$serviceKey] = array_merge($GLOBALS['T3_SERVICES'][$serviceType][$serviceKey], $GLOBALS['TYPO3_CONF_VARS']['T3_SERVICES'][$serviceType][$serviceKey]);
-            }
-            // OS check
-            // Empty $os means 'not limited to one OS', therefore a check is not needed
-            if ($GLOBALS['T3_SERVICES'][$serviceType][$serviceKey]['available'] && $GLOBALS['T3_SERVICES'][$serviceType][$serviceKey]['os'] != '') {
-                $os_type = TYPO3_OS === 'WIN' ? 'WIN' : 'UNIX';
-                $os = GeneralUtility::trimExplode(',', strtoupper($GLOBALS['T3_SERVICES'][$serviceType][$serviceKey]['os']));
-                if (!in_array($os_type, $os, true)) {
-                    self::deactivateService($serviceType, $serviceKey);
-                }
-            }
-            // Convert subtype list to array for quicker access
-            $GLOBALS['T3_SERVICES'][$serviceType][$serviceKey]['serviceSubTypes'] = [];
-            $serviceSubTypes = GeneralUtility::trimExplode(',', $info['subtype']);
-            foreach ($serviceSubTypes as $subtype) {
-                $GLOBALS['T3_SERVICES'][$serviceType][$serviceKey]['serviceSubTypes'][$subtype] = $subtype;
+        if (!$serviceType) {
+            throw new \InvalidArgumentException('No serviceType given.', 1507321535);
+        }
+        if (!is_array($info)) {
+            throw new \InvalidArgumentException('No information array given.', 1507321542);
+        }
+        $info['priority'] = max(0, min(100, $info['priority']));
+        $GLOBALS['T3_SERVICES'][$serviceType][$serviceKey] = $info;
+        $GLOBALS['T3_SERVICES'][$serviceType][$serviceKey]['extKey'] = $extKey;
+        $GLOBALS['T3_SERVICES'][$serviceType][$serviceKey]['serviceKey'] = $serviceKey;
+        $GLOBALS['T3_SERVICES'][$serviceType][$serviceKey]['serviceType'] = $serviceType;
+        // Change the priority (and other values) from $GLOBALS['TYPO3_CONF_VARS']
+        // $GLOBALS['TYPO3_CONF_VARS']['T3_SERVICES'][$serviceType][$serviceKey]['priority']
+        // even the activation is possible (a unix service might be possible on windows for some reasons)
+        if (is_array($GLOBALS['TYPO3_CONF_VARS']['T3_SERVICES'][$serviceType][$serviceKey])) {
+            // No check is done here - there might be configuration values only the service type knows about, so
+            // we pass everything
+            $GLOBALS['T3_SERVICES'][$serviceType][$serviceKey] = array_merge($GLOBALS['T3_SERVICES'][$serviceType][$serviceKey], $GLOBALS['TYPO3_CONF_VARS']['T3_SERVICES'][$serviceType][$serviceKey]);
+        }
+        // OS check
+        // Empty $os means 'not limited to one OS', therefore a check is not needed
+        if ($GLOBALS['T3_SERVICES'][$serviceType][$serviceKey]['available'] && $GLOBALS['T3_SERVICES'][$serviceType][$serviceKey]['os'] != '') {
+            $os_type = TYPO3_OS === 'WIN' ? 'WIN' : 'UNIX';
+            $os = GeneralUtility::trimExplode(',', strtoupper($GLOBALS['T3_SERVICES'][$serviceType][$serviceKey]['os']));
+            if (!in_array($os_type, $os, true)) {
+                self::deactivateService($serviceType, $serviceKey);
             }
         }
+        // Convert subtype list to array for quicker access
+        $GLOBALS['T3_SERVICES'][$serviceType][$serviceKey]['serviceSubTypes'] = [];
+        $serviceSubTypes = GeneralUtility::trimExplode(',', $info['subtype']);
+        foreach ($serviceSubTypes as $subtype) {
+            $GLOBALS['T3_SERVICES'][$serviceType][$serviceKey]['serviceSubTypes'][$subtype] = $subtype;
+        }
     }
 
     /**
@@ -1190,18 +1202,17 @@ class ExtensionManagementUtility
      */
     public static function addPlugin($itemArray, $type = 'list_type', $extensionKey = null)
     {
-        $extensionKey = $extensionKey ?: $GLOBALS['_EXTKEY'];
         if (!isset($extensionKey)) {
-            throw new \RuntimeException(
+            throw new \InvalidArgumentException(
                 'No extension key could be determined when calling addPlugin()!'
                 . LF
-                . 'This method is meant to be called from an ext_tables.php or Configuration/TCA/Overrides file. '
-                . 'If you call it from Configuration/TCA/Overrides, the extension key needs to be specified as third parameter. '
+                . 'This method is meant to be called from Configuration/TCA/Overrides files. '
+                . 'The extension key needs to be specified as third parameter. '
                 . 'Calling it from any other place e.g. ext_localconf.php does not work and is not supported.',
                 1404068038
             );
         }
-        if ($extensionKey && !$itemArray[2] && isset($GLOBALS['TYPO3_LOADED_EXT'][$extensionKey]['ext_icon'])) {
+        if (!$itemArray[2] && isset($GLOBALS['TYPO3_LOADED_EXT'][$extensionKey]['ext_icon'])) {
             $itemArray[2] = 'EXT:' . $extensionKey . '/' . $GLOBALS['TYPO3_LOADED_EXT'][$extensionKey]['ext_icon'];
         }
         if (is_array($GLOBALS['TCA']['tt_content']['columns']) && is_array($GLOBALS['TCA']['tt_content']['columns'][$type]['config']['items'])) {
@@ -1272,14 +1283,14 @@ class ExtensionManagementUtility
      * @param string $_ unused since TYPO3 CMS 8
      * @param string $suffix Is used as a suffix of the class name (e.g. "_pi1")
      * @param string $type See description above
-     * @param int $cached If $cached is set as USER content object (cObject) is created - otherwise a USER_INT object is created.
+     * @param bool $cacheable If $cached is set as USER content object (cObject) is created - otherwise a USER_INT object is created.
      */
-    public static function addPItoST43($key, $_, $suffix = '', $type = 'list_type', $cached = 0)
+    public static function addPItoST43($key, $_, $suffix = '', $type = 'list_type', $cacheable = false)
     {
         $cN = self::getCN($key);
         // General plugin
         $pluginContent = trim('
-plugin.' . $cN . $suffix . ' = USER' . ($cached ? '' : '_INT') . '
+plugin.' . $cN . $suffix . ' = USER' . ($cacheable ? '' : '_INT') . '
 plugin.' . $cN . $suffix . '.userFunc = ' . $cN . $suffix . '->main
 ');
         self::addTypoScript($key, 'setup', '
@@ -1330,7 +1341,13 @@ tt_content.' . $key . $suffix . ' {
      */
     public static function addStaticFile($extKey, $path, $title)
     {
-        if ($extKey && $path && is_array($GLOBALS['TCA']['sys_template']['columns'])) {
+        if (!$extKey) {
+            throw new \InvalidArgumentException('No extension key given.', 1507321291);
+        }
+        if (!$path) {
+            throw new \InvalidArgumentException('No file path given.', 1507321297);
+        }
+        if (is_array($GLOBALS['TCA']['sys_template']['columns'])) {
             $value = str_replace(',', '', 'EXT:' . $extKey . '/' . $path);
             $itemArray = [trim($title . ' (' . $extKey . ')'), $value];
             $GLOBALS['TCA']['sys_template']['columns']['include_static_file']['config']['items'][] = $itemArray;
@@ -1406,10 +1423,12 @@ tt_content.' . $key . $suffix . ' {
      * @param string $content Is the TS content, will be prefixed with a [GLOBAL] line and a comment-header.
      * @param int|string string pointing to the "key" of a static_file template ([reduced extension_key]/[local path]). The points is that the TypoScript you add is included only IF that static template is included (and in that case, right after). So effectively the TypoScript you set can specifically overrule settings from those static templates.
      */
-    public static function addTypoScript($key, $type, $content, $afterStaticUid = 0)
+    public static function addTypoScript(string $key, string $type, string $content, $afterStaticUid = 0)
     {
-        if ($type === 'setup' || $type === 'constants') {
-            $content = '
+        if ($type !== 'setup' && $type !== 'constants') {
+            throw new \InvalidArgumentException('Argument $type must be set to either "setup" or "constants" when calling addTypoScript from extension "' . $key . '"', 1507321200);
+        }
+        $content = '
 
 [GLOBAL]
 #############################################
@@ -1417,17 +1436,16 @@ tt_content.' . $key . $suffix . ' {
 #############################################
 
 ' . $content;
-            if ($afterStaticUid) {
-                // If 'content (default)' is targeted (static uid 43),
-                // the content is added after typoscript of type contentRendering, eg. fluid_styled_content, see EXT:frontend/TemplateService for more information on how the code is parsed
-                if ($afterStaticUid === 'defaultContentRendering' || $afterStaticUid == 43) {
-                    $GLOBALS['TYPO3_CONF_VARS']['FE']['defaultTypoScript_' . $type . '.']['defaultContentRendering'] .= $content;
-                } else {
-                    $GLOBALS['TYPO3_CONF_VARS']['FE']['defaultTypoScript_' . $type . '.'][$afterStaticUid] .= $content;
-                }
+        if ($afterStaticUid) {
+            // If 'content (default)' is targeted (static uid 43),
+            // the content is added after typoscript of type contentRendering, eg. fluid_styled_content, see EXT:frontend/TemplateService for more information on how the code is parsed
+            if ($afterStaticUid === 'defaultContentRendering' || $afterStaticUid == 43) {
+                $GLOBALS['TYPO3_CONF_VARS']['FE']['defaultTypoScript_' . $type . '.']['defaultContentRendering'] .= $content;
             } else {
-                $GLOBALS['TYPO3_CONF_VARS']['FE']['defaultTypoScript_' . $type] .= $content;
+                $GLOBALS['TYPO3_CONF_VARS']['FE']['defaultTypoScript_' . $type . '.'][$afterStaticUid] .= $content;
             }
+        } else {
+            $GLOBALS['TYPO3_CONF_VARS']['FE']['defaultTypoScript_' . $type] .= $content;
         }
     }
 
@@ -1828,9 +1846,12 @@ tt_content.' . $key . $suffix . ' {
      * This method is usually only used by extension that fiddle
      * with the loaded extensions. An example is the extension
      * manager and the install tool.
+     *
+     * @deprecated CacheManager provides the functionality directly
      */
     public static function removeCacheFiles()
     {
+        trigger_error('removeCacheFiles() will be removed in TYPO3 v10. Use CacheManager directly to flush all system caches.', E_USER_DEPRECATED);
         self::getCacheManager()->flushCachesInGroup('system');
     }
 
diff --git a/typo3/sysext/core/Documentation/Changelog/master/Breaking-82899-MoreRestrictingChecksForAPIMethodsInExtensionManagementUtility.rst b/typo3/sysext/core/Documentation/Changelog/master/Breaking-82899-MoreRestrictingChecksForAPIMethodsInExtensionManagementUtility.rst
new file mode 100644 (file)
index 0000000..4620aee
--- /dev/null
@@ -0,0 +1,43 @@
+.. include:: ../../Includes.txt
+
+========================================================================================
+Breaking: #82899 - More restricting checks for API methods in ExtensionManagementUtility
+========================================================================================
+
+See :issue:`82899`
+
+Description
+===========
+
+The following methods within :php:``ExtensionManagementUtility``, the primary API class for
+extensions registering additional components like plugins, modules or extending TCA functionality
+now throw Exceptions with invalid calls:
+
+1. ``addLLrefForTCAdescr()`` requires a non-empty string as first argument
+2. ``addNavigationComponent()`` requires the third argument ($extensionKey)
+3. ``addService()`` requires the second argument to be non-empty, and the fourth argument as array
+4. ``addPlugin()`` requires the third argument ($extensionKey) to be set
+5. ``addStaticFile()`` requires the second a third argument to be non-empty
+6. ``addTypoScript()`` requires the second argument to be either `setup` or `constants`
+
+
+Impact
+======
+
+Calling any of the methods mentioned will trigger a "InvalidArgumentException".
+
+
+Affected Installations
+======================
+
+Any TYPO3 installation with an extension calling any of the methods above with missing
+information.
+
+
+Migration
+=========
+
+Add the required parameters to the API calls in your extension registration files, typically
+located within ``ext_localconf.php``, ``ext_tables.php`` or ``Configuration/TCA/*`` of a extension.
+
+.. index:: PHP-API, NotScanned
\ No newline at end of file
diff --git a/typo3/sysext/core/Documentation/Changelog/master/Deprecation-82899-ExtensionManagementUtilityMethods.rst b/typo3/sysext/core/Documentation/Changelog/master/Deprecation-82899-ExtensionManagementUtilityMethods.rst
new file mode 100644 (file)
index 0000000..9e4025b
--- /dev/null
@@ -0,0 +1,46 @@
+.. include:: ../../Includes.txt
+
+========================================================
+Deprecation: #82899 - ExtensionManagementUtility methods
+========================================================
+
+See :issue:`82899`
+
+Description
+===========
+
+The following methods have been marked as deprecated in :php:``ExtensionManagementUtility``
+
+* siteRelPath()
+* getExtensionKeyByPrefix()
+* removeCacheFiles()
+
+Additionally the second method parameter of :php:``ExtensionManagementUtility::isLoaded()`` to
+throw a exception when an extension is not loaded, has been marked as deprecated, and should not
+be used anymore.
+
+
+Impact
+======
+
+Calling any of the methods or ``isLoaded()`` with a second argument set explictly will trigger
+a deprecation message.
+
+
+Affected Installations
+======================
+
+Any TYPO3 installation with an extension calling any of the methods above.
+
+
+Migration
+=========
+
+Use :php:``PathUtility::stripPathSitePrefix(ExtensionManagementUtility::extPath($extensionKey))``
+instead of :php:``ExtensionManagementUtility::siteRelPath()``.
+
+Instead of calling :php:``getExtensionKeyByPrefix()`` use the extension key directly.
+
+Use CacheManager API directly instead of calling :php:``removeCacheFiles()``.
+
+.. index:: PHP-API, FullyScanned
\ No newline at end of file
index ca8d171..6b13e65 100644 (file)
@@ -102,20 +102,9 @@ class ExtensionManagementUtilityTest extends \TYPO3\TestingFramework\Core\Unit\U
     /**
      * @test
      */
-    public function isLoadedReturnsFalseIfExtensionIsNotLoadedAndExitIsDisabled()
+    public function isLoadedReturnsFalseIfExtensionIsNotLoaded()
     {
-        $this->assertFalse(ExtensionManagementUtility::isLoaded($this->getUniqueId('foobar'), false));
-    }
-
-    /**
-     * @test
-     */
-    public function isLoadedThrowsExceptionIfExtensionIsNotLoaded()
-    {
-        $this->expectException(\BadFunctionCallException::class);
-        $this->expectExceptionCode(1270853910);
-
-        $this->assertFalse(ExtensionManagementUtility::isLoaded($this->getUniqueId('foobar'), true));
+        $this->assertFalse(ExtensionManagementUtility::isLoaded($this->getUniqueId('foobar')));
     }
 
     ///////////////////////////////
@@ -239,77 +228,6 @@ class ExtensionManagementUtilityTest extends \TYPO3\TestingFramework\Core\Unit\U
         $this->assertSame($expectedPrefix, ExtensionManagementUtility::getCN($extensionName));
     }
 
-    /////////////////////////////////////////////
-    // Tests concerning getExtensionKeyByPrefix
-    /////////////////////////////////////////////
-    /**
-     * @test
-     * @see ExtensionManagementUtility::getExtensionKeyByPrefix
-     */
-    public function getExtensionKeyByPrefixForLoadedExtensionWithUnderscoresReturnsExtensionKey()
-    {
-        ExtensionManagementUtility::clearExtensionKeyMap();
-        $uniqueSuffix = $this->getUniqueId('test');
-        $extensionKey = 'tt_news' . $uniqueSuffix;
-        $extensionPrefix = 'tx_ttnews' . $uniqueSuffix;
-        $package = $this->getMockBuilder(Package::class)
-                ->disableOriginalConstructor()
-                ->setMethods(['getPackageKey'])
-                ->getMock();
-        $package->expects($this->exactly(2))
-                ->method('getPackageKey')
-                ->will($this->returnValue($extensionKey));
-        /** @var PackageManager|\PHPUnit_Framework_MockObject_MockObject $packageManager */
-        $packageManager = $this->getMockBuilder(PackageManager::class)
-            ->setMethods(['getActivePackages'])
-            ->getMock();
-        $packageManager->expects($this->once())
-                ->method('getActivePackages')
-                ->will($this->returnValue([$extensionKey => $package]));
-        ExtensionManagementUtility::setPackageManager($packageManager);
-        $this->assertEquals($extensionKey, ExtensionManagementUtility::getExtensionKeyByPrefix($extensionPrefix));
-    }
-
-    /**
-     * @test
-     * @see ExtensionManagementUtility::getExtensionKeyByPrefix
-     */
-    public function getExtensionKeyByPrefixForLoadedExtensionWithoutUnderscoresReturnsExtensionKey()
-    {
-        ExtensionManagementUtility::clearExtensionKeyMap();
-        $uniqueSuffix = $this->getUniqueId('test');
-        $extensionKey = 'kickstarter' . $uniqueSuffix;
-        $extensionPrefix = 'tx_kickstarter' . $uniqueSuffix;
-        $package = $this->getMockBuilder(Package::class)
-                ->disableOriginalConstructor()
-                ->setMethods(['getPackageKey'])
-                ->getMock();
-        $package->expects($this->exactly(2))
-                ->method('getPackageKey')
-                ->will($this->returnValue($extensionKey));
-        /** @var PackageManager|\PHPUnit_Framework_MockObject_MockObject $packageManager */
-        $packageManager = $this->getMockBuilder(PackageManager::class)
-            ->setMethods(['getActivePackages'])
-            ->getMock();
-        $packageManager->expects($this->once())
-                ->method('getActivePackages')
-                ->will($this->returnValue([$extensionKey => $package]));
-        ExtensionManagementUtility::setPackageManager($packageManager);
-        $this->assertEquals($extensionKey, ExtensionManagementUtility::getExtensionKeyByPrefix($extensionPrefix));
-    }
-
-    /**
-     * @test
-     * @see ExtensionManagementUtility::getExtensionKeyByPrefix
-     */
-    public function getExtensionKeyByPrefixForNotLoadedExtensionReturnsFalse()
-    {
-        ExtensionManagementUtility::clearExtensionKeyMap();
-        $uniqueSuffix = $this->getUniqueId('test');
-        $extensionPrefix = 'tx_unloadedextension' . $uniqueSuffix;
-        $this->assertFalse(ExtensionManagementUtility::getExtensionKeyByPrefix($extensionPrefix));
-    }
-
     //////////////////////////////////////
     // Tests concerning addToAllTCAtypes
     //////////////////////////////////////
@@ -1730,23 +1648,6 @@ class ExtensionManagementUtilityTest extends \TYPO3\TestingFramework\Core\Unit\U
     }
 
     /////////////////////////////////////////
-    // Tests concerning removeCacheFiles
-    /////////////////////////////////////////
-    /**
-     * @test
-     */
-    public function removeCacheFilesFlushesSystemCaches()
-    {
-        /** @var CacheManager|\PHPUnit_Framework_MockObject_MockObject $mockCacheManager */
-        $mockCacheManager = $this->getMockBuilder(CacheManager::class)
-            ->setMethods(['flushCachesInGroup'])
-            ->getMock();
-        $mockCacheManager->expects($this->once())->method('flushCachesInGroup')->with('system');
-        ExtensionManagementUtilityAccessibleProxy::setCacheManager($mockCacheManager);
-        ExtensionManagementUtility::removeCacheFiles();
-    }
-
-    /////////////////////////////////////////
     // Tests concerning getExtensionVersion
     /////////////////////////////////////////
     /**
@@ -1934,31 +1835,9 @@ class ExtensionManagementUtilityTest extends \TYPO3\TestingFramework\Core\Unit\U
     /**
      * @test
      */
-    public function addPluginSetsTcaCorrectlyForGivenExtKeyAsGlobal()
-    {
-        $extKey = 'indexed_search';
-        $GLOBALS['TYPO3_LOADED_EXT'] = [];
-        $GLOBALS['TYPO3_LOADED_EXT'][$extKey]['ext_icon'] = 'foo.gif';
-        $GLOBALS['_EXTKEY'] = $extKey;
-        $expectedTCA = [
-            [
-                'label',
-                $extKey,
-                'EXT:' . $extKey . '/foo.gif'
-            ]
-        ];
-        $GLOBALS['TCA']['tt_content']['columns']['list_type']['config']['items'] = [];
-        ExtensionManagementUtility::addPlugin(['label', $extKey]);
-
-        $this->assertEquals($expectedTCA, $GLOBALS['TCA']['tt_content']['columns']['list_type']['config']['items']);
-    }
-
-    /**
-     * @test
-     */
     public function addPluginThrowsExceptionForMissingExtkey()
     {
-        $this->expectException(\RuntimeException::class);
+        $this->expectException(\InvalidArgumentException::class);
         $this->expectExceptionCode(1404068038);
 
         ExtensionManagementUtility::addPlugin('test');
diff --git a/typo3/sysext/core/Tests/Unit_Deprecated/Utility/ExtensionManagementUtilityTest.php b/typo3/sysext/core/Tests/Unit_Deprecated/Utility/ExtensionManagementUtilityTest.php
new file mode 100644 (file)
index 0000000..73b2838
--- /dev/null
@@ -0,0 +1,277 @@
+<?php
+namespace TYPO3\CMS\Core\Tests\Unit\Utility;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use TYPO3\CMS\Core\Cache\CacheManager;
+use TYPO3\CMS\Core\Compatibility\LoadedExtensionsArray;
+use TYPO3\CMS\Core\Package\Package;
+use TYPO3\CMS\Core\Package\PackageManager;
+use TYPO3\CMS\Core\Tests\Unit\Utility\AccessibleProxies\ExtensionManagementUtilityAccessibleProxy;
+use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+
+/**
+ * Test case
+ */
+class ExtensionManagementUtilityTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
+{
+    /**
+     * @var array A backup of registered singleton instances
+     */
+    protected $singletonInstances = [];
+
+    /**
+     * @var \TYPO3\CMS\Core\Package\PackageManager
+     */
+    protected $backUpPackageManager;
+
+    protected function setUp()
+    {
+        $this->singletonInstances = GeneralUtility::getSingletonInstances();
+        $this->backUpPackageManager = ExtensionManagementUtilityAccessibleProxy::getPackageManager();
+        $this->singletonInstances = GeneralUtility::getSingletonInstances();
+    }
+
+    protected function tearDown()
+    {
+        ExtensionManagementUtility::clearExtensionKeyMap();
+        ExtensionManagementUtilityAccessibleProxy::setPackageManager($this->backUpPackageManager);
+        ExtensionManagementUtilityAccessibleProxy::setCacheManager(null);
+        $GLOBALS['TYPO3_LOADED_EXT'] = new LoadedExtensionsArray($this->backUpPackageManager);
+        GeneralUtility::resetSingletonInstances($this->singletonInstances);
+        parent::tearDown();
+    }
+
+    /**
+     * @param string $packageKey
+     * @param array $packageMethods
+     * @return PackageManager|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected function createMockPackageManagerWithMockPackage($packageKey, $packageMethods = ['getPackagePath', 'getPackageKey'])
+    {
+        $packagePath = PATH_site . 'typo3temp/var/tests/' . $packageKey . '/';
+        GeneralUtility::mkdir_deep($packagePath);
+        $this->testFilesToDelete[] = $packagePath;
+        $package = $this->getMockBuilder(Package::class)
+                ->disableOriginalConstructor()
+                ->setMethods($packageMethods)
+                ->getMock();
+        $packageManager = $this->getMockBuilder(PackageManager::class)
+            ->setMethods(['isPackageActive', 'getPackage', 'getActivePackages'])
+            ->getMock();
+        $package->expects($this->any())
+                ->method('getPackagePath')
+                ->will($this->returnValue($packagePath));
+        $package->expects($this->any())
+                ->method('getPackageKey')
+                ->will($this->returnValue($packageKey));
+        $packageManager->expects($this->any())
+                ->method('isPackageActive')
+                ->will($this->returnValueMap([
+                    [null, false],
+                    [$packageKey, true]
+                ]));
+        $packageManager->expects($this->any())
+                ->method('getPackage')
+                ->with($this->equalTo($packageKey))
+                ->will($this->returnValue($package));
+        $packageManager->expects($this->any())
+                ->method('getActivePackages')
+                ->will($this->returnValue([$packageKey => $package]));
+        return $packageManager;
+    }
+
+    ///////////////////////////////
+    // Tests concerning isLoaded
+    ///////////////////////////////
+    /**
+     * @test
+     */
+    public function isLoadedReturnsFalseIfExtensionIsNotLoadedAndExitIsDisabled()
+    {
+        $this->assertFalse(ExtensionManagementUtility::isLoaded($this->getUniqueId('foobar'), false));
+    }
+
+    ///////////////////////////////
+    // Tests concerning extPath
+    ///////////////////////////////
+    /**
+     * @test
+     */
+    public function extPathThrowsExceptionIfExtensionIsNotLoaded()
+    {
+        $this->expectException(\BadFunctionCallException::class);
+        $this->expectExceptionCode(1365429656);
+
+        $packageName = $this->getUniqueId('foo');
+        /** @var PackageManager|\PHPUnit_Framework_MockObject_MockObject $packageManager */
+        $packageManager = $this->getMockBuilder(PackageManager::class)
+            ->setMethods(['isPackageActive'])
+            ->getMock();
+        $packageManager->expects($this->once())
+                ->method('isPackageActive')
+                ->with($this->equalTo($packageName))
+                ->will($this->returnValue(false));
+        ExtensionManagementUtility::setPackageManager($packageManager);
+        ExtensionManagementUtility::extPath($packageName);
+    }
+
+    /**
+     * @test
+     */
+    public function extPathAppendsScriptNameToPath()
+    {
+        $package = $this->getMockBuilder(Package::class)
+                ->disableOriginalConstructor()
+                ->setMethods(['getPackagePath'])
+                ->getMock();
+        /** @var PackageManager|\PHPUnit_Framework_MockObject_MockObject $packageManager */
+        $packageManager = $this->getMockBuilder(PackageManager::class)
+            ->setMethods(['isPackageActive', 'getPackage'])
+            ->getMock();
+        $package->expects($this->once())
+                ->method('getPackagePath')
+                ->will($this->returnValue(PATH_site . 'foo/'));
+        $packageManager->expects($this->once())
+                ->method('isPackageActive')
+                ->with($this->equalTo('foo'))
+                ->will($this->returnValue(true));
+        $packageManager->expects($this->once())
+                ->method('getPackage')
+                ->with('foo')
+                ->will($this->returnValue($package));
+        ExtensionManagementUtility::setPackageManager($packageManager);
+        $this->assertSame(PATH_site . 'foo/bar.txt', ExtensionManagementUtility::extPath('foo', 'bar.txt'));
+    }
+
+    //////////////////////
+    // Utility functions
+    //////////////////////
+    /**
+     * Generates a basic TCA for a given table.
+     *
+     * @param string $table name of the table, must not be empty
+     * @return array generated TCA for the given table, will not be empty
+     */
+    private function generateTCAForTable($table)
+    {
+        $tca = [];
+        $tca[$table] = [];
+        $tca[$table]['columns'] = [
+            'fieldA' => [],
+            'fieldC' => []
+        ];
+        $tca[$table]['types'] = [
+            'typeA' => ['showitem' => 'fieldA, fieldB, fieldC;labelC, --palette--;;paletteC, fieldC1, fieldD, fieldD1'],
+            'typeB' => ['showitem' => 'fieldA, fieldB, fieldC;labelC, --palette--;;paletteC, fieldC1, fieldD, fieldD1'],
+            'typeC' => ['showitem' => 'fieldC;;paletteD']
+        ];
+        $tca[$table]['palettes'] = [
+            'paletteA' => ['showitem' => 'fieldX, fieldX1, fieldY'],
+            'paletteB' => ['showitem' => 'fieldX, fieldX1, fieldY'],
+            'paletteC' => ['showitem' => 'fieldX, fieldX1, fieldY'],
+            'paletteD' => ['showitem' => 'fieldX, fieldX1, fieldY']
+        ];
+        return $tca;
+    }
+
+    /////////////////////////////////////////////
+    // Tests concerning getExtensionKeyByPrefix
+    /////////////////////////////////////////////
+    /**
+     * @test
+     * @see ExtensionManagementUtility::getExtensionKeyByPrefix
+     */
+    public function getExtensionKeyByPrefixForLoadedExtensionWithUnderscoresReturnsExtensionKey()
+    {
+        ExtensionManagementUtility::clearExtensionKeyMap();
+        $uniqueSuffix = $this->getUniqueId('test');
+        $extensionKey = 'tt_news' . $uniqueSuffix;
+        $extensionPrefix = 'tx_ttnews' . $uniqueSuffix;
+        $package = $this->getMockBuilder(Package::class)
+                ->disableOriginalConstructor()
+                ->setMethods(['getPackageKey'])
+                ->getMock();
+        $package->expects($this->exactly(2))
+                ->method('getPackageKey')
+                ->will($this->returnValue($extensionKey));
+        /** @var PackageManager|\PHPUnit_Framework_MockObject_MockObject $packageManager */
+        $packageManager = $this->getMockBuilder(PackageManager::class)
+            ->setMethods(['getActivePackages'])
+            ->getMock();
+        $packageManager->expects($this->once())
+                ->method('getActivePackages')
+                ->will($this->returnValue([$extensionKey => $package]));
+        ExtensionManagementUtility::setPackageManager($packageManager);
+        $this->assertEquals($extensionKey, ExtensionManagementUtility::getExtensionKeyByPrefix($extensionPrefix));
+    }
+
+    /**
+     * @test
+     * @see ExtensionManagementUtility::getExtensionKeyByPrefix
+     */
+    public function getExtensionKeyByPrefixForLoadedExtensionWithoutUnderscoresReturnsExtensionKey()
+    {
+        ExtensionManagementUtility::clearExtensionKeyMap();
+        $uniqueSuffix = $this->getUniqueId('test');
+        $extensionKey = 'kickstarter' . $uniqueSuffix;
+        $extensionPrefix = 'tx_kickstarter' . $uniqueSuffix;
+        $package = $this->getMockBuilder(Package::class)
+                ->disableOriginalConstructor()
+                ->setMethods(['getPackageKey'])
+                ->getMock();
+        $package->expects($this->exactly(2))
+                ->method('getPackageKey')
+                ->will($this->returnValue($extensionKey));
+        /** @var PackageManager|\PHPUnit_Framework_MockObject_MockObject $packageManager */
+        $packageManager = $this->getMockBuilder(PackageManager::class)
+            ->setMethods(['getActivePackages'])
+            ->getMock();
+        $packageManager->expects($this->once())
+                ->method('getActivePackages')
+                ->will($this->returnValue([$extensionKey => $package]));
+        ExtensionManagementUtility::setPackageManager($packageManager);
+        $this->assertEquals($extensionKey, ExtensionManagementUtility::getExtensionKeyByPrefix($extensionPrefix));
+    }
+
+    /**
+     * @test
+     * @see ExtensionManagementUtility::getExtensionKeyByPrefix
+     */
+    public function getExtensionKeyByPrefixForNotLoadedExtensionReturnsFalse()
+    {
+        ExtensionManagementUtility::clearExtensionKeyMap();
+        $uniqueSuffix = $this->getUniqueId('test');
+        $extensionPrefix = 'tx_unloadedextension' . $uniqueSuffix;
+        $this->assertFalse(ExtensionManagementUtility::getExtensionKeyByPrefix($extensionPrefix));
+    }
+
+    /////////////////////////////////////////
+    // Tests concerning removeCacheFiles
+    /////////////////////////////////////////
+    /**
+     * @test
+     */
+    public function removeCacheFilesFlushesSystemCaches()
+    {
+        /** @var CacheManager|\PHPUnit_Framework_MockObject_MockObject $mockCacheManager */
+        $mockCacheManager = $this->getMockBuilder(CacheManager::class)
+            ->setMethods(['flushCachesInGroup'])
+            ->getMock();
+        $mockCacheManager->expects($this->once())->method('flushCachesInGroup')->with('system');
+        ExtensionManagementUtilityAccessibleProxy::setCacheManager($mockCacheManager);
+        ExtensionManagementUtility::removeCacheFiles();
+    }
+}
index 0cb0877..5eda4f6 100644 (file)
@@ -15,6 +15,7 @@ namespace TYPO3\CMS\Documentation\Utility;
  */
 
 use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
+use TYPO3\CMS\Core\Utility\PathUtility;
 
 /**
  * Misc utility.
@@ -59,16 +60,16 @@ class MiscUtility
         $documentPath = $basePath . $documentKey . '/';
 
         // Fallback icon
-        $icon = ExtensionManagementUtility::getExtensionIcon(ExtensionManagementUtility::extPath('documentation'));
-        $icon = ExtensionManagementUtility::siteRelPath('documentation') . $icon;
+        $icon = ExtensionManagementUtility::getExtensionIcon(ExtensionManagementUtility::extPath('documentation'), true);
+        $icon = PathUtility::stripPathSitePrefix($icon);
 
         if (\TYPO3\CMS\Core\Utility\GeneralUtility::isFirstPartOfStr($documentKey, 'typo3cms.extensions.')) {
             // Standard extension icon
             $extensionKey = substr($documentKey, 20);
             if (ExtensionManagementUtility::isLoaded($extensionKey)) {
                 $extensionPath = ExtensionManagementUtility::extPath($extensionKey);
-                $siteRelativePath = ExtensionManagementUtility::siteRelPath($extensionKey);
-                $icon = $siteRelativePath . ExtensionManagementUtility::getExtensionIcon($extensionPath);
+                $icon = ExtensionManagementUtility::getExtensionIcon($extensionPath, true);
+                $icon = PathUtility::stripPathSitePrefix($icon);
             }
         } elseif (is_file(PATH_site . $documentPath . 'icon.png')) {
             $icon = $documentPath . 'icon.png';
index b269820..a780acf 100644 (file)
@@ -18,7 +18,6 @@ use TYPO3\CMS\Backend\Utility\BackendUtility;
 use TYPO3\CMS\Core\Imaging\Icon;
 use TYPO3\CMS\Core\Imaging\IconFactory;
 use TYPO3\CMS\Core\Type\Bitmask\JsConfirmation;
-use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Core\Utility\MathUtility;
 use TYPO3\CMS\Core\Utility\PathUtility;
@@ -298,7 +297,7 @@ class FrontendEditPanel
     {
         $width = MathUtility::forceIntegerInRange($this->backendUser->getTSConfigVal('options.feedit.popupWidth'), 690, 5000, 690);
         $height = MathUtility::forceIntegerInRange($this->backendUser->getTSConfigVal('options.feedit.popupHeight'), 500, 5000, 500);
-        $onclick = 'vHWin=window.open(' . GeneralUtility::quoteJSvalue($url . '&returnUrl=' . rawurlencode(PathUtility::getAbsoluteWebPath(ExtensionManagementUtility::siteRelPath('backend') . 'Resources/Private/Templates/Close.html'))) . ',\'FEquickEditWindow\',\'width=' . $width . ',height=' . $height . ',status=0,menubar=0,scrollbars=1,resizable=1\');vHWin.focus();return false;';
+        $onclick = 'vHWin=window.open(' . GeneralUtility::quoteJSvalue($url . '&returnUrl=' . rawurlencode(PathUtility::getAbsoluteWebPath(GeneralUtility::getFileAbsFileName('EXT:backend/Resources/Private/Templates/Close.html')))) . ',\'FEquickEditWindow\',\'width=' . $width . ',height=' . $height . ',status=0,menubar=0,scrollbars=1,resizable=1\');vHWin.focus();return false;';
         return '<a href="#" class="typo3-editPanel-btn typo3-editPanel-btn-default frontEndEditIconLinks ' . htmlspecialchars($additionalClasses) . '" onclick="' . htmlspecialchars($onclick) . '" style="display: none;">' . $string . '</a>';
     }
 
index 5a00f88..7df30e5 100644 (file)
@@ -44,10 +44,10 @@ use TYPO3\CMS\Core\TypoScript\Parser\TypoScriptParser;
 use TYPO3\CMS\Core\TypoScript\TypoScriptService;
 use TYPO3\CMS\Core\Utility\ArrayUtility;
 use TYPO3\CMS\Core\Utility\DebugUtility;
-use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Core\Utility\MailUtility;
 use TYPO3\CMS\Core\Utility\MathUtility;
+use TYPO3\CMS\Core\Utility\PathUtility;
 use TYPO3\CMS\Core\Utility\StringUtility;
 use TYPO3\CMS\Core\Versioning\VersionState;
 use TYPO3\CMS\Extbase\Service\FlexFormService;
@@ -3634,16 +3634,17 @@ class ContentObjectRenderer
             $conf['icon.']['path'] = isset($conf['icon.']['path.'])
                 ? $this->stdWrap($conf['icon.']['path'], $conf['icon.']['path.'])
                 : $conf['icon.']['path'];
-            $iconP = !empty($conf['icon.']['path'])
+            $iconPath = !empty($conf['icon.']['path'])
                 ? $conf['icon.']['path']
-                : ExtensionManagementUtility::siteRelPath('frontend') . 'Resources/Public/Icons/FileIcons/';
+                : GeneralUtility::getFileAbsFileName('EXT:frontend/Resources/Public/Icons/FileIcons/');
             $conf['icon.']['ext'] = isset($conf['icon.']['ext.'])
                 ? $this->stdWrap($conf['icon.']['ext'], $conf['icon.']['ext.'])
                 : $conf['icon.']['ext'];
             $iconExt = !empty($conf['icon.']['ext']) ? '.' . $conf['icon.']['ext'] : '.gif';
-            $icon = @is_file(($iconP . $fI['fileext'] . $iconExt))
-                ? $iconP . $fI['fileext'] . $iconExt
-                : $iconP . 'default' . $iconExt;
+            $icon = @is_file(($iconPath . $fI['fileext'] . $iconExt))
+                ? $iconPath . $fI['fileext'] . $iconExt
+                : $iconPath . 'default' . $iconExt;
+            $icon = PathUtility::stripPathSitePrefix($icon);
             // Checking for images: If image, then return link to thumbnail.
             $IEList = isset($conf['icon_image_ext_list.']) ? $this->stdWrap($conf['icon_image_ext_list'], $conf['icon_image_ext_list.']) : $conf['icon_image_ext_list'];
             $image_ext_list = str_replace(' ', '', strtolower($IEList));
@@ -3651,7 +3652,8 @@ class ContentObjectRenderer
                 if ($conf['iconCObject']) {
                     $icon = $this->cObjGetSingle($conf['iconCObject'], $conf['iconCObject.'], 'iconCObject');
                 } else {
-                    $notFoundThumb = ExtensionManagementUtility::siteRelPath('core') . 'Resources/Public/Images/NotFound.gif';
+                    $notFoundThumb = GeneralUtility::getFileAbsFileName('EXT:core/Resources/Public/Images/NotFound.gif');
+                    $notFoundThumb = PathUtility::stripPathSitePrefix($notFoundThumb);
                     $sizeParts = [64, 64];
                     if ($GLOBALS['TYPO3_CONF_VARS']['GFX']['thumbnails']) {
                         // using the File Abstraction Layer to generate a preview image
index 9991ab3..bf5f98f 100644 (file)
@@ -18,7 +18,6 @@ use TYPO3\CMS\Core\Imaging\GraphicalFunctions;
 use TYPO3\CMS\Core\Resource\File;
 use TYPO3\CMS\Core\Resource\ProcessedFile;
 use TYPO3\CMS\Core\Utility\ArrayUtility;
-use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
 use TYPO3\CMS\Core\Utility\File\BasicFileUtility;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Core\Utility\MathUtility;
@@ -557,7 +556,7 @@ class GifBuilder extends GraphicalFunctions
         }
         $conf['fontFile'] = $this->checkFile($conf['fontFile']);
         if (!$conf['fontFile']) {
-            $conf['fontFile'] = ExtensionManagementUtility::siteRelPath('core') . 'Resources/Private/Font/nimbus.ttf';
+            $conf['fontFile'] = $this->checkFile('EXT:core/Resources/Private/Font/nimbus.ttf');
         }
         if (!$conf['iterations']) {
             $conf['iterations'] = 1;
index 2832fcf..d5e7683 100644 (file)
@@ -25,6 +25,7 @@ use TYPO3\CMS\Core\TimeTracker\TimeTracker;
 use TYPO3\CMS\Core\Type\Bitmask\Permission;
 use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Core\Utility\PathUtility;
 
 /**
  * View class for the admin panel in frontend editing.
@@ -360,8 +361,8 @@ class AdminPanelView
         $output[] = '  </div>';
         $output[] = '</form>';
         if ($this->getBackendUser()->uc['TSFE_adminConfig']['display_top']) {
-            $frontendPathExtBackend = htmlspecialchars($this->getTypoScriptFrontendController()->absRefPrefix) . ExtensionManagementUtility::siteRelPath('backend');
-            $output[] = '<script type="text/javascript" src="' . $frontendPathExtBackend . 'Resources/Public/JavaScript/jsfunc.evalfield.js"></script>';
+            $evalFieldJavaScriptFile = GeneralUtility::getFileAbsFileName('EXT:backend/Resources/Public/JavaScript/jsfunc.evalfield.js');
+            $output[] = '<script type="text/javascript" src="' . htmlspecialchars(PathUtility::getAbsoluteWebPath($evalFieldJavaScriptFile)) . '"></script>';
             $output[] = '<script type="text/javascript">/*<![CDATA[*/' . GeneralUtility::minifyJavaScript('
                                var evalFunc = new evalFunc();
                                        // TSFEtypo3FormFieldSet()
@@ -391,8 +392,8 @@ class AdminPanelView
                                }') . '/*]]>*/</script>';
             $output[] = '<script language="javascript" type="text/javascript">' . $this->extJSCODE . '</script>';
         }
-        $frontendPathExtFrontend = htmlspecialchars($this->getTypoScriptFrontendController()->absRefPrefix) . ExtensionManagementUtility::siteRelPath('frontend');
-        $output[] = '<link type="text/css" rel="stylesheet" href="' . $frontendPathExtFrontend . 'Resources/Public/Css/adminpanel.css" media="all" />';
+        $cssFileLocation = GeneralUtility::getFileAbsFileName('EXT:frontend/Resources/Public/Css/adminpanel.css');
+        $output[] = '<link type="text/css" rel="stylesheet" href="' . htmlspecialchars(PathUtility::getAbsoluteWebPath($cssFileLocation)) . '" media="all" />';
         $output[] = $this->getAdminPanelHeaderData();
         $output[] = '<!-- TYPO3 admin panel end -->';
 
index 3630154..e078f4f 100644 (file)
@@ -22,6 +22,7 @@ use TYPO3\CMS\Core\Html\HtmlParser;
 use TYPO3\CMS\Core\TypoScript\TypoScriptService;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Core\Utility\MathUtility;
+use TYPO3\CMS\Core\Utility\PathUtility;
 use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
 
 /**
@@ -517,8 +518,10 @@ class SearchController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionControlle
             ]);
             // check if the access is restricted
             if (is_array($this->requiredFrontendUsergroups[$pathId]) && !empty($this->requiredFrontendUsergroups[$pathId])) {
-                $resultData['access'] = '<img src="' . \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::siteRelPath('indexed_search')
-                    . 'Resources/Public/Icons/FileTypes/locked.gif" width="12" height="15" vspace="5" title="'
+                $lockedIcon = GeneralUtility::getFileAbsFileName('EXT:indexed_search/Resources/Public/Icons/FileTypes/locked.gif');
+                $lockedIcon = PathUtility::getAbsoluteWebPath($lockedIcon);
+                $resultData['access'] = '<img src="' . htmlspecialchars($lockedIcon) . '"'
+                    . ' width="12" height="15" vspace="5" title="'
                     . sprintf(LocalizationUtility::translate('result.memberGroups', 'IndexedSearch'), implode(',', array_unique($this->requiredFrontendUsergroups[$pathId])))
                     . '" alt="" />';
             }
index 3fe445f..d40438c 100644 (file)
@@ -497,7 +497,7 @@ class UpgradeController extends AbstractController
         // and if their content is not in incoming "hashes" array, mark as "not affected"
         $documentationFile = new DocumentationFile();
         $finder = new Finder();
-        $restFilesBasePath = PATH_site . ExtensionManagementUtility::siteRelPath('core') . 'Documentation/Changelog';
+        $restFilesBasePath = ExtensionManagementUtility::extPath('core') . 'Documentation/Changelog';
         $restFiles = $finder->files()->in($restFilesBasePath);
         $fullyScannedRestFilesNotAffected = [];
         foreach ($restFiles as $restFile) {
@@ -593,7 +593,7 @@ class UpgradeController extends AbstractController
         }
 
         // Prepare match output
-        $restFilesBasePath = PATH_site . ExtensionManagementUtility::siteRelPath('core') . 'Documentation/Changelog';
+        $restFilesBasePath = ExtensionManagementUtility::extPath('core') . 'Documentation/Changelog';
         $documentationFile = new DocumentationFile();
         $preparedMatches = [];
         foreach ($matches as $match) {
@@ -1071,7 +1071,7 @@ class UpgradeController extends AbstractController
     {
         $documentationFileService = new DocumentationFile();
         $documentationFiles = $documentationFileService->findDocumentationFiles(
-            strtr(realpath(PATH_site . ExtensionManagementUtility::siteRelPath('core') . 'Documentation/Changelog'), '\\', '/')
+            strtr(realpath(ExtensionManagementUtility::extPath('core') . 'Documentation/Changelog'), '\\', '/')
         );
         $documentationFiles = array_reverse($documentationFiles);
 
index f22f3b4..4a92cb0 100644 (file)
@@ -53,7 +53,7 @@ class DocumentationFile
         if ($this->registry === null) {
             $this->registry = new Registry();
         }
-        $this->changelogPath = $changelogDir !== '' ? $changelogDir : realpath(PATH_site . ExtensionManagementUtility::siteRelPath('core') . 'Documentation/Changelog');
+        $this->changelogPath = $changelogDir !== '' ? $changelogDir : realpath(ExtensionManagementUtility::extPath('core') . 'Documentation/Changelog');
         $this->changelogPath = strtr($this->changelogPath, '\\', '/');
     }
 
index e655131..62d63f5 100644 (file)
@@ -33,4 +33,10 @@ return [
             'Deprecation-54152-DeprecateArgumentsOfBackendUtilityGetPagesTSconfig.rst',
         ],
     ],
+    'TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded' => [
+        'maximumNumberOfArguments' => 1,
+        'restFiles' => [
+            'Deprecation-82899-ExtensionManagementUtilityMethods.rst',
+        ],
+    ],
 ];
index 7b66ff7..6788f44 100644 (file)
@@ -463,4 +463,32 @@ return [
             'Deprecation-82438-DeprecationMethods.rst',
         ],
     ],
+    'TYPO3\CMS\Core\Utility\ExtensionManagementUtility::siteRelPath' => [
+        'numberOfMandatoryArguments' => 0,
+        'maximumNumberOfArguments' => 0,
+        'restFiles' => [
+            'Deprecation-82899-ExtensionManagementUtilityMethods.rst',
+        ],
+    ],
+    'TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addNavigationComponent' => [
+        'numberOfMandatoryArguments' => 3,
+        'maximumNumberOfArguments' => 3,
+        'restFiles' => [
+            'Breaking-82899-MoreRestrictingChecksForAPIMethodsInExtensionManagementUtility.rst',
+        ],
+    ],
+    'TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addStaticFile' => [
+        'numberOfMandatoryArguments' => 3,
+        'maximumNumberOfArguments' => 3,
+        'restFiles' => [
+            'Breaking-82899-MoreRestrictingChecksForAPIMethodsInExtensionManagementUtility.rst',
+        ],
+    ],
+    'TYPO3\CMS\Core\Utility\ExtensionManagementUtility::removeCacheFiles' => [
+        'numberOfMandatoryArguments' => 0,
+        'maximumNumberOfArguments' => 0,
+        'restFiles' => [
+            'Deprecation-82899-ExtensionManagementUtilityMethods.rst',
+        ],
+    ],
 ];
index 13fbb5d..3addfcc 100644 (file)
@@ -15,6 +15,8 @@ namespace TYPO3\CMS\Lang\Domain\Repository;
  */
 
 use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Core\Utility\PathUtility;
 use TYPO3\CMS\Extbase\Object\ObjectManagerInterface;
 use TYPO3\CMS\Extensionmanager\Utility\ListUtility;
 use TYPO3\CMS\Lang\Domain\Model\Extension;
@@ -128,7 +130,8 @@ class ExtensionRepository
             $extensionIcon = ExtensionManagementUtility::getExtensionIcon(PATH_site . $extensionEntry['siteRelPath'] . '/');
         }
         if (empty($extensionIcon)) {
-            $extensionIcon = ExtensionManagementUtility::siteRelPath('core') . 'Resources/Public/Icons/Extension.png';
+            $extensionIcon = GeneralUtility::getFileAbsFileName('EXT:core/Resources/Public/Icons/Extension.png');
+            $extensionIcon = PathUtility::stripPathSitePrefix($extensionIcon);
         } else {
             $extensionIcon = '../' . $extensionEntry['siteRelPath'] . '/' . $extensionIcon;
         }
index e1e28bd..f77efba 100644 (file)
@@ -18,7 +18,6 @@ use Psr\Http\Message\ResponseInterface;
 use Psr\Http\Message\ServerRequestInterface;
 use TYPO3\CMS\Core\Page\PageRenderer;
 use TYPO3\CMS\Core\SingletonInterface;
-use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 
 /**
@@ -63,7 +62,6 @@ class RsaEncryptionEncoder implements SingletonInterface
             // Register ajax handler url
             $code = 'var TYPO3RsaEncryptionPublicKeyUrl = ' . GeneralUtility::quoteJSvalue(GeneralUtility::getIndpEnv('TYPO3_SITE_PATH') . 'index.php?eID=RsaPublicKeyGenerationController') . ';';
             $pageRenderer->addJsInlineCode('TYPO3RsaEncryptionPublicKeyUrl', $code);
-            $javascriptPath = ExtensionManagementUtility::siteRelPath('rsaauth') . 'Resources/Public/JavaScript/';
             if (!$GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['debug']) {
                 $files = ['RsaEncryptionWithLib.min.js'];
             } else {
@@ -73,7 +71,7 @@ class RsaEncryptionEncoder implements SingletonInterface
                 ];
             }
             foreach ($files as $file) {
-                $pageRenderer->addJsFile($javascriptPath . $file);
+                $pageRenderer->addJsFile('EXT:rsaauth/Resources/Public/JavaScript/' . $file);
             }
         }
     }