From 8e9f31c29e55ced3ecf38ff19d6957b295bea5b5 Mon Sep 17 00:00:00 2001 From: rotimi Date: Mon, 5 Feb 2024 01:55:35 -0700 Subject: [PATCH] PHP 8.1 Refactorings --- src/GDAO/Model.php | 21 +++--- src/GDAO/Model/CollectionInterface.php | 11 ++- src/GDAO/Model/RecordInterface.php | 2 +- ...alueNotRetrievableAfterInsertException.php | 6 -- tests/ModelTest.php | 68 ++++++------------- 5 files changed, 45 insertions(+), 63 deletions(-) delete mode 100644 src/GDAO/ModelPrimaryColValueNotRetrievableAfterInsertException.php diff --git a/src/GDAO/Model.php b/src/GDAO/Model.php index cc08976..83c92ee 100644 --- a/src/GDAO/Model.php +++ b/src/GDAO/Model.php @@ -12,13 +12,12 @@ * the future. * * @author Rotimi Adegbamigbe - * @copyright (c) 2023, Rotexsoft + * @copyright (c) 2024, Rotexsoft */ abstract class Model implements \Stringable { /** * Name of the primary key column in the db table associated with this model - * Default value is null. * * This is a REQUIRED field & must be properly set by consumers of this class * @@ -1478,11 +1477,6 @@ public abstract function getPDO(): \PDO; /** * Insert one row to the model table with the specified values. * - * An exception (\GDAO\ModelPrimaryColValueNotRetrievableAfterInsertException) - * should be thrown if the primary key col is auto-incrementing and the - * auto-incremented primary-key value of the inserted record could not be - * retrieved (in this case the insert could have still been successful). - * * An exception (\GDAO\ModelInvalidInsertValueSuppliedException) should be * thrown if any of the values supplied for insertion is not a boolean, NULL, * number or string value (this should happen before even attempting to @@ -1507,7 +1501,6 @@ public abstract function getPDO(): \PDO; * * @throws \PDOException * @throws \GDAO\ModelInvalidInsertValueSuppliedException - * @throws \GDAO\ModelPrimaryColValueNotRetrievableAfterInsertException */ public abstract function insert(array $data_2_insert = []): bool|array; @@ -1611,9 +1604,13 @@ public abstract function updateMatchingDbTableRows( * with the latest value of the $this->updated_timestamp_column_name field * from the database if $this->updated_timestamp_column_name !== null * + * An exception (\GDAO\ModelInvalidInsertValueSuppliedException) should be + * thrown if $record->getModel()->getTableName() !== $this->getTableName(). + * * @return $this * * @throws \PDOException + * @throws \GDAO\ModelInvalidUpdateValueSuppliedException */ public abstract function updateSpecifiedRecord(\GDAO\Model\RecordInterface $record): static; @@ -1640,6 +1637,13 @@ public function getDsn(): string { return $this->dsn; } + /** + * Consumers of implementations of this package should only call + * this method when debugging applications. Code shipped to production + * environments should not have calls to this method in them in order + * not to leak the database password into exception stack traces if + * such applications end up displaying exceptions to their end users. + */ public function getPasswd(): string { return $this->passwd; @@ -1718,6 +1722,7 @@ public function getTableColNames(): array { if (is_string($key)) { $keys_2_return[] = $key; + } elseif (is_string($potential_col_metadata)) { $keys_2_return[] = $potential_col_metadata; diff --git a/src/GDAO/Model/CollectionInterface.php b/src/GDAO/Model/CollectionInterface.php index fb907c7..38ea362 100644 --- a/src/GDAO/Model/CollectionInterface.php +++ b/src/GDAO/Model/CollectionInterface.php @@ -8,7 +8,7 @@ * Represents a collection of \GDAO\Model\RecordInterface objects. * * @author Rotimi Adegbamigbe - * @copyright (c) 2023, Rotexsoft + * @copyright (c) 2024, Rotexsoft * */ interface CollectionInterface extends \ArrayAccess, \Countable, \IteratorAggregate, \Stringable @@ -226,4 +226,13 @@ public function preSaveAll(bool $group_inserts_together=false): void; * @param bool $group_inserts_together exact value passed to $this->saveAll($group_inserts_together) */ public function postSaveAll(bool|array $save_all_result, bool $group_inserts_together=false): void; + + /** + * Only removes a record from the collection, but DOESN'T delete the record's data from the db + * If the specified record doesn't exist in the collection, it does not need to throw an exception + * You should call the record object's delete method if you also want the data deleted from the db + * + * @param \GDAO\Model\RecordInterface $record Record to be removed from the collection + */ + public function removeRecord(\GDAO\Model\RecordInterface $record): static; } diff --git a/src/GDAO/Model/RecordInterface.php b/src/GDAO/Model/RecordInterface.php index 4842bbe..fab8bd2 100644 --- a/src/GDAO/Model/RecordInterface.php +++ b/src/GDAO/Model/RecordInterface.php @@ -7,7 +7,7 @@ * * Contains a list of methods that Record classes must implement. * - * @copyright (c) 2023, Rotexsoft + * @copyright (c) 2024, Rotexsoft */ interface RecordInterface extends \ArrayAccess, \Countable, \IteratorAggregate, \Stringable { diff --git a/src/GDAO/ModelPrimaryColValueNotRetrievableAfterInsertException.php b/src/GDAO/ModelPrimaryColValueNotRetrievableAfterInsertException.php deleted file mode 100644 index 87efecf..0000000 --- a/src/GDAO/ModelPrimaryColValueNotRetrievableAfterInsertException.php +++ /dev/null @@ -1,6 +0,0 @@ -_mock_model_obj_with_no_db_connection = - new \ModelForTestingNonAbstractMethods('', '', '', [], '', ''); - - //////////////////////////////////////////////////////////////////////// - $this->_mock_model_obj_with_memory_sqlite_connection = - new \ModelForTestingNonAbstractMethods('', '', '', [], '', ''); - - $pdo = new \PDO("sqlite::memory:"); - $this->_mock_model_obj_with_memory_sqlite_connection->setPDO($pdo); - //////////////////////////////////////////////////////////////////////// } //////////////////////////////////////////////////////////////////////////////// @@ -92,16 +78,12 @@ public function testThatConstructorSetsModelPropertiesCorrectlyViaTheExtraoptsAr 'foreign_key_col_in_foreign_table' => 'output_id', 'primary_key_col_in_foreign_table' => 'output_id', 'foreign_models_class_name' => '\\VendorName\\PackageName\\ModelClassName', - 'foreign_modelscollection_class_name' => '\\VendorName\\PackageName\\ModelClassName\\Collection', - 'foreign_modelsrecord_class_name' => '\StdClass', - 'foreign_table_sql_params' => [ - 'cols' => ['project_outputs.deliverable_id', 'component_deliverables.deliverable', 'component_deliverables.component_id'], - 'where' => [ - [ 'col' => 'project_outputs.hidden_fiscal_year', 'op' => '=', 'val' => 16 ], - [ 'col' => 'project_outputs.deactivated', 'op' => '=', 'val' => 0], - [ 'col' => 'project_outputs.parent_id', 'op' => 'is-null'], - ], - ] + 'foreign_models_collection_class_name' => '\\VendorName\\PackageName\\ModelClassName\\Collection', + 'foreign_models_record_class_name' => '\StdClass', + 'sql_query_modifier' => function(object $selectObj): object { + // Do some stuff to / with $selectObj + return $selectObj; + }, ], ]; @@ -169,9 +151,9 @@ public function testThatConstructorSetsModelPropertiesCorrectlyViaTheExtraoptsAr $model->setPrimaryCol('new_pk_col') ->setTableName('new_table_name'); - $model_obj_as_array = $model->toArray(); // repopulate after calling setters - $this->assertTrue($model_obj_as_array['primary_col'] === 'new_pk_col', $msg); - $this->assertTrue($model_obj_as_array['table_name'] === 'new_table_name', $msg); + $model_obj_as_array2 = $model->toArray(); // repopulate after calling setters + $this->assertTrue($model_obj_as_array2['primary_col'] === 'new_pk_col', $msg); + $this->assertTrue($model_obj_as_array2['table_name'] === 'new_table_name', $msg); $this->assertTrue($model->getPrimaryCol() === 'new_pk_col', $msg); $this->assertTrue($model->getTableName() === 'new_table_name', $msg); } @@ -361,16 +343,12 @@ public function testThatGetRelationNamesWorksAsExpected(): void { 'foreign_key_col_in_foreign_table' => 'output_id', 'primary_key_col_in_foreign_table' => 'output_id', 'foreign_models_class_name' => '\\VendorName\\PackageName\\ModelClassName', - 'foreign_modelscollection_class_name' => '\\VendorName\\PackageName\\ModelClassName\\Collection', - 'foreign_modelsrecord_class_name' => '\StdClass', - 'foreign_table_sql_params' => [ - 'cols' => ['project_outputs.deliverable_id', 'component_deliverables.deliverable', 'component_deliverables.component_id'], - 'where' => [ - [ 'col' => 'project_outputs.hidden_fiscal_year', 'op' => '=', 'val' => 16 ], - [ 'col' => 'project_outputs.deactivated', 'op' => '=', 'val' => 0], - [ 'col' => 'project_outputs.parent_id', 'op' => 'is-null'], - ], - ] + 'foreign_models_collection_class_name' => '\\VendorName\\PackageName\\ModelClassName\\Collection', + 'foreign_models_record_class_name' => '\StdClass', + 'sql_query_modifier' => function(object $selectObj): object { + // Do some stuff to / with $selectObj + return $selectObj; + }, ], 'a_relation_name2'=> [ 'relation_type' => \GDAO\Model::RELATION_TYPE_HAS_MANY, @@ -379,16 +357,12 @@ public function testThatGetRelationNamesWorksAsExpected(): void { 'foreign_key_col_in_foreign_table' => 'output_id', 'primary_key_col_in_foreign_table' => 'output_id', 'foreign_models_class_name' => '\\VendorName\\PackageName\\ModelClassName', - 'foreign_modelscollection_class_name' => '\\VendorName\\PackageName\\ModelClassName\\Collection', - 'foreign_modelsrecord_class_name' => '\StdClass', - 'foreign_table_sql_params' => [ - 'cols' => ['project_outputs.deliverable_id', 'component_deliverables.deliverable', 'component_deliverables.component_id'], - 'where' => [ - [ 'col' => 'project_outputs.hidden_fiscal_year', 'op' => '=', 'val' => 16 ], - [ 'col' => 'project_outputs.deactivated', 'op' => '=', 'val' => 0], - [ 'col' => 'project_outputs.parent_id', 'op' => 'is-null'], - ], - ] + 'foreign_models_collection_class_name' => '\\VendorName\\PackageName\\ModelClassName\\Collection', + 'foreign_models_record_class_name' => '\StdClass', + 'sql_query_modifier' => function(object $selectObj): object { + // Do some stuff to / with $selectObj + return $selectObj; + }, ], ];