FEATURE: Allow remapping of usages for redefiined classes

* As we already adjust function, trait and interface definitions, we now
  also migrate the usage of the old versions.
* This is done in second run, as mentioned in adjusted Readme.

Relates: #36
This commit is contained in:
Daniel Siepmann 2017-03-23 13:09:58 +01:00
parent 8fbe25a422
commit 6420c72945
Signed by: Daniel Siepmann
GPG key ID: 33D6629915560EF4
4 changed files with 157 additions and 29 deletions

View file

@ -71,6 +71,13 @@ new ones like ``\TYPO3\Extbase\...``. This is done for:
- Convert old legacy class definitions in extensions to namespace ones. - Convert old legacy class definitions in extensions to namespace ones.
- Convert usage of previously converted class definitions. On first run the definition will be
converted, on second 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.
- Add missing vendor to plugin and module registrations and configurations. - 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 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 single Variable, together with your extension key, as this is not recognized. So the following

View file

@ -22,6 +22,7 @@ namespace Typo3Update\Sniffs\LegacyClassnames;
use PHP_CodeSniffer_File as PhpCsFile; use PHP_CodeSniffer_File as PhpCsFile;
use PHP_CodeSniffer_Sniff as PhpCsSniff; use PHP_CodeSniffer_Sniff as PhpCsSniff;
use Typo3Update\Sniffs\LegacyClassnames\Mapping;
use Typo3Update\Sniffs\OptionsAccessTrait; use Typo3Update\Sniffs\OptionsAccessTrait;
/** /**
@ -31,12 +32,6 @@ abstract class AbstractClassnameChecker implements PhpCsSniff
{ {
use OptionsAccessTrait; 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.
* Used to check clas names for warnings. * Used to check clas names for warnings.
@ -47,17 +42,9 @@ abstract class AbstractClassnameChecker implements PhpCsSniff
*/ */
public $legacyExtensions = ['Extbase', 'Fluid']; public $legacyExtensions = ['Extbase', 'Fluid'];
/** public function __construct()
* @param string $mappingFile File containing php array for mapping.
*/
private function initialize($mappingFile = __DIR__ . '/../../../../../LegacyClassnames.php')
{ {
if ($this->legacyClassnames !== []) { $this->legacyMapping = Mapping::getInstance();
return;
}
$legacyClassnames = require $mappingFile;
$this->legacyClassnames = $legacyClassnames['aliasToClassNameMapping'];
} }
/** /**
@ -111,8 +98,7 @@ abstract class AbstractClassnameChecker implements PhpCsSniff
*/ */
protected function isLegacyClassname($classname) protected function isLegacyClassname($classname)
{ {
$this->initialize(); return $this->legacyMapping->isLegacyClassname($classname);
return isset($this->legacyClassnames[strtolower($classname)]);
} }
/** /**
@ -146,8 +132,21 @@ abstract class AbstractClassnameChecker implements PhpCsSniff
*/ */
protected 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);
} }
/** /**

View file

@ -0,0 +1,124 @@
<?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.
*/
class Mapping
{
use OptionsAccessTrait;
// Singleton implementation - Start
static protected $instance = null;
public static function getInstance()
{
if (static::$instance === null) {
static::$instance = new Mapping();
}
return static::$instance;
}
private function __clone()
{
}
private function __wakeup()
{
}
private function __construct()
{
// $mappingFile = $this->getMappingFile();
$mappingFile = __DIR__ . '/../../../../../LegacyClassnames.php';
$this->mappings = require $mappingFile;
}
// 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;
}
// $mappingFile = $this->getMappingFile();
$mappingFile = __DIR__ . '/../../../../../LegacyClassnames.php';
file_put_contents(
$mappingFile,
'<?php' . PHP_EOL . 'return ' . var_export($this->mappings, true) . ';'
);
}
}

View file

@ -109,6 +109,10 @@ class Typo3Update_Sniffs_LegacyClassnames_MissingNamespaceSniff extends Abstract
$this->getNamespacePosition($phpcsFile), $this->getNamespacePosition($phpcsFile),
'<?php' . $lineEndings . $this->getNamespaceDefinition($classname) . $suffix '<?php' . $lineEndings . $this->getNamespaceDefinition($classname) . $suffix
); );
$this->addLegacyClassname(
$classname,
$this->getNamespace($classname) . '\\' . $this->getNewClassname($classname)
);
} }
/** /**
@ -130,14 +134,7 @@ class Typo3Update_Sniffs_LegacyClassnames_MissingNamespaceSniff extends Abstract
*/ */
protected function getNamespaceDefinition($classname) protected function getNamespaceDefinition($classname)
{ {
$vendor = trim($this->getVendor(), '\\/'); return 'namespace ' . $this->getNamespace($classname) . ';';
return 'namespace '
. $vendor
. '\\'
. $this->getNamespace($classname)
. ';'
;
} }
/** /**
@ -150,11 +147,12 @@ class Typo3Update_Sniffs_LegacyClassnames_MissingNamespaceSniff extends Abstract
*/ */
protected function getNamespace($classname) protected function getNamespace($classname)
{ {
$vendor = trim($this->getVendor(), '\\/');
$classnameParts = explode('_', $classname); $classnameParts = explode('_', $classname);
unset($classnameParts[0]); // Remove Tx_ unset($classnameParts[0]); // Remove Tx_
unset($classnameParts[count($classnameParts)]); // Remove class name itself. unset($classnameParts[count($classnameParts)]); // Remove class name itself.
return implode('\\', $classnameParts); return $vendor . '\\' . implode('\\', $classnameParts);
} }
} }