Loading src/Data/DataManager.php +3 −3 Original line number Diff line number Diff line Loading @@ -103,9 +103,9 @@ class DataManager $config['key'] ?? $idCol, $config['options'] ?? [] ); if ($result['insert'] + $result['update'] + $result['delete'] > 0) { if ($result['insert'] + $result['update'] + $result['delete'] + ($result['undelete'] ?? 0) + ($result['soft-delete'] ?? 0) > 0) { $msg = str_pad($table, 31, ' '); $msg .= 'Insert: ' . $result['insert'] . ', Update: ' . $result['update'] . ', Delete: ' . $result['delete']; $msg .= 'Insert: ' . ($result['insert'] + ($result['undelete'] ?? 0)) . ', Update: ' . $result['update'] . ', Delete: ' . ($result['delete'] + ($result['soft-delete'] ?? 0)); $this->getBdd()->logMsg($msg); } } Loading src/Table.php +145 −70 Original line number Diff line number Diff line Loading @@ -125,7 +125,7 @@ class Table 'case' => -1, 'types' => $this->makeTypesOptions(), 'key' => null, 'orderBy' => '', 'order-by' => '', ]; $options = array_merge($defaultOptions, $options); Loading @@ -146,8 +146,8 @@ class Table $params = []; $sql .= $this->makeWhere($where, $options, $params); if ($options['orderBy']) { $sql .= ' ORDER BY ' . $options['orderBy']; if ($options['order-by']) { $sql .= ' ORDER BY ' . $options['order-by']; } $select = $this->getBdd()->select($sql, $params, $options); Loading Loading @@ -418,46 +418,104 @@ class Table private function mergeDiff(array &$o, array &$n, array &$options): array { $diff = []; foreach ($o as $c => $ov) { if ($options['has-historique']) { if ($c == $options['histo-creation-column'] || $c == $options['histo-createur-id-column'] || $c == $options['histo-modification-column'] || $c == $options['histo-modificateur-id-column'] || $c == $options['histo-destruction-column'] || $c == $options['histo-destructeur-id-column'] ) { continue; // on ignore les colonnes relatives aux historiques } } $newc = $n[$c] ?? null; $oldc = $o[$c] ?? null; if ($newc instanceof \DateTime) $newc = $newc->format('Y-m-d H:i:s'); if ($oldc instanceof \DateTime) $oldc = $oldc->format('Y-m-d H:i:s'); if ($newc != $oldc && array_key_exists($c, $n) && $c != $options['id-column']) { $ok = empty($options['update-cols']); // OK par défaut si une liste n'a pas été établie manuellement if (in_array($c, $options['update-cols'])) $ok = true; if (in_array($c, $options['update-ignore-cols'])) $ok = false; if (in_array($c, $options['update-only-null']) && $oldc !== null) $ok = false; if ($ok) { if ((is_float($newc) || is_double($newc)) && (is_float($oldc) || is_double($oldc))) { // nécessaire à cause des pb de précision des float/doubles en PHP : // dans ce cas, on considère quand même que les 2 chiffres sont identiques => diff négligeable $ok = (abs($newc - $oldc) > 0.0000000001); } } if ($ok) { $diff[$c] = $n[$c]; } } } return $diff; } public function merge(array $data, $key, array $options = []): array { $result = ['insert' => 0, 'update' => 0, 'delete' => 0, 'soft-delete' => 0]; $ddl = $this->getDdl(); $bdd = $this->getBdd(); /* Initialisation */ /* Initialisation des options */ $hasHistorique = $this->hasHistorique(); $defaultOptions = [ 'custom-select' => null, 'where' => null, 'key' => $key, 'delete' => true, 'soft-delete' => false, 'soft-delete' => true, 'undelete' => true, 'insert' => true, 'update' => true, 'return-insert-data' => false, 'update-cols' => [], 'update-ignore-cols' => [], 'update-only-null' => [], 'id-column' => $bdd->getOption(Bdd::OPTION_ID_COLUMN), 'has-historique' => $hasHistorique, 'histo-user-id' => null, 'histo-date' => new \DateTime(), ]; if ($hasHistorique) { $defaultOptions['histo-user-id'] = $bdd->getHistoUserId(); $defaultOptions['histo-creation-column'] = $bdd->getOption(Bdd::OPTION_HISTO_CREATION_COLUMN); $defaultOptions['histo-createur-id-column'] = $bdd->getOption(Bdd::OPTION_HISTO_CREATEUR_ID_COLUMN); $defaultOptions['histo-modification-column'] = $bdd->getOption(Bdd::OPTION_HISTO_MODIFICATION_COLUMN); $defaultOptions['histo-modificateur-id-column'] = $bdd->getOption(Bdd::OPTION_HISTO_MODIFICATEUR_ID_COLUMN); $defaultOptions['histo-destruction-column'] = $bdd->getOption(Bdd::OPTION_HISTO_DESTRUCTION_COLUMN); $defaultOptions['histo-destructeur-id-column'] = $bdd->getOption(Bdd::OPTION_HISTO_DESTRUCTEUR_ID_COLUMN); $result = ['insert' => 0, 'update' => 0, 'delete' => 0, 'soft-delete' => 0, 'undelete' => 0]; } else { $result = ['insert' => 0, 'update' => 0, 'delete' => 0]; } $options = array_merge($defaultOptions, $options); if ($options['return-insert-data']) { $result['insert-data'] = []; } $ddl = $this->getDdl(); $bdd = $this->getBdd(); $histoUserId = $bdd->getHistoUserId(); $hasHistorique = $this->hasHistorique(); $idCol = $this->getBdd()->getOption(Bdd::OPTION_ID_COLUMN); if (empty($options['where']) && $hasHistorique) { $histoDestructionCol = $this->getBdd()->getOption(Bdd::OPTION_HISTO_DESTRUCTION_COLUMN); $options['where'] = $histoDestructionCol . ' IS NULL'; if ($hasHistorique && (null === $options['histo-user-id'])) { throw new \Exception('L\'id de l\'utilisateur pour la gestion des historiques doit être fourni en configuration ou bien en option'); } /* Mise en forme des nouvelles données */ $new = []; foreach ($data as $d) { foreach ($data as $i => $d) { foreach ($d as $c => $v) { if (isset($ddl['columns'][$c])) { if (isset($options['columns'][$c]['transformer'])) { Loading @@ -482,73 +540,90 @@ class Table $selOptions['fetch'] = Bdd::FETCH_EACH; $stmt = $this->select($options['where'], $selOptions); while ($o = $stmt->next()) { // récupération de k et n // récupération de k et n & on détermine quelle action effectuer $k = $this->makeKey($o, $key); $action = null; // rien à faire par défaut if (array_key_exists($k, $new)) { $n = $new[$k]; unset($new[$k]); } else { $n = null; unset($new[$k]); // on retire de suite du tableau $diff = $this->mergeDiff($o, $n, $options); if (!empty($diff)) { if ($options['update']) { $action = 'update'; } if (empty($n) && $options['soft-delete'] && $hasHistorique && $histoUserId !== null) { // SOFT DELETE $histoDestructionCol = $this->getBdd()->getOption(Bdd::OPTION_HISTO_DESTRUCTION_COLUMN); $histoDestructeurIdCol = $this->getBdd()->getOption(Bdd::OPTION_HISTO_DESTRUCTEUR_ID_COLUMN); //On ne delete pas mais on historise $n = $o; $n[$histoDestructionCol] = new \DateTime(); $n[$histoDestructeurIdCol] = $histoUserId; $this->update($n, $this->makeKeyArray($o, $k)); $result['soft-delete']++; } elseif (empty($n) && !$options['soft-delete']) { // DELETE if ($options['delete']) { $this->delete($this->makeKeyArray($o, $key)); $result['delete']++; } elseif ($hasHistorique) { if ($options['undelete'] && array_key_exists($options['histo-destruction-column'], $o) && $o[$options['histo-destruction-column']]) { $action = 'undelete'; } } elseif ($options['update']) { // UPDATE si différent!! $toUpdate = []; foreach ($o as $c => $ov) { $newc = $n[$c] ?? null; $oldc = $o[$c] ?? null; if ($newc instanceof \DateTime) $newc = $newc->format('Y-m-d H:i:s'); if ($oldc instanceof \DateTime) $oldc = $oldc->format('Y-m-d H:i:s'); if ($newc != $oldc && array_key_exists($c, $n) && $c != $idCol) { $ok = empty($options['update-cols']); // OK par défaut si une liste n'a pas été établie manuellement if (in_array($c, $options['update-cols'])) $ok = true; if (in_array($c, $options['update-ignore-cols'])) $ok = false; if (in_array($c, $options['update-only-null']) && $oldc !== null) $ok = false; if ($ok) { if ((is_float($newc) || is_double($newc)) && (is_float($oldc) || is_double($oldc))) { if (abs($newc - $oldc) > 0.0000000001) { // nécessaire à cause des pb de précision des float/doubles en PHP : // dans ce cas, on considère quand même que les 2 chiffres sont identiques $toUpdate[$c] = $n[$c]; } } else { $toUpdate[$c] = $n[$c]; if ($options['has-historique']) { if (null === $o[$options['histo-destruction-column']]) { // opération de soft-delete if ($options['soft-delete']) { $action = 'soft-delete'; } } } else { // opération de delete if ($options['delete']) { $action = 'delete'; } } } if (!empty($toUpdate)) { // on effectue l'action if ($action) { switch ($action) { case 'delete': $this->delete($this->makeKeyArray($o, $key)); break; case 'soft-delete': $toUpdate = [ $options['histo-destruction-column'] => $options['histo-date'], $options['histo-destructeur-id-column'] => $options['histo-user-id'], ]; $this->update($toUpdate, $this->makeKeyArray($o, $key), ['ddl' => $ddl]); $result['update']++; break; case 'undelete': $toUpdate = [ $options['histo-destruction-column'] => null, $options['histo-destructeur-id-column'] => null, ]; $this->update($toUpdate, $this->makeKeyArray($o, $key), ['ddl' => $ddl]); break; case 'update': $toUpdate = $diff; if ($hasHistorique) { $toUpdate[$options['histo-modification-column']] = $options['histo-date']; $toUpdate[$options['histo-modificateur-id-column']] = $options['histo-user-id']; } $this->update($toUpdate, $this->makeKeyArray($o, $key), ['ddl' => $ddl]); break; } $result[$action]++; } } /* Pour finir, insertion de tous les nouveaux éléments */ foreach ($new as $k => $n) { if ($options['insert']) { if ($hasHistorique) { $n[$options['histo-creation-column']] = $options['histo-date']; $n[$options['histo-createur-id-column']] = $options['histo-user-id']; $n[$options['histo-modification-column']] = $options['histo-date']; $n[$options['histo-modificateur-id-column']] = $options['histo-user-id']; } $this->insert($n); $result['insert']++; if ($options['return-insert-data']) { $insertedData = []; if (isset($n[$idCol])) { $insertedData[$idCol] = $n[$idCol]; if (isset($n[$options['id-column']])) { $insertedData[$options['id-column']] = $n[$options['id-column']]; } foreach ($key as $null => $kc) { $insertedData[$kc] = $n[$kc]; Loading Loading
src/Data/DataManager.php +3 −3 Original line number Diff line number Diff line Loading @@ -103,9 +103,9 @@ class DataManager $config['key'] ?? $idCol, $config['options'] ?? [] ); if ($result['insert'] + $result['update'] + $result['delete'] > 0) { if ($result['insert'] + $result['update'] + $result['delete'] + ($result['undelete'] ?? 0) + ($result['soft-delete'] ?? 0) > 0) { $msg = str_pad($table, 31, ' '); $msg .= 'Insert: ' . $result['insert'] . ', Update: ' . $result['update'] . ', Delete: ' . $result['delete']; $msg .= 'Insert: ' . ($result['insert'] + ($result['undelete'] ?? 0)) . ', Update: ' . $result['update'] . ', Delete: ' . ($result['delete'] + ($result['soft-delete'] ?? 0)); $this->getBdd()->logMsg($msg); } } Loading
src/Table.php +145 −70 Original line number Diff line number Diff line Loading @@ -125,7 +125,7 @@ class Table 'case' => -1, 'types' => $this->makeTypesOptions(), 'key' => null, 'orderBy' => '', 'order-by' => '', ]; $options = array_merge($defaultOptions, $options); Loading @@ -146,8 +146,8 @@ class Table $params = []; $sql .= $this->makeWhere($where, $options, $params); if ($options['orderBy']) { $sql .= ' ORDER BY ' . $options['orderBy']; if ($options['order-by']) { $sql .= ' ORDER BY ' . $options['order-by']; } $select = $this->getBdd()->select($sql, $params, $options); Loading Loading @@ -418,46 +418,104 @@ class Table private function mergeDiff(array &$o, array &$n, array &$options): array { $diff = []; foreach ($o as $c => $ov) { if ($options['has-historique']) { if ($c == $options['histo-creation-column'] || $c == $options['histo-createur-id-column'] || $c == $options['histo-modification-column'] || $c == $options['histo-modificateur-id-column'] || $c == $options['histo-destruction-column'] || $c == $options['histo-destructeur-id-column'] ) { continue; // on ignore les colonnes relatives aux historiques } } $newc = $n[$c] ?? null; $oldc = $o[$c] ?? null; if ($newc instanceof \DateTime) $newc = $newc->format('Y-m-d H:i:s'); if ($oldc instanceof \DateTime) $oldc = $oldc->format('Y-m-d H:i:s'); if ($newc != $oldc && array_key_exists($c, $n) && $c != $options['id-column']) { $ok = empty($options['update-cols']); // OK par défaut si une liste n'a pas été établie manuellement if (in_array($c, $options['update-cols'])) $ok = true; if (in_array($c, $options['update-ignore-cols'])) $ok = false; if (in_array($c, $options['update-only-null']) && $oldc !== null) $ok = false; if ($ok) { if ((is_float($newc) || is_double($newc)) && (is_float($oldc) || is_double($oldc))) { // nécessaire à cause des pb de précision des float/doubles en PHP : // dans ce cas, on considère quand même que les 2 chiffres sont identiques => diff négligeable $ok = (abs($newc - $oldc) > 0.0000000001); } } if ($ok) { $diff[$c] = $n[$c]; } } } return $diff; } public function merge(array $data, $key, array $options = []): array { $result = ['insert' => 0, 'update' => 0, 'delete' => 0, 'soft-delete' => 0]; $ddl = $this->getDdl(); $bdd = $this->getBdd(); /* Initialisation */ /* Initialisation des options */ $hasHistorique = $this->hasHistorique(); $defaultOptions = [ 'custom-select' => null, 'where' => null, 'key' => $key, 'delete' => true, 'soft-delete' => false, 'soft-delete' => true, 'undelete' => true, 'insert' => true, 'update' => true, 'return-insert-data' => false, 'update-cols' => [], 'update-ignore-cols' => [], 'update-only-null' => [], 'id-column' => $bdd->getOption(Bdd::OPTION_ID_COLUMN), 'has-historique' => $hasHistorique, 'histo-user-id' => null, 'histo-date' => new \DateTime(), ]; if ($hasHistorique) { $defaultOptions['histo-user-id'] = $bdd->getHistoUserId(); $defaultOptions['histo-creation-column'] = $bdd->getOption(Bdd::OPTION_HISTO_CREATION_COLUMN); $defaultOptions['histo-createur-id-column'] = $bdd->getOption(Bdd::OPTION_HISTO_CREATEUR_ID_COLUMN); $defaultOptions['histo-modification-column'] = $bdd->getOption(Bdd::OPTION_HISTO_MODIFICATION_COLUMN); $defaultOptions['histo-modificateur-id-column'] = $bdd->getOption(Bdd::OPTION_HISTO_MODIFICATEUR_ID_COLUMN); $defaultOptions['histo-destruction-column'] = $bdd->getOption(Bdd::OPTION_HISTO_DESTRUCTION_COLUMN); $defaultOptions['histo-destructeur-id-column'] = $bdd->getOption(Bdd::OPTION_HISTO_DESTRUCTEUR_ID_COLUMN); $result = ['insert' => 0, 'update' => 0, 'delete' => 0, 'soft-delete' => 0, 'undelete' => 0]; } else { $result = ['insert' => 0, 'update' => 0, 'delete' => 0]; } $options = array_merge($defaultOptions, $options); if ($options['return-insert-data']) { $result['insert-data'] = []; } $ddl = $this->getDdl(); $bdd = $this->getBdd(); $histoUserId = $bdd->getHistoUserId(); $hasHistorique = $this->hasHistorique(); $idCol = $this->getBdd()->getOption(Bdd::OPTION_ID_COLUMN); if (empty($options['where']) && $hasHistorique) { $histoDestructionCol = $this->getBdd()->getOption(Bdd::OPTION_HISTO_DESTRUCTION_COLUMN); $options['where'] = $histoDestructionCol . ' IS NULL'; if ($hasHistorique && (null === $options['histo-user-id'])) { throw new \Exception('L\'id de l\'utilisateur pour la gestion des historiques doit être fourni en configuration ou bien en option'); } /* Mise en forme des nouvelles données */ $new = []; foreach ($data as $d) { foreach ($data as $i => $d) { foreach ($d as $c => $v) { if (isset($ddl['columns'][$c])) { if (isset($options['columns'][$c]['transformer'])) { Loading @@ -482,73 +540,90 @@ class Table $selOptions['fetch'] = Bdd::FETCH_EACH; $stmt = $this->select($options['where'], $selOptions); while ($o = $stmt->next()) { // récupération de k et n // récupération de k et n & on détermine quelle action effectuer $k = $this->makeKey($o, $key); $action = null; // rien à faire par défaut if (array_key_exists($k, $new)) { $n = $new[$k]; unset($new[$k]); } else { $n = null; unset($new[$k]); // on retire de suite du tableau $diff = $this->mergeDiff($o, $n, $options); if (!empty($diff)) { if ($options['update']) { $action = 'update'; } if (empty($n) && $options['soft-delete'] && $hasHistorique && $histoUserId !== null) { // SOFT DELETE $histoDestructionCol = $this->getBdd()->getOption(Bdd::OPTION_HISTO_DESTRUCTION_COLUMN); $histoDestructeurIdCol = $this->getBdd()->getOption(Bdd::OPTION_HISTO_DESTRUCTEUR_ID_COLUMN); //On ne delete pas mais on historise $n = $o; $n[$histoDestructionCol] = new \DateTime(); $n[$histoDestructeurIdCol] = $histoUserId; $this->update($n, $this->makeKeyArray($o, $k)); $result['soft-delete']++; } elseif (empty($n) && !$options['soft-delete']) { // DELETE if ($options['delete']) { $this->delete($this->makeKeyArray($o, $key)); $result['delete']++; } elseif ($hasHistorique) { if ($options['undelete'] && array_key_exists($options['histo-destruction-column'], $o) && $o[$options['histo-destruction-column']]) { $action = 'undelete'; } } elseif ($options['update']) { // UPDATE si différent!! $toUpdate = []; foreach ($o as $c => $ov) { $newc = $n[$c] ?? null; $oldc = $o[$c] ?? null; if ($newc instanceof \DateTime) $newc = $newc->format('Y-m-d H:i:s'); if ($oldc instanceof \DateTime) $oldc = $oldc->format('Y-m-d H:i:s'); if ($newc != $oldc && array_key_exists($c, $n) && $c != $idCol) { $ok = empty($options['update-cols']); // OK par défaut si une liste n'a pas été établie manuellement if (in_array($c, $options['update-cols'])) $ok = true; if (in_array($c, $options['update-ignore-cols'])) $ok = false; if (in_array($c, $options['update-only-null']) && $oldc !== null) $ok = false; if ($ok) { if ((is_float($newc) || is_double($newc)) && (is_float($oldc) || is_double($oldc))) { if (abs($newc - $oldc) > 0.0000000001) { // nécessaire à cause des pb de précision des float/doubles en PHP : // dans ce cas, on considère quand même que les 2 chiffres sont identiques $toUpdate[$c] = $n[$c]; } } else { $toUpdate[$c] = $n[$c]; if ($options['has-historique']) { if (null === $o[$options['histo-destruction-column']]) { // opération de soft-delete if ($options['soft-delete']) { $action = 'soft-delete'; } } } else { // opération de delete if ($options['delete']) { $action = 'delete'; } } } if (!empty($toUpdate)) { // on effectue l'action if ($action) { switch ($action) { case 'delete': $this->delete($this->makeKeyArray($o, $key)); break; case 'soft-delete': $toUpdate = [ $options['histo-destruction-column'] => $options['histo-date'], $options['histo-destructeur-id-column'] => $options['histo-user-id'], ]; $this->update($toUpdate, $this->makeKeyArray($o, $key), ['ddl' => $ddl]); $result['update']++; break; case 'undelete': $toUpdate = [ $options['histo-destruction-column'] => null, $options['histo-destructeur-id-column'] => null, ]; $this->update($toUpdate, $this->makeKeyArray($o, $key), ['ddl' => $ddl]); break; case 'update': $toUpdate = $diff; if ($hasHistorique) { $toUpdate[$options['histo-modification-column']] = $options['histo-date']; $toUpdate[$options['histo-modificateur-id-column']] = $options['histo-user-id']; } $this->update($toUpdate, $this->makeKeyArray($o, $key), ['ddl' => $ddl]); break; } $result[$action]++; } } /* Pour finir, insertion de tous les nouveaux éléments */ foreach ($new as $k => $n) { if ($options['insert']) { if ($hasHistorique) { $n[$options['histo-creation-column']] = $options['histo-date']; $n[$options['histo-createur-id-column']] = $options['histo-user-id']; $n[$options['histo-modification-column']] = $options['histo-date']; $n[$options['histo-modificateur-id-column']] = $options['histo-user-id']; } $this->insert($n); $result['insert']++; if ($options['return-insert-data']) { $insertedData = []; if (isset($n[$idCol])) { $insertedData[$idCol] = $n[$idCol]; if (isset($n[$options['id-column']])) { $insertedData[$options['id-column']] = $n[$options['id-column']]; } foreach ($key as $null => $kc) { $insertedData[$kc] = $n[$kc]; Loading