diff --git a/README.md b/README.md index dbbb1e0..025fc45 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ be done in place, so it is best to either do this in a separate copy of the code, or on top of a git repository where you can easily reset --hard if you need to. -**Download**: https://github.com/zendframework/Namespacer/blob/master/namespacer.phar?raw=true +**Download**: https://github.com/dmnc/Namespacer/blob/master/namespacer.phar?raw=true * First, create a map file: @@ -20,8 +20,19 @@ if you need to. namespacer.phar map --mapfile types.php --source path/to/src ``` -* Second, transform the types located in the map file: +* Second, if you want to maintain legacy classes extending your new ones: + + ``` + namespacer.phar legacy --mapfile types.php --target path/for/legacy/files + ``` + +* Thirdly, transform the types located in the map file: ``` namespacer.phar transform --mapfile types.php ``` + +* Last, fix any used namespaces + ``` + namespacer.phar fix --mapfile types.php --target path/to/src + ``` diff --git a/config/module.config.php b/config/module.config.php index 566309c..686aa5a 100644 --- a/config/module.config.php +++ b/config/module.config.php @@ -59,6 +59,15 @@ ), ), ), + 'namespacer-legacy' => array( + 'options' => array( + 'route' => 'legacy [--mapfile=] [--target=]', + 'defaults' => array( + 'controller' => 'Namespacer\Controller\Controller', + 'action' => 'legacyExtension', + ), + ), + ), ), ), ), diff --git a/src/Namespacer/Controller/Controller.php b/src/Namespacer/Controller/Controller.php index 5cbf2aa..d15797a 100644 --- a/src/Namespacer/Controller/Controller.php +++ b/src/Namespacer/Controller/Controller.php @@ -10,6 +10,7 @@ use Namespacer\Model\Map; use Namespacer\Model\Mapper; use Namespacer\Model\Transformer; +use Namespacer\Model\LegacyExtension; use Zend\Mvc\Controller\AbstractActionController; class Controller extends AbstractActionController @@ -52,6 +53,17 @@ public function transformAction() } } + public function legacyExtensionAction() + { + $mapfile = $this->params()->fromRoute('mapfile'); + $target = $this->params()->fromRoute('target'); + $data = include $mapfile; + $map = new Map($data); + $transformer = new LegacyExtension($map); + + $transformer->createLegacyClasses($target); + } + public function fixAction() { $mapfile = $this->params()->fromRoute('mapfile'); diff --git a/src/Namespacer/Model/LegacyExtension.php b/src/Namespacer/Model/LegacyExtension.php new file mode 100644 index 0000000..a2825ef --- /dev/null +++ b/src/Namespacer/Model/LegacyExtension.php @@ -0,0 +1,58 @@ +map = $map; + } + + public function createLegacyClasses($directory = false) + { + $fileRenamings = $this->map->getExtensionMap($directory); + + foreach ($fileRenamings as $legacyPath => $data) { + $legacyDir = dirname($legacyPath); + if (!file_exists($legacyDir)) { + mkdir($legacyDir, 0777, true); + } + touch($legacyPath); + + $this->createLegacyFile($legacyPath, $data); + } + } + + protected function createLegacyFile($file, $data) + { + $tokens = token_get_all(file_get_contents($data['original_file'])); + + $contents = ''; + $token = reset($tokens); + do { + if (T_TRAIT === $token[0]) { + $contents .= $token[1] . ' ' . $data['class']; + $contents .= "\n{\n"; + $contents .= " use \\" . $data['extends'] . ";"; + $contents .= "\n}\n"; + break; + } + if (T_CLASS === $token[0] || T_INTERFACE === $token[0]) { + $contents .= $token[1] . ' ' . $data['class']; + $contents .= " extends \\" . $data['extends']; + $contents .= "\n{\n}\n"; + break; + } else { + $contents .= (is_array($token)) ? $token[1] : $token; + } + } while ($token = next($tokens)); + + file_put_contents($file, $contents); + } +} diff --git a/src/Namespacer/Model/Map.php b/src/Namespacer/Model/Map.php index e1d0493..9f79b97 100644 --- a/src/Namespacer/Model/Map.php +++ b/src/Namespacer/Model/Map.php @@ -53,6 +53,24 @@ public function getNewFiles() return $data; } + public function getExtensionMap($directory = false) + { + $data = array(); + foreach ($this->mapData as $item) { + if ($directory) { + $file = str_replace($item['root_directory'], $directory, $item['original_file']); + } else { + $file = $item['original_file']; + } + $data[$file] = array( + 'extends' => $item['new_namespace'] . '\\' . $item['new_class'], + 'class' => $item['original_class'], + 'original_file' => $item['original_file'] + ); + } + return $data; + } + public function getClassTransformations() { $data = array(); @@ -61,4 +79,4 @@ public function getClassTransformations() } return $data; } -} \ No newline at end of file +} diff --git a/src/Namespacer/Model/Transformer.php b/src/Namespacer/Model/Transformer.php index 285363c..28d56fa 100644 --- a/src/Namespacer/Model/Transformer.php +++ b/src/Namespacer/Model/Transformer.php @@ -47,6 +47,17 @@ public function modifyNamespaceAndClassNames() } } + public function modifyOriginalContentForExtension() + { + $extensionMap = $this->map->getExtensionMap(); + foreach ($extensionMap as $file => $extends) { + if (!file_exists($file)) { + throw new \RuntimeException('The file ' . $file . ' could not be found in the filesystem, check your map file is correct.'); + } + $this->modifyOriginalFileforExtension($file, $extends); + } + } + public function modifyContentForUseStatements() { $files = $this->map->getNewFiles(); @@ -103,6 +114,33 @@ protected function modifyFileWithNewNamespaceAndClass($file, $names) file_put_contents($file, $contents); } + protected function modifyOriginalFileforExtension($file, $names) + { + $tokens = token_get_all(file_get_contents($file)); + + $contents = ''; + $token = reset($tokens); + do { + if (T_TRAIT === $token[0]) { + $contents .= $token[1] . ' ' . $names['class']; + $contents .= "\n{\n"; + $contents .= " use \\" . $names['extends'] . ";"; + $contents .= "\n}\n"; + break 2; + } + if ($this->isClass($token[0])) { + $contents .= $token[1] . ' ' . $names['class']; + $contents .= " extends \\" . $names['extends']; + $contents .= "\n{\n}\n"; + break 2; + } else { + $contents .= (is_array($token)) ? $token[1] : $token; + } + } while ($token = next($tokens)); + + file_put_contents($file, $contents); + } + protected function modifyFileWithNewUseStatements($file, $classTransformations) { $tokens = token_get_all(file_get_contents($file));