Skip to content

Commit

Permalink
Rename and include plugins.
Browse files Browse the repository at this point in the history
  • Loading branch information
dereuromark committed Dec 2, 2024
1 parent 29f299a commit cbc0eab
Show file tree
Hide file tree
Showing 3 changed files with 155 additions and 82 deletions.
6 changes: 3 additions & 3 deletions docs/en/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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


Expand Down
79 changes: 0 additions & 79 deletions src/Middleware/MigrationsMiddleware.php

This file was deleted.

152 changes: 152 additions & 0 deletions src/Middleware/PendingMigrationsMiddleware.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
<?php
declare(strict_types=1);

namespace Migrations\Middleware;

use Cake\Console\ConsoleIo;
use Cake\Core\Configure;
use Cake\Core\Exception\CakeException;
use Cake\Core\InstanceConfigTrait;
use Cake\Core\Plugin;
use Cake\Datasource\ConnectionManager;
use Cake\Utility\Inflector;
use Migrations\Config\Config;
use Migrations\Migration\Manager;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;

class PendingMigrationsMiddleware implements MiddlewareInterface
{
use InstanceConfigTrait;

protected array $_defaultConfig = [
'paths' => [
'migrations' => ROOT . DS . 'config' . DS . 'Migrations' . DS,
],
'environment' => [
'connection' => 'default',
'migration_table' => 'phinxlog',
],
'plugins' => null,
];

/**
* @param array<string, mixed> $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<string, string>
*/
protected function pendingMigrations(): array
{
$pending = [];
if (!$this->checkAppMigrations()) {
$pending['app'] = 'bin/cake migrations migrate';
}

/** @var array<string> $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;
}
}

0 comments on commit cbc0eab

Please sign in to comment.