From 1192ed1635bd723f6cd31ab5c2bd4288bff6d36d Mon Sep 17 00:00:00 2001 From: Rudi Servo Date: Sun, 6 Aug 2023 20:32:06 +0000 Subject: [PATCH] Fixed Phalcon\Mvc\Model\Metadata::initialize behaviour [#16393] --- CHANGELOG-5.0.md | 5 + phalcon/Mvc/Model/MetaData.zep | 190 +++++++++--------- .../MetaData/Adapter/ReadMetadataCest.php | 9 +- 3 files changed, 107 insertions(+), 97 deletions(-) diff --git a/CHANGELOG-5.0.md b/CHANGELOG-5.0.md index 23084bcec2..f7e275f54e 100644 --- a/CHANGELOG-5.0.md +++ b/CHANGELOG-5.0.md @@ -5,9 +5,14 @@ ### Added - Added `Phalcon\Mvc\Model::appendMessagedFrom` for code consistency and to add messages from another another model. [#16391](https://github.com/phalcon/cphalcon/issues/16391) - Added `Phalcon\Autoload\Loader::isRegistered` for debugging purposes [#16391](https://github.com/phalcon/cphalcon/issues/16391) +- Added `Phalcon\Mvc\Model\Metadata::initializeMetadata` [#16393] (https://github.com/phalcon/cphalcon/issues/16393) +- Added `Phalcon\Mvc\Model\Metadata::initializeMetadata` [#16393] (https://github.com/phalcon/cphalcon/issues/16393) +- Added `Phalcon\Mvc\Model\Metadata::getMetaDataUniqueKey` [#16393] (https://github.com/phalcon/cphalcon/issues/16393) +- Added `Phalcon\Mvc\Model\Metadata::getColumnMapUniqueKey` [#16393] (https://github.com/phalcon/cphalcon/issues/16393) ### Changed - Refactored `Phalcon\Mvc\Model::doLowUpdate` and `Phalcon\Mvc\Model::postSaveRelatedRecords` for better code logic and a clearer seperation of behaviour although it lead to partially repeated code.[#16391](https://github.com/phalcon/cphalcon/issues/16391) +- Cleaned `Phalcon\Mvc\Model\Metadata::initialize` [#16393] (https://github.com/phalcon/cphalcon/issues/16393) ### Fixed diff --git a/phalcon/Mvc/Model/MetaData.zep b/phalcon/Mvc/Model/MetaData.zep index 42c7fc55dd..6e0042998d 100644 --- a/phalcon/Mvc/Model/MetaData.zep +++ b/phalcon/Mvc/Model/MetaData.zep @@ -484,10 +484,10 @@ abstract class MetaData implements InjectionAwareInterface, MetaDataInterface let columnMap = this->getReverseColumnMap(model); if typeof columnMap == "array" { - return isset columnMap[attribute]; + return isset(columnMap[attribute]); } - return isset this->readMetaData(model)[self::MODELS_DATA_TYPES][attribute]; + return isset(this->readMetaData(model)[self::MODELS_DATA_TYPES][attribute]); } /** @@ -525,21 +525,16 @@ abstract class MetaData implements InjectionAwareInterface, MetaDataInterface */ final public function readColumnMap( model) -> array | null { - var keyName, data; + var keyName; if !globals_get("orm.column_renaming") { return null; } - - let keyName = get_class_lower(model); - - if !fetch data, this->columnMap[keyName] { - this->initialize(model, null, null, null); - - let data = this->columnMap[keyName]; + let keyName = this->getColumnMapUniqueKey(model); + if keyName !== null { + return this->columnMap[keyName]; } - - return data; + return null; } /** @@ -556,23 +551,16 @@ abstract class MetaData implements InjectionAwareInterface, MetaDataInterface */ final public function readColumnMapIndex( model, int index) { - var keyName, columnMapModel, map; + var keyName; if !globals_get("orm.column_renaming") { return null; } - - let keyName = get_class_lower(model); - - if !fetch columnMapModel, this->columnMap[keyName] { - this->initialize(model, null, null, null); - - let columnMapModel = this->columnMap[keyName]; + let keyName = this->getColumnMapUniqueKey(model); + if keyName !== null { + return this->columnMap[keyName][index]; } - - fetch map, columnMapModel[index]; - - return map; + return null; } /** @@ -586,24 +574,14 @@ abstract class MetaData implements InjectionAwareInterface, MetaDataInterface * ); *``` */ - final public function readMetaData( model) -> array + final public function readMetaData( model) -> array | null { - var source, schema; - string key; - - let source = model->getSource(), - schema = model->getSchema(); - - /* - * Unique key for meta-data is created using class-name-schema-source - */ - let key = get_class_lower(model) . "-" . schema . source; - - if !isset this->metaData[key] { - this->initialize(model, key, source, schema); + var key; + let key = this->getMetaDataUniqueKey(model); + if key !== null { + return this->metaData[key]; } - - return this->metaData[key]; + return null; } /** @@ -618,24 +596,14 @@ abstract class MetaData implements InjectionAwareInterface, MetaDataInterface * ); *``` */ - final public function readMetaDataIndex( model, int index) + final public function readMetaDataIndex( model, int index) -> array | null { - var source, schema; - string key; - - let source = model->getSource(), - schema = model->getSchema(); - - /* - * Unique key for meta-data is created using class-name-schema-source - */ - let key = get_class_lower(model) . "-" . schema . source; - - if !isset this->metaData[key][index] { - this->initialize(model, key, source, schema); + var key; + let key = this->getMetaDataUniqueKey(model); + if key !== null { + return this->metaData[key][index]; } - - return this->metaData[key][index]; + return null; } /** @@ -766,44 +734,36 @@ abstract class MetaData implements InjectionAwareInterface, MetaDataInterface */ final public function writeMetaDataIndex( model, int index, var data) -> void { - var source, schema; - string key; - - if unlikely (typeof data != "array" && typeof data != "string" && typeof data != "boolean") { - throw new Exception("Invalid data for index"); - } - - let source = model->getSource(), - schema = model->getSchema(); - - /* - * Unique key for meta-data is created using class-name-schema-table - */ - let key = get_class_lower(model) . "-" . schema . source; - - if !isset this->metaData[key] { - this->initialize(model, key, source, schema); + var key; + let key = this->getMetaDataUniqueKey(model); + if key !== null { + let this->metaData[key][index] = data; } + } - let this->metaData[key][index] = data; + /** + * Initialize old behaviour for compatability + */ + final protected function initialize( model, var key, var table, var schema) + { + this->initializeMetaData(model, key); + this->initializeColumnMap(model, key); } /** * Initialize the metadata for certain table */ - final protected function initialize( model, var key, var table, var schema) + final protected function initializeMetaData( model, var key) -> bool { - var strategy, className, metaData, data, modelMetadata, modelColumnMap, - container, keyName; + var strategy, metaData, data, modelMetadata, container; string prefixKey; - let strategy = null, - className = get_class(model); + let strategy = null; if key !== null { let metaData = this->metaData; - if !isset metaData[key] { + if false === isset(metaData[key]) { /** * The meta-data is read from the adapter always if not available in metaData property */ @@ -821,7 +781,7 @@ abstract class MetaData implements InjectionAwareInterface, MetaDataInterface if unlikely typeof modelMetadata != "array" { throw new Exception( - "Invalid meta-data for model " . className + "Invalid meta-data for model " . get_class(model) ); } } else { @@ -847,53 +807,61 @@ abstract class MetaData implements InjectionAwareInterface, MetaDataInterface this->{"write"}(prefixKey, modelMetadata); } } + return true; } + return false; + } + /** + * Initialize ColumnMap for a certain table + */ + final protected function initializeColumnMap( model, key) -> bool + { + var strategy, data, modelColumnMap, container; + string prefixKey; /** * Check for a column map, store in columnMap in order and reversed order */ if !globals_get("orm.column_renaming") { - return null; + return false; } - let keyName = strtolower(className); - - if isset this->columnMap[keyName] { - return null; + if true === isset(this->columnMap[key]) { + return false; } /** * Create the map key name * Check if the meta-data is already in the adapter */ - let prefixKey = "map-" . keyName, + let prefixKey = "map-" . key, data = this->{"read"}(prefixKey); if data !== null { - let this->columnMap[keyName] = data; + let this->columnMap[key] = data; - return null; + return false; } /** * Get the meta-data extraction strategy */ - if typeof strategy != "object" { - let container = this->getDI(), - strategy = this->getStrategy(); - } + + let container = this->getDI(), + strategy = this->getStrategy(); /** * Get the meta-data * Update the column map locally */ let modelColumnMap = strategy->getColumnMaps(model, container), - this->columnMap[keyName] = modelColumnMap; + this->columnMap[key] = modelColumnMap; /** * Write the data to the adapter */ this->{"write"}(prefixKey, modelColumnMap); + return true; } /** @@ -928,4 +896,38 @@ abstract class MetaData implements InjectionAwareInterface, MetaDataInterface return value; } + + /** + * Returns a MetaData Unique key for meta-data is created using className + * + * @return string + */ + public final function getMetaDataUniqueKey( model) -> string | null + { + string key; + let key = get_class_lower(model); + if false === isset(this->metaData[key]) { + if false === this->initializeMetaData(model, key) { + return null; + } + } + return key; + } + + /** + * Returns a ColumnMap Unique key for meta-data is created using className + * + * @return string + */ + public final function getColumnMapUniqueKey( model) -> string | null + { + string key; + let key = get_class_lower(model); + if false === isset(this->columnMap[key]) { + if false === this->initializeColumnMap(model, key) { + return null; + } + } + return key; + } } diff --git a/tests/database/Mvc/Model/MetaData/Adapter/ReadMetadataCest.php b/tests/database/Mvc/Model/MetaData/Adapter/ReadMetadataCest.php index 11d446c877..78d57e450b 100644 --- a/tests/database/Mvc/Model/MetaData/Adapter/ReadMetadataCest.php +++ b/tests/database/Mvc/Model/MetaData/Adapter/ReadMetadataCest.php @@ -87,6 +87,7 @@ public function mvcModelMetadataGetAttributesRedis( 'photo_id', ]; $actual = $metadata->getAttributes($model); + $columnMap = $metadata->getColumnMap($model); $I->assertEquals($expected, $actual); $model = new AlbumPhoto(); @@ -97,6 +98,7 @@ public function mvcModelMetadataGetAttributesRedis( 'position', ]; $actual = $metadata->getAttributes($model); + $columnMap = $metadata->getColumnMap($model); $I->assertEquals($expected, $actual); $model = new Photo(); @@ -120,6 +122,7 @@ public function mvcModelMetadataGetAttributesRedis( 'wins', ]; $actual = $metadata->getAttributes($model); + $columnMap = $metadata->getColumnMap($model); $I->assertEquals($expected, $actual); $service = $adapter->getAdapter(); @@ -165,7 +168,7 @@ private function getExamples(): array private function getKeyData(): array { return [ - 'meta-phalcon\tests\fixtures\models\albumphoto-album_photo' => [ + 'meta-phalcon\tests\fixtures\models\albumphoto' => [ 0 => [ 'id', 'photo_id', @@ -220,7 +223,7 @@ private function getKeyData(): array 0 => null, 1 => null, ], - 'meta-phalcon\tests\fixtures\models\photo-photo' => [ + 'meta-phalcon\tests\fixtures\models\photo' => [ 0 => [ 'id', 'date_uploaded', @@ -345,7 +348,7 @@ private function getKeyData(): array 0 => null, 1 => null, ], - 'meta-phalcon\tests\fixtures\models\album-album' => [ + 'meta-phalcon\tests\fixtures\models\album' => [ 0 => [ 'id', 'name',