Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrations builtin backend #706

Merged
merged 8 commits into from
Apr 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions psalm-baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,11 @@
<code>$executedVersion</code>
</ReferenceReusedFromConfusingScope>
</file>
<file src="src/Migration/PhinxBackend.php">
<DeprecatedTrait>
<code>ConfigurationTrait</code>
</DeprecatedTrait>
</file>
<file src="src/Migrations.php">
<DeprecatedTrait>
<code>ConfigurationTrait</code>
Expand Down
3 changes: 2 additions & 1 deletion src/Command/MarkMigratedCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,8 @@ public function execute(Arguments $args, ConsoleIo $io): ?int
return self::CODE_ERROR;
}

$manager->markVersionsAsMigrated($path, $versions, $io);
$output = $manager->markVersionsAsMigrated($path, $versions);
array_map(fn ($line) => $io->out($line), $output);

return self::CODE_SUCCESS;
}
Expand Down
1 change: 0 additions & 1 deletion src/Db/Adapter/PdoAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,6 @@ public function setOptions(array $options): AdapterInterface
{
parent::setOptions($options);

// TODO: Consider renaming this class to ConnectionAdapter
if (isset($options['connection']) && $options['connection'] instanceof Connection) {
$this->setConnection($options['connection']);
}
Expand Down
251 changes: 251 additions & 0 deletions src/Migration/BuiltinBackend.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,251 @@
<?php
declare(strict_types=1);

/**
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
* @link https://cakephp.org CakePHP(tm) Project
* @license https://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Migrations\Migration;

use Cake\Console\Arguments;
use Cake\Console\ConsoleIo;
use Cake\Console\TestSuite\StubConsoleInput;
use Cake\Console\TestSuite\StubConsoleOutput;
use DateTime;
use InvalidArgumentException;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Output\NullOutput;
use Symfony\Component\Console\Output\OutputInterface;

/**
* The Migrations class is responsible for handling migrations command
* within an none-shell application.
*
* @internal
*/
class BuiltinBackend
{
/**
* The OutputInterface.
* Should be a \Symfony\Component\Console\Output\NullOutput instance
*
* @var \Symfony\Component\Console\Output\OutputInterface
*/
protected OutputInterface $output;

/**
* Manager instance
*
* @var \Migrations\Migration\Manager|null
*/
protected ?Manager $manager = null;

/**
* Default options to use
*
* @var array<string, mixed>
*/
protected array $default = [];

/**
* Current command being run.
* Useful if some logic needs to be applied in the ConfigurationTrait depending
* on the command
*
* @var string
*/
protected string $command;

/**
* Stub input to feed the manager class since we might not have an input ready when we get the Manager using
* the `getManager()` method
*
* @var \Symfony\Component\Console\Input\ArrayInput
*/
protected ArrayInput $stubInput;

/**
* Constructor
*
* @param array<string, mixed> $default Default option to be used when calling a method.
* Available options are :
* - `connection` The datasource connection to use
* - `source` The folder where migrations are in
* - `plugin` The plugin containing the migrations
*/
public function __construct(array $default = [])
{
$this->output = new NullOutput();
$this->stubInput = new ArrayInput([]);

if ($default) {
$this->default = $default;
}
}

/**
* Returns the status of each migrations based on the options passed
*
* @param array<string, mixed> $options Options to pass to the command
* Available options are :
*
* - `format` Format to output the response. Can be 'json'
* - `connection` The datasource connection to use
* - `source` The folder where migrations are in
* - `plugin` The plugin containing the migrations
* @return array The migrations list and their statuses
*/
public function status(array $options = []): array
{
$manager = $this->getManager($options);

return $manager->printStatus($options['format'] ?? null);
}

/**
* Migrates available migrations
*
* @param array<string, mixed> $options Options to pass to the command
* Available options are :
*
* - `target` The version number to migrate to. If not provided, will migrate
* everything it can
* - `connection` The datasource connection to use
* - `source` The folder where migrations are in
* - `plugin` The plugin containing the migrations
* - `date` The date to migrate to
* @return bool Success
*/
public function migrate(array $options = []): bool
{
$manager = $this->getManager($options);

if (!empty($options['date'])) {
$date = new DateTime($options['date']);

$manager->migrateToDateTime($date);

return true;
}

$manager->migrate($options['target'] ?? null);

return true;
}

/**
* Rollbacks migrations
*
* @param array<string, mixed> $options Options to pass to the command
* Available options are :
*
* - `target` The version number to migrate to. If not provided, will only migrate
* the last migrations registered in the phinx log
* - `connection` The datasource connection to use
* - `source` The folder where migrations are in
* - `plugin` The plugin containing the migrations
* - `date` The date to rollback to
* @return bool Success
*/
public function rollback(array $options = []): bool
{
$manager = $this->getManager($options);

if (!empty($options['date'])) {
$date = new DateTime($options['date']);

$manager->rollbackToDateTime($date);

return true;
}

$manager->rollback($options['target'] ?? null);

return true;
}

/**
* Marks a migration as migrated
*
* @param int|string|null $version The version number of the migration to mark as migrated
* @param array<string, mixed> $options Options to pass to the command
* Available options are :
*
* - `connection` The datasource connection to use
* - `source` The folder where migrations are in
* - `plugin` The plugin containing the migrations
* @return bool Success
*/
public function markMigrated(int|string|null $version = null, array $options = []): bool
{
if (
isset($options['target']) &&
isset($options['exclude']) &&
isset($options['only'])
) {
$exceptionMessage = 'You should use `exclude` OR `only` (not both) along with a `target` argument';
throw new InvalidArgumentException($exceptionMessage);
}
$args = new Arguments([(string)$version], $options, ['version']);

$manager = $this->getManager($options);
$config = $manager->getConfig();
$path = $config->getMigrationPaths()[0];

$versions = $manager->getVersionsToMark($args);
$manager->markVersionsAsMigrated($path, $versions);

return true;
}

/**
* Seed the database using a seed file
*
* @param array<string, mixed> $options Options to pass to the command
* Available options are :
*
* - `connection` The datasource connection to use
* - `source` The folder where migrations are in
* - `plugin` The plugin containing the migrations
* - `seed` The seed file to use
* @return bool Success
*/
public function seed(array $options = []): bool
{
$seed = $options['seed'] ?? null;
$manager = $this->getManager($options);
$manager->seed($seed);

return true;
}

/**
* Returns an instance of Manager
*
* @param array $options The options for manager creation
* @return \Migrations\Migration\Manager Instance of Manager
*/
public function getManager(array $options): Manager
{
$options += $this->default;

$factory = new ManagerFactory([
'plugin' => $options['plugin'] ?? null,
'source' => $options['source'] ?? null,
'connection' => $options['connection'] ?? 'default',
]);
$io = new ConsoleIo(
new StubConsoleOutput(),
new StubConsoleOutput(),
new StubConsoleInput([]),
);

return $factory->createManager($io);
}
}
Loading
Loading