diff --git a/config/module.config.php b/config/module.config.php index 8a103dddbb5f4dcc6889a14e9d28b597293ec92e..8f99f9f4f732cc14db7b0260de637ce40b835251 100644 --- a/config/module.config.php +++ b/config/module.config.php @@ -6,17 +6,10 @@ return [ 'unicaen-bddadmin' => [ 'connection' => [ - 'default' => [ - 'driver' => 'Postgresql', // par défaut, ou Oracle ou Mysql - 'host' => '', - 'port' => '', - 'dbname' => '', - 'user' => '', - 'password' => '', - ], - // Autres instances de la BDD ], + 'current_connection' => 'default', + 'ddl' => [ 'dir' => 'data/ddl', 'columns_positions_file' => 'data/ddl_columns_pos.php', @@ -61,23 +54,30 @@ return [ 'service_manager' => [ 'factories' => [ Bdd::class => BddFactory::class, - Command\InstallBddCommand::class => Command\CommandFactory::class, - Command\UpdateBddCommand::class => Command\CommandFactory::class, + Command\InstallCommand::class => Command\CommandFactory::class, + Command\UpdateCommand::class => Command\CommandFactory::class, Command\UpdateDdlCommand::class => Command\CommandFactory::class, Command\UpdateDataCommand::class => Command\CommandFactory::class, - Command\ClearBddCommand::class => Command\CommandFactory::class, + Command\ClearCommand::class => Command\CommandFactory::class, + Command\CopyToCommand::class => Command\CommandFactory::class, + Command\CopyFromCommand::class => Command\CommandFactory::class, + Command\LoadCommand::class => Command\CommandFactory::class, + Command\SaveCommand::class => Command\CommandFactory::class, ], ], 'laminas-cli' => [ 'commands' => [ - 'bddadmin:install-bdd' => Command\InstallBddCommand::class, - 'bddadmin:update-bdd' => Command\UpdateBddCommand::class, - 'bddadmin:clear-bdd' => Command\ClearBddCommand::class, + 'bddadmin:install' => Command\InstallCommand::class, + 'bddadmin:update' => Command\UpdateCommand::class, + 'bddadmin:clear' => Command\ClearCommand::class, 'bddadmin:update-ddl' => Command\UpdateDdlCommand::class, 'bddadmin:update-data' => Command\UpdateDataCommand::class, - + 'bddadmin:copy-to' => Command\CopyToCommand::class, + 'bddadmin:copy-from' => Command\CopyFromCommand::class, + 'bddadmin:load' => Command\LoadCommand::class, + 'bddadmin:save' => Command\SaveCommand::class, ], ], ]; \ No newline at end of file diff --git a/config/unicaen-bddadmin.local.php.dist b/config/unicaen-bddadmin.local.php.dist index 3d5d49bedb1390d740e31c0aa5fd36e95e0a0e0e..1ff0093c68eb48975046abd61bf1fa2199f8035f 100644 --- a/config/unicaen-bddadmin.local.php.dist +++ b/config/unicaen-bddadmin.local.php.dist @@ -7,7 +7,7 @@ return [ 'unicaen-bddadmin' => [ 'connection' => [ - 'default' => [ // généralement : base de dév + 'default' => [ // généralement : base de dév, peut s'appeler autrement que 'default' 'host' => 'à renseigner ...', 'port' => 'à renseigner ...', 'dbname' => 'à renseigner ...', @@ -26,5 +26,8 @@ return [ ... */ ], + + /* Connexion à utiliser par défaut, nom à sélectionner parmi la liste des connexions disponibles */ + //'current_connection' => 'default', ], ]; \ No newline at end of file diff --git a/src/Bdd.php b/src/Bdd.php index d2551ea0189686e57732585dd461e65cc54a97dd..9553feeb5d5c44287a7c4ce74f0bacc9409b10c3 100644 --- a/src/Bdd.php +++ b/src/Bdd.php @@ -37,9 +37,8 @@ class Bdd use LoggerAwareTrait; use OptionsTrait; - const CONNECTION_DEFAULT = 'default'; - const OPTION_CONNECTION = 'connection'; + const OPTION_CURRENT_CONNECTION = 'current_connection'; const OPTION_DDL = 'ddl'; const OPTION_DATA = 'data'; const OPTION_MIGRATION = 'migration'; @@ -123,7 +122,7 @@ class Bdd Ddl::SCHEMA . '.drop' => 'Suppression des schémas', ]; - private string $connection = self::CONNECTION_DEFAULT; + private string $connection = 'default'; /** @var array|Bdd[] */ private array $bdds = []; @@ -149,16 +148,20 @@ class Bdd - public function __construct(array $options = [], string $connection = self::CONNECTION_DEFAULT) + public function __construct(array $options = [], ?string $connection = null) { - $this->connection = $connection; - if (!empty($options)) { // Compatibilité avec l'ancienne configuration des connections if (!isset($options[self::OPTION_CONNECTION]) && isset($options['host'])) { $options = [self::OPTION_CONNECTION => [$connection => $options]]; } $this->setOptions($options); + + if (empty($connection)){ + $connection = $this->getOption(self::OPTION_CURRENT_CONNECTION, 'default'); + } + $this->connection = $connection; + $this->connect(); } @@ -179,6 +182,23 @@ class Bdd + public function getConnectionName(): string + { + return $this->connection; + } + + + + public function getBdds(): array + { + $bdds = $this->getOption(self::OPTION_CONNECTION); + unset($bdds[$this->getOption(self::OPTION_CURRENT_CONNECTION)]); + + return array_keys($bdds); + } + + + public function getBdd(string $connection): self { if (!array_key_exists($connection, $this->bdds)) { @@ -858,8 +878,8 @@ class Bdd $this->logTitle('Génération de la DDL à partir de la base de données'); try { - $filters = $bdd->getFiltersForUpdateDdl(); - $ddl = $bdd->getDdl($filters); + $filters = $this->getFiltersForUpdateDdl(); + $ddl = $this->getDdl($filters); $ddl->saveToDir(); $this->logSuccess('DDL mise à jour'); } catch (\Throwable $e) { @@ -1087,6 +1107,8 @@ class Bdd $this->create($source, $filters); + $this->majSequences(); + $this->logEnd(); return $this; @@ -1185,10 +1207,12 @@ class Bdd $ddl->loadFromFile($tmpPath . '/bdd.ddl'); $ddl->filter($filters); + $schDdl = $ddl->get(Ddl::SCHEMA); + $sDdl = $ddl->get(Ddl::SEQUENCE); $tDdl = $ddl->get(Ddl::TABLE); $this->drop(); - $this->create([Ddl::TABLE => $tDdl]); + $this->create([Ddl::SCHEMA => $schDdl, Ddl::SEQUENCE => $sDdl, Ddl::TABLE => $tDdl]); $tables = array_keys($tDdl); @@ -1203,8 +1227,14 @@ class Bdd } } $this->inCopy = false; - $this->create($ddl, [Ddl::SCHEMA => ['excludes' => '%']]); - $this->create($ddl, [Ddl::TABLE => ['excludes' => '%']]); + if ($filters instanceof DdlFilters) { + $filters = $filters->toArray(); + } + $filters[Ddl::SCHEMA] = ['excludes' => '%']; + $filters[Ddl::SEQUENCE] = ['excludes' => '%']; + $filters[Ddl::TABLE] = ['excludes' => '%']; + + $this->create($ddl, $filters); $this->majSequences($ddl); diff --git a/src/Command/ClearBddCommand.php b/src/Command/ClearCommand.php similarity index 79% rename from src/Command/ClearBddCommand.php rename to src/Command/ClearCommand.php index 65db9dd4a48caa15c2126c1838c9efe7f6a8ddeb..4fde4c0acb84df3802dba8e96e99b1a0b3fe567e 100644 --- a/src/Command/ClearBddCommand.php +++ b/src/Command/ClearCommand.php @@ -11,14 +11,21 @@ use Unicaen\BddAdmin\Data\DataManager; use Unicaen\BddAdmin\Ddl\Ddl; /** - * Description of ClearBddCommand + * Description of ClearCommand * * @author Laurent Lécluse <laurent.lecluse at unicaen.fr> */ -class ClearBddCommand extends Command +class ClearCommand extends Command { use BddAwareTrait; + protected function configure(): void + { + $this->setDescription('Vide la base de données'); + } + + + protected function execute(InputInterface $input, OutputInterface $output): int { $io = new SymfonyStyle($input, $output); diff --git a/src/Command/CopyFromCommand.php b/src/Command/CopyFromCommand.php new file mode 100644 index 0000000000000000000000000000000000000000..1d70120e967c20005c7e61708ed330093d9c2072 --- /dev/null +++ b/src/Command/CopyFromCommand.php @@ -0,0 +1,59 @@ +<?php + +namespace Unicaen\BddAdmin\Command; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; +use Unicaen\BddAdmin\BddAwareTrait; +use Unicaen\BddAdmin\Data\DataManager; +use Unicaen\BddAdmin\Ddl\Ddl; + +/** + * Description of CopyFromCommand + * + * @author Laurent Lécluse <laurent.lecluse at unicaen.fr> + */ +class CopyFromCommand extends Command +{ + use BddAwareTrait; + + protected function configure(): void + { + $this + ->setDescription('Copie depuis une autre BDD') + ->addArgument('source', InputArgument::OPTIONAL, 'Nom de la BDD d\'origine'); + } + + + + protected function execute(InputInterface $input, OutputInterface $output): int + { + $io = new SymfonyStyle($input, $output); + $bdd = $this->getBdd()->setLogger($io); + + $bdds = $bdd->getBdds(); + + if (empty($bdds)) { + $io->error('Aucune base de donnée possible n\'est en source : copie impossible'); + $io->info('Veuillez ajouter d\'autres connexions en configuration dans unicaen-bddadmin/connection'); + return Command::INVALID; + } + + $source = $input->getArgument('source'); + + if (!$source) { + $source = $io->choice( + 'Veuillez choisir une base de données source', + $bdd->getBdds() + ); + } + + // Lance la copie + $bdd->copy($source); + + return Command::SUCCESS; + } +} \ No newline at end of file diff --git a/src/Command/CopyToCommand.php b/src/Command/CopyToCommand.php new file mode 100644 index 0000000000000000000000000000000000000000..1c1f23391b5623226050a08e6865f82836703425 --- /dev/null +++ b/src/Command/CopyToCommand.php @@ -0,0 +1,59 @@ +<?php + +namespace Unicaen\BddAdmin\Command; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; +use Unicaen\BddAdmin\BddAwareTrait; +use Unicaen\BddAdmin\Data\DataManager; +use Unicaen\BddAdmin\Ddl\Ddl; + +/** + * Description of CopyToCommand + * + * @author Laurent Lécluse <laurent.lecluse at unicaen.fr> + */ +class CopyToCommand extends Command +{ + use BddAwareTrait; + + protected function configure(): void + { + $this + ->setDescription('Copie vers une autre BDD') + ->addArgument('destination', InputArgument::OPTIONAL, 'Nom de la BDD de destination'); + } + + + + protected function execute(InputInterface $input, OutputInterface $output): int + { + $io = new SymfonyStyle($input, $output); + $bdd = $this->getBdd()->setLogger($io); + + $bdds = $bdd->getBdds(); + + if (empty($bdds)) { + $io->error('Aucune base de donnée possible n\'est en destination : copie impossible'); + $io->info('Veuillez ajouter d\'autres connexions en configuration dans unicaen-bddadmin/connection'); + return Command::INVALID; + } + + $destination = $input->getArgument('destination'); + + if (!$destination) { + // Si l'argument n'est pas fourni, on demande à l'utilisateur de choisir une valeur + $destination = $io->choice( + 'Veuillez choisir une base de données de destination', + $bdd->getBdds() + ); + } + + $bdd->copyTo($destination); + + return Command::SUCCESS; + } +} \ No newline at end of file diff --git a/src/Command/InstallBddCommand.php b/src/Command/InstallCommand.php similarity index 78% rename from src/Command/InstallBddCommand.php rename to src/Command/InstallCommand.php index add9613c3edf4cc5e8e2a278882f90731e3cbcb0..dd4b17d0af188e41bbdbbf5c610b2b6c69f109b3 100644 --- a/src/Command/InstallBddCommand.php +++ b/src/Command/InstallCommand.php @@ -15,10 +15,17 @@ use Unicaen\BddAdmin\Ddl\Ddl; * * @author Laurent Lécluse <laurent.lecluse at unicaen.fr> */ -class InstallBddCommand extends Command +class InstallCommand extends Command { use BddAwareTrait; + protected function configure(): void + { + $this->setDescription('Peuple la base de données à partir de la DDL et du jeu de données par défaut'); + } + + + protected function execute(InputInterface $input, OutputInterface $output): int { $io = new SymfonyStyle($input, $output); diff --git a/src/Command/LoadCommand.php b/src/Command/LoadCommand.php new file mode 100644 index 0000000000000000000000000000000000000000..e7908305bfc609aa58d355d2f8ee3a6eb242d412 --- /dev/null +++ b/src/Command/LoadCommand.php @@ -0,0 +1,52 @@ +<?php + +namespace Unicaen\BddAdmin\Command; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Question\ConfirmationQuestion; +use Symfony\Component\Console\Style\SymfonyStyle; +use Unicaen\BddAdmin\BddAwareTrait; +use Unicaen\BddAdmin\Data\DataManager; +use Unicaen\BddAdmin\Ddl\Ddl; + +/** + * Description of LoadCommand + * + * @author Laurent Lécluse <laurent.lecluse at unicaen.fr> + */ +class LoadCommand extends Command +{ + use BddAwareTrait; + + protected function configure(): void + { + $this->setDescription('Chargement de la base de données depuis un fichier') + ->addArgument('filename', InputArgument::REQUIRED, 'Chemin du fichier de sauvegarde'); + } + + + + protected function execute(InputInterface $input, OutputInterface $output): int + { + $io = new SymfonyStyle($input, $output); + $bdd = $this->getBdd()->setLogger($io); + + $filename = $input->getArgument('filename'); + + if (!str_starts_with($filename, DIRECTORY_SEPARATOR)){ + $filename = $_SERVER['PWD'].DIRECTORY_SEPARATOR.$filename; + } + + if (!file_exists($filename)){ + $io->error('Le fichier '.$filename.' n\'existe pas'); + return Command::FAILURE; + } + + $bdd->load($filename); + + return Command::SUCCESS; + } +} \ No newline at end of file diff --git a/src/Command/SaveCommand.php b/src/Command/SaveCommand.php new file mode 100644 index 0000000000000000000000000000000000000000..d0220f57079f220b5d6cc85b0a48fec02e28cf90 --- /dev/null +++ b/src/Command/SaveCommand.php @@ -0,0 +1,60 @@ +<?php + +namespace Unicaen\BddAdmin\Command; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Question\ConfirmationQuestion; +use Symfony\Component\Console\Style\SymfonyStyle; +use Unicaen\BddAdmin\BddAwareTrait; +use Unicaen\BddAdmin\Data\DataManager; +use Unicaen\BddAdmin\Ddl\Ddl; + +/** + * Description of SaveCommand + * + * @author Laurent Lécluse <laurent.lecluse at unicaen.fr> + */ +class SaveCommand extends Command +{ + use BddAwareTrait; + + protected function configure(): void + { + $this->setDescription('Sauvegarde de la base de données dans un fichier') + ->addArgument('filename', InputArgument::REQUIRED, 'Chemin du fichier de destination'); + } + + + + protected function execute(InputInterface $input, OutputInterface $output): int + { + $io = new SymfonyStyle($input, $output); + $bdd = $this->getBdd()->setLogger($io); + + $filename = $input->getArgument('filename'); + + if (!str_starts_with($filename, DIRECTORY_SEPARATOR)){ + $filename = $_SERVER['PWD'].DIRECTORY_SEPARATOR.$filename; + } + + if (file_exists($filename)){ + $helper = $this->getHelper('question'); + $question = new ConfirmationQuestion('Le fichier existe déjà, voulez-vous le remplacer ? (yes/no) [no]: ', false); + + if (!$helper->ask($input, $output, $question)) { + $io->warning('Opération annulée par l\'utilisateur.'); + return Command::FAILURE; + }else{ + unlink($filename); + } + } + + $bdd->save($filename); + + return Command::SUCCESS; + } + +} \ No newline at end of file diff --git a/src/Command/UpdateBddCommand.php b/src/Command/UpdateCommand.php similarity index 75% rename from src/Command/UpdateBddCommand.php rename to src/Command/UpdateCommand.php index f3977b04404391f9dabc09f14bd442442e5f16ab..27678ec6955477e020d92512fc555a07363a57a8 100644 --- a/src/Command/UpdateBddCommand.php +++ b/src/Command/UpdateCommand.php @@ -12,14 +12,21 @@ use Unicaen\BddAdmin\Ddl\Ddl; use Unicaen\BddAdmin\Migration\MigrationManager; /** - * Description of UpdateBddCommand + * Description of UpdateCommand * * @author Laurent Lécluse <laurent.lecluse at unicaen.fr> */ -class UpdateBddCommand extends Command +class UpdateCommand extends Command { use BddAwareTrait; + protected function configure(): void + { + $this->setDescription('Met à jour la base de données & ses données à partir de la DDL et du jeu de données'); + } + + + protected function execute(InputInterface $input, OutputInterface $output): int { $io = new SymfonyStyle($input, $output); diff --git a/src/Command/UpdateDataCommand.php b/src/Command/UpdateDataCommand.php index d1ef14363c5080c431be12da597499302643e202..f1d37e7ccd885fc03f3220331cc7d1bb98e2a48b 100644 --- a/src/Command/UpdateDataCommand.php +++ b/src/Command/UpdateDataCommand.php @@ -17,10 +17,17 @@ use Unicaen\BddAdmin\Ddl\Ddl; class UpdateDataCommand extends Command { use BddAwareTrait; - + + protected function configure(): void + { + $this->setDescription('Met à jour les données de la base de données'); + } + + + protected function execute(InputInterface $input, OutputInterface $output): int { - $io = new SymfonyStyle($input, $output); + $io = new SymfonyStyle($input, $output); $bdd = $this->getBdd()->setLogger($io); $bdd->updateData(); diff --git a/src/Command/UpdateDdlCommand.php b/src/Command/UpdateDdlCommand.php index 75e18777ce329b25cc36853fed3b1836c05435a8..64b76a4443866793ddb072dbfaf305d2566f5605 100644 --- a/src/Command/UpdateDdlCommand.php +++ b/src/Command/UpdateDdlCommand.php @@ -17,6 +17,13 @@ class UpdateDdlCommand extends Command { use BddAwareTrait; + protected function configure(): void + { + $this->setDescription('Met à jour la DDL à partir des définitions de la base de données'); + } + + + protected function execute(InputInterface $input, OutputInterface $output): int { $io = new SymfonyStyle($input, $output); diff --git a/src/Logger/DefaultLogger.php b/src/Logger/DefaultLogger.php index 1c82933a742114bc19179d43e409ee6bbaa820c2..26fb890d83bb39b6a56a963278ca18b48c3cf465 100644 --- a/src/Logger/DefaultLogger.php +++ b/src/Logger/DefaultLogger.php @@ -80,7 +80,7 @@ class DefaultLogger implements LoggerInterface - public function error(Throwable|string $e): void + public function error(\Throwable|string $e): void { if ($e instanceof \Throwable) { $e = $e->getMessage(); diff --git a/src/Logger/LoggerInterface.php b/src/Logger/LoggerInterface.php index d7b5940df7209fc94680e6774f5df8307b902602..8e134a975e24ee2fe71aa906723f6370e63a8e9c 100644 --- a/src/Logger/LoggerInterface.php +++ b/src/Logger/LoggerInterface.php @@ -12,7 +12,7 @@ interface LoggerInterface - public function error(Throwable|string $e): void; + public function error(\Throwable|string $e): void; diff --git a/src/Logger/SymfonyStyleLogger.php b/src/Logger/SymfonyStyleLogger.php index 9e1ee50386bdbbba36819e8a9baee503024e4e1e..f82a15fe55db2f0f100a874e421a67ea4a696308 100644 --- a/src/Logger/SymfonyStyleLogger.php +++ b/src/Logger/SymfonyStyleLogger.php @@ -69,7 +69,7 @@ class SymfonyStyleLogger implements LoggerInterface - public function error(Throwable|string $e): void + public function error(\Throwable|string $e): void { if ($e instanceof \Throwable) { $e = $e->getMessage(); diff --git a/src/Util.php b/src/Util.php index e9fc0991909db67c38abeee0a3906a7fc69d99a4..fadce8b2ac4d90674afd0e23f6a516ef426cb866 100644 --- a/src/Util.php +++ b/src/Util.php @@ -55,7 +55,11 @@ class Util . self::arrayExport($value, "$indent "); } - return "[\n" . implode(",\n", $r) . ",\n" . $indent . "]"; + if (!empty($r)) { + return "[\n" . implode(",\n", $r) . ",\n" . $indent . "]"; + }else{ + return "[]"; + } case "boolean": return $var ? "TRUE" : "FALSE"; default: