This commit is contained in:
Markus
2022-04-28 09:40:10 +02:00
commit 795794f992
9586 changed files with 1146991 additions and 0 deletions

View File

@@ -0,0 +1,155 @@
<?php
/**
* This file is part of CodeIgniter 4 framework.
*
* (c) CodeIgniter Foundation <admin@codeigniter.com>
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace CodeIgniter\Commands\Database;
use CodeIgniter\CLI\BaseCommand;
use CodeIgniter\CLI\CLI;
use CodeIgniter\Config\Factories;
use CodeIgniter\Database\SQLite3\Connection;
use Config\Database;
use Throwable;
/**
* Creates a new database.
*/
class CreateDatabase extends BaseCommand
{
/**
* The group the command is lumped under
* when listing commands.
*
* @var string
*/
protected $group = 'Database';
/**
* The Command's name
*
* @var string
*/
protected $name = 'db:create';
/**
* the Command's short description
*
* @var string
*/
protected $description = 'Create a new database schema.';
/**
* the Command's usage
*
* @var string
*/
protected $usage = 'db:create <db_name> [options]';
/**
* The Command's arguments
*
* @var array<string, string>
*/
protected $arguments = [
'db_name' => 'The database name to use',
];
/**
* The Command's options
*
* @var array<string, string>
*/
protected $options = [
'--ext' => 'File extension of the database file for SQLite3. Can be `db` or `sqlite`. Defaults to `db`.',
];
/**
* Creates a new database.
*/
public function run(array $params)
{
$name = array_shift($params);
if (empty($name)) {
$name = CLI::prompt('Database name', null, 'required'); // @codeCoverageIgnore
}
try {
/**
* @var Database $config
*/
$config = config('Database');
// Set to an empty database to prevent connection errors.
$group = ENVIRONMENT === 'testing' ? 'tests' : $config->defaultGroup;
$config->{$group}['database'] = '';
$db = Database::connect();
// Special SQLite3 handling
if ($db instanceof Connection) {
$ext = $params['ext'] ?? CLI::getOption('ext') ?? 'db';
if (! in_array($ext, ['db', 'sqlite'], true)) {
$ext = CLI::prompt('Please choose a valid file extension', ['db', 'sqlite']); // @codeCoverageIgnore
}
if ($name !== ':memory:') {
$name = str_replace(['.db', '.sqlite'], '', $name) . ".{$ext}";
}
$config->{$group}['DBDriver'] = 'SQLite3';
$config->{$group}['database'] = $name;
if ($name !== ':memory:') {
$dbName = strpos($name, DIRECTORY_SEPARATOR) === false ? WRITEPATH . $name : $name;
if (is_file($dbName)) {
CLI::error("Database \"{$dbName}\" already exists.", 'light_gray', 'red');
CLI::newLine();
return;
}
unset($dbName);
}
// Connect to new SQLite3 to create new database
$db = Database::connect(null, false);
$db->connect();
if (! is_file($db->getDatabase()) && $name !== ':memory:') {
// @codeCoverageIgnoreStart
CLI::error('Database creation failed.', 'light_gray', 'red');
CLI::newLine();
return;
// @codeCoverageIgnoreEnd
}
} elseif (! Database::forge()->createDatabase($name)) {
// @codeCoverageIgnoreStart
CLI::error('Database creation failed.', 'light_gray', 'red');
CLI::newLine();
return;
// @codeCoverageIgnoreEnd
}
CLI::write("Database \"{$name}\" successfully created.", 'green');
CLI::newLine();
} catch (Throwable $e) {
$this->showError($e);
} finally {
// Reset the altered config no matter what happens.
Factories::reset('config');
}
}
}

View File

@@ -0,0 +1,102 @@
<?php
/**
* This file is part of CodeIgniter 4 framework.
*
* (c) CodeIgniter Foundation <admin@codeigniter.com>
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace CodeIgniter\Commands\Database;
use CodeIgniter\CLI\BaseCommand;
use CodeIgniter\CLI\CLI;
use Config\Services;
use Throwable;
/**
* Runs all new migrations.
*/
class Migrate extends BaseCommand
{
/**
* The group the command is lumped under
* when listing commands.
*
* @var string
*/
protected $group = 'Database';
/**
* The Command's name
*
* @var string
*/
protected $name = 'migrate';
/**
* the Command's short description
*
* @var string
*/
protected $description = 'Locates and runs all new migrations against the database.';
/**
* the Command's usage
*
* @var string
*/
protected $usage = 'migrate [options]';
/**
* the Command's Options
*
* @var array
*/
protected $options = [
'-n' => 'Set migration namespace',
'-g' => 'Set database group',
'--all' => 'Set for all namespaces, will ignore (-n) option',
];
/**
* Ensures that all migrations have been run.
*/
public function run(array $params)
{
$runner = Services::migrations();
$runner->clearCliMessages();
CLI::write(lang('Migrations.latest'), 'yellow');
$namespace = $params['n'] ?? CLI::getOption('n');
$group = $params['g'] ?? CLI::getOption('g');
try {
if (array_key_exists('all', $params) || CLI::getOption('all')) {
$runner->setNamespace(null);
} elseif ($namespace) {
$runner->setNamespace($namespace);
}
if (! $runner->latest($group)) {
CLI::error(lang('Migrations.generalFault'), 'light_gray', 'red'); // @codeCoverageIgnore
}
$messages = $runner->getCliMessages();
foreach ($messages as $message) {
CLI::write($message);
}
CLI::write('Done migrations.', 'green');
// @codeCoverageIgnoreStart
} catch (Throwable $e) {
$this->showError($e);
// @codeCoverageIgnoreEnd
}
}
}

View File

@@ -0,0 +1,87 @@
<?php
/**
* This file is part of CodeIgniter 4 framework.
*
* (c) CodeIgniter Foundation <admin@codeigniter.com>
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace CodeIgniter\Commands\Database;
use CodeIgniter\CLI\BaseCommand;
use CodeIgniter\CLI\CLI;
/**
* Does a rollback followed by a latest to refresh the current state
* of the database.
*/
class MigrateRefresh extends BaseCommand
{
/**
* The group the command is lumped under
* when listing commands.
*
* @var string
*/
protected $group = 'Database';
/**
* The Command's name
*
* @var string
*/
protected $name = 'migrate:refresh';
/**
* the Command's short description
*
* @var string
*/
protected $description = 'Does a rollback followed by a latest to refresh the current state of the database.';
/**
* the Command's usage
*
* @var string
*/
protected $usage = 'migrate:refresh [options]';
/**
* the Command's Options
*
* @var array
*/
protected $options = [
'-n' => 'Set migration namespace',
'-g' => 'Set database group',
'--all' => 'Set latest for all namespace, will ignore (-n) option',
'-f' => 'Force command - this option allows you to bypass the confirmation question when running this command in a production environment',
];
/**
* Does a rollback followed by a latest to refresh the current state
* of the database.
*/
public function run(array $params)
{
$params['b'] = 0;
if (ENVIRONMENT === 'production') {
// @codeCoverageIgnoreStart
$force = array_key_exists('f', $params) || CLI::getOption('f');
if (! $force && CLI::prompt(lang('Migrations.refreshConfirm'), ['y', 'n']) === 'n') {
return;
}
$params['f'] = null;
// @codeCoverageIgnoreEnd
}
$this->call('migrate:rollback', $params);
$this->call('migrate', $params);
}
}

View File

@@ -0,0 +1,110 @@
<?php
/**
* This file is part of CodeIgniter 4 framework.
*
* (c) CodeIgniter Foundation <admin@codeigniter.com>
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace CodeIgniter\Commands\Database;
use CodeIgniter\CLI\BaseCommand;
use CodeIgniter\CLI\CLI;
use Config\Services;
use Throwable;
/**
* Runs all of the migrations in reverse order, until they have
* all been unapplied.
*/
class MigrateRollback extends BaseCommand
{
/**
* The group the command is lumped under
* when listing commands.
*
* @var string
*/
protected $group = 'Database';
/**
* The Command's name
*
* @var string
*/
protected $name = 'migrate:rollback';
/**
* the Command's short description
*
* @var string
*/
protected $description = 'Runs the "down" method for all migrations in the last batch.';
/**
* the Command's usage
*
* @var string
*/
protected $usage = 'migrate:rollback [options]';
/**
* the Command's Options
*
* @var array
*/
protected $options = [
'-b' => 'Specify a batch to roll back to; e.g. "3" to return to batch #3 or "-2" to roll back twice',
'-g' => 'Set database group',
'-f' => 'Force command - this option allows you to bypass the confirmation question when running this command in a production environment',
];
/**
* Runs all of the migrations in reverse order, until they have
* all been unapplied.
*/
public function run(array $params)
{
if (ENVIRONMENT === 'production') {
// @codeCoverageIgnoreStart
$force = array_key_exists('f', $params) || CLI::getOption('f');
if (! $force && CLI::prompt(lang('Migrations.rollBackConfirm'), ['y', 'n']) === 'n') {
return;
}
// @codeCoverageIgnoreEnd
}
$runner = Services::migrations();
$group = $params['g'] ?? CLI::getOption('g');
if (is_string($group)) {
$runner->setGroup($group);
}
try {
$batch = $params['b'] ?? CLI::getOption('b') ?? $runner->getLastBatch() - 1;
CLI::write(lang('Migrations.rollingBack') . ' ' . $batch, 'yellow');
if (! $runner->regress($batch)) {
CLI::error(lang('Migrations.generalFault'), 'light_gray', 'red'); // @codeCoverageIgnore
}
$messages = $runner->getCliMessages();
foreach ($messages as $message) {
CLI::write($message);
}
CLI::write('Done rolling back migrations.', 'green');
// @codeCoverageIgnoreStart
} catch (Throwable $e) {
$this->showError($e);
// @codeCoverageIgnoreEnd
}
}
}

View File

@@ -0,0 +1,164 @@
<?php
/**
* This file is part of CodeIgniter 4 framework.
*
* (c) CodeIgniter Foundation <admin@codeigniter.com>
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace CodeIgniter\Commands\Database;
use CodeIgniter\CLI\BaseCommand;
use CodeIgniter\CLI\CLI;
use Config\Services;
/**
* Displays a list of all migrations and whether they've been run or not.
*/
class MigrateStatus extends BaseCommand
{
/**
* The group the command is lumped under
* when listing commands.
*
* @var string
*/
protected $group = 'Database';
/**
* The Command's name
*
* @var string
*/
protected $name = 'migrate:status';
/**
* the Command's short description
*
* @var string
*/
protected $description = 'Displays a list of all migrations and whether they\'ve been run or not.';
/**
* the Command's usage
*
* @var string
*/
protected $usage = 'migrate:status [options]';
/**
* the Command's Options
*
* @var array<string, string>
*/
protected $options = [
'-g' => 'Set database group',
];
/**
* Namespaces to ignore when looking for migrations.
*
* @var string[]
*/
protected $ignoredNamespaces = [
'CodeIgniter',
'Config',
'Kint',
'Laminas\ZendFrameworkBridge',
'Laminas\Escaper',
'Psr\Log',
];
/**
* Displays a list of all migrations and whether they've been run or not.
*
* @param array<string, mixed> $params
*/
public function run(array $params)
{
$runner = Services::migrations();
$group = $params['g'] ?? CLI::getOption('g');
// Get all namespaces
$namespaces = Services::autoloader()->getNamespace();
// Collection of migration status
$status = [];
foreach (array_keys($namespaces) as $namespace) {
if (ENVIRONMENT !== 'testing') {
// Make Tests\\Support discoverable for testing
$this->ignoredNamespaces[] = 'Tests\Support'; // @codeCoverageIgnore
}
if (in_array($namespace, $this->ignoredNamespaces, true)) {
continue;
}
if (APP_NAMESPACE !== 'App' && $namespace === 'App') {
continue; // @codeCoverageIgnore
}
$migrations = $runner->findNamespaceMigrations($namespace);
if (empty($migrations)) {
continue;
}
$history = $runner->getHistory((string) $group);
ksort($migrations);
foreach ($migrations as $uid => $migration) {
$migrations[$uid]->name = mb_substr($migration->name, mb_strpos($migration->name, $uid . '_'));
$date = '---';
$group = '---';
$batch = '---';
foreach ($history as $row) {
// @codeCoverageIgnoreStart
if ($runner->getObjectUid($row) !== $migration->uid) {
continue;
}
$date = date('Y-m-d H:i:s', $row->time);
$group = $row->group;
$batch = $row->batch;
// @codeCoverageIgnoreEnd
}
$status[] = [
$namespace,
$migration->version,
$migration->name,
$group,
$date,
$batch,
];
}
}
if (! $status) {
// @codeCoverageIgnoreStart
CLI::error(lang('Migrations.noneFound'), 'light_gray', 'red');
CLI::newLine();
return;
// @codeCoverageIgnoreEnd
}
$headers = [
CLI::color(lang('Migrations.namespace'), 'yellow'),
CLI::color(lang('Migrations.version'), 'yellow'),
CLI::color(lang('Migrations.filename'), 'yellow'),
CLI::color(lang('Migrations.group'), 'yellow'),
CLI::color(str_replace(': ', '', lang('Migrations.on')), 'yellow'),
CLI::color(lang('Migrations.batch'), 'yellow'),
];
CLI::table($status, $headers);
}
}

View File

@@ -0,0 +1,82 @@
<?php
/**
* This file is part of CodeIgniter 4 framework.
*
* (c) CodeIgniter Foundation <admin@codeigniter.com>
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace CodeIgniter\Commands\Database;
use CodeIgniter\CLI\BaseCommand;
use CodeIgniter\CLI\CLI;
use CodeIgniter\Database\Seeder;
use Config\Database;
use Throwable;
/**
* Runs the specified Seeder file to populate the database
* with some data.
*/
class Seed extends BaseCommand
{
/**
* The group the command is lumped under
* when listing commands.
*
* @var string
*/
protected $group = 'Database';
/**
* The Command's name
*
* @var string
*/
protected $name = 'db:seed';
/**
* the Command's short description
*
* @var string
*/
protected $description = 'Runs the specified seeder to populate known data into the database.';
/**
* the Command's usage
*
* @var string
*/
protected $usage = 'db:seed <seeder_name>';
/**
* the Command's Arguments
*
* @var array<string, string>
*/
protected $arguments = [
'seeder_name' => 'The seeder name to run',
];
/**
* Passes to Seeder to populate the database.
*/
public function run(array $params)
{
$seeder = new Seeder(new Database());
$seedName = array_shift($params);
if (empty($seedName)) {
$seedName = CLI::prompt(lang('Migrations.migSeeder'), null, 'required'); // @codeCoverageIgnore
}
try {
$seeder->call($seedName);
} catch (Throwable $e) {
$this->showError($e);
}
}
}