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

4.next - Add base seed #760

Merged
merged 5 commits into from
Oct 26, 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
2 changes: 2 additions & 0 deletions src/AbstractSeed.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
* Class AbstractSeed
* Extends Phinx base AbstractSeed class in order to extend the features the seed class
* offers.
*
* @deprecated 4.5.0 You should use Migrations\BaseSeed for new seeds.
*/
abstract class AbstractSeed extends BaseAbstractSeed
{
Expand Down
235 changes: 235 additions & 0 deletions src/BaseSeed.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@
<?php
declare(strict_types=1);

/**
* MIT License
* For full license information, please view the LICENSE file that was distributed with this source code.
*/

namespace Migrations;

use Cake\Console\ConsoleIo;
use Migrations\Config\ConfigInterface;
use Migrations\Db\Adapter\AdapterInterface;
use Migrations\Db\Table;
use Migrations\Migration\ManagerFactory;
use RuntimeException;
use function Cake\Core\pluginSplit;

/**
* Base seed implementation
*
* Provides base functionality for seeds to extend.
*/
class BaseSeed implements SeedInterface
{
protected ?AdapterInterface $adapter = null;
protected ?ConsoleIo $io = null;
protected ?ConfigInterface $config;

/**
* No-op constructor.
*/
public function __construct()
{
}

/**
* {@inheritDoc}
*/
public function run(): void
{
}

/**
* {@inheritDoc}
*/
public function getDependencies(): array
{
return [];
}

/**
* {@inheritDoc}
*/
public function setAdapter(AdapterInterface $adapter)
{
$this->adapter = $adapter;

return $this;
}

/**
* {@inheritDoc}
*/
public function getAdapter(): AdapterInterface
{
if (!$this->adapter) {
throw new RuntimeException('Adapter not set.');
}

return $this->adapter;
}

/**
* {@inheritDoc}
*/
public function setIo(ConsoleIo $io)
{
$this->io = $io;

return $this;
}

/**
* {@inheritDoc}
*/
public function getIo(): ?ConsoleIo
{
return $this->io;
}

/**
* {@inheritDoc}
*/
public function getConfig(): ?ConfigInterface
{
return $this->config;
}

/**
* {@inheritDoc}
*/
public function setConfig(ConfigInterface $config)
{
$this->config = $config;

return $this;
}

/**
* {@inheritDoc}
*/
public function getName(): string
{
return static::class;
}

/**
* {@inheritDoc}
*/
public function execute(string $sql, array $params = []): int
{
return $this->getAdapter()->execute($sql, $params);
}

/**
* {@inheritDoc}
*/
public function query(string $sql, array $params = []): mixed
{
return $this->getAdapter()->query($sql, $params);
}

/**
* {@inheritDoc}
*/
public function fetchRow(string $sql): array|false
{
return $this->getAdapter()->fetchRow($sql);
}

/**
* {@inheritDoc}
*/
public function fetchAll(string $sql): array
{
return $this->getAdapter()->fetchAll($sql);
}

/**
* {@inheritDoc}
*/
public function insert(string $tableName, array $data): void
{
// convert to table object
$table = new Table($tableName, [], $this->getAdapter());
$table->insert($data)->save();
}

/**
* {@inheritDoc}
*/
public function hasTable(string $tableName): bool
{
return $this->getAdapter()->hasTable($tableName);
}

/**
* {@inheritDoc}
*/
public function table(string $tableName, array $options = []): Table
{
return new Table($tableName, $options, $this->getAdapter());
}

/**
* {@inheritDoc}
*/
public function shouldExecute(): bool
{
return true;
}

/**
* {@inheritDoc}
*/
public function call(string $seeder, array $options = []): void
{
$io = $this->getIo();
assert($io !== null, 'Requires ConsoleIo');
$io->out('');
$io->out(
' ====' .
' <info>' . $seeder . ':</info>' .
' <comment>seeding</comment>'
);

$start = microtime(true);
$this->runCall($seeder, $options);
$end = microtime(true);

$io->out(
' ====' .
' <info>' . $seeder . ':</info>' .
' <comment>seeded' .
' ' . sprintf('%.4fs', $end - $start) . '</comment>'
);
$io->out('');
}

/**
* Calls another seeder from this seeder.
* It will load the Seed class you are calling and run it.
*
* @param string $seeder Name of the seeder to call from the current seed
* @param array $options The CLI options passed to ManagerFactory.
* @return void
*/
protected function runCall(string $seeder, array $options = []): void
{
[$pluginName, $seeder] = pluginSplit($seeder);
$adapter = $this->getAdapter();
$connection = $adapter->getConnection()->configName();

$factory = new ManagerFactory([
'plugin' => $options['plugin'] ?? $pluginName ?? null,
'source' => $options['source'] ?? null,
'connection' => $options['connection'] ?? $connection,
]);
$io = $this->getIo();
assert($io !== null, 'Missing ConsoleIo instance');
$manager = $factory->createManager($io);
$manager->seed($seeder);
}
}
5 changes: 3 additions & 2 deletions src/SeedInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ public function hasTable(string $tableName): bool;
* @param array<string, mixed> $options Options
* @return \Migrations\Db\Table
*/
public function table(string $tableName, array $options): Table;
public function table(string $tableName, array $options = []): Table;

/**
* Checks to see if the seed should be executed.
Expand All @@ -180,7 +180,8 @@ public function shouldExecute(): bool;
* for instance to respect foreign key constraints.
*
* @param string $seeder Name of the seeder to call from the current seed
* @param array $options The CLI options for the seeder.
* @return void
*/
public function call(string $seeder): void;
public function call(string $seeder, array $options = []): void;
}
4 changes: 2 additions & 2 deletions src/Shim/SeedAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ public function hasTable(string $tableName): bool
/**
* {@inheritDoc}
*/
public function table(string $tableName, array $options): Table
public function table(string $tableName, array $options = []): Table
{
throw new RuntimeException('Not implemented');
}
Expand All @@ -245,7 +245,7 @@ public function shouldExecute(): bool
/**
* {@inheritDoc}
*/
public function call(string $seeder): void
public function call(string $seeder, array $options = []): void
{
throw new RuntimeException('Not implemented');
}
Expand Down
19 changes: 19 additions & 0 deletions tests/TestCase/Command/SeedCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,25 @@ public function testSeederOne(): void
$this->assertEquals(1, $query->fetchColumn(0));
}

public function testSeederBaseSeed(): void
{
$this->createTables();
$this->exec('migrations seed -c test --source BaseSeeds --seed MigrationSeedNumbers');
$this->assertExitSuccess();
$this->assertOutputContains('MigrationSeedNumbers:</info> <comment>seeding');
$this->assertOutputContains('AnotherNumbersSeed:</info> <comment>seeding');
$this->assertOutputContains('radix=10');
$this->assertOutputContains('fetchRow=121');
$this->assertOutputContains('hasTable=1');
$this->assertOutputContains('fetchAll=121');
$this->assertOutputContains('All Done');

$connection = ConnectionManager::get('test');
$query = $connection->execute('SELECT COUNT(*) FROM numbers');
// Two seeders run == 2 rows
$this->assertEquals(2, $query->fetchColumn(0));
}

public function testSeederImplictAll(): void
{
$this->createTables();
Expand Down
45 changes: 45 additions & 0 deletions tests/test_app/config/BaseSeeds/MigrationSeedNumbers.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

use Migrations\BaseSeed;

/**
* NumbersSeed seed.
*/
class MigrationSeedNumbers extends BaseSeed
{
/**
* Run Method.
*
* Write your database seeder using this method.
*
* More information on writing seeders is available here:
* https://book.cakephp.org/phinx/0/en/seeding.html
*/
public function run(): void
{
$data = [
[
'number' => '5',
'radix' => '10',
],
];

// Call various methods on the seeder for runtime checks
// and generate output to assert behavior with in an integration test.
$this->table('numbers');
$this->insert('numbers', $data);

$this->call('AnotherNumbersSeed', ['source' => 'AltSeeds']);

$io = $this->getIo();
$query = $this->query('SELECT radix FROM numbers');
$io->out('radix=' . $query->fetchColumn(0));

$row = $this->fetchRow('SELECT 121 as row_val');
$io->out('fetchRow=' . $row['row_val']);
$io->out('hasTable=' . $this->hasTable('numbers'));

$rows = $this->fetchAll('SELECT 121 as row_val');
$io->out('fetchAll=' . $rows[0]['row_val']);
}
}
Loading