diff --git a/app/src/Command/TransmogrifyCommand.php b/app/src/Command/TransmogrifyCommand.php index bd07edc61..77afe4056 100644 --- a/app/src/Command/TransmogrifyCommand.php +++ b/app/src/Command/TransmogrifyCommand.php @@ -43,6 +43,8 @@ use Doctrine\DBAL\Exception\ForeignKeyConstraintViolationException; class TransmogrifyCommand extends Command { + use \App\Lib\Traits\LabeledLogTrait; + // Tables must be listed in order of primary key dependencies. protected $tables = [ 'cos' => [ @@ -263,6 +265,7 @@ class TransmogrifyCommand extends Command { 'co_person_id' => 'person_id', 'org_identity_id' => 'external_identity_id', 'actor_co_person_id' => 'actor_person_id', + 'actor_api_user_id' => 'actor_api_user_id', 'co_person_role_id' => 'person_role_id', // XXX temporary until tables are migrated 'co_group_id' => null, @@ -389,7 +392,7 @@ public function execute(Arguments $args, ConsoleIo $io) { if(!empty($atables) && !in_array($t, $atables)) continue; - $io->out("===" . $t . "==="); + $io->info(Inflector::classify($t) . "(" . $t . ")"); // Run any pre processing functions for the table. @@ -401,18 +404,19 @@ public function execute(Arguments $args, ConsoleIo $io) { $count = $this->inconn->fetchOne("SELECT COUNT(*) FROM " . $this->tables[$t]['source']); - $io->out("= Processing " . $count . " records"); - $insql = "SELECT * FROM " . $this->tables[$t]['source'] . " ORDER BY id ASC"; $stmt = $this->inconn->query($insql); $tally = 0; + $warns = 0; + $err = 0; while($row = $stmt->fetch()) { if(!empty($row[ $this->tables[$t]['displayField'] ])) { - $io->out("$t " . $row[ $this->tables[$t]['displayField'] ] . "...", 0); + // Use this in the message. Modify last + $this->llog("debug", "$t " . $row[ $this->tables[$t]['displayField'] ]); } - + try { // Make a copy of the original data for any post processing followups $origRow = $row; @@ -423,9 +427,12 @@ public function execute(Arguments $args, ConsoleIo $io) { $this->fixBooleans($t, $row); $this->mapFields($t, $row); - - $this->outconn->insert($t, $row); - + + // Insert only if the record does not already exists + $Model = $this->getTableLocator()->get($t); + if($Model->find()->where(['id' => $row['id']])->count() === 0) { + $this->outconn->insert($t, $row); + } $this->cacheResults($t, $row); // Run any post processing functions for the row. @@ -441,27 +448,35 @@ public function execute(Arguments $args, ConsoleIo $io) { // load this record. This can happen, eg, because the source_field_id // did not load, perhaps because it was associated with an Org Identity // not linked to a CO Person that was not migrated. - - $io->err("WARNING: Skipping record " . $row['id'] . " due to invalid foreign key: " . $e->getMessage()); + $warns++; + $this->llog("debug", "WARNING: Skipping record " . $row['id'] . " due to invalid foreign key: " . $e->getMessage()); } catch(\InvalidArgumentException $e) { // If we can't find a value for mapping we skip the record // (ie: mapFields basically requires a successful mapping) - - $io->err("WARNING: Skipping record " . $row['id'] . ": " . $e->getMessage()); + $warns++; + $this->llog("debug", "WARNING: Skipping record " . $row['id'] . ": " . $e->getMessage()); } catch(\Exception $e) { - $io->err("ERROR: Record " . $row['id'] . ": " . $e->getMessage()); + $err++; + $this->llog("debug", "ERROR: Record " . $row['id'] . ": " . $e->getMessage()); } $tally++; - $io->out(floor(($tally * 100)/$count) . "% done"); + $this->cliLogPercentage($tally, $count); } $max = $this->inconn->fetchOne('SELECT MAX(id) FROM ' . $this->tables[$t]['source']); $max++; - - $io->out("= New max: " . $max); + $stdout_msg = "(New max: " . $max . ")"; + if($warns > 0) { + $stdout_msg .= "(Warnings: " . $warns . ")"; + } + if($err > 0) { + $stdout_msg .= "(Errors: " . $err . ")"; + } + + $io->out($stdout_msg); // Strictly speaking we should use prepared statements, but we control the // data here, and also we're executing a maintenance operation (so query @@ -905,8 +920,12 @@ protected function processExtendedAttributes() { // Extended Attributes were not changelog enabled $this->fixChangelog('ad_hoc_attributes', $adhocRow, true); $this->fixBooleans('ad_hoc_attributes', $adhocRow); - - $this->outconn->insert('ad_hoc_attributes', $adhocRow); + + try { + $this->outconn->insert('ad_hoc_attributes', $adhocRow); + } catch (\Doctrine\DBAL\Exception\UniqueConstraintViolationException $e) { + $this->llog("debug", "record already exists: " . print_r($adhocRow, true)); + } } } } diff --git a/app/src/Lib/Traits/LabeledLogTrait.php b/app/src/Lib/Traits/LabeledLogTrait.php index c36b7949d..6bffb90d0 100644 --- a/app/src/Lib/Traits/LabeledLogTrait.php +++ b/app/src/Lib/Traits/LabeledLogTrait.php @@ -65,4 +65,20 @@ public function llog(string $level, string $msg) { Log::write($level, $m); } + + /** + * Print formatted cli percentage + * + * @since COmanage Registry v5.0.0 + * @param int $done Number of iterations completed + * @param string $total Total number of iterations + * @return string Formated string with line return offset + */ + + public function cliLogPercentage(int $done, int $total): void { + $perc = floor(($done / $total) * 100); + $left = 100 - $perc; + $out = sprintf("\033[0G\033[2K[%'={$perc}s>%-{$left}s] - $perc%% -- $done/$total", "", ""); + fwrite(STDERR, $out); + } } diff --git a/app/src/Model/Table/CoSettingsTable.php b/app/src/Model/Table/CoSettingsTable.php index 9ed048d5f..8fa7d1758 100644 --- a/app/src/Model/Table/CoSettingsTable.php +++ b/app/src/Model/Table/CoSettingsTable.php @@ -210,7 +210,14 @@ public function addDefaults(int $coId): int { // 'co_theme_id' => null, // 'global_search_limit' => DEF_GLOBAL_SEARCH_LIMIT ]; - + + // Check if we already have Settings for this CO + $settings = $this->find()->where([ 'co_id' => $defaultSettings['co_id'] ])->first(); + // If the record already exists update else create a new one + if(!empty($settings->{'id'})) { + return $settings->{'id'}; + } + $obj = $this->newEntity($defaultSettings); $this->save($obj);