22
33 namespace Quellabs \ObjectQuel \Persistence ;
44
5- use Quellabs \ObjectQuel \Annotations \Orm \Column ;
65 use Quellabs \ObjectQuel \DatabaseAdapter \DatabaseAdapter ;
76 use Quellabs \ObjectQuel \EntityStore ;
87 use Quellabs \ObjectQuel \OrmException ;
@@ -20,25 +19,25 @@ class UpdatePersister {
2019 * Reference to the UnitOfWork that manages persistence operations
2120 * This is a duplicate of the parent's unitOfWork property with a different naming convention
2221 */
23- protected UnitOfWork $ unitOfWork ;
22+ private UnitOfWork $ unitOfWork ;
2423
2524 /**
2625 * The EntityStore that maintains metadata about entities and their mappings
2726 * Used to retrieve information about entity tables, columns and identifiers
2827 */
29- protected EntityStore $ entityStore ;
28+ private EntityStore $ entityStore ;
3029
3130 /**
32- * Utility for handling entity property access and manipulation
33- * Provides methods to get and set entity properties regardless of their visibility
31+ * Database connection adapter used for executing SQL queries
32+ * Abstracts the underlying database system and provides a unified interface
3433 */
35- protected PropertyHandler $ propertyHandler ;
34+ private DatabaseAdapter $ connection ;
3635
3736 /**
38- * Database connection adapter used for executing SQL queries
39- * Abstracts the underlying database system and provides a unified interface
37+ * Handles values with @Orm\Version annotations
38+ * @var VersionValueHandler
4039 */
41- protected DatabaseAdapter $ connection ;
40+ private VersionValueHandler $ valueHandler ;
4241
4342 /**
4443 * UpdatePersister constructor
@@ -47,8 +46,8 @@ class UpdatePersister {
4746 public function __construct (UnitOfWork $ unitOfWork ) {
4847 $ this ->unitOfWork = $ unitOfWork ;
4948 $ this ->entityStore = $ unitOfWork ->getEntityStore ();
50- $ this ->propertyHandler = $ unitOfWork ->getPropertyHandler ();
5149 $ this ->connection = $ unitOfWork ->getConnection ();
50+ $ this ->valueHandler = new VersionValueHandler ($ unitOfWork ->getConnection (), $ unitOfWork ->getEntityStore (), $ unitOfWork , $ unitOfWork ->getPropertyHandler ());
5251 }
5352
5453 /**
@@ -60,7 +59,7 @@ public function __construct(UnitOfWork $unitOfWork) {
6059 public function persist (object $ entity ): void {
6160 // Retrieve basic information needed for the update
6261 // Get the table name where the entity is stored
63- $ tableName = $ this ->escapeIdentifier ($ this ->entityStore ->getOwningTable ($ entity ));
62+ $ tableName = $ this ->valueHandler -> escapeIdentifier ($ this ->entityStore ->getOwningTable ($ entity ));
6463
6564 // Serialize the entity's current state into an array of column name => value pairs
6665 $ serializedEntity = $ this ->unitOfWork ->getSerializer ()->serialize ($ entity );
@@ -117,7 +116,7 @@ public function persist(object $entity): void {
117116 }
118117
119118 // Fetch version values from the database (if any)
120- $ fetchedDatetimeValues = $ this ->fetchUpdatedVersionValues (
119+ $ fetchedDatetimeValues = $ this ->valueHandler -> fetchUpdatedVersionValues (
121120 $ tableName ,
122121 $ versionColumns ,
123122 $ primaryKeyColumnNames ,
@@ -126,16 +125,7 @@ public function persist(object $entity): void {
126125
127126 // Update the entity with the new version values so the in-memory object
128127 // matches the database state and can be used for subsequent operations
129- $ this ->updateEntityVersionValues ($ entity , $ fetchedDatetimeValues );
130- }
131-
132- /**
133- * Escapes a database identifier (table or column name)
134- * @param string $identifier The identifier to escape
135- * @return string The escaped identifier wrapped in backticks
136- */
137- protected function escapeIdentifier (string $ identifier ): string {
138- return '` ' . str_replace ('` ' , '`` ' , $ identifier ) . '` ' ;
128+ $ this ->valueHandler ->updateEntityVersionValues ($ entity , $ fetchedDatetimeValues );
139129 }
140130
141131 /**
@@ -174,7 +164,7 @@ protected function buildVersionSetClause(array $versionColumns, array &$params):
174164
175165 // Process each version column according to its type
176166 foreach ($ versionColumns as $ property => $ versionColumn ) {
177- $ columnName = $ this ->escapeIdentifier ($ versionColumn ['name ' ]);
167+ $ columnName = $ this ->valueHandler -> escapeIdentifier ($ versionColumn ['name ' ]);
178168
179169 switch ($ versionColumn ['column ' ]->getType ()) {
180170 case 'integer ' :
@@ -215,7 +205,7 @@ protected function buildFieldsSetClause(array $changedFields, array &$params): a
215205 $ setClauseParts = [];
216206 foreach ($ changedFields as $ columnName => $ value ) {
217207 $ paramName = "field_ {$ columnName }" ;
218- $ setClauseParts [] = $ this ->escapeIdentifier ($ columnName ) . "=: {$ paramName }" ;
208+ $ setClauseParts [] = $ this ->valueHandler -> escapeIdentifier ($ columnName ) . "=: {$ paramName }" ;
219209 $ params [$ paramName ] = $ value ;
220210 }
221211
@@ -239,7 +229,7 @@ protected function buildWhereClause(array $primaryKeyColumnNames, array $primary
239229 // This includes primary key columns to identify the record
240230 foreach ($ primaryKeyColumnNames as $ columnName ) {
241231 $ paramName = "pk_ {$ columnName }" ;
242- $ whereClauseParts [] = $ this ->escapeIdentifier ($ columnName ) . "=: {$ paramName }" ;
232+ $ whereClauseParts [] = $ this ->valueHandler -> escapeIdentifier ($ columnName ) . "=: {$ paramName }" ;
243233 $ params [$ paramName ] = $ primaryKeyValues [$ columnName ];
244234 }
245235
@@ -249,7 +239,7 @@ protected function buildWhereClause(array $primaryKeyColumnNames, array $primary
249239 foreach ($ versionColumns as $ property => $ versionColumn ) {
250240 $ columnName = $ versionColumn ['name ' ];
251241 $ paramName = "where_version_ {$ columnName }" ;
252- $ whereClauseParts [] = $ this ->escapeIdentifier ($ columnName ) . "=: {$ paramName }" ;
242+ $ whereClauseParts [] = $ this ->valueHandler -> escapeIdentifier ($ columnName ) . "=: {$ paramName }" ;
253243
254244 // Use the original version value from our snapshot
255245 $ params [$ paramName ] = $ originalData [$ columnName ];
@@ -258,66 +248,4 @@ protected function buildWhereClause(array $primaryKeyColumnNames, array $primary
258248 // Combine all WHERE clause parts
259249 return implode (" AND " , $ whereClauseParts );
260250 }
261-
262- /**
263- * Fetches version values back from the database after update
264- * Required to ensure in-memory entity matches database state exactly
265- * @param string $tableName Escaped table name
266- * @param array $versionColumns All version column metadata
267- * @param array $primaryKeyColumnNames Primary key column names
268- * @param array $primaryKeyValues Primary key values
269- * @return array Fetched version values as property_name => value pairs
270- */
271- protected function fetchUpdatedVersionValues (string $ tableName , array $ versionColumns , array $ primaryKeyColumnNames , array $ primaryKeyValues ): array {
272- // Do nothing when no version columns exist
273- if (empty ($ versionColumns )) {
274- return [];
275- }
276-
277- // Build a SELECT query to retrieve all version columns
278- $ selectColumns = array_map (fn ($ vc ) => $ this ->escapeIdentifier ($ vc ['name ' ]), $ versionColumns );
279-
280- // Build WHERE clause using only primary keys to identify the row we just updated
281- $ whereClauseParts = [];
282- $ selectParams = [];
283-
284- foreach ($ primaryKeyColumnNames as $ columnName ) {
285- $ paramName = "pk_ {$ columnName }" ;
286- $ whereClauseParts [] = $ this ->escapeIdentifier ($ columnName ) . "=: {$ paramName }" ;
287- $ selectParams [$ paramName ] = $ primaryKeyValues [$ columnName ];
288- }
289-
290- // Build select query
291- $ selectSql = "SELECT " . implode (", " , $ selectColumns ) . " FROM {$ tableName } WHERE " . implode (" AND " , $ whereClauseParts );
292-
293- // Execute select query
294- $ result = $ this ->connection ->Execute ($ selectSql , $ selectParams );
295-
296- // Collect fetched datetime values
297- if (!$ result || !($ row = $ result ->fetchAssoc ())) {
298- return [];
299- }
300-
301- return array_map (function ($ vc ) use ($ row ) {
302- return $ row [$ vc ['name ' ]];
303- }, $ versionColumns );
304- }
305-
306- /**
307- * Updates the entity with new version values from the database
308- * @param object $entity The entity to update
309- * @param array $fetchedValues Fetched version values as property_name => value pairs
310- * @return void
311- */
312- protected function updateEntityVersionValues (object $ entity , array $ fetchedValues ): void {
313- if (empty ($ fetchedValues )) {
314- return ;
315- }
316-
317- $ annotations = $ this ->entityStore ->getAnnotations ($ entity , Column::class);
318- foreach ($ fetchedValues as $ property => $ newValue ) {
319- $ normalizedValue = $ this ->unitOfWork ->getSerializer ()->normalizeValue ($ annotations [$ property ], $ newValue );
320- $ this ->propertyHandler ->set ($ entity , $ property , $ normalizedValue );
321- }
322- }
323251 }
0 commit comments