From 1465601b431cc234f2e656f757191edc813ed519 Mon Sep 17 00:00:00 2001 From: saeid Date: Sun, 19 Apr 2020 01:09:30 +0430 Subject: [PATCH 1/5] scan migrations and exclude bake commands if bake plugin does not exists --- src/Plugin.php | 114 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) diff --git a/src/Plugin.php b/src/Plugin.php index 4916476e..2e50ce12 100644 --- a/src/Plugin.php +++ b/src/Plugin.php @@ -13,7 +13,13 @@ */ namespace Migrations; +use Cake\Console\BaseCommand; +use Cake\Console\CommandCollection; +use Cake\Console\CommandInterface; use Cake\Core\BasePlugin; +use Cake\Core\Plugin as CorePlugin; +use Cake\Filesystem\Filesystem; +use Cake\Utility\Inflector; /** * Plugin class for migrations @@ -33,4 +39,112 @@ class Plugin extends BasePlugin * @var bool */ protected $routesEnabled = false; + + /** + * Add migrations commands. + * + * @param \Cake\Console\CommandCollection $collection The command collection to update + * @return \Cake\Console\CommandCollection + */ + public function console(CommandCollection $collection): CommandCollection + { + if (class_exists('Bake\Command\SimpleBakeCommand')) { + $commands = $collection->discoverPlugin($this->getName()); + + return $collection->addMany($commands); + } + if (!CorePlugin::isLoaded($this->name)) { + return []; + } + $path = CorePlugin::classPath($this->name); + $namespace = str_replace('/', '\\', $this->name); + $prefix = Inflector::underscore($this->name) . '.'; + + $commands = $this->scanDir($path . 'Command', $namespace . '\Command\\', $prefix); + $commands = $this->resolveNames($commands, $collection); + + return $collection->addMany($commands); + } + + /** + * Scan a directory for .php files and return the class names that + * should be within them. + * and ignore bake commands. + * + * @param string $path The directory to read. + * @param string $namespace The namespace the commands live in. + * @param string $prefix The prefix to apply to commands for their full name. + * @return array The list of shell info arrays based on scanning the filesystem and inflection. + */ + protected function scanDir(string $path, string $namespace, string $prefix): array + { + if (!is_dir($path)) { + return []; + } + + $classPattern = '/Command\.php$/'; + $fs = new Filesystem(); + /** @var \SplFileInfo[] $files */ + $files = $fs->find($path, $classPattern); + + $commands = []; + foreach ($files as $fileInfo) { + $file = $fileInfo->getFilename(); + $part = substr($file, 0, 4); + // ignore bake commands + if (strtolower($part) === 'bake') { + continue; + } + + $name = Inflector::underscore(preg_replace($classPattern, '', $file)); + + $class = $namespace . $fileInfo->getBasename('.php'); + /** @psalm-suppress DeprecatedClass */ + if (!is_subclass_of($class, CommandInterface::class)) { + continue; + } + if (is_subclass_of($class, BaseCommand::class)) { + $name = $class::defaultName(); + } + $commands[$path . DS . $file] = [ + 'fullName' => $prefix . $name, + 'name' => $name, + 'class' => $class, + ]; + } + + ksort($commands); + + return array_values($commands); + } + + /** + * Resolve names based on existing commands + * + * @param array $input The results of a CommandScanner operation. + * @param \Cake\Console\CommandCollection $collection The command collection + * @return string[] A flat map of command names => class names. + */ + protected function resolveNames(array $input, CommandCollection $collection): array + { + $out = []; + foreach ($input as $info) { + $name = $info['name']; + $addLong = $name !== $info['fullName']; + + // If the short name has been used, use the full name. + // This allows app shells to have name preference. + // and app shells to overwrite core shells. + if ($collection->has($name) && $addLong) { + $name = $info['fullName']; + } + + $out[$name] = $info['class']; + if ($addLong) { + $out[$info['fullName']] = $info['class']; + } + } + + return $out; + } } From 3312b3ed1ad5e4404e96bdc7e208bb99a3f3a2f6 Mon Sep 17 00:00:00 2001 From: saeid Date: Sun, 19 Apr 2020 01:40:24 +0430 Subject: [PATCH 2/5] pin to bake +2.1 to use new twig dependency --- composer.json | 2 +- tests/TestCase/TestCase.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index c68a3868..718a4b79 100644 --- a/composer.json +++ b/composer.json @@ -26,7 +26,7 @@ "require-dev": { "phpunit/phpunit": "~8.5.0", "cakephp/cakephp": "^4.0.5", - "cakephp/bake": "^2.0.9", + "cakephp/bake": "^2.1.0", "cakephp/cakephp-codesniffer": "~4.1.0" }, "autoload": { diff --git a/tests/TestCase/TestCase.php b/tests/TestCase/TestCase.php index f72f43f0..e8b0e5a3 100644 --- a/tests/TestCase/TestCase.php +++ b/tests/TestCase/TestCase.php @@ -41,7 +41,7 @@ public function setUp(): void parent::setUp(); Router::reload(); - $this->loadPlugins(['WyriHaximus/TwigView']); + $this->loadPlugins(['Cake/TwigView']); } public function tearDown(): void From 61b101bb90d000f21491b23066ad0f42fd434ef2 Mon Sep 17 00:00:00 2001 From: saeid Date: Mon, 20 Apr 2020 00:08:14 +0430 Subject: [PATCH 3/5] use element function for twig --- templates/bake/config/snapshot.twig | 6 +++--- templates/bake/element/create-tables.twig | 11 ++++++----- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/templates/bake/config/snapshot.twig b/templates/bake/config/snapshot.twig index cde848ed..ad67fb47 100644 --- a/templates/bake/config/snapshot.twig +++ b/templates/bake/config/snapshot.twig @@ -40,12 +40,12 @@ class {{ name }} extends AbstractMigration */ public function up() { -{% element 'Migrations.create-tables' { +{{~ element('Migrations.create-tables', { tables: tables, autoId: autoId, useSchema: false -} %} - } +}) +}} } /** * Down Method. diff --git a/templates/bake/element/create-tables.twig b/templates/bake/element/create-tables.twig index f4bb0383..8f4a2e33 100644 --- a/templates/bake/element/create-tables.twig +++ b/templates/bake/element/create-tables.twig @@ -58,12 +58,13 @@ ) {% endfor %} ->create(); -{% endfor %} +{% endfor -%} {% if createData.constraints %} {% for table, tableConstraints in createData.constraints %} -{% element 'Migrations.add-foreign-keys' { +{{- element('Migrations.add-foreign-keys', { constraints: tableConstraints, table: table - } %} -{% endfor %} -{% endif %} + }) +-}} +{% endfor -%} +{% endif -%} From 9347560be374651132d5c73d773ac7cdec2b2a0c Mon Sep 17 00:00:00 2001 From: saeid Date: Mon, 20 Apr 2020 00:42:08 +0430 Subject: [PATCH 4/5] new twig version needs to `App.paths.templates` + cs --- src/Plugin.php | 2 +- tests/test_app/App/Template/.gitkeep | 0 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 tests/test_app/App/Template/.gitkeep diff --git a/src/Plugin.php b/src/Plugin.php index 2e50ce12..95ba7f43 100644 --- a/src/Plugin.php +++ b/src/Plugin.php @@ -54,7 +54,7 @@ public function console(CommandCollection $collection): CommandCollection return $collection->addMany($commands); } if (!CorePlugin::isLoaded($this->name)) { - return []; + return $collection; } $path = CorePlugin::classPath($this->name); $namespace = str_replace('/', '\\', $this->name); diff --git a/tests/test_app/App/Template/.gitkeep b/tests/test_app/App/Template/.gitkeep new file mode 100644 index 00000000..e69de29b From 88671b5b29c53d3f91f834b02967b0cbe819ed4a Mon Sep 17 00:00:00 2001 From: saeid Date: Fri, 24 Apr 2020 15:20:34 +0430 Subject: [PATCH 5/5] add migration commands manually --- src/Plugin.php | 115 ++++++++++--------------------------------------- 1 file changed, 22 insertions(+), 93 deletions(-) diff --git a/src/Plugin.php b/src/Plugin.php index 95ba7f43..c0c6e45a 100644 --- a/src/Plugin.php +++ b/src/Plugin.php @@ -13,13 +13,8 @@ */ namespace Migrations; -use Cake\Console\BaseCommand; use Cake\Console\CommandCollection; -use Cake\Console\CommandInterface; use Cake\Core\BasePlugin; -use Cake\Core\Plugin as CorePlugin; -use Cake\Filesystem\Filesystem; -use Cake\Utility\Inflector; /** * Plugin class for migrations @@ -40,6 +35,19 @@ class Plugin extends BasePlugin */ protected $routesEnabled = false; + protected $migrationCommandsList = [ + Command\MigrationsCommand::class, + Command\MigrationsCreateCommand::class, + Command\MigrationsDumpCommand::class, + Command\MigrationsMarkMigratedCommand::class, + Command\MigrationsMigrateCommand::class, + Command\MigrationsCacheBuildCommand::class, + Command\MigrationsCacheClearCommand::class, + Command\MigrationsRollbackCommand::class, + Command\MigrationsSeedCommand::class, + Command\MigrationsStatusCommand::class, + ]; + /** * Add migrations commands. * @@ -53,98 +61,19 @@ public function console(CommandCollection $collection): CommandCollection return $collection->addMany($commands); } - if (!CorePlugin::isLoaded($this->name)) { - return $collection; - } - $path = CorePlugin::classPath($this->name); - $namespace = str_replace('/', '\\', $this->name); - $prefix = Inflector::underscore($this->name) . '.'; - - $commands = $this->scanDir($path . 'Command', $namespace . '\Command\\', $prefix); - $commands = $this->resolveNames($commands, $collection); - - return $collection->addMany($commands); - } - - /** - * Scan a directory for .php files and return the class names that - * should be within them. - * and ignore bake commands. - * - * @param string $path The directory to read. - * @param string $namespace The namespace the commands live in. - * @param string $prefix The prefix to apply to commands for their full name. - * @return array The list of shell info arrays based on scanning the filesystem and inflection. - */ - protected function scanDir(string $path, string $namespace, string $prefix): array - { - if (!is_dir($path)) { - return []; - } - - $classPattern = '/Command\.php$/'; - $fs = new Filesystem(); - /** @var \SplFileInfo[] $files */ - $files = $fs->find($path, $classPattern); - $commands = []; - foreach ($files as $fileInfo) { - $file = $fileInfo->getFilename(); - $part = substr($file, 0, 4); - // ignore bake commands - if (strtolower($part) === 'bake') { - continue; - } - - $name = Inflector::underscore(preg_replace($classPattern, '', $file)); - - $class = $namespace . $fileInfo->getBasename('.php'); - /** @psalm-suppress DeprecatedClass */ - if (!is_subclass_of($class, CommandInterface::class)) { - continue; - } - if (is_subclass_of($class, BaseCommand::class)) { - $name = $class::defaultName(); - } - $commands[$path . DS . $file] = [ - 'fullName' => $prefix . $name, - 'name' => $name, - 'class' => $class, - ]; - } - - ksort($commands); - - return array_values($commands); - } - - /** - * Resolve names based on existing commands - * - * @param array $input The results of a CommandScanner operation. - * @param \Cake\Console\CommandCollection $collection The command collection - * @return string[] A flat map of command names => class names. - */ - protected function resolveNames(array $input, CommandCollection $collection): array - { - $out = []; - foreach ($input as $info) { - $name = $info['name']; - $addLong = $name !== $info['fullName']; - + foreach ($this->migrationCommandsList as $class) { + $name = $class::defaultName(); // If the short name has been used, use the full name. - // This allows app shells to have name preference. - // and app shells to overwrite core shells. - if ($collection->has($name) && $addLong) { - $name = $info['fullName']; - } - - $out[$name] = $info['class']; - if ($addLong) { - $out[$info['fullName']] = $info['class']; + // This allows app commands to have name preference. + // and app commands to overwrite migration commands. + if (!$collection->has($name)) { + $commands[$name] = $class; } + // full name + $commands['migrations.' . $name] = $class; } - return $out; + return $collection->addMany($commands); } }