From 38d689d50b86a95a18ae07a6d39562ba57eeb2e5 Mon Sep 17 00:00:00 2001 From: Benni Mack <benni@typo3.org> Date: Thu, 2 Nov 2017 06:54:47 +0100 Subject: [PATCH] [!!!][TASK] Streamline ExtensionManagementUtility 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> --- .../backend/Classes/Backend/Avatar/Avatar.php | 4 +- .../Controller/EditDocumentController.php | 19 +- .../Utility/ExtensionManagementUtility.php | 155 +++++----- ...APIMethodsInExtensionManagementUtility.rst | 43 +++ ...2899-ExtensionManagementUtilityMethods.rst | 46 +++ .../ExtensionManagementUtilityTest.php | 127 +------- .../ExtensionManagementUtilityTest.php | 277 ++++++++++++++++++ .../Classes/Utility/MiscUtility.php | 9 +- .../feedit/Classes/FrontendEditPanel.php | 3 +- .../ContentObject/ContentObjectRenderer.php | 16 +- .../frontend/Classes/Imaging/GifBuilder.php | 3 +- .../frontend/Classes/View/AdminPanelView.php | 9 +- .../Classes/Controller/SearchController.php | 7 +- .../Classes/Controller/UpgradeController.php | 6 +- .../UpgradeAnalysis/DocumentationFile.php | 2 +- .../MethodArgumentDroppedStaticMatcher.php | 6 + .../Php/MethodCallStaticMatcher.php | 28 ++ .../Domain/Repository/ExtensionRepository.php | 5 +- .../rsaauth/Classes/RsaEncryptionEncoder.php | 4 +- 19 files changed, 543 insertions(+), 226 deletions(-) create mode 100644 typo3/sysext/core/Documentation/Changelog/master/Breaking-82899-MoreRestrictingChecksForAPIMethodsInExtensionManagementUtility.rst create mode 100644 typo3/sysext/core/Documentation/Changelog/master/Deprecation-82899-ExtensionManagementUtilityMethods.rst create mode 100644 typo3/sysext/core/Tests/Unit_Deprecated/Utility/ExtensionManagementUtilityTest.php diff --git a/typo3/sysext/backend/Classes/Backend/Avatar/Avatar.php b/typo3/sysext/backend/Classes/Backend/Avatar/Avatar.php index 4da6f7aa2999..5aacf8a9e182 100644 --- a/typo3/sysext/backend/Classes/Backend/Avatar/Avatar.php +++ b/typo3/sysext/backend/Classes/Backend/Avatar/Avatar.php @@ -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 ); diff --git a/typo3/sysext/backend/Classes/Controller/EditDocumentController.php b/typo3/sysext/backend/Classes/Controller/EditDocumentController.php index 89f71b6fced5..07dcc08875ae 100644 --- a/typo3/sysext/backend/Classes/Controller/EditDocumentController.php +++ b/typo3/sysext/backend/Classes/Controller/EditDocumentController.php @@ -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 diff --git a/typo3/sysext/core/Classes/Utility/ExtensionManagementUtility.php b/typo3/sysext/core/Classes/Utility/ExtensionManagementUtility.php index b4989b44b4ed..02cfb2e77e3f 100644 --- a/typo3/sysext/core/Classes/Utility/ExtensionManagementUtility.php +++ b/typo3/sysext/core/Classes/Utility/ExtensionManagementUtility.php @@ -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 index 000000000000..4620aee788c8 --- /dev/null +++ b/typo3/sysext/core/Documentation/Changelog/master/Breaking-82899-MoreRestrictingChecksForAPIMethodsInExtensionManagementUtility.rst @@ -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 index 000000000000..9e4025b273c5 --- /dev/null +++ b/typo3/sysext/core/Documentation/Changelog/master/Deprecation-82899-ExtensionManagementUtilityMethods.rst @@ -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 diff --git a/typo3/sysext/core/Tests/Unit/Utility/ExtensionManagementUtilityTest.php b/typo3/sysext/core/Tests/Unit/Utility/ExtensionManagementUtilityTest.php index ca8d171586b8..6b13e657ab0f 100644 --- a/typo3/sysext/core/Tests/Unit/Utility/ExtensionManagementUtilityTest.php +++ b/typo3/sysext/core/Tests/Unit/Utility/ExtensionManagementUtilityTest.php @@ -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 ////////////////////////////////////// @@ -1729,23 +1647,6 @@ class ExtensionManagementUtilityTest extends \TYPO3\TestingFramework\Core\Unit\U $this->assertEquals(40, strlen($sha1)); } - ///////////////////////////////////////// - // 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 ///////////////////////////////////////// @@ -1931,34 +1832,12 @@ class ExtensionManagementUtilityTest extends \TYPO3\TestingFramework\Core\Unit\U $this->assertEquals($expectedTCA, $GLOBALS['TCA']['tt_content']['columns']['list_type']['config']['items']); } - /** - * @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 index 000000000000..73b283820eb2 --- /dev/null +++ b/typo3/sysext/core/Tests/Unit_Deprecated/Utility/ExtensionManagementUtilityTest.php @@ -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(); + } +} diff --git a/typo3/sysext/documentation/Classes/Utility/MiscUtility.php b/typo3/sysext/documentation/Classes/Utility/MiscUtility.php index 0cb0877d7908..5eda4f6ea8ab 100644 --- a/typo3/sysext/documentation/Classes/Utility/MiscUtility.php +++ b/typo3/sysext/documentation/Classes/Utility/MiscUtility.php @@ -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'; diff --git a/typo3/sysext/feedit/Classes/FrontendEditPanel.php b/typo3/sysext/feedit/Classes/FrontendEditPanel.php index b26982059335..a780acfe0b77 100644 --- a/typo3/sysext/feedit/Classes/FrontendEditPanel.php +++ b/typo3/sysext/feedit/Classes/FrontendEditPanel.php @@ -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>'; } diff --git a/typo3/sysext/frontend/Classes/ContentObject/ContentObjectRenderer.php b/typo3/sysext/frontend/Classes/ContentObject/ContentObjectRenderer.php index 5a00f88f2ac8..7df30e54d7ce 100644 --- a/typo3/sysext/frontend/Classes/ContentObject/ContentObjectRenderer.php +++ b/typo3/sysext/frontend/Classes/ContentObject/ContentObjectRenderer.php @@ -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 diff --git a/typo3/sysext/frontend/Classes/Imaging/GifBuilder.php b/typo3/sysext/frontend/Classes/Imaging/GifBuilder.php index 9991ab3850c5..bf5f98f25677 100644 --- a/typo3/sysext/frontend/Classes/Imaging/GifBuilder.php +++ b/typo3/sysext/frontend/Classes/Imaging/GifBuilder.php @@ -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; diff --git a/typo3/sysext/frontend/Classes/View/AdminPanelView.php b/typo3/sysext/frontend/Classes/View/AdminPanelView.php index 2832fcf1ae82..d5e768390eea 100644 --- a/typo3/sysext/frontend/Classes/View/AdminPanelView.php +++ b/typo3/sysext/frontend/Classes/View/AdminPanelView.php @@ -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 -->'; diff --git a/typo3/sysext/indexed_search/Classes/Controller/SearchController.php b/typo3/sysext/indexed_search/Classes/Controller/SearchController.php index 3630154d8f0d..e078f4f0dee1 100644 --- a/typo3/sysext/indexed_search/Classes/Controller/SearchController.php +++ b/typo3/sysext/indexed_search/Classes/Controller/SearchController.php @@ -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="" />'; } diff --git a/typo3/sysext/install/Classes/Controller/UpgradeController.php b/typo3/sysext/install/Classes/Controller/UpgradeController.php index 3fe445f3f788..d40438c0dc00 100644 --- a/typo3/sysext/install/Classes/Controller/UpgradeController.php +++ b/typo3/sysext/install/Classes/Controller/UpgradeController.php @@ -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); diff --git a/typo3/sysext/install/Classes/UpgradeAnalysis/DocumentationFile.php b/typo3/sysext/install/Classes/UpgradeAnalysis/DocumentationFile.php index f22f3b4904a7..4a92cb08b158 100644 --- a/typo3/sysext/install/Classes/UpgradeAnalysis/DocumentationFile.php +++ b/typo3/sysext/install/Classes/UpgradeAnalysis/DocumentationFile.php @@ -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, '\\', '/'); } diff --git a/typo3/sysext/install/Configuration/ExtensionScanner/Php/MethodArgumentDroppedStaticMatcher.php b/typo3/sysext/install/Configuration/ExtensionScanner/Php/MethodArgumentDroppedStaticMatcher.php index e6551317cc70..62d63f50b97f 100644 --- a/typo3/sysext/install/Configuration/ExtensionScanner/Php/MethodArgumentDroppedStaticMatcher.php +++ b/typo3/sysext/install/Configuration/ExtensionScanner/Php/MethodArgumentDroppedStaticMatcher.php @@ -33,4 +33,10 @@ return [ 'Deprecation-54152-DeprecateArgumentsOfBackendUtilityGetPagesTSconfig.rst', ], ], + 'TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded' => [ + 'maximumNumberOfArguments' => 1, + 'restFiles' => [ + 'Deprecation-82899-ExtensionManagementUtilityMethods.rst', + ], + ], ]; diff --git a/typo3/sysext/install/Configuration/ExtensionScanner/Php/MethodCallStaticMatcher.php b/typo3/sysext/install/Configuration/ExtensionScanner/Php/MethodCallStaticMatcher.php index 7b66ff7306a1..6788f44a156d 100644 --- a/typo3/sysext/install/Configuration/ExtensionScanner/Php/MethodCallStaticMatcher.php +++ b/typo3/sysext/install/Configuration/ExtensionScanner/Php/MethodCallStaticMatcher.php @@ -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', + ], + ], ]; diff --git a/typo3/sysext/lang/Classes/Domain/Repository/ExtensionRepository.php b/typo3/sysext/lang/Classes/Domain/Repository/ExtensionRepository.php index 13fbb5d1f2bb..3addfcc057bc 100644 --- a/typo3/sysext/lang/Classes/Domain/Repository/ExtensionRepository.php +++ b/typo3/sysext/lang/Classes/Domain/Repository/ExtensionRepository.php @@ -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; } diff --git a/typo3/sysext/rsaauth/Classes/RsaEncryptionEncoder.php b/typo3/sysext/rsaauth/Classes/RsaEncryptionEncoder.php index e1e28bdc9e98..f77efba0d58e 100644 --- a/typo3/sysext/rsaauth/Classes/RsaEncryptionEncoder.php +++ b/typo3/sysext/rsaauth/Classes/RsaEncryptionEncoder.php @@ -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); } } } -- GitLab