Merge remote-tracking branch 'origin/develop' into feature/38-add-typoscript-tokenizer

This commit is contained in:
Daniel Siepmann 2017-04-06 08:10:15 +02:00
commit 0e5d74b51d
Signed by: Daniel Siepmann
GPG key ID: 33D6629915560EF4
28 changed files with 1508 additions and 124 deletions

View file

@ -49,6 +49,8 @@ new ones like ``\TYPO3\Extbase\...``. This is done for:
- Static calls like ``t3lib_div::`` to ``\TYPO3\Core\Utility\GeneralUtility``. - Static calls like ``t3lib_div::`` to ``\TYPO3\Core\Utility\GeneralUtility``.
- Static call also checks for ``::class``, as technically we just look before the ``::``.
- Typehints in methods and function like injects. - Typehints in methods and function like injects.
- ``instanceof`` checks. - ``instanceof`` checks.
@ -69,11 +71,43 @@ new ones like ``\TYPO3\Extbase\...``. This is done for:
- ``catch`` of legacy class names. - ``catch`` of legacy class names.
- Convert old legacy class *definitions* in extensions to namespaces.
- Convert usage of previously converted class definitions. On first run the definition will be
converted, on second run the usage. This is due to the fact, that PHPCS might find the definition
after the usage, so please run twice.
*NOTE* The configured file will be updated after each run, for each converted class, trait and
interface definition. See options.
- Add missing vendor to plugin and module registrations and configurations.
You might want to set this to non fixable and warning if you already provide the vendor inside a
single Variable, together with your extension key, as this is not recognized. So the following
will be recognized:
- ``$_EXTKEY,``
- ``$VENDOR . $_EXTKEY,``
- ``'VENDOR.' . $_EXTKEY,``
While the following will not:
- ``$key = 'Vendor.' . $_EXTKEY;``
Also we check for the following deprecated calls: Also we check for the following deprecated calls:
- Check for ``create`` on ``ObjectManager``, which is "stupid" just all ``create`` calls are marked - Check for ``create`` on ``ObjectManager``, which is "stupid" just all ``create`` calls are marked
with a warning. with a warning.
Beside the features above which are covered by ``phpcs`` and phpcbf``, the following linting is also
available to generate a report of possible issues and during coding through ``phpcs``:
- Check for usage of removed functions.
The functions are configured via yaml files. The location of them is configurable, default is
inside the standard itself, and we try to deliver all information.
For configuration options see ``removedFunctionConfigFiles``.
What does it look like? What does it look like?
======================= =======================
@ -152,3 +186,37 @@ Example:
.. code:: bash .. code:: bash
--runtime-set mappingFile /projects/typo3_installation/vendor/composer/autoload_classaliasmap.php --runtime-set mappingFile /projects/typo3_installation/vendor/composer/autoload_classaliasmap.php
``vendor``
Configure your vendor through ``ruleset.xml`` or using ``--runtime-set``. Default is
``YourCompany``.
Example:
.. code:: xml
<config name="vendor" value="YourVendor"/>
Example:
.. code:: bash
--runtime-set vendor YourVendor
``removedFunctionConfigFiles``
Configure your vendor through ``ruleset.xml`` or using ``--runtime-set``. Default is
``Configuration/Removed/Functions/*.yaml`` inside the standard itself.
Globing is used, so placeholders like ``*`` are possible, see
https://secure.php.net/manual/en/function.glob.php
Example:
.. code:: xml
<config name="removedFunctionConfigFiles" value="/Some/Absolute/Path/*.yaml"/>
Example:
.. code:: bash
--runtime-set removedFunctionConfigFiles "/Some/Absolute/Path/*.yaml"

View file

@ -17,8 +17,9 @@
} }
], ],
"require": { "require": {
"helmich/typo3-typoscript-parser": "dev-feature/allow-eol-handling",
"squizlabs/php_codesniffer": "2.8.*", "squizlabs/php_codesniffer": "2.8.*",
"helmich/typo3-typoscript-parser": "dev-feature/allow-eol-handling" "symfony/yaml": "3.2.*"
}, },
"license": "GPL-2.0+", "license": "GPL-2.0+",
"authors": [ "authors": [

View file

@ -0,0 +1,218 @@
# Breaking changes in 7.0: https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Index.html#breaking-changes
'7.0':
\TYPO3\CMS\Core\Utility\GeneralUtility::loadTCA:
newFunctionCall: null
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-61785-LoadTcaFunctionRemoved.html'
\TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController->getCompressedTCarray:
newFunctionCall: 'Full TCA is always loaded during bootstrap in FE, the method is obsolete. If an eid script calls this method to load TCA, use \TYPO3\CMS\Frontend\Utility\EidUtility::initTCA() instead'
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-61785-FrontendTcaFunctionsRemoved.html'
\TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController->includeTCA:
newFunctionCall: 'Full TCA is always loaded during bootstrap in FE, the method is obsolete. If an eid script calls this method to load TCA, use \TYPO3\CMS\Frontend\Utility\EidUtility::initTCA() instead'
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-61785-FrontendTcaFunctionsRemoved.html'
\TYPO3\CMS\Core\Utility\MailUtility::mail:
newFunctionCall: 'Use the \TYPO3\CMS\Core\Mail\Mailer API for sending email'
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-61783-RemoveDeprecatedMailFunctionality.html'
\TYPO3\CMS\Core\Utility\GeneralUtility::plainMailEncoded:
newFunctionCall: 'Use the \TYPO3\CMS\Core\Mail\Mailer API for sending email'
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-61783-RemoveDeprecatedMailFunctionality.html'
\TYPO3\CMS\Frontend\Utility\EidUtility::connectDB:
newFunctionCall: null
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-61863-ConnectDbFunctionRemoved.html'
\TYPO3\CMS\Core\Utility\GeneralUtility::int_from_ver:
newFunctionCall: 'Replace the usage of the removed function with \TYPO3\CMS\Core\Utility\VersionNumberUtility::convertVersionNumberToInteger()'
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-61860-RemoveIntFromVerFunction.html'
\TYPO3\CMS\Core\DataHandlin\DataHandler->getUniqueFields:
newFunctionCall: 'Replace all calls to \TYPO3\CMS\Core\DataHandling\DataHandler::getUniqueFields() with calls to \TYPO3\CMS\Version\Hook\DataHandlerHook::getUniqueFields()'
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-61822-GetUniqueFieldsFunctionRemoved.html'
\TYPO3\CMS\Core\Utility\PhpOptionsUtility::isSafeModeEnabled:
newFunctionCall: null
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-61820-PhpOptionsUtilityDeprecatedFunctionsRemoved.html'
\TYPO3\CMS\Core\Utility\PhpOptionsUtility::isMagicQuotesGpcEnabled:
newFunctionCall: null
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-61820-PhpOptionsUtilityDeprecatedFunctionsRemoved.html'
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLocalconfWritable:
newFunctionCall: null
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-61802-IsLocalconfWritableFunctionRemoved.html'
\TYPO3\CMS\Extbase\Object\ObjectManager->create:
newFunctionCall: 'Use ObjectManager::get() instead'
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-62673-ExtbaseDeprecatedCodeRemoved.html'
\TYPO3\CMS\Extbase\Persistence\Generic\Backend->replaceObject:
newFunctionCall: 'Removed without replacement'
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-62673-ExtbaseDeprecatedCodeRemoved.html'
\TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface->setReturnRawQueryResult:
newFunctionCall: 'Removed without replacement'
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-62673-ExtbaseDeprecatedCodeRemoved.html'
\TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface->getReturnRawQueryResult:
newFunctionCall: 'Use the parameter on $query->execute() directly'
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-62673-ExtbaseDeprecatedCodeRemoved.html'
\TYPO3\CMS\Extbase\Persistence\Generic\Typo3QuerySettings->setSysLanguageUid:
newFunctionCall: 'Use setLanguageUid() instead'
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-62673-ExtbaseDeprecatedCodeRemoved.html'
\TYPO3\CMS\Extbase\Persistence\Generic\Typo3QuerySettings->getSysLanguageUid:
newFunctionCall: 'Use getLanguageUid() instead'
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-62673-ExtbaseDeprecatedCodeRemoved.html'
\TYPO3\CMS\Lang\LanguageService->JScharCode:
newFunctionCall: 'Use GeneralUtility::quoteJSvalue instead'
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-62670-DeprecatedCodeRemovalInMultipleSysexts.html'
\TYPO3\CMS\Frontend\ContentObjec\ContentObjectRenderer->joinTSarrays:
newFunctionCall: null
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-62670-DeprecatedCodeRemovalInMultipleSysexts.html'
\TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController->tidyHTML:
newFunctionCall: 'You may use the tidy extension from TER'
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-62670-DeprecatedCodeRemovalInMultipleSysexts.html'
\TYPO3\CMS\Recordlist\Browser\ElementBrowser->isWebFolder:
newFunctionCall: null
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-62670-DeprecatedCodeRemovalInMultipleSysexts.html'
\TYPO3\CMS\Recordlist\Browser\ElementBrowser->checkFolder:
newFunctionCall: null
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-62670-DeprecatedCodeRemovalInMultipleSysexts.html'
\TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRecordList->getTreeObject:
newFunctionCall: null
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-62670-DeprecatedCodeRemovalInMultipleSysexts.html'
\TYPO3\CMS\Filelist\FileList->dirData:
newFunctionCall: null
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-62670-DeprecatedCodeRemovalInMultipleSysexts.html'
\TYPO3\CMS\Frontend\ContentObject\FilesContentObject->stdWrapValue:
newFunctionCall: 'Use ContentObjectRenderer::stdWrapValue instead'
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-62670-DeprecatedCodeRemovalInMultipleSysexts.html'
\TYPO3\CMS\Impexp\Controller\ImportExportController->userTempFolder:
newFunctionCall: 'Use getDefaultImportExportFolder instead'
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-62670-DeprecatedCodeRemovalInMultipleSysexts.html'
\TYPO3\CMS\Impexp\Controller\ImportExportController->userSaveFolder:
newFunctionCall: 'Use getDefaultImportExportFolder instead'
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-62670-DeprecatedCodeRemovalInMultipleSysexts.html'
\TYPO3\CMS\Lowlevel\View\DatabaseIntegrityView->func_filesearch:
newFunctionCall: null
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-62670-DeprecatedCodeRemovalInMultipleSysexts.html'
\TYPO3\CMS\Lowlevel\View\DatabaseIntegrityView->findFile:
newFunctionCall: null
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-62670-DeprecatedCodeRemovalInMultipleSysexts.html'
\TYPO3\CMS\Rtehtmlarea\RteHtmlAreaBase->buildStyleSheet:
newFunctionCall: null
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-62670-DeprecatedCodeRemovalInMultipleSysexts.html'
\TYPO3\CMS\Rtehtmlarea\RteHtmlAreaBase->loremIpsumInsert:
newFunctionCall: null
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-62670-DeprecatedCodeRemovalInMultipleSysexts.html'
\TYPO3\CMS\Workspaces\Service\StagesService->checkCustomStagingForWS:
newFunctionCall: null
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-62670-DeprecatedCodeRemovalInMultipleSysexts.html'
\TYPO3\CMS\Core\DataHandling\DataHandler->clear_cache:
newFunctionCall: 'Use ->clear_cacheCmd() instead. Alternatively you can call ->registerPageCacheClearing() from a hook to not immediately clear the cache but register clearing after DataHandler operation finishes'
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-62416-DeprecatedCodeRemovalInCoreSysext.html'
\TYPO3\CMS\Core\DataHandling\DataHandler->internal_clearPageCache:
newFunctionCall: 'Use the cache manager directly'
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-62416-DeprecatedCodeRemovalInCoreSysext.html'
\TYPO3\CMS\Core\Utility\GeneralUtility::array_merge_recursive_overrule:
newFunctionCall: 'Use ArrayUtility::mergeRecursiveWithOverrule() instead. WARNING: The new method changed its signature and does not return the first parameter anymore'
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-62416-DeprecatedCodeRemovalInCoreSysext.html'
\TYPO3\CMS\Core\Utility\GeneralUtility::htmlspecialchars_decode:
newFunctionCall: 'Use native PHP htmlspecialchars_decode() function'
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-62416-DeprecatedCodeRemovalInCoreSysext.html'
# NOTE: This is useless, adding a warning to all "get" methods is crazy.
# Also this is already handeled by: Typo3Update_Sniffs_LegacyClassnames_InstantiationWithObjectManagerSniff
# \TYPO3\CMS\Core\Category\CategoryRegistry->get:
# newFunctionCall: 'Use isRegistered() instead'
# docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-62416-DeprecatedCodeRemovalInCoreSysext.html'
\TYPO3\CMS\Core\Category\CategoryRegistry->applyTca:
newFunctionCall: null
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-62416-DeprecatedCodeRemovalInCoreSysext.html'
# NOTE: This is useless, adding a warning to all "findByUid" methods is crazy.
# Many calls to repositories will be marked as warning
# \TYPO3\CMS\Core\Resource\FileRepository->findByUid:
# newFunctionCall: null
# docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-62416-DeprecatedCodeRemovalInCoreSysext.html'
\TYPO3\CMS\Core\Resource\FileRepository->addToIndex:
newFunctionCall: null
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-62416-DeprecatedCodeRemovalInCoreSysext.html'
\TYPO3\CMS\Core\Resource\FileRepository->getFileIndexRecordsForFolder:
newFunctionCall: 'Use FileIndexRepository::findByFolder() instead'
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-62416-DeprecatedCodeRemovalInCoreSysext.html'
\TYPO3\CMS\Core\Resource\FileRepository->getFileIndexRecord:
newFunctionCall: 'Use FileIndexRepository::findOneByFileObject() instead'
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-62416-DeprecatedCodeRemovalInCoreSysext.html'
\TYPO3\CMS\Core\Resource\FileRepository->findBySha1Hash:
newFunctionCall: 'Use FileIndexRepository::findByContentHash() instead'
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-62416-DeprecatedCodeRemovalInCoreSysext.html'
# NOTE: This is useless, adding a warning to all "update" methods is crazy.
# All repository updates will be marked as warning
# \TYPO3\CMS\Core\Resource\FileRepository->update:
# newFunctionCall: 'Use FileIndexRepository::update() instead'
# docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-62416-DeprecatedCodeRemovalInCoreSysext.html'
\TYPO3\CMS\Core\Resource\ResourceStorage->getFolderByIdentifier:
newFunctionCall: 'Use getFolder() instead'
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-62416-DeprecatedCodeRemovalInCoreSysext.html'
\TYPO3\CMS\Core\Resource\ResourceStorage->getFileByIdentifier:
newFunctionCall: 'Use getFileInfoByIdentifier() instead'
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-62416-DeprecatedCodeRemovalInCoreSysext.html'
\TYPO3\CMS\Core\Resource\ResourceStorage->getFileList:
newFunctionCall: 'Use getFilesInFolder() instead'
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-62416-DeprecatedCodeRemovalInCoreSysext.html'
\TYPO3\CMS\Core\Resource\ResourceStorage->getFolderList:
newFunctionCall: 'Use getFoldersInFolder() instead'
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-62416-DeprecatedCodeRemovalInCoreSysext.html'
\TYPO3\CMS\Core\Resource\ResourceStorage->fetchFolderListFromDriver:
newFunctionCall: 'Use getFoldersInFolder() instead'
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-62416-DeprecatedCodeRemovalInCoreSysext.html'
\TYPO3\CMS\Core\Utility\File\BasicFileUtility->getTotalFileInfo:
newFunctionCall: "Use ResourceStorage instead via $GLOBALS['BE_USER']->getFileStorages()"
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-62416-DeprecatedCodeRemovalInCoreSysext.html'
\TYPO3\CMS\Core\Utility\File\BasicFileUtility->checkFileNameLen:
newFunctionCall: "Use ResourceStorage instead via $GLOBALS['BE_USER']->getFileStorages()"
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-62416-DeprecatedCodeRemovalInCoreSysext.html'
\TYPO3\CMS\Core\Utility\File\BasicFileUtility->isPathValid:
newFunctionCall: 'Use GeneralUtility::validPathStr() instead'
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-62416-DeprecatedCodeRemovalInCoreSysext.html'
\TYPO3\CMS\Core\Utility\File\BasicFileUtility->blindPath:
newFunctionCall: null
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-62416-DeprecatedCodeRemovalInCoreSysext.html'
\TYPO3\CMS\Core\Utility\File\BasicFileUtility->findTempFolder:
newFunctionCall: null
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-62416-DeprecatedCodeRemovalInCoreSysext.html'
\TYPO3\CMS\Core\Utility\File\BasicFileUtility->rmDoubleSlash:
newFunctionCall: null
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-62416-DeprecatedCodeRemovalInCoreSysext.html'
\TYPO3\CMS\Core\Utility\File\BasicFileUtility->cleanDirectoryName:
newFunctionCall: 'Use PathUtility::getCanonicalPath() instead'
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-62416-DeprecatedCodeRemovalInCoreSysext.html'
\TYPO3\CMS\Core\Utility\File\ExtendedFileUtility->init_actionPerms:
newFunctionCall: 'Use setActionPermissions() instead'
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-62416-DeprecatedCodeRemovalInCoreSysext.html'
\TYPO3\CMS\Core\Utility\File\ExtendedFileUtility->printLogErrorMessages:
newFunctionCall: 'Use pushErrorMessagesToFlashMessageQueue() instead'
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-62416-DeprecatedCodeRemovalInCoreSysext.html'
\TYPO3\CMS\Core\Utility\File\ExtendedFileUtility->findRecycler:
newFunctionCall: 'Use \TYPO3\CMS\Core\Resource\ResourceStorage instead'
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-62416-DeprecatedCodeRemovalInCoreSysext.html'
\TYPO3\CMS\Core\Html\RteHtmlParser->findRecycler:
newFunctionCall: "Use $fileFactory->getFolderObjectFromCombinedIdentifier($GLOBALS['TYPO3_CONF_VARS']['BE']['RTE_imageStorageDir']); instead"
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-62416-DeprecatedCodeRemovalInCoreSysext.html'
\TYPO3\CMS\Rtehtmlarea\SelectImage->getRTEImageStorageDir:
newFunctionCall: "Use $fileFactory->getFolderObjectFromCombinedIdentifier($GLOBALS['TYPO3_CONF_VARS']['BE']['RTE_imageStorageDir']); instead"
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-62416-DeprecatedCodeRemovalInCoreSysext.html'
\TYPO3\CMS\Core\Localization\Locales->getTerLocales:
newFunctionCall: null
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-62416-DeprecatedCodeRemovalInCoreSysext.html'
\TYPO3\CMS\Core\Localization\Locales->getTerLocaleDependencies:
newFunctionCall: null
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-62416-DeprecatedCodeRemovalInCoreSysext.html'
\TYPO3\CMS\Core\Localization\Locales->convertToTerLocales:
newFunctionCall: null
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-62416-DeprecatedCodeRemovalInCoreSysext.html'
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::getInsertionNeedles:
newFunctionCall: null
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-62416-DeprecatedCodeRemovalInCoreSysext.html'
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::insertModuleFunction:
newFunctionCall: null
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-62416-DeprecatedCodeRemovalInCoreSysext.html'
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::getRequiredExtensionListArray:
newFunctionCall: null
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-62416-DeprecatedCodeRemovalInCoreSysext.html'
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::writeNewExtensionList:
newFunctionCall: null
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-62416-DeprecatedCodeRemovalInCoreSysext.html'
\TYPO3\CMS\Core\Utility\PhpOptionsUtility::isSqlSafeModeEnabled:
newFunctionCall: null
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-62416-DeprecatedCodeRemovalInCoreSysext.html'
\TYPO3\CMS\Core\Core\ClassLoader::getAliasForClassName:
newFunctionCall: 'Use getAliasesForClassName() instead'
docsUrl: 'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.0/Breaking-62416-DeprecatedCodeRemovalInCoreSysext.html'

View file

@ -0,0 +1,4 @@
# Breaking changes in 7.1: https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.1/Index.html
# Nothing in here? Right, there were no breaking changes to functions in this version.
# We keep this file to let you know we didn't forget anything.
'7.1': []

View file

@ -0,0 +1,36 @@
# Breaking changes in 7.2: https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.2/Index.html
'7.2':
\TYPO3\CMS\Core\Page\PageRenderer->setSvgPath:
newFunctionCall: 'Use 3rd party library instead, which is already loaded by TYPO3'
docsUrl: https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.2/Breaking-65962-WebSVGLibraryAndAPIRemoved.html
\TYPO3\CMS\Core\Page\PageRenderer->loadSvg:
newFunctionCall: 'Use 3rd party library instead, which is already loaded by TYPO3'
docsUrl: https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.2/Breaking-65962-WebSVGLibraryAndAPIRemoved.html
\TYPO3\CMS\Core\Page\PageRenderer->enableSvgDebug:
newFunctionCall: 'Use 3rd party library instead, which is already loaded by TYPO3'
docsUrl: https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.2/Breaking-65962-WebSVGLibraryAndAPIRemoved.html
\TYPO3\CMS\Core\Page\PageRenderer->svgForceFlash:
newFunctionCall: 'Use 3rd party library instead, which is already loaded by TYPO3'
docsUrl: https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.2/Breaking-65962-WebSVGLibraryAndAPIRemoved.html
\TYPO3\CMS\Backend\Controller\LoginController->makeLoginForm:
newFunctionCall: 'Use the new Fluid View to adjust the login screen instead'
docsUrl: https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.2/Breaking-65939-BackendLoginRefactoring.html
\TYPO3\CMS\Backend\Controller\LoginController->makeLogoutForm:
newFunctionCall: 'Use the new Fluid View to adjust the login screen instead'
docsUrl: https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.2/Breaking-65939-BackendLoginRefactoring.html
\TYPO3\CMS\Backend\Controller\LoginController->wrapLoginForm:
newFunctionCall: 'Use the new Fluid View to adjust the login screen instead'
docsUrl: https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.2/Breaking-65939-BackendLoginRefactoring.html
\TYPO3\CMS\Backend\Controller\LoginController->makeLoginBoxImage:
newFunctionCall: 'Use the new Fluid View to adjust the login screen instead'
docsUrl: https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.2/Breaking-65939-BackendLoginRefactoring.html
\TYPO3\CMS\Backend\Controller\LoginController->makeLoginNews:
newFunctionCall: 'Use the new Fluid View to adjust the login screen instead'
docsUrl: https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.2/Breaking-65939-BackendLoginRefactoring.html
\TYPO3\CMS\Backend\Controller\LoginController->emitRenderLoginFormSignal:
newFunctionCall: 'Use the new Fluid View to adjust the login screen instead'
docsUrl: https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.2/Breaking-65939-BackendLoginRefactoring.html
# NOTE: This is useless, adding a warning to all "getSignalSlotDispatcher" methods is crazy, many developers implement such a method.
# \TYPO3\CMS\Backend\Controller\LoginController->getSignalSlotDispatcher:
# newFunctionCall: 'Use the new Fluid View to adjust the login screen instead'
# docsUrl: https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.2/Breaking-65939-BackendLoginRefactoring.html

View file

@ -0,0 +1,13 @@
# Breaking changes in 7.3: https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.3/Index.html#breaking-changes
'7.3':
# NOTE: If this is making you crazy, just disable via ruleset.xml or phpcs.xml
parent::initializeObject:
newFunctionCall: 'Remove call, if this is inside a child of \TYPO3\CMS\Extbase\DomainObject\AbstractDomainObject, there is no initializeObject in the parent anymore.'
docsUrl: https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.3/Breaking-67402-ExtbaseAbstractDomainObjectInitializeObject.html
\TYPO3\CMS\Extbase\Persistence\Repository::replace:
newFunctionCall: null
docsUrl: https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.3/Breaking-63835-RemoveDeprecatedExtbasePersistenceParts.html
\TYPO3\CMS\Extbase\Persistence\Generic\Backend::setDeletedObjects:
newFunctionCall: null
docsUrl: https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.3/Breaking-63835-RemoveDeprecatedExtbasePersistenceParts.html

View file

@ -0,0 +1,81 @@
# Breaking changes in 7.4: https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.4/Index.html#breaking-changes
'7.4':
\TYPO3\CMS\Core\Page\PageRenderer::setExtCorePath:
newFunctionCall: null
docsUrl: https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.4/Breaking-68001-RemovedExtJSCoreAndExtJSAdapters.html
\TYPO3\CMS\Core\Page\PageRenderer::getExtCorePath:
newFunctionCall: null
docsUrl: https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.4/Breaking-68001-RemovedExtJSCoreAndExtJSAdapters.html
\TYPO3\CMS\Core\Page\PageRenderer::loadExtCore:
newFunctionCall: null
docsUrl: https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.4/Breaking-68001-RemovedExtJSCoreAndExtJSAdapters.html
\TYPO3\CMS\Core\Page\PageRenderer::enableExtCoreDebug:
newFunctionCall: null
docsUrl: https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.4/Breaking-68001-RemovedExtJSCoreAndExtJSAdapters.html
\TYPO3\CMS\Core\Page\PageRenderer::setExtCorePath:
newFunctionCall: null
docsUrl: https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.4/Breaking-68001-RemovedExtJSCoreAndExtJSAdapters.html
\TYPO3\CMS\Backend\Controller\EditDocumentController->functionMenus:
newFunctionCall: null
docsUrl: https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.4/Breaking-67753-DropSecondaryOptions.html
\TYPO3\CMS\Backend\Utility\BackendUtility::getFileIcon:
newFunctionCall: 'Use \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIconForFile() insteadenableExtCoreDebug'
docsUrl: https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.4/Breaking-67654-RemoveGLOBALSFILEICONSFunctionality.html
\TYPO3\CMS\Frontend\Page\PageGenerator::getIncFiles:
newFunctionCall: 'Use hooks during the Frontend set up to execute custom PHP code'
docsUrl: https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.4/Breaking-67646-LibraryInclusionInFrontend.html
\TYPO3\CMS\Backend\Template\DocumentTemplate\DocumentTemplate->formWidthText:
newFunctionCall: null
docsUrl: https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.4/Breaking-67565-DeprecatedBackendRelatedMethodsRemoved.html
\TYPO3\CMS\Backend\View\PageLayoutView->getBackendLayoutConfiguration:
newFunctionCall: null
docsUrl: https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.4/Breaking-67565-DeprecatedBackendRelatedMethodsRemoved.html
\TYPO3\CMS\Backend\View\PageLayoutView->wordWrapper:
newFunctionCall: null
docsUrl: https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.4/Breaking-67565-DeprecatedBackendRelatedMethodsRemoved.html
\TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController->checkJumpUrlReferer:
newFunctionCall: null
docsUrl: https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.4/Breaking-66602-RemoveRefererCheckWhileHandlingJumpUrl.html
\TYPO3\CMS\Core\Utility\OpcodeCacheUtility::initialize:
newFunctionCall: 'Use new service class instead \TYPO3\CMS\Core\Service\OpcodeCacheService'
docsUrl: https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.4/Breaking-63838-ChangedOpcodeCacheUtilityBeingAServiceClass.html
\TYPO3\CMS\Core\Utility\OpcodeCacheUtility::clearAllActive:
newFunctionCall: 'Use new service class instead \TYPO3\CMS\Core\Service\OpcodeCacheService'
docsUrl: https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.4/Breaking-63838-ChangedOpcodeCacheUtilityBeingAServiceClass.html
\TYPO3\CMS\Core\Utility\OpcodeCacheUtility::getAllActive:
newFunctionCall: 'Use new service class instead \TYPO3\CMS\Core\Service\OpcodeCacheService'
docsUrl: https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.4/Breaking-63838-ChangedOpcodeCacheUtilityBeingAServiceClass.html
\TYPO3\CMS\Backend\Tree\View\PagePositionMap->JSimgFunc:
newFunctionCall: 'Use proper styling for a tree list'
docsUrl: https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.4/Breaking-56951-RemoveUnusedMethodsInPagePositionMap.html
\TYPO3\CMS\Backend\Tree\View\PagePositionMap->insertQuadLines:
newFunctionCall: 'Use proper styling for a tree list'
docsUrl: https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.4/Breaking-56951-RemoveUnusedMethodsInPagePositionMap.html
\TYPO3\CMS\Core\Page\PageRenderer->enableExtJSQuickTips:
newFunctionCall: 'Use bootstrap tooltips, which work out of the box as alternative. Simple add data-toggle="tooltip" and data-title="your tooltip" to any element you want'
docsUrl: https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.4/Breaking-68276-RemoveExtJSQuicktipsIfPossible.html
\TYPO3\CMS\IndexedSearch\Indexer->removeLoginpagesWithContentHash:
newFunctionCall: null
docsUrl: https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.4/Breaking-68193-DropRemoveLoginpagesWithContentHashFromIndexerphp.html
\TYPO3\CMS\Frontend\Controller\ExtDirectEidController->actionIsAllowed:
newFunctionCall: 'Migrate your eID scripts to the new PSR-7 compliant model'
docsUrl: https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.4/Breaking-68186-AdjustedAndRemovedMethodsInEIDArea.html
# NOTE: It does not make sense to warn about all render methods
# \TYPO3\CMS\Frontend\Controller\ExtDirectEidController->render:
# newFunctionCall: 'Migrate your eID scripts to the new PSR-7 compliant model'
# docsUrl: https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.4/Breaking-68186-AdjustedAndRemovedMethodsInEIDArea.html
\TYPO3\CMS\Frontend\Utility\EidUtility::isEidRequest:
newFunctionCall: 'Migrate your eID scripts to the new PSR-7 compliant model'
docsUrl: https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.4/Breaking-68186-AdjustedAndRemovedMethodsInEIDArea.html
\TYPO3\CMS\Frontend\Utility\EidUtility::getEidScriptPath:
newFunctionCall: 'Migrate your eID scripts to the new PSR-7 compliant model'
docsUrl: https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.4/Breaking-68186-AdjustedAndRemovedMethodsInEIDArea.html
\TYPO3\CMS\Backend\View\PageLayoutView->linkRTEbutton:
newFunctionCall: null
docsUrl: https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.4/Breaking-68020-DroppedDisableBigButtons.html
\TYPO3\CMS\Backend\View\PageLayoutView->isRTEforField:
newFunctionCall: null
docsUrl: https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.4/Breaking-68020-DroppedDisableBigButtons.html
\TYPO3\CMS\Backend\View\PageLayoutView->getSpecConfForField:
newFunctionCall: null
docsUrl: https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.4/Breaking-68020-DroppedDisableBigButtons.html

View file

@ -0,0 +1,2 @@
# Breaking changes in 7.5: https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.5/Index.html#breaking-changes
'7.5': []

View file

@ -0,0 +1,99 @@
<?php
/*
* Copyright (C) 2017 Daniel Siepmann <coding@daniel-siepmann.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
use PHP_CodeSniffer_File as PhpCsFile;
use PHP_CodeSniffer_Sniff as PhpCsSniff;
use PHP_CodeSniffer_Tokens as PhpCsTokens;
/**
* Analyses feature 6991.
*
* @see https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.6/Feature-69916-PSR-7-basedRoutingForBackendAJAXRequests.html
*/
class Typo3Update_Sniffs_Deprecated_AjaxRegistrationSniff implements PhpCsSniff
{
/**
* Defines files to check.
* As soon as PHP_CS 3 is used, define them in ruleset.xml.
*
* @var array<string>
*/
public $filenamesToCheck = [
'ext_tables.php',
'ext_localconf.php',
];
/**
* Returns the token types that this sniff is interested in.
*
* @return array<int>
*/
public function register()
{
return PhpCsTokens::$stringTokens;
}
/**
* Processes the tokens that this sniff is interested in.
*
* @param PhpCsFile $phpcsFile The file where the token was found.
* @param int $stackPtr The position in the stack where
* the token was found.
*
* @return void
*/
public function process(PhpCsFile $phpcsFile, $stackPtr)
{
if (in_array(basename($phpcsFile->getFilename()), $this->filenamesToCheck) === false) {
return;
}
$tokens = $phpcsFile->getTokens();
if (preg_match('/"AJAX"|\'AJAX\'/', $tokens[$stackPtr]['content']) !== 1) {
return;
}
$equalSign = $phpcsFile->findNext(T_EQUAL, $stackPtr, null, false, null, true);
if ($equalSign === false) {
return;
}
$tokenToCheck = $phpcsFile->findNext(T_WHITESPACE, $equalSign + 1, null, true, null, true);
if ($tokenToCheck === false) {
return;
}
$token = $tokens[$tokenToCheck];
if ($token['code'] !== T_CONSTANT_ENCAPSED_STRING) {
return;
}
$phpcsFile->addWarning(
'Defining AJAX using %s is no longer supported with a single String like %s.'
. ' Since TYPO3 7.6, use PSR-7-based Routing for Backend AJAX Requests.'
. ' See: %s',
$tokenToCheck,
'',
[
"\$GLOBALS['TYPO3_CONF_VARS']['BE']['AJAX'][\$ajaxID]",
$token['content'],
'https://docs.typo3.org/typo3cms/extensions/core/Changelog/7.6/Feature-69916-PSR-7-basedRoutingForBackendAJAXRequests.html'
]
);
}
}

View file

@ -22,17 +22,16 @@ namespace Typo3Update\Sniffs\LegacyClassnames;
use PHP_CodeSniffer as PhpCs; use PHP_CodeSniffer as PhpCs;
use PHP_CodeSniffer_File as PhpCsFile; use PHP_CodeSniffer_File as PhpCsFile;
use PHP_CodeSniffer_Sniff as PhpCsSniff;
use Typo3Update\Sniffs\LegacyClassnames\Mapping;
use Typo3Update\Sniffs\OptionsAccessTrait;
/** /**
* Provide common uses for all sniffs, regarding class name checks. * Provide common uses for all sniffs, regarding class name checks.
*/ */
trait ClassnameCheckerTrait abstract class AbstractClassnameChecker implements PhpCsSniff
{ {
/** use OptionsAccessTrait;
* Contains mapping from old -> new class names.
* @var array
*/
private $legacyClassnames = [];
/** /**
* A list of extension names that might contain legacy class names. * A list of extension names that might contain legacy class names.
@ -45,20 +44,22 @@ trait ClassnameCheckerTrait
public $legacyExtensions = ['Extbase', 'Fluid']; public $legacyExtensions = ['Extbase', 'Fluid'];
/** /**
* Initialize, used internally, to not initialize if not needed inside __construct. * @var Mapping
*/ */
private function initialize() protected $legacyMapping;
{
$mappingFile = PhpCs::getConfigData('mappingFile');
if (!$mappingFile) {
$mappingFile = __DIR__ . '/../../../../../LegacyClassnames.php';
}
if ($this->legacyClassnames !== []) {
return;
}
$legacyClassnames = require $mappingFile; /**
$this->legacyClassnames = $legacyClassnames['aliasToClassNameMapping']; * Used by some sniffs to keep original token for replacement.
*
* E.g. when Token itself is a whole inline comment, and we just want to replace the classname within.
*
* @var string
*/
protected $originalTokenContent = '';
public function __construct()
{
$this->legacyMapping = Mapping::getInstance();
} }
/** /**
@ -110,10 +111,9 @@ trait ClassnameCheckerTrait
* @param string $classname * @param string $classname
* @return bool * @return bool
*/ */
private function isLegacyClassname($classname) protected function isLegacyClassname($classname)
{ {
$this->initialize(); return $this->legacyMapping->isLegacyClassname($classname);
return isset($this->legacyClassnames[strtolower($classname)]);
} }
/** /**
@ -145,10 +145,23 @@ trait ClassnameCheckerTrait
* @param string $classname * @param string $classname
* @return string * @return string
*/ */
private function getNewClassname($classname) protected function getNewClassname($classname)
{ {
$this->initialize(); return $this->legacyMapping->getNewClassname($classname);
return $this->legacyClassnames[strtolower($classname)]; }
/**
* Use to add new mappings found during parsing.
* E.g. in MissingNamespaceSniff old class definitions are fixed and a new mapping exists afterwards.
*
* @param string $legacyClassname
* @param string $newClassname
*
* @return void
*/
protected function addLegacyClassname($legacyClassname, $newClassname)
{
$this->legacyMapping->addLegacyClassname($legacyClassname, $newClassname);
} }
/** /**
@ -206,17 +219,22 @@ trait ClassnameCheckerTrait
* @param PhpCsFile $phpcsFile * @param PhpCsFile $phpcsFile
* @param int $classnamePosition * @param int $classnamePosition
* @param string $classname * @param string $classname
* @param bool $forceEmptyPrefix Defines whether '\\' prefix should be checked or always be left out.
*/ */
private function replaceLegacyClassname(PhpCsFile $phpcsFile, $classnamePosition, $classname) protected function replaceLegacyClassname(
{ PhpCsFile $phpcsFile,
$classnamePosition,
$classname,
$forceEmptyPrefix = false
) {
$prefix = '\\'; $prefix = '\\';
if ($phpcsFile->getTokens()[$classnamePosition -1]['code'] === T_NS_SEPARATOR) { if ($forceEmptyPrefix || $phpcsFile->getTokens()[$classnamePosition -1]['code'] === T_NS_SEPARATOR) {
$prefix = ''; $prefix = '';
} }
$phpcsFile->fixer->replaceToken( $phpcsFile->fixer->replaceToken(
$classnamePosition, $classnamePosition,
$this->getTokenForReplacement($prefix . $this->getNewClassname($classname)) $this->getTokenForReplacement($prefix . $this->getNewClassname($classname), $classname)
); );
} }
@ -224,12 +242,13 @@ trait ClassnameCheckerTrait
* String to use for replacing / fixing the token. * String to use for replacing / fixing the token.
* Default is class name itself, can be overwritten in sniff for special behaviour. * Default is class name itself, can be overwritten in sniff for special behaviour.
* *
* @param string $classname * @param string $newClassname
* @param string $originalClassname
* @return string * @return string
*/ */
protected function getTokenForReplacement($classname) protected function getTokenForReplacement($newClassname, $originalClassname)
{ {
return $classname; return $newClassname;
} }
/** /**

View file

@ -19,27 +19,22 @@
* 02110-1301, USA. * 02110-1301, USA.
*/ */
use PHP_CodeSniffer_File as PhpCsFile;
use Typo3Update\Sniffs\LegacyClassnames\AbstractClassnameChecker;
/** /**
* Migrate PHP Doc comments. * Migrate PHP Doc comments.
* *
* E.g. annotations like @param or @return, see $allowedTags. * E.g. annotations like @param or @return, see $allowedTags.
*/ */
class Typo3Update_Sniffs_LegacyClassnames_DocCommentSniff implements PHP_CodeSniffer_Sniff class Typo3Update_Sniffs_LegacyClassnames_DocCommentSniff extends AbstractClassnameChecker
{ {
use \Typo3Update\Sniffs\LegacyClassnames\ClassnameCheckerTrait;
/** /**
* The configured tags will be processed. * The configured tags will be processed.
* @var array<string> * @var array<string>
*/ */
public $allowedTags = ['@param', '@return', '@var']; public $allowedTags = ['@param', '@return', '@var'];
/**
* Original token content for reuse accross methods.
* @var string
*/
protected $originalTokenContent = '';
/** /**
* Returns the token types that this sniff is interested in. * Returns the token types that this sniff is interested in.
* *
@ -55,13 +50,13 @@ class Typo3Update_Sniffs_LegacyClassnames_DocCommentSniff implements PHP_CodeSni
/** /**
* Processes the tokens that this sniff is interested in. * Processes the tokens that this sniff is interested in.
* *
* @param PHP_CodeSniffer_File $phpcsFile The file where the token was found. * @param PhpCsFile $phpcsFile The file where the token was found.
* @param int $stackPtr The position in the stack where * @param int $stackPtr The position in the stack where
* the token was found. * the token was found.
* *
* @return void * @return void
*/ */
public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) public function process(PhpCsFile $phpcsFile, $stackPtr)
{ {
$tokens = $phpcsFile->getTokens(); $tokens = $phpcsFile->getTokens();
if (!in_array($tokens[$stackPtr]['content'], $this->allowedTags)) { if (!in_array($tokens[$stackPtr]['content'], $this->allowedTags)) {
@ -71,22 +66,32 @@ class Typo3Update_Sniffs_LegacyClassnames_DocCommentSniff implements PHP_CodeSni
if ($classnamePosition === false) { if ($classnamePosition === false) {
return; return;
} }
$classname = explode(' ', $tokens[$classnamePosition]['content'])[0]; $classnames = explode('|', explode(' ', $tokens[$classnamePosition]['content'])[0]);
$this->originalTokenContent = $tokens[$classnamePosition]['content']; $this->originalTokenContent = $tokens[$classnamePosition]['content'];
foreach ($classnames as $classname) {
$this->addFixableError($phpcsFile, $classnamePosition, $classname); $this->addFixableError($phpcsFile, $classnamePosition, $classname);
} }
}
/** /**
* As token contains more then just class name, we have to build new content ourself. * As token contains more then just class name, we have to build new content ourself.
* *
* @param string $classname * @param string $newClassname
* @param string $originalClassname
* @return string * @return string
*/ */
protected function getTokenForReplacement($classname) protected function getTokenForReplacement($newClassname, $originalClassname)
{ {
$token = explode(' ', $this->originalTokenContent); $token = explode(' ', $this->originalTokenContent);
$token[0] = $classname;
$classNames = explode('|', $token[0]);
foreach ($classNames as $position => $classname) {
if ($classname === $originalClassname) {
$classNames[$position] = $newClassname;
}
}
$token[0] = implode('|', $classNames);
return implode(' ', $token); return implode(' ', $token);
} }

View file

@ -19,13 +19,14 @@
* 02110-1301, USA. * 02110-1301, USA.
*/ */
use PHP_CodeSniffer_File as PhpCsFile;
use Typo3Update\Sniffs\LegacyClassnames\AbstractClassnameChecker;
/** /**
* Detect and migrate extend and implement of old legacy classnames. * Detect and migrate extend and implement of old legacy classnames.
*/ */
class Typo3Update_Sniffs_LegacyClassnames_InheritanceSniff implements PHP_CodeSniffer_Sniff class Typo3Update_Sniffs_LegacyClassnames_InheritanceSniff extends AbstractClassnameChecker
{ {
use \Typo3Update\Sniffs\LegacyClassnames\ClassnameCheckerTrait;
/** /**
* Returns the token types that this sniff is interested in. * Returns the token types that this sniff is interested in.
* *
@ -38,4 +39,56 @@ class Typo3Update_Sniffs_LegacyClassnames_InheritanceSniff implements PHP_CodeSn
T_IMPLEMENTS, T_IMPLEMENTS,
]; ];
} }
/**
* Processes the tokens that this sniff is interested in.
*
* This is the default implementation, as most of the time next T_STRING is
* the class name. This way only the register method has to be registered
* in default cases.
*
* @param PhpCsFile $phpcsFile The file where the token was found.
* @param int $stackPtr The position in the stack where
* the token was found.
*
* @return void
*/
public function process(PhpCsFile $phpcsFile, $stackPtr)
{
if ($phpcsFile->getTokens()[$stackPtr]['code'] === T_IMPLEMENTS) {
$this->processInterfaces($phpcsFile, $stackPtr);
return;
}
parent::process($phpcsFile, $stackPtr);
}
/**
* Process all interfaces for current class.
*
* @param PhpCsFile $phpcsFile
* @param int $stackPtr
*
* @return void
*/
protected function processInterfaces(PhpCsFile $phpcsFile, $stackPtr)
{
$interfaces = $phpcsFile->findImplementedInterfaceNames($phpcsFile->findPrevious(T_CLASS, $stackPtr));
if ($interfaces === false) {
return;
}
foreach ($interfaces as $interface) {
if (! $this->isLegacyClassname($interface)) {
continue;
}
$position = $phpcsFile->findNext(T_STRING, $stackPtr, null, false, $interface);
if ($position === false) {
continue;
}
$this->addFixableError($phpcsFile, $position, $interface);
}
}
} }

View file

@ -19,19 +19,14 @@
* 02110-1301, USA. * 02110-1301, USA.
*/ */
use PHP_CodeSniffer_File as PhpCsFile;
use Typo3Update\Sniffs\LegacyClassnames\AbstractClassnameChecker;
/** /**
* Migrate PHP inline comments, e.g. for IDEs. * Migrate PHP inline comments, e.g. for IDEs.
*/ */
class Typo3Update_Sniffs_LegacyClassnames_InlineCommentSniff implements PHP_CodeSniffer_Sniff class Typo3Update_Sniffs_LegacyClassnames_InlineCommentSniff extends AbstractClassnameChecker
{ {
use \Typo3Update\Sniffs\LegacyClassnames\ClassnameCheckerTrait;
/**
* Original token content for reuse accross methods.
* @var string
*/
protected $originalTokenContent = '';
/** /**
* Returns the token types that this sniff is interested in. * Returns the token types that this sniff is interested in.
* *
@ -47,19 +42,20 @@ class Typo3Update_Sniffs_LegacyClassnames_InlineCommentSniff implements PHP_Code
/** /**
* Processes the tokens that this sniff is interested in. * Processes the tokens that this sniff is interested in.
* *
* @param PHP_CodeSniffer_File $phpcsFile The file where the token was found. * @param PhpCsFile $phpcsFile The file where the token was found.
* @param int $stackPtr The position in the stack where * @param int $stackPtr The position in the stack where
* the token was found. * the token was found.
* *
* @return void * @return void
*/ */
public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) public function process(PhpCsFile $phpcsFile, $stackPtr)
{ {
$tokens = $phpcsFile->getTokens(); $tokens = $phpcsFile->getTokens();
$this->originalTokenContent = $tokens[$stackPtr]['content']; $this->originalTokenContent = $tokens[$stackPtr]['content'];
$commentParts = preg_split('/\s+/', $this->originalTokenContent); $commentParts = preg_split('/\s+/', $this->originalTokenContent);
if (count($commentParts) !== 5 || $commentParts[1] !== '@var' || ($commentParts[2][0] !== '$' && $commentParts[3][0] !== '$')) { if (count($commentParts) !== 5 || $commentParts[1] !== '@var'
|| ($commentParts[2][0] !== '$' && $commentParts[3][0] !== '$')) {
return; return;
} }
@ -85,13 +81,14 @@ class Typo3Update_Sniffs_LegacyClassnames_InlineCommentSniff implements PHP_Code
/** /**
* As token contains more then just class name, we have to build new content ourself. * As token contains more then just class name, we have to build new content ourself.
* *
* @param string $classname * @param string $newClassname
* @param string $originalClassname
* @return string * @return string
*/ */
protected function getTokenForReplacement($classname) protected function getTokenForReplacement($newClassname, $originalClassname)
{ {
$token = preg_split('/\s+/', $this->originalTokenContent); $token = preg_split('/\s+/', $this->originalTokenContent);
$token[$this->getClassnamePosition($token)] = $classname; $token[$this->getClassnamePosition($token)] = $newClassname;
return implode(' ', $token); return implode(' ', $token);
} }

View file

@ -19,13 +19,13 @@
* 02110-1301, USA. * 02110-1301, USA.
*/ */
use Typo3Update\Sniffs\LegacyClassnames\AbstractClassnameChecker;
/** /**
* Detect and migrate instanceof checks of old legacy classnames. * Detect and migrate instanceof checks of old legacy classnames.
*/ */
class Typo3Update_Sniffs_LegacyClassnames_InstanceofSniff implements PHP_CodeSniffer_Sniff class Typo3Update_Sniffs_LegacyClassnames_InstanceofSniff extends AbstractClassnameChecker
{ {
use \Typo3Update\Sniffs\LegacyClassnames\ClassnameCheckerTrait;
/** /**
* Returns the token types that this sniff is interested in. * Returns the token types that this sniff is interested in.
* *

View file

@ -19,22 +19,17 @@
* 02110-1301, USA. * 02110-1301, USA.
*/ */
use PHP_CodeSniffer_File as PhpCsFile;
use PHP_CodeSniffer_Tokens as Tokens; use PHP_CodeSniffer_Tokens as Tokens;
use Typo3Update\Sniffs\LegacyClassnames\AbstractClassnameChecker;
/** /**
* Detect and migrate instantiations of old legacy classnames using "makeInstance". * Detect and migrate instantiations of old legacy classnames using "makeInstance".
*/ */
class Typo3Update_Sniffs_LegacyClassnames_InstantiationWithMakeInstanceSniff implements PHP_CodeSniffer_Sniff class Typo3Update_Sniffs_LegacyClassnames_InstantiationWithMakeInstanceSniff extends AbstractClassnameChecker
{ {
use \Typo3Update\Sniffs\LegacyClassnames\ClassnameCheckerTrait;
use \Typo3Update\Sniffs\ExtendedPhpCsSupportTrait; use \Typo3Update\Sniffs\ExtendedPhpCsSupportTrait;
/**
* Original token content for reuse accross methods.
* @var string
*/
protected $originalTokenContent = '';
/** /**
* Returns the token types that this sniff is interested in. * Returns the token types that this sniff is interested in.
* *
@ -48,13 +43,13 @@ class Typo3Update_Sniffs_LegacyClassnames_InstantiationWithMakeInstanceSniff imp
/** /**
* Processes the tokens that this sniff is interested in. * Processes the tokens that this sniff is interested in.
* *
* @param PHP_CodeSniffer_File $phpcsFile The file where the token was found. * @param PhpCsFile $phpcsFile The file where the token was found.
* @param int $stackPtr The position in the stack where * @param int $stackPtr The position in the stack where
* the token was found. * the token was found.
* *
* @return void * @return void
*/ */
public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) public function process(PhpCsFile $phpcsFile, $stackPtr)
{ {
if (!$this->isFunctionCall($phpcsFile, $stackPtr)) { if (!$this->isFunctionCall($phpcsFile, $stackPtr)) {
return; return;
@ -78,11 +73,12 @@ class Typo3Update_Sniffs_LegacyClassnames_InstantiationWithMakeInstanceSniff imp
/** /**
* As token contains more then just class name, we have to build new content ourself. * As token contains more then just class name, we have to build new content ourself.
* *
* @param string $classname * @param string $newClassname
* @param string $originalClassname
* @return string * @return string
*/ */
protected function getTokenForReplacement($classname) protected function getTokenForReplacement($newClassname, $originalClassname)
{ {
return $this->getTokenReplacementForString($classname); return $this->getTokenReplacementForString($newClassname);
} }
} }

View file

@ -19,13 +19,13 @@
* 02110-1301, USA. * 02110-1301, USA.
*/ */
use Typo3Update\Sniffs\LegacyClassnames\AbstractClassnameChecker;
/** /**
* Detect and migrate old legacy classnames instantiations using phps "new". * Detect and migrate old legacy classnames instantiations using phps "new".
*/ */
class Typo3Update_Sniffs_LegacyClassnames_InstantiationWithNewSniff implements PHP_CodeSniffer_Sniff class Typo3Update_Sniffs_LegacyClassnames_InstantiationWithNewSniff extends AbstractClassnameChecker
{ {
use \Typo3Update\Sniffs\LegacyClassnames\ClassnameCheckerTrait;
/** /**
* Returns the token types that this sniff is interested in. * Returns the token types that this sniff is interested in.
* *

View file

@ -19,14 +19,15 @@
* 02110-1301, USA. * 02110-1301, USA.
*/ */
use PHP_CodeSniffer_File as PhpCsFile;
use PHP_CodeSniffer_Tokens as Tokens; use PHP_CodeSniffer_Tokens as Tokens;
use Typo3Update\Sniffs\LegacyClassnames\AbstractClassnameChecker;
/** /**
* Detect and migrate old legacy classname instantiations using objectmanager create and get. * Detect and migrate old legacy classname instantiations using objectmanager create and get.
*/ */
class Typo3Update_Sniffs_LegacyClassnames_InstantiationWithObjectManagerSniff implements PHP_CodeSniffer_Sniff class Typo3Update_Sniffs_LegacyClassnames_InstantiationWithObjectManagerSniff extends AbstractClassnameChecker
{ {
use \Typo3Update\Sniffs\LegacyClassnames\ClassnameCheckerTrait;
use \Typo3Update\Sniffs\ExtendedPhpCsSupportTrait; use \Typo3Update\Sniffs\ExtendedPhpCsSupportTrait;
/** /**
@ -42,13 +43,13 @@ class Typo3Update_Sniffs_LegacyClassnames_InstantiationWithObjectManagerSniff im
/** /**
* Processes the tokens that this sniff is interested in. * Processes the tokens that this sniff is interested in.
* *
* @param PHP_CodeSniffer_File $phpcsFile The file where the token was found. * @param PhpCsFile $phpcsFile The file where the token was found.
* @param int $stackPtr The position in the stack where * @param int $stackPtr The position in the stack where
* the token was found. * the token was found.
* *
* @return void * @return void
*/ */
public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) public function process(PhpCsFile $phpcsFile, $stackPtr)
{ {
if (!$this->isFunctionCall($phpcsFile, $stackPtr)) { if (!$this->isFunctionCall($phpcsFile, $stackPtr)) {
return; return;
@ -82,11 +83,12 @@ class Typo3Update_Sniffs_LegacyClassnames_InstantiationWithObjectManagerSniff im
/** /**
* As token contains more then just class name, we have to build new content ourself. * As token contains more then just class name, we have to build new content ourself.
* *
* @param string $classname * @param string $newClassname
* @param string $originalClassname
* @return string * @return string
*/ */
protected function getTokenForReplacement($classname) protected function getTokenForReplacement($newClassname, $originalClassname)
{ {
return $this->getTokenReplacementForString($classname); return $this->getTokenReplacementForString($newClassname);
} }
} }

View file

@ -19,22 +19,16 @@
* 02110-1301, USA. * 02110-1301, USA.
*/ */
use PHP_CodeSniffer_Tokens as Tokens; use PHP_CodeSniffer_File as PhpcsFile;
use Typo3Update\Sniffs\LegacyClassnames\AbstractClassnameChecker;
/** /**
* Detect and migrate instantiations of old legacy classnames using "makeInstance". * Detect and migrate instantiations of old legacy classnames using "makeInstance".
*/ */
class Typo3Update_Sniffs_LegacyClassnames_IsACallSniff implements PHP_CodeSniffer_Sniff class Typo3Update_Sniffs_LegacyClassnames_IsACallSniff extends AbstractClassnameChecker
{ {
use \Typo3Update\Sniffs\LegacyClassnames\ClassnameCheckerTrait;
use \Typo3Update\Sniffs\ExtendedPhpCsSupportTrait; use \Typo3Update\Sniffs\ExtendedPhpCsSupportTrait;
/**
* Original token content for reuse accross methods.
* @var string
*/
protected $originalTokenContent = '';
/** /**
* Returns the token types that this sniff is interested in. * Returns the token types that this sniff is interested in.
* *
@ -48,13 +42,13 @@ class Typo3Update_Sniffs_LegacyClassnames_IsACallSniff implements PHP_CodeSniffe
/** /**
* Processes the tokens that this sniff is interested in. * Processes the tokens that this sniff is interested in.
* *
* @param PHP_CodeSniffer_File $phpcsFile The file where the token was found. * @param PhpCsFile $phpcsFile The file where the token was found.
* @param int $stackPtr The position in the stack where * @param int $stackPtr The position in the stack where
* the token was found. * the token was found.
* *
* @return void * @return void
*/ */
public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) public function process(PhpCsFile $phpcsFile, $stackPtr)
{ {
if (!$this->isFunctionCall($phpcsFile, $stackPtr)) { if (!$this->isFunctionCall($phpcsFile, $stackPtr)) {
return; return;
@ -78,11 +72,12 @@ class Typo3Update_Sniffs_LegacyClassnames_IsACallSniff implements PHP_CodeSniffe
/** /**
* As token contains more then just class name, we have to build new content ourself. * As token contains more then just class name, we have to build new content ourself.
* *
* @param string $classname * @param string $newClassname
* @param string $originalClassname
* @return string * @return string
*/ */
protected function getTokenForReplacement($classname) protected function getTokenForReplacement($newClassname, $originalClassname)
{ {
return $this->getTokenReplacementForString($classname); return $this->getTokenReplacementForString($newClassname);
} }
} }

View file

@ -0,0 +1,123 @@
<?php
namespace Typo3Update\Sniffs\LegacyClassnames;
/*
* Copyright (C) 2017 Daniel Siepmann <coding@daniel-siepmann.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
use Typo3Update\Sniffs\OptionsAccessTrait;
/**
* Singleton wrapper for mappings.
*
* Will check the configured file for whether a class is legacy and provides further methods.
* Also can update to add new migrated class names.
*/
final class Mapping
{
use OptionsAccessTrait;
// Singleton implementation - Start
static protected $instance = null;
/**
* Get the singleton instance.
*
* @return Mapping
*/
public static function getInstance()
{
if (static::$instance === null) {
static::$instance = new Mapping();
}
return static::$instance;
}
private function __clone()
{
}
private function __wakeup()
{
}
private function __construct()
{
$this->mappings = require $this->getMappingFile();
}
// Singleton implementation - End
/**
* Contains mappings as defined by composer for alias mapping.
* @var array
*/
protected $mappings = [];
/**
* Checks whether a mapping exists for the given $classname,
* indicating it's legacy.
*
* @param string $classname
* @return bool
*/
public function isLegacyClassname($classname)
{
return isset($this->mappings['aliasToClassNameMapping'][strtolower($classname)]);
}
/**
* @param string $classname
* @return string
*/
public function getNewClassname($classname)
{
return $this->mappings['aliasToClassNameMapping'][strtolower($classname)];
}
/**
* Use to add new mappings found during parsing.
* E.g. in MissingNamespaceSniff old class definitions are fixed and a new mapping exists afterwards.
*
* @param string $legacyClassname
* @param string $newClassname
*
* @return void
*/
public function addLegacyClassname($legacyClassname, $newClassname)
{
$key = strtolower($legacyClassname);
$this->mappings['aliasToClassNameMapping'][$key] = $newClassname;
$this->mappings['classNameToAliasMapping'][$newClassname] = [$key => $key];
}
/**
* Used to persist new mappings.
*/
public function __destruct()
{
// For some reasons desctruct is called multiple times, while construct
// is called once. Until we know the issue and fix it, this is our
// workaround to not break the file and do stuff in an unkown instance.
if ($this !== static::$instance) {
return;
}
file_put_contents(
$this->getMappingFile(),
'<?php' . PHP_EOL . 'return ' . var_export($this->mappings, true) . ';'
);
}
}

View file

@ -0,0 +1,164 @@
<?php
/*
* Copyright (C) 2017 Daniel Siepmann <coding@daniel-siepmann.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
use PHP_CodeSniffer_File as PhpCsFile;
use Typo3Update\Sniffs\LegacyClassnames\AbstractClassnameChecker;
/**
* Detect missing namespaces for class definitions.
*/
class Typo3Update_Sniffs_LegacyClassnames_MissingNamespaceSniff extends AbstractClassnameChecker
{
/**
* Returns the token types that this sniff is interested in.
*
* @return array<int>
*/
public function register()
{
return [
T_CLASS,
T_INTERFACE,
T_TRAIT,
];
}
/**
* Processes the tokens that this sniff is interested in.
*
* @param PhpCsFile $phpcsFile The file where the token was found.
* @param int $stackPtr The position in the stack where
* the token was found.
*
* @return void
*/
public function process(PhpCsFile $phpcsFile, $stackPtr)
{
$tokens = $phpcsFile->getTokens();
$namespacePosition = $phpcsFile->findPrevious(T_NAMESPACE, $stackPtr);
if ($namespacePosition !== false) {
return;
}
$classnamePosition = $phpcsFile->findNext(T_STRING, $stackPtr);
if ($classnamePosition === false) {
return;
}
$classname = $tokens[$classnamePosition]['content'];
$this->addFixableError($phpcsFile, $classnamePosition, $classname);
}
/**
* Overwrite as we don't look up the classname, but check whether the style is legacy.
*
* @param string $classname
* @return bool
*/
protected function isLegacyClassname($classname)
{
return strpos($classname, 'Tx_') === 0;
}
/**
* @param string $classname
* @return string
*/
protected function getNewClassname($classname)
{
return substr($classname, strrpos($classname, '_') + 1);
}
/**
*
* @param PhpCsFile $phpcsFile
* @param int $classnamePosition
* @param string $classname
* @param bool $forceEmptyPrefix Defines whether '\\' prefix should be checked or always be left out.
*/
protected function replaceLegacyClassname(
PhpCsFile $phpcsFile,
$classnamePosition,
$classname,
$forceEmptyPrefix = true
) {
parent::replaceLegacyClassname($phpcsFile, $classnamePosition, $classname, $forceEmptyPrefix);
$tokens = $phpcsFile->getTokens();
$lineEndings = PhpCsFile::detectLineEndings($phpcsFile->getFilename());
$suffix = $lineEndings;
if ($tokens[1]['code'] !== T_WHITESPACE) {
$suffix .= $lineEndings;
}
$phpcsFile->fixer->replaceToken(
$this->getNamespacePosition($phpcsFile),
'<?php' . $lineEndings . $this->getNamespaceDefinition($classname) . $suffix
);
$this->addLegacyClassname(
$classname,
$this->getNamespace($classname) . '\\' . $this->getNewClassname($classname)
);
}
/**
* @param PhpCsFile $phpcsFile
* @return int|false
*/
protected function getNamespacePosition(PhpCsFile $phpcsFile)
{
return $phpcsFile->findNext(T_OPEN_TAG, 0);
}
/**
* Returns whole statement to define namespace.
*
* E.g. namespace VENDOR\ExtName\FolderName;
*
* @param string $classname
* @return string
*/
protected function getNamespaceDefinition($classname)
{
return 'namespace ' . $this->getNamespace($classname) . ';';
}
/**
* Returns namespace, based on legacy class name.
*
* E.g. Tx_ExtName_FolderName_FileName -> VENDOR\ExtName\FolderName
*
* @param string $classname
* @return string
*/
protected function getNamespace($classname)
{
$vendor = trim($this->getVendor(), '\\/');
$classnameParts = explode('_', $classname);
unset($classnameParts[0]); // Remove Tx_
unset($classnameParts[count($classnameParts)]); // Remove class name itself.
return $vendor . '\\' . implode('\\', $classnameParts);
}
}

View file

@ -0,0 +1,114 @@
<?php
/*
* Copyright (C) 2017 Daniel Siepmann <coding@daniel-siepmann.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
use PHP_CodeSniffer_File as PhpCsFile;
use PHP_CodeSniffer_Sniff as PhpCsSniff;
use PHP_CodeSniffer_Tokens as Tokens;
/**
* Detect whether vendor is missing for plugins and modules registrations and configurations.
*/
class Typo3Update_Sniffs_LegacyClassnames_MissingVendorForPluginsAndModulesSniff implements PhpCsSniff
{
use \Typo3Update\Sniffs\ExtendedPhpCsSupportTrait;
use \Typo3Update\Sniffs\OptionsAccessTrait;
/**
* Returns the token types that this sniff is interested in.
*
* @return array<int>
*/
public function register()
{
return Tokens::$functionNameTokens;
}
/**
* Processes the tokens that this sniff is interested in.
*
* @param PhpCsFile $phpcsFile The file where the token was found.
* @param int $stackPtr The position in the stack where
* the token was found.
*
* @return void
*/
public function process(PhpCsFile $phpcsFile, $stackPtr)
{
$functionsToHandle = ['registerPlugin', 'configurePlugin', 'registerModule'];
if (!$this->isFunctionCall($phpcsFile, $stackPtr)) {
return;
}
$tokens = $phpcsFile->getTokens();
if (!in_array($tokens[$stackPtr]['content'], $functionsToHandle)) {
return;
}
$firstArgument = $phpcsFile->findNext([T_WHITESPACE, T_OPEN_PARENTHESIS], $stackPtr + 1, null, true);
if (! $this->isVendorMissing($phpcsFile, $firstArgument)) {
return;
}
$fix = $phpcsFile->addFixableError(
'No vendor is given, that will break TYPO3 handling for namespaced classes.'
. ' Add vendor before Extensionkey like: "%s." . $_EXTKEY',
$firstArgument,
'missingVendor',
[$this->getVendor()]
);
if ($fix === true) {
$phpcsFile->fixer->replaceToken(
$firstArgument,
"'{$this->getVendor()}.' . {$tokens[$firstArgument]['content']}"
);
}
}
/**
* Checks whether vendor is missing in given argument.
*
* @param PhpCsFile $phpcsFile
* @param int|bool $argumentStart
*
* @return bool
*/
protected function isVendorMissing(PhpCsFile $phpcsFile, $argumentStart)
{
if ($argumentStart === false) {
return false;
}
$argumentEnd = $phpcsFile->findNext(T_COMMA, $argumentStart);
if ($argumentEnd === false) {
return false;
}
$stringConcats = array_filter(
array_slice($phpcsFile->getTokens(), $argumentStart, $argumentEnd - $argumentStart),
function (array $token) {
return $token['code'] === 'PHPCS_T_STRING_CONCAT';
}
);
return count($stringConcats) === 0;
}
}

View file

@ -19,13 +19,13 @@
* 02110-1301, USA. * 02110-1301, USA.
*/ */
use Typo3Update\Sniffs\LegacyClassnames\AbstractClassnameChecker;
/** /**
* Detect and migrate static calls to old legacy classnames. * Detect and migrate static calls to old legacy classnames.
*/ */
class Typo3Update_Sniffs_LegacyClassnames_StaticCallSniff implements PHP_CodeSniffer_Sniff class Typo3Update_Sniffs_LegacyClassnames_StaticCallSniff extends AbstractClassnameChecker
{ {
use \Typo3Update\Sniffs\LegacyClassnames\ClassnameCheckerTrait;
/** /**
* Define whether the T_STRING default behaviour should be checked before * Define whether the T_STRING default behaviour should be checked before
* or after the $stackPtr. * or after the $stackPtr.

View file

@ -19,15 +19,13 @@
* 02110-1301, USA. * 02110-1301, USA.
*/ */
use PHP_CodeSniffer_Tokens as Tokens; use Typo3Update\Sniffs\LegacyClassnames\AbstractClassnameChecker;
/** /**
* Migrate Typehints in catch statements. * Migrate Typehints in catch statements.
*/ */
class Typo3Update_Sniffs_LegacyClassnames_TypehintCatchExceptionSniff implements PHP_CodeSniffer_Sniff class Typo3Update_Sniffs_LegacyClassnames_TypehintCatchExceptionSniff extends AbstractClassnameChecker
{ {
use \Typo3Update\Sniffs\LegacyClassnames\ClassnameCheckerTrait;
/** /**
* Returns the token types that this sniff is interested in. * Returns the token types that this sniff is interested in.
* *

View file

@ -19,15 +19,14 @@
* 02110-1301, USA. * 02110-1301, USA.
*/ */
use PHP_CodeSniffer_Tokens as Tokens; use PHP_CodeSniffer_File as PhpCsFile;
use Typo3Update\Sniffs\LegacyClassnames\AbstractClassnameChecker;
/** /**
* Migrate Typehints in function / method definitions. * Migrate Typehints in function / method definitions.
*/ */
class Typo3Update_Sniffs_LegacyClassnames_TypehintSniff implements PHP_CodeSniffer_Sniff class Typo3Update_Sniffs_LegacyClassnames_TypehintSniff extends AbstractClassnameChecker
{ {
use \Typo3Update\Sniffs\LegacyClassnames\ClassnameCheckerTrait;
/** /**
* Returns the token types that this sniff is interested in. * Returns the token types that this sniff is interested in.
* *
@ -41,13 +40,13 @@ class Typo3Update_Sniffs_LegacyClassnames_TypehintSniff implements PHP_CodeSniff
/** /**
* Processes the tokens that this sniff is interested in. * Processes the tokens that this sniff is interested in.
* *
* @param PHP_CodeSniffer_File $phpcsFile The file where the token was found. * @param PhpCsFile $phpcsFile The file where the token was found.
* @param int $stackPtr The position in the stack where * @param int $stackPtr The position in the stack where
* the token was found. * the token was found.
* *
* @return void * @return void
*/ */
public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) public function process(PhpCsFile $phpcsFile, $stackPtr)
{ {
$params = $phpcsFile->getMethodParameters($stackPtr); $params = $phpcsFile->getMethodParameters($stackPtr);
foreach ($params as $parameter) { foreach ($params as $parameter) {

View file

@ -19,15 +19,16 @@
* 02110-1301, USA. * 02110-1301, USA.
*/ */
use PHP_CodeSniffer_Tokens as Tokens; use PHP_CodeSniffer_File as PhpCsFile;
use Typo3Update\Sniffs\LegacyClassnames\AbstractClassnameChecker;
/** /**
* Migrate old legacy class names in use statements. * Detect and migrate use statements with legacy classnames..
*
* According to PSR-2, only one class per use statement is expected.
*/ */
class Typo3Update_Sniffs_LegacyClassnames_UseSniff implements PHP_CodeSniffer_Sniff class Typo3Update_Sniffs_LegacyClassnames_UseSniff extends AbstractClassnameChecker
{ {
use \Typo3Update\Sniffs\LegacyClassnames\ClassnameCheckerTrait;
/** /**
* Returns the token types that this sniff is interested in. * Returns the token types that this sniff is interested in.
* *
@ -37,4 +38,21 @@ class Typo3Update_Sniffs_LegacyClassnames_UseSniff implements PHP_CodeSniffer_Sn
{ {
return [T_USE]; return [T_USE];
} }
/**
* Overwrite to remove prefix.
*
* @param PhpCsFile $phpcsFile
* @param int $classnamePosition
* @param string $classname
* @param bool $forceEmptyPrefix Defines whether '\\' prefix should be checked or always be left out.
*/
protected function replaceLegacyClassname(
PhpCsFile $phpcsFile,
$classnamePosition,
$classname,
$forceEmptyPrefix = true
) {
return parent::replaceLegacyClassname($phpcsFile, $classnamePosition, $classname, $forceEmptyPrefix);
}
} }

View file

@ -0,0 +1,74 @@
<?php
namespace Typo3Update\Sniffs;
/*
* Copyright (C) 2017 Daniel Siepmann <coding@daniel-siepmann.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
use PHP_CodeSniffer as PhpCs;
/**
* Wrapper to retrieve options from PhpCs with defaults.
*/
trait OptionsAccessTrait
{
/**
* Returns the configured vendor, e.g. to generate new namespaces.
*
* @return string
*/
public function getVendor()
{
$vendor = PhpCs::getConfigData('vendor');
if (!$vendor) {
$vendor = 'YourCompany';
}
return trim($vendor, '\\/');
}
/**
* Returns the configured file path containing the mappings for classes, interfaced and traits.
*
* @return string
*/
public function getMappingFile()
{
$mappingFile = PhpCs::getConfigData('mappingFile');
if (!$mappingFile) {
$mappingFile = __DIR__ . '/../../../../LegacyClassnames.php';
}
return $mappingFile;
}
/**
* Returns an array of absolute file names containing removed function configurations.
*
* @return \Generator
*/
public function getRemovedFunctionConfigFiles()
{
$configFiles = PhpCs::getConfigData('removedFunctionConfigFiles');
if (!$configFiles) {
$configFiles = __DIR__ . '/../Configuration/Removed/Functions/*.yaml';
}
foreach ((new \GlobIterator($configFiles)) as $file) {
yield (string) $file;
}
}
}

View file

@ -0,0 +1,301 @@
<?php
/*
* Copyright (C) 2017 Daniel Siepmann <coding@daniel-siepmann.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
use PHP_CodeSniffer_File as PhpCsFile;
use PHP_CodeSniffer_Sniff as PhpCsSniff;
use PHP_CodeSniffer_Tokens as Tokens;
use Symfony\Component\Yaml\Yaml;
/**
* Sniff that handles all calls to removed functions.
*
* Removed functions are configured using YAML-Files, for examples see src/Standards/Typo3Update/Configuration/Removed/Functions/7.0.yaml
* Also check out the configuration options in Readme.rst.
*/
class Typo3Update_Sniffs_Removed_GenericFunctionCallSniff implements PhpCsSniff
{
use \Typo3Update\Sniffs\ExtendedPhpCsSupportTrait;
use \Typo3Update\Sniffs\OptionsAccessTrait;
/**
* Configuration to define removed functions.
*
* @var array
*/
protected static $configuredFunctions = [];
/**
* Function for the current sniff instance.
* @var array
*/
private $removedFunctions = [];
/**
* TODO: Multiple files allowed, using glob ...
* to allow splitting per ext (extbase, fluid, ...) and TYPO3 Version 7.1, 7.0, ...
*/
public function __construct()
{
if (static::$configuredFunctions === []) {
foreach ($this->getRemovedFunctionConfigFiles() as $file) {
static::$configuredFunctions = array_merge(
static::$configuredFunctions,
$this->prepareStructure(Yaml::parse(file_get_contents((string) $file)))
);
}
}
}
/**
* Prepares structure from config for later usage.
*
* @param array $typo3Versions
* @return array
*/
protected function prepareStructure(array $typo3Versions)
{
$newStructure = [];
foreach ($typo3Versions as $typo3Version => $functions) {
foreach ($functions as $function => $config) {
// Split static methods and methods.
$split = preg_split('/::|->/', $function);
$newStructure[$function] = $config;
$newStructure[$function]['static'] = strpos($function, '::') !== false;
$newStructure[$function]['fqcn'] = null;
$newStructure[$function]['class'] = null;
$newStructure[$function]['function'] = $split[0];
$newStructure[$function]['version_removed'] = $typo3Version;
// If split contains two parts, it's a class with method
if (isset($split[1])) {
$newStructure[$function]['fqcn'] = $split[0];
$newStructure[$function]['class'] = array_slice(
explode('\\', $newStructure[$function]['fqcn']),
-1
)[0];
$newStructure[$function]['function'] = $split[1];
}
};
}
return $newStructure;
}
/**
* Returns the token types that this sniff is interested in.
*
* @return array<int>
*/
public function register()
{
return Tokens::$functionNameTokens;
}
/**
* Processes the tokens that this sniff is interested in.
*
* This is the default implementation, as most of the time next T_STRING is
* the class name. This way only the register method has to be registered
* in default cases.
*
* @param PhpCsFile $phpcsFile The file where the token was found.
* @param int $stackPtr The position in the stack where
* the token was found.
*
* @return void
*/
public function process(PhpCsFile $phpcsFile, $stackPtr)
{
if (!$this->isFunctionCallRemoved($phpcsFile, $stackPtr)) {
return;
}
$this->addWarning($phpcsFile, $stackPtr);
}
/**
* Check whether function at given point is removed.
*
* @return bool
*/
protected function isFunctionCallRemoved(PhpCsFile $phpcsFile, $stackPtr)
{
if (!$this->isFunctionCall($phpcsFile, $stackPtr)) {
return false;
}
$tokens = $phpcsFile->getTokens();
$staticPosition = $phpcsFile->findPrevious(T_WHITESPACE, $stackPtr - 1, null, true, null, true);
$functionName = $tokens[$stackPtr]['content'];
$isStatic = false;
$class = false;
if ($staticPosition !== false) {
$isStatic = $tokens[$staticPosition]['code'] === T_DOUBLE_COLON;
}
if ($isStatic) {
$class = $phpcsFile->findPrevious(T_STRING, $staticPosition, null, false, null, true);
if ($class !== false) {
$class = $tokens[$class]['content'];
}
}
$this->removedFunctions = $this->getMatchingRemovedFunctions($functionName, $class, $isStatic);
return $this->removedFunctions !== [];
}
/**
* Returns all matching removed functions for given arguments.
*
* @param string $functionName
* @param string $className The last part of the class name, splitted by namespaces.
* @param bool $isStatic
*
* @return void
*/
protected function getMatchingRemovedFunctions($functionName, $className, $isStatic)
{
// We will not match any static method, without the class name, at least for now.
// Otherwise we could handle them the same way as instance methods.
if ($isStatic === true && $className === false) {
return;
}
return array_filter(
static::$configuredFunctions,
function ($config) use ($functionName, $isStatic, $className) {
return $functionName === $config['function']
&& $isStatic === $config['static']
&& (
$className === $config['class']
|| $className === false
)
;
}
);
}
/**
* Add warning for the given token position.
*
* @param PhpCsFile $phpcsFile
* @param int $tokenPosition
*
* @return void
*/
protected function addWarning(PhpCsFile $phpcsFile, $tokenPosition)
{
foreach ($this->removedFunctions as $function) {
$phpcsFile->addWarning(
'Legacy function calls are not allowed; found %s. Removed in %s. %s. See: %s',
$tokenPosition,
$this->getFunctionIdentifier($function),
[
$this->getOldfunctionCall($function),
$this->getRemovedVersion($function),
$this->getNewFunctionCall($function),
$this->getDocsUrl($function),
]
);
}
}
/**
* Identifier for configuring this specific error / warning through PHPCS.
*
* @param array $config The converted structure for a single function.
*
* @return string
*/
protected function getFunctionIdentifier(array $config)
{
return $config['class'] . '.' . $config['function'];
}
/**
* The original function call, to allow user to check matches.
*
* As we match the function name, that can be provided by multiple classes,
* you should provide an example, so users can check that this is the
* legacy one.
*
* @param array $config The converted structure for a single function.
*
* @return string
*/
protected function getOldFunctionCall(array $config)
{
$concat = '->';
if ($config['static']) {
$concat = '::';
}
return $config['fqcn'] . $concat . $config['function'];
}
/**
* Returns TYPO3 version when the current function was removed.
*
* To let user decide whether this is important for him.
*
* @param array $config The converted structure for a single function.
*
* @return string
*/
protected function getRemovedVersion(array $config)
{
return $config['version_removed'];
}
/**
* The new function call, or information how to migrate.
*
* To provide feedback for user to ease migration.
*
* @param array $config The converted structure for a single function.
*
* @return string
*/
protected function getNewFunctionCall(array $config)
{
$newCall = $config['newFunctionCall'];
if ($newCall !== null) {
return $newCall;
}
return 'There is no replacement, just remove call';
}
/**
* Allow user to lookup the official docs related to this deprecation / breaking change.
*
* @param array $config The converted structure for a single function.
*
* @return string
*/
protected function getDocsUrl(array $config)
{
return $config['docsUrl'];
}
}

View file

@ -12,4 +12,8 @@
<property name="allowedTags" type="array" value="@param,@return,@var,@see,@throws"/> <property name="allowedTags" type="array" value="@param,@return,@var,@see,@throws"/>
</properties> </properties>
</rule> </rule>
<rule ref="Typo3Update.LegacyClassnames.MissingNamespace.legacyClassname">
<message>Legacy class definitions are not allowed; found "%s". Wrap your class inside a namespace.</message>
</rule>
</ruleset> </ruleset>