From cbc0eab3ae2dca842858df6503b64c17d1a7b7ad Mon Sep 17 00:00:00 2001 From: mscherer Date: Fri, 29 Nov 2024 16:15:14 +0100 Subject: [PATCH] Rename and include plugins. --- docs/en/index.rst | 6 +- src/Middleware/MigrationsMiddleware.php | 79 --------- .../PendingMigrationsMiddleware.php | 152 ++++++++++++++++++ 3 files changed, 155 insertions(+), 82 deletions(-) delete mode 100644 src/Middleware/MigrationsMiddleware.php create mode 100644 src/Middleware/PendingMigrationsMiddleware.php diff --git a/docs/en/index.rst b/docs/en/index.rst index 290d90d3..ef2d5dea 100644 --- a/docs/en/index.rst +++ b/docs/en/index.rst @@ -1180,14 +1180,14 @@ for instance when deploying on your production environment, by using the Alert of missing migrations --------------------------- -You can use the ``Migrations.Migrations`` middleware in local development +You can use the ``Migrations.PendingMigrations`` middleware in local development to alert developers about new migrations that are not yet being applied:: - use Migrations\Middleware\MigrationsMiddleware; + use Migrations\Middleware\PendingMigrationsMiddleware; $middlewareQueue ... // ErrorHandler middleware - ->add(new MigrationsMiddleware($yourConfig)) + ->add(new PendingMigrationsMiddleware($yourConfig)) ... // rest diff --git a/src/Middleware/MigrationsMiddleware.php b/src/Middleware/MigrationsMiddleware.php deleted file mode 100644 index 57d85fd6..00000000 --- a/src/Middleware/MigrationsMiddleware.php +++ /dev/null @@ -1,79 +0,0 @@ - [ - 'migrations' => ROOT . DS . 'config' . DS . 'Migrations' . DS, - ], - 'environment' => [ - 'adapter' => null, - 'connection' => 'default', - 'database' => null, - 'migration_table' => 'phinxlog', - ], - ]; - - /** - * @param array $config - */ - public function __construct(array $config = []) - { - $this->setConfig($config); - } - - /** - * Process method. - * - * @param \Psr\Http\Message\ServerRequestInterface $request The request. - * @param \Psr\Http\Server\RequestHandlerInterface $handler The request handler. - * @throws \Cake\Core\Exception\CakeException - * @return \Psr\Http\Message\ResponseInterface A response. - */ - public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface - { - if (!Configure::read('debug')) { - return $handler->handle($request); - } - - if (!$this->hasPendingMigrations()) { - return $handler->handle($request); - } - - throw new CakeException('Pending migrations need to be run: `bin/cake migrations migrate`.', 503); - } - - /** - * @return bool - */ - protected function hasPendingMigrations(): bool - { - $config = new Config($this->_config); - $manager = new Manager($config, new ConsoleIo()); - - $migrations = $manager->getMigrations(); - foreach ($migrations as $migration) { - if (!$manager->isMigrated($migration->getVersion())) { - return true; - } - } - - return false; - } -} diff --git a/src/Middleware/PendingMigrationsMiddleware.php b/src/Middleware/PendingMigrationsMiddleware.php new file mode 100644 index 00000000..43350a78 --- /dev/null +++ b/src/Middleware/PendingMigrationsMiddleware.php @@ -0,0 +1,152 @@ + [ + 'migrations' => ROOT . DS . 'config' . DS . 'Migrations' . DS, + ], + 'environment' => [ + 'connection' => 'default', + 'migration_table' => 'phinxlog', + ], + 'plugins' => null, + ]; + + /** + * @param array $config + */ + public function __construct(array $config = []) + { + if (!empty($config['plugins']) && $config['plugins'] === true) { + $config['plugins'] = Plugin::loaded(); + } + + $this->setConfig($config); + } + + /** + * Process method. + * + * @param \Psr\Http\Message\ServerRequestInterface $request The request. + * @param \Psr\Http\Server\RequestHandlerInterface $handler The request handler. + * @throws \Cake\Core\Exception\CakeException + * @return \Psr\Http\Message\ResponseInterface A response. + */ + public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface + { + if (!Configure::read('debug')) { + return $handler->handle($request); + } + + $pendingMigrations = $this->pendingMigrations(); + if (!$pendingMigrations) { + return $handler->handle($request); + } + + $message = sprintf('Pending migrations need to be run for %s:', implode(', ', array_keys($pendingMigrations))) . PHP_EOL; + $message .= '`' . implode('`,' . PHP_EOL . '`', $pendingMigrations) . '`'; + + throw new CakeException($message, 503); + } + + /** + * @return array + */ + protected function pendingMigrations(): array + { + $pending = []; + if (!$this->checkAppMigrations()) { + $pending['app'] = 'bin/cake migrations migrate'; + } + + /** @var array $plugins */ + $plugins = (array)$this->_config['plugins']; + foreach ($plugins as $plugin) { + if (!$this->checkPluginMigrations($plugin)) { + $pending[$plugin] = 'bin/cake migrations migrate -p ' . $plugin; + } + } + + return $pending; + } + + /** + * @return bool + */ + protected function checkAppMigrations(): bool + { + $connection = ConnectionManager::get($this->_config['environment']['connection']); + $database = $connection->config()['database']; + $this->_config['environment']['database'] = $database; + + $config = new Config($this->_config); + $manager = new Manager($config, new ConsoleIo()); + + $migrations = $manager->getMigrations(); + foreach ($migrations as $migration) { + if (!$manager->isMigrated($migration->getVersion())) { + return false; + } + } + + return true; + } + + /** + * @param string $plugin + * @return bool + */ + protected function checkPluginMigrations(string $plugin): bool + { + $pluginPath = Plugin::path($plugin); + if (!is_dir($pluginPath . 'config' . DS . 'Migrations' . DS)) { + return true; + } + + $config = [ + 'paths' => [ + 'migrations' => $pluginPath . 'config' . DS . 'Migrations' . DS, + ], + ] + $this->_config; + + //TODO: reuse refactored own method in ManagerFactory etc + $table = 'phinxlog'; + $prefix = Inflector::underscore($plugin) . '_'; + $prefix = str_replace(['\\', '/', '.'], '_', $prefix); + $table = $prefix . $table; + + $config['environment']['migration_table'] = $table; + + $managerConfig = new Config($config); + $manager = new Manager($managerConfig, new ConsoleIo()); + + $migrations = $manager->getMigrations(); + foreach ($migrations as $migration) { + if (!$manager->isMigrated($migration->getVersion())) { + return false; + } + } + + return true; + } +}