From 8c3fbc869d9e31ff4013099138d86f64c9d1c7af Mon Sep 17 00:00:00 2001 From: Luke Towers Date: Mon, 21 Nov 2022 00:30:29 -0600 Subject: [PATCH 1/7] Improve support for multiple database connections Use the parent model's connection when calling makeRelation( ) and call makeRelation from the deferred binding logic to more closely mirror Laravel's functionality. --- src/Database/Concerns/HasRelationships.php | 29 ++++++++++------------ src/Database/Traits/DeferredBinding.php | 3 +-- 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/src/Database/Concerns/HasRelationships.php b/src/Database/Concerns/HasRelationships.php index c79e63e1e..aa9b599f1 100644 --- a/src/Database/Concerns/HasRelationships.php +++ b/src/Database/Concerns/HasRelationships.php @@ -1,19 +1,20 @@ getRelationTypeDefinition($type, $name) !== null) { @@ -234,11 +233,9 @@ public function getRelationType($name) } /** - * Returns a relation class object - * @param string $name Relation name - * @return \Winter\Storm\Database\Relations\Relation|null + * Returns a new instance of a related model */ - public function makeRelation($name) + public function makeRelation(string $name): ?Model { $relationType = $this->getRelationType($name); $relation = $this->getRelationDefinition($name); @@ -248,7 +245,7 @@ public function makeRelation($name) } $relationClass = $relation[0]; - return new $relationClass(); + return $this->newRelatedInstance($relationClass); } /** diff --git a/src/Database/Traits/DeferredBinding.php b/src/Database/Traits/DeferredBinding.php index e49750de2..d0acdf708 100644 --- a/src/Database/Traits/DeferredBinding.php +++ b/src/Database/Traits/DeferredBinding.php @@ -132,8 +132,7 @@ protected function commitDeferredOfType($sessionKey, $include = null, $exclude = /* * Find the slave model */ - $slaveClass = $binding->slave_type; - $slaveModel = new $slaveClass; + $slaveModel = $this->makeRelation($relationName) ?: new $binding->slave_type; $slaveModel = $slaveModel->find($binding->slave_id); if (!$slaveModel) { From 6d1c1c11e69d4a5ade4cf24439bce60218915840 Mon Sep 17 00:00:00 2001 From: Luke Towers Date: Mon, 21 Nov 2022 00:41:46 -0600 Subject: [PATCH 2/7] Type hints and code formatting --- src/Database/Relations/BelongsTo.php | 9 ++---- .../Relations/Concerns/AttachOneOrMany.php | 3 +- .../Concerns/BelongsOrMorphsToMany.php | 3 +- .../Relations/Concerns/HasOneOrMany.php | 3 +- .../Relations/Concerns/MorphOneOrMany.php | 3 +- src/Database/Traits/DeferredBinding.php | 30 +++++++++---------- 6 files changed, 21 insertions(+), 30 deletions(-) diff --git a/src/Database/Relations/BelongsTo.php b/src/Database/Relations/BelongsTo.php index 1a133f6b1..f708d56a2 100644 --- a/src/Database/Relations/BelongsTo.php +++ b/src/Database/Relations/BelongsTo.php @@ -35,8 +35,7 @@ public function add(Model $model, $sessionKey = null) { if ($sessionKey === null) { $this->associate($model); - } - else { + } else { $this->child->bindDeferred($this->relationName, $model, $sessionKey); } } @@ -48,8 +47,7 @@ public function remove(Model $model, $sessionKey = null) { if ($sessionKey === null) { $this->dissociate(); - } - else { + } else { $this->child->unbindDeferred($this->relationName, $model, $sessionKey); } } @@ -78,8 +76,7 @@ public function setSimpleValue($value) $this->associate($value); $this->child->setRelation($this->relationName, $value); - } - else { + } else { $this->child->setAttribute($this->getForeignKeyName(), $value); $this->child->reloadRelations($this->relationName); } diff --git a/src/Database/Relations/Concerns/AttachOneOrMany.php b/src/Database/Relations/Concerns/AttachOneOrMany.php index 22e761e44..760cd1d6b 100644 --- a/src/Database/Relations/Concerns/AttachOneOrMany.php +++ b/src/Database/Relations/Concerns/AttachOneOrMany.php @@ -216,8 +216,7 @@ public function add(Model $model, $sessionKey = null) * */ $this->parent->fireEvent('model.relation.afterAdd', [$this->relationName, $model]); - } - else { + } else { $this->parent->bindDeferred($this->relationName, $model, $sessionKey); } } diff --git a/src/Database/Relations/Concerns/BelongsOrMorphsToMany.php b/src/Database/Relations/Concerns/BelongsOrMorphsToMany.php index 6b3e50698..e07d38281 100644 --- a/src/Database/Relations/Concerns/BelongsOrMorphsToMany.php +++ b/src/Database/Relations/Concerns/BelongsOrMorphsToMany.php @@ -243,8 +243,7 @@ public function add(Model $model, $sessionKey = null, $pivotData = []) if ($sessionKey === null || $sessionKey === false) { $this->attach($model, $pivotData); $this->parent->reloadRelations($this->relationName); - } - else { + } else { $this->parent->bindDeferred($this->relationName, $model, $sessionKey, $pivotData); } } diff --git a/src/Database/Relations/Concerns/HasOneOrMany.php b/src/Database/Relations/Concerns/HasOneOrMany.php index 918604cb9..b6fe905b1 100644 --- a/src/Database/Relations/Concerns/HasOneOrMany.php +++ b/src/Database/Relations/Concerns/HasOneOrMany.php @@ -102,8 +102,7 @@ public function add(Model $model, $sessionKey = null) * */ $this->parent->fireEvent('model.relation.afterAdd', [$this->relationName, $model]); - } - else { + } else { $this->parent->bindDeferred($this->relationName, $model, $sessionKey); } } diff --git a/src/Database/Relations/Concerns/MorphOneOrMany.php b/src/Database/Relations/Concerns/MorphOneOrMany.php index 6add0dcb4..2bb7c49a1 100644 --- a/src/Database/Relations/Concerns/MorphOneOrMany.php +++ b/src/Database/Relations/Concerns/MorphOneOrMany.php @@ -88,8 +88,7 @@ public function add(Model $model, $sessionKey = null) * */ $this->parent->fireEvent('model.relation.afterAdd', [$this->relationName, $model]); - } - else { + } else { $this->parent->bindDeferred($this->relationName, $model, $sessionKey); } } diff --git a/src/Database/Traits/DeferredBinding.php b/src/Database/Traits/DeferredBinding.php index d0acdf708..3ba668a9f 100644 --- a/src/Database/Traits/DeferredBinding.php +++ b/src/Database/Traits/DeferredBinding.php @@ -1,5 +1,7 @@ hasRelation($relationName)) { return false; @@ -27,7 +29,7 @@ public function isDeferrable($relationName) /** * Bind a deferred relationship to the supplied record. */ - public function bindDeferred($relation, $record, $sessionKey, $pivotData = []) + public function bindDeferred(string $relation, Model $record, string $sessionKey, array $pivotData = []): DeferredBindingModel { $binding = new DeferredBindingModel; $binding->setConnection($this->getConnectionName()); @@ -45,7 +47,7 @@ public function bindDeferred($relation, $record, $sessionKey, $pivotData = []) /** * Unbind a deferred relationship to the supplied record. */ - public function unbindDeferred($relation, $record, $sessionKey) + public function unbindDeferred(string $relation, Model $record, string $sessionKey): DeferredBindingModel { $binding = new DeferredBindingModel; $binding->setConnection($this->getConnectionName()); @@ -62,7 +64,7 @@ public function unbindDeferred($relation, $record, $sessionKey) /** * Cancel all deferred bindings to this model. */ - public function cancelDeferred($sessionKey) + public function cancelDeferred(string $sessionKey): void { DeferredBindingModel::cancelDeferredActions(get_class($this), $sessionKey); } @@ -70,7 +72,7 @@ public function cancelDeferred($sessionKey) /** * Commit all deferred bindings to this model. */ - public function commitDeferred($sessionKey) + public function commitDeferred(string $sessionKey): void { $this->commitDeferredOfType($sessionKey); DeferredBindingModel::flushDuplicateCache(); @@ -81,7 +83,7 @@ public function commitDeferred($sessionKey) * It is a rare need to have to call this, since it only applies to the * "belongs to" relationship which generally does not need deferring. */ - protected function commitDeferredBefore($sessionKey) + protected function commitDeferredBefore(string $sessionKey): void { $this->commitDeferredOfType($sessionKey, 'belongsTo'); } @@ -89,7 +91,7 @@ protected function commitDeferredBefore($sessionKey) /** * Internally used method to commit all deferred bindings after saving. */ - protected function commitDeferredAfter($sessionKey) + protected function commitDeferredAfter(string $sessionKey): void { $this->commitDeferredOfType($sessionKey, null, 'belongsTo'); DeferredBindingModel::flushDuplicateCache(); @@ -98,7 +100,7 @@ protected function commitDeferredAfter($sessionKey) /** * Internal method for committing deferred relations. */ - protected function commitDeferredOfType($sessionKey, $include = null, $exclude = null) + protected function commitDeferredOfType(string $sessionKey, string|array|null $include = null, string|array|null $exclude = null): void { if (!strlen($sessionKey)) { return; @@ -120,8 +122,7 @@ protected function commitDeferredOfType($sessionKey, $include = null, $exclude = if ($include) { $allowedTypes = array_intersect($allowedTypes, (array) $include); - } - elseif ($exclude) { + } elseif ($exclude) { $allowedTypes = array_diff($allowedTypes, (array) $exclude); } @@ -151,8 +152,7 @@ protected function commitDeferredOfType($sessionKey, $include = null, $exclude = } else { $relationObj->add($slaveModel); } - } - else { + } else { $relationObj->remove($slaveModel); } @@ -162,9 +162,8 @@ protected function commitDeferredOfType($sessionKey, $include = null, $exclude = /** * Returns any outstanding binding records for this model. - * @return \Winter\Storm\Database\Collection */ - protected function getDeferredBindingRecords($sessionKey) + protected function getDeferredBindingRecords(string $sessionKey): Collection { $binding = new DeferredBindingModel; @@ -179,9 +178,8 @@ protected function getDeferredBindingRecords($sessionKey) /** * Returns all possible relation types that can be deferred. - * @return array */ - protected function getDeferrableRelationTypes() + protected function getDeferrableRelationTypes(): array { return [ 'hasMany', From aef287e69f7ff00ea6b2e05517000347adc5c64f Mon Sep 17 00:00:00 2001 From: Luke Towers Date: Mon, 21 Nov 2022 09:18:37 -0600 Subject: [PATCH 3/7] Type hinting --- src/Database/Concerns/HasRelationships.php | 11 ++++------- src/Database/Models/DeferredBinding.php | 17 ++++++++--------- src/Database/Traits/DeferredBinding.php | 2 +- 3 files changed, 13 insertions(+), 17 deletions(-) diff --git a/src/Database/Concerns/HasRelationships.php b/src/Database/Concerns/HasRelationships.php index aa9b599f1..069c8e943 100644 --- a/src/Database/Concerns/HasRelationships.php +++ b/src/Database/Concerns/HasRelationships.php @@ -132,7 +132,7 @@ trait HasRelationships 'attachOne', 'attachMany', 'hasOneThrough', - 'hasManyThrough' + 'hasManyThrough', ]; // @@ -142,9 +142,8 @@ trait HasRelationships /** * Checks if model has a relationship by supplied name. * @param string $name Relation name - * @return bool */ - public function hasRelation($name) + public function hasRelation($name): bool { return $this->getRelationDefinition($name) !== null; } @@ -152,9 +151,8 @@ public function hasRelation($name) /** * Returns relationship details from a supplied name. * @param string $name Relation name - * @return array|null */ - public function getRelationDefinition($name) + public function getRelationDefinition($name): ?array { if (($type = $this->getRelationType($name)) !== null) { return (array) $this->getRelationTypeDefinition($type, $name) + $this->getRelationDefaults($type); @@ -196,9 +194,8 @@ public function getRelationTypeDefinition($type, $name) /** * Returns relationship details for all relations defined on this model. - * @return array */ - public function getRelationDefinitions() + public function getRelationDefinitions(): array { $result = []; diff --git a/src/Database/Models/DeferredBinding.php b/src/Database/Models/DeferredBinding.php index 5f2e1f113..97c354a6c 100644 --- a/src/Database/Models/DeferredBinding.php +++ b/src/Database/Models/DeferredBinding.php @@ -1,7 +1,7 @@ findBindingRecord()) { /* @@ -60,7 +60,7 @@ public function beforeCreate() /** * Finds a duplicate binding record. */ - protected function findBindingRecord() + protected function findBindingRecord(): ?self { return self::where('master_type', $this->master_type) ->where('master_field', $this->master_field) @@ -74,7 +74,7 @@ protected function findBindingRecord() /** * Cancel all deferred bindings to this model. */ - public static function cancelDeferredActions($masterType, $sessionKey) + public static function cancelDeferredActions(string $masterType, string $sessionKey): void { $records = self::where('master_type', $masterType) ->where('session_key', $sessionKey) @@ -88,7 +88,7 @@ public static function cancelDeferredActions($masterType, $sessionKey) /** * Delete this binding and cancel is actions */ - public function deleteCancel() + public function deleteCancel(): void { $this->deleteSlaveRecord(); $this->delete(); @@ -97,7 +97,7 @@ public function deleteCancel() /** * Clean up orphan bindings. */ - public static function cleanUp($days = 5) + public static function cleanUp(int $days = 5): void { $records = self::where('created_at', '<', Carbon::now()->subDays($days)->toDateTimeString())->get(); @@ -109,7 +109,7 @@ public static function cleanUp($days = 5) /** * Logic to cancel a bindings action. */ - protected function deleteSlaveRecord() + protected function deleteSlaveRecord(): void { /* * Try to delete unbound hasOne/hasMany records from the details table @@ -144,8 +144,7 @@ protected function deleteSlaveRecord() if (!$relatedObj->$foreignKey) { $relatedObj->delete(); } - } - catch (Exception $ex) { + } catch (Exception $ex) { // Do nothing } } diff --git a/src/Database/Traits/DeferredBinding.php b/src/Database/Traits/DeferredBinding.php index 3ba668a9f..af916f60a 100644 --- a/src/Database/Traits/DeferredBinding.php +++ b/src/Database/Traits/DeferredBinding.php @@ -1,7 +1,7 @@ Date: Mon, 21 Nov 2022 15:21:52 -0600 Subject: [PATCH 4/7] Fix return types --- src/Database/Models/DeferredBinding.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Database/Models/DeferredBinding.php b/src/Database/Models/DeferredBinding.php index 97c354a6c..dc4dd1d4f 100644 --- a/src/Database/Models/DeferredBinding.php +++ b/src/Database/Models/DeferredBinding.php @@ -39,7 +39,7 @@ class DeferredBinding extends Model /** * Prevents duplicates and conflicting binds. */ - public function beforeCreate(): null|false + public function beforeCreate() { if ($existingRecord = $this->findBindingRecord()) { /* From efe427da14783b0a8d4fd5e3accafe5daa61cc07 Mon Sep 17 00:00:00 2001 From: Luke Towers Date: Mon, 21 Nov 2022 15:37:38 -0600 Subject: [PATCH 5/7] Appease PHPStan --- src/Database/Models/DeferredBinding.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Database/Models/DeferredBinding.php b/src/Database/Models/DeferredBinding.php index dc4dd1d4f..5c9b17fa9 100644 --- a/src/Database/Models/DeferredBinding.php +++ b/src/Database/Models/DeferredBinding.php @@ -60,7 +60,7 @@ public function beforeCreate() /** * Finds a duplicate binding record. */ - protected function findBindingRecord(): ?self + protected function findBindingRecord(): ?\Illuminate\Database\Eloquent\Model { return self::where('master_type', $this->master_type) ->where('master_field', $this->master_field) From 042ae5a147176dd7f87510550f2c6a3bce2d3010 Mon Sep 17 00:00:00 2001 From: Luke Towers Date: Mon, 21 Nov 2022 15:44:48 -0600 Subject: [PATCH 6/7] PHPStan fix --- src/Database/Models/DeferredBinding.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Database/Models/DeferredBinding.php b/src/Database/Models/DeferredBinding.php index 5c9b17fa9..890008368 100644 --- a/src/Database/Models/DeferredBinding.php +++ b/src/Database/Models/DeferredBinding.php @@ -59,8 +59,10 @@ public function beforeCreate() /** * Finds a duplicate binding record. + * + * @return self|null */ - protected function findBindingRecord(): ?\Illuminate\Database\Eloquent\Model + protected function findBindingRecord() { return self::where('master_type', $this->master_type) ->where('master_field', $this->master_field) From ba4f531100c16b802bfe41dee6be36d1f19631dc Mon Sep 17 00:00:00 2001 From: Luke Towers Date: Mon, 21 Nov 2022 15:52:29 -0600 Subject: [PATCH 7/7] PHPStan You're wrong, I just don't have the time to tell you how :P --- src/Database/Models/DeferredBinding.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Database/Models/DeferredBinding.php b/src/Database/Models/DeferredBinding.php index 890008368..ad7c37b0c 100644 --- a/src/Database/Models/DeferredBinding.php +++ b/src/Database/Models/DeferredBinding.php @@ -59,8 +59,6 @@ public function beforeCreate() /** * Finds a duplicate binding record. - * - * @return self|null */ protected function findBindingRecord() {