From c004cf6458416f04f020a4373cf0125c3cc34745 Mon Sep 17 00:00:00 2001 From: Jacques Florian Date: Fri, 28 Jun 2024 12:26:58 +0200 Subject: [PATCH 01/10] [Bug fix] Fix BelongToMany when using ObjectId in relation --- src/Relations/BelongsToMany.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Relations/BelongsToMany.php b/src/Relations/BelongsToMany.php index 8ff311f3f..7b58098f1 100644 --- a/src/Relations/BelongsToMany.php +++ b/src/Relations/BelongsToMany.php @@ -202,7 +202,13 @@ public function attach($id, array $attributes = [], $touch = true) // Attach the new ids to the parent model. if ($this->parent instanceof \MongoDB\Laravel\Eloquent\Model) { - $this->parent->push($this->relatedPivotKey, (array) $id, true); + if ($id instanceof \MongoDB\BSON\ObjectId) { + $id = [$id]; + } else { + $id = (array) $id; + } + + $this->parent->push($this->relatedPivotKey, $id, true); } else { $instance = new $this->related(); $instance->forceFill([$this->relatedKey => $id]); From a25ef4068c5ac037a870620fc5aea94d86c9d082 Mon Sep 17 00:00:00 2001 From: Jacques Florian Date: Fri, 28 Jun 2024 13:21:07 +0200 Subject: [PATCH 02/10] Fix, detach with Objectid --- src/Relations/BelongsToMany.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Relations/BelongsToMany.php b/src/Relations/BelongsToMany.php index 7b58098f1..8251a2a6d 100644 --- a/src/Relations/BelongsToMany.php +++ b/src/Relations/BelongsToMany.php @@ -235,7 +235,11 @@ public function detach($ids = [], $touch = true) // If associated IDs were passed to the method we will only delete those // associations, otherwise all of the association ties will be broken. // We'll return the numbers of affected rows when we do the deletes. - $ids = (array) $ids; + if ($ids instanceof \MongoDB\BSON\ObjectId) { + $ids = [$ids]; + } else { + $ids = (array) $ids; + } // Detach all ids from the parent model. if ($this->parent instanceof \MongoDB\Laravel\Eloquent\Model) { From e86f00bfdfb65bb2c5d0bbcb8cf4b910d2f6757c Mon Sep 17 00:00:00 2001 From: florianJacques Date: Sun, 30 Jun 2024 14:58:03 +0200 Subject: [PATCH 03/10] Add sync and toggle relation helper --- src/Relations/BelongsToMany.php | 149 +++++++++++++++++++++++++++----- 1 file changed, 128 insertions(+), 21 deletions(-) diff --git a/src/Relations/BelongsToMany.php b/src/Relations/BelongsToMany.php index 8251a2a6d..a3c4e29c4 100644 --- a/src/Relations/BelongsToMany.php +++ b/src/Relations/BelongsToMany.php @@ -4,16 +4,16 @@ namespace MongoDB\Laravel\Relations; +use BackedEnum; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Collection; +use \Illuminate\Support\Collection as BaseCollection; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsToMany as EloquentBelongsToMany; use Illuminate\Support\Arr; use function array_diff; -use function array_keys; use function array_map; -use function array_merge; use function array_values; use function assert; use function count; @@ -107,8 +107,35 @@ public function create(array $attributes = [], array $joining = [], $touch = tru return $instance; } - /** @inheritdoc */ - public function sync($ids, $detaching = true) + /** + * Format the sync / toggle record list so that it is keyed by ID. + * + * @param array $records + * @return array + */ + protected function formatRecordsList($records): array + { + //Support for an object type id. + //Removal of attribute management because there is no pivot table + return collect($records)->map(function ($id) { + if ($id instanceof BackedEnum) { + $id = $id->value; + } + + return $id; + })->all(); + } + + /** + * Toggles a model (or models) from the parent. + * + * Each existing model is detached, and non existing ones are attached. + * + * @param mixed $ids + * @param bool $touch + * @return array + */ + public function toggle($ids, $touch = true) { $changes = [ 'attached' => [], @@ -130,25 +157,95 @@ public function sync($ids, $detaching = true) false => $this->parent->{$this->relationName} ?: [], }; - if ($current instanceof Collection) { + // Support Base Collection + if ($current instanceof BaseCollection) { $current = $this->parseIds($current); } + $current = Arr::wrap($current); $records = $this->formatRecordsList($ids); - $current = Arr::wrap($current); + $detach = array_values(array_intersect($current, $records)); - $detach = array_diff($current, array_keys($records)); + if (count($detach) > 0) { + $this->detach($detach, false); + + $changes['detached'] = (array) array_map(function ($v) { + return is_numeric($v) ? (int) $v : (string) $v; + }, $detach); + } + + // Finally, for all of the records which were not "detached", we'll attach the + // records into the intermediate table. Then, we will add those attaches to + // this change list and get ready to return these results to the callers. + $attach = array_values(array_diff($records, $current)); + + if (count($attach) > 0) { + $this->attach($attach, [], false); + + $changes['attached'] = (array) array_map(function ($v) { + return $this->castKey($v); + }, $attach); + } + + // Once we have finished attaching or detaching the records, we will see if we + // have done any attaching or detaching, and if we have we will touch these + // relationships if they are configured to touch on any database updates. + if ($touch && (count($changes['attached']) || + count($changes['detached']))) { + + $this->parent->touch(); + $this->newRelatedQuery()->whereIn($this->relatedKey, $ids)->touch(); + } + + return $changes; + } - // We need to make sure we pass a clean array, so that it is not interpreted - // as an associative array. - $detach = array_values($detach); + + /** + * Sync the intermediate tables with a list of IDs or collection of models. + * + * @param \Illuminate\Support\Collection|\Illuminate\Database\Eloquent\Model|array $ids + * @param bool $detaching + * @return array + */ + public function sync($ids, $detaching = true) + { + $changes = [ + 'attached' => [], + 'detached' => [], + 'updated' => [], + ]; + + if ($ids instanceof Collection) { + $ids = $this->parseIds($ids); + } elseif ($ids instanceof Model) { + $ids = $this->parseIds($ids); + } + + // First we need to attach any of the associated models that are not currently + // in this joining table. We'll spin through the given IDs, checking to see + // if they exist in the array of current ones, and if not we will insert. + $current = match ($this->parent instanceof \MongoDB\Laravel\Eloquent\Model) { + true => $this->parent->{$this->relatedPivotKey} ?: [], + false => $this->parent->{$this->relationName} ?: [], + }; + + // Support Base Collection + if ($current instanceof BaseCollection) { + $current = $this->parseIds($current); + } + + $current = Arr::wrap($current); + $records = $this->formatRecordsList($ids); + + $detach = array_values(array_diff($current, $records)); // Next, we will take the differences of the currents and given IDs and detach // all of the entities that exist in the "current" array but are not in the // the array of the IDs given to the method which will complete the sync. if ($detaching && count($detach) > 0) { - $this->detach($detach); + $this->detach($detach, false); $changes['detached'] = (array) array_map(function ($v) { return is_numeric($v) ? (int) $v : (string) $v; @@ -158,13 +255,18 @@ public function sync($ids, $detaching = true) // Now we are finally ready to attach the new records. Note that we'll disable // touching until after the entire operation is complete so we don't fire a // ton of touch operations until we are totally done syncing the records. - $changes = array_merge( - $changes, - $this->attachNew($records, $current, false), - ); + foreach ($records as $id) { + // Only non strict check if exist no update s possible beacause no attributtes + if (!in_array($id, $current)) { + $this->attach($id, [], false); + $changes['attached'][] = $this->castKey($id); + } + } - if (count($changes['attached']) || count($changes['updated'])) { - $this->touchIfTouching(); + if ((count($changes['attached']) || count($changes['detached']))) { + $touches = array_merge($detach, $records); + $this->parent->touch(); + $this->newRelatedQuery()->whereIn($this->relatedKey, $touches)->touch(); } return $changes; @@ -207,7 +309,7 @@ public function attach($id, array $attributes = [], $touch = true) } else { $id = (array) $id; } - + $this->parent->push($this->relatedPivotKey, $id, true); } else { $instance = new $this->related(); @@ -220,13 +322,16 @@ public function attach($id, array $attributes = [], $touch = true) return; } - $this->touchIfTouching(); + $this->parent->touch(); + $this->newRelatedQuery()->whereIn($this->relatedKey, (array) $id); } /** @inheritdoc */ public function detach($ids = [], $touch = true) { - if ($ids instanceof Model) { + if ($ids instanceof Collection) { + $ids = $this->parseIds($ids); + } elseif ($ids instanceof Model) { $ids = $this->parseIds($ids); } @@ -247,6 +352,7 @@ public function detach($ids = [], $touch = true) } else { $value = $this->parent->{$this->relationName} ->filter(fn ($rel) => ! in_array($rel->{$this->relatedKey}, $ids)); + $this->parent->setRelation($this->relationName, $value); } @@ -261,7 +367,8 @@ public function detach($ids = [], $touch = true) $query->pull($this->foreignPivotKey, $this->parent->{$this->parentKey}); if ($touch) { - $this->touchIfTouching(); + $this->parent->touch(); + $query->touch(); } return count($ids); From ed36b81ef292dda329248b0113098d39fca1fa6e Mon Sep 17 00:00:00 2001 From: florianJacques Date: Sun, 30 Jun 2024 15:26:59 +0200 Subject: [PATCH 04/10] Fix uses --- src/Relations/BelongsToMany.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Relations/BelongsToMany.php b/src/Relations/BelongsToMany.php index a3c4e29c4..d1f19ae3d 100644 --- a/src/Relations/BelongsToMany.php +++ b/src/Relations/BelongsToMany.php @@ -7,7 +7,7 @@ use BackedEnum; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Collection; -use \Illuminate\Support\Collection as BaseCollection; +use Illuminate\Support\Collection as BaseCollection; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsToMany as EloquentBelongsToMany; use Illuminate\Support\Arr; From 070a61113cf2a41b27b8d18b3ff9be41db9d1cd0 Mon Sep 17 00:00:00 2001 From: florianJacques Date: Sun, 30 Jun 2024 17:01:57 +0200 Subject: [PATCH 05/10] Prevent ket casting for build eagerLoading Dictionary --- src/Relations/BelongsToMany.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Relations/BelongsToMany.php b/src/Relations/BelongsToMany.php index d1f19ae3d..43922fdb9 100644 --- a/src/Relations/BelongsToMany.php +++ b/src/Relations/BelongsToMany.php @@ -386,6 +386,12 @@ protected function buildDictionary(Collection $results) foreach ($results as $result) { foreach ($result->$foreign as $item) { + + //Prevent if id is non keyable + if ($item instanceof \MongoDB\BSON\ObjectId) { + $item = (string) $item; + } + $dictionary[$item][] = $result; } } From 1aa438c9d5eedd768b8078082e8fdcec7c77cfc6 Mon Sep 17 00:00:00 2001 From: florianJacques Date: Sun, 30 Jun 2024 17:21:27 +0200 Subject: [PATCH 06/10] Add is method for Oid managment --- src/Eloquent/Model.php | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/Eloquent/Model.php b/src/Eloquent/Model.php index f7b4f1f36..198190282 100644 --- a/src/Eloquent/Model.php +++ b/src/Eloquent/Model.php @@ -771,4 +771,29 @@ public function refresh() return $this; } + + /** + * Determine if two models have the same ID and belong to the same table. + * + * @param \Illuminate\Database\Eloquent\Model|null $model + * @return bool + */ + public function is($model) + { + $modelKey = $model?->getKey(); + $currentKey = $this->getKey(); + + if ($modelKey instanceof \MongoDB\BSON\ObjectId) { + $modelKey = (string) $modelKey; + } + + if ($currentKey instanceof \MongoDB\BSON\ObjectId) { + $currentKey = (string) $currentKey; + } + + return ! is_null($model) && + $currentKey === $modelKey && + $this->getTable() === $model->getTable() && + $this->getConnectionName() === $model->getConnectionName(); + } } From 15a120e1de7c87f588fdb51fbf629a60657c53b6 Mon Sep 17 00:00:00 2001 From: florianJacques Date: Sun, 30 Jun 2024 19:01:33 +0200 Subject: [PATCH 07/10] Add tests --- tests/Models/PlanetOid.php | 23 +++++++ tests/Models/SpaceExplorerOid.php | 23 +++++++ tests/RelationsTest.php | 105 ++++++++++++++++++++++++++++++ 3 files changed, 151 insertions(+) create mode 100644 tests/Models/PlanetOid.php create mode 100644 tests/Models/SpaceExplorerOid.php diff --git a/tests/Models/PlanetOid.php b/tests/Models/PlanetOid.php new file mode 100644 index 000000000..67a7da683 --- /dev/null +++ b/tests/Models/PlanetOid.php @@ -0,0 +1,23 @@ +belongsToMany(SpaceExplorerOid::class); + } +} diff --git a/tests/Models/SpaceExplorerOid.php b/tests/Models/SpaceExplorerOid.php new file mode 100644 index 000000000..c3512e597 --- /dev/null +++ b/tests/Models/SpaceExplorerOid.php @@ -0,0 +1,23 @@ +belongsToMany(PlanetOid::class); + } +} diff --git a/tests/RelationsTest.php b/tests/RelationsTest.php index 368406feb..782c3459e 100644 --- a/tests/RelationsTest.php +++ b/tests/RelationsTest.php @@ -14,9 +14,11 @@ use MongoDB\Laravel\Tests\Models\Item; use MongoDB\Laravel\Tests\Models\Label; use MongoDB\Laravel\Tests\Models\Photo; +use MongoDB\Laravel\Tests\Models\PlanetOid; use MongoDB\Laravel\Tests\Models\Role; use MongoDB\Laravel\Tests\Models\Skill; use MongoDB\Laravel\Tests\Models\Soft; +use MongoDB\Laravel\Tests\Models\SpaceExplorerOid; use MongoDB\Laravel\Tests\Models\User; class RelationsTest extends TestCase @@ -35,6 +37,8 @@ public function tearDown(): void Photo::truncate(); Label::truncate(); Skill::truncate(); + SpaceExplorerOid::truncate(); + PlanetOid::truncate(); } public function testHasMany(): void @@ -1273,4 +1277,105 @@ public function testWhereBelongsTo() $this->assertCount(3, $items); } + + public function testBelongsToManyOid(): void + { + $explorer = SpaceExplorerOid::create(['name' => 'John Doe']); + + // Add 2 explorer + $explorer->planetsVisited()->save(new PlanetOid(['name' => 'Mars'])); + $explorer->planetsVisited()->create(['name' => 'Jupiter']); + + // Refetch + $explorer = SpaceExplorerOid::with('planetsVisited')->find($explorer->_id); + $planet = PlanetOid::with('visitors')->first(); + + // Check for relation attributes + $this->assertArrayHasKey('space_explorer_oid_ids', $planet->getAttributes()); + $this->assertArrayHasKey('planet_oid_ids', $explorer->getAttributes()); + + $planets = $explorer->getRelation('planetsVisited'); + $explorers = $planet->getRelation('visitors'); + + $this->assertInstanceOf(Collection::class, $planets); + $this->assertInstanceOf(Collection::class, $explorers); + $this->assertInstanceOf(SpaceExplorerOid::class, $explorers[0]); + $this->assertInstanceOf(PlanetOid::class, $planets[0]); + $this->assertCount(2, $explorer->planetsVisited); + $this->assertCount(1, $planet->visitors); + + // Now create a new explorer to an existing planet + $explorer = $planet->visitors()->create(['name' => 'skaywalker']); + + $this->assertInstanceOf(Collection::class, $explorer->planetsVisited); + $this->assertInstanceOf(PlanetOid::class, $explorer->planetsVisited->first()); + $this->assertCount(1, $explorer->planetsVisited); + + // Get explorer and unattached planet + $explorer = SpaceExplorerOid::where('name', '=', 'skaywalker')->first(); + $planet = PlanetOid::where('name', '=', 'Jupiter')->first(); + + // Check the models are what they should be + $this->assertInstanceOf(PlanetOid::class, $planet); + $this->assertInstanceOf(SpaceExplorerOid::class, $explorer); + + // Assert they are not attached + $this->assertNotContains($planet->_id, $explorer->planet_oid_ids); + $this->assertNotContains($explorer->_id, $planet->space_explorer_oid_ids); + $this->assertCount(1, $explorer->planetsVisited); + $this->assertCount(1, $planet->visitors); + + // Attach the planet to the explorer + $explorer->planetsVisited()->attach($planet); + + // Get the new explorer model + $explorer = SpaceExplorerOid::where('name', '=', 'skaywalker')->first(); + $planet = PlanetOid::where('name', '=', 'Mars')->first(); + + // Assert they are attached + $this->assertNotContains($planet->_id, $explorer->planet_oid_ids); + $this->assertNotContains($explorer->_id, $planet->space_explorer_oid_ids); + $this->assertCount(2, $explorer->planetsVisited); + $this->assertCount(2, $planet->visitors); + + + // Detach planets from explorer + $explorer->planetsVisited()->sync([]); + + // Get the new user model + $explorer = SpaceExplorerOid::where('name', '=', 'skaywalker')->first(); + $planet = PlanetOid::where('name', '=', 'Mars')->first(); + + // Assert they are attached + $this->assertNotContains($planet->_id, $explorer->planet_oid_ids); + $this->assertNotContains($explorer->_id, $planet->space_explorer_oid_ids); + $this->assertCount(0, $explorer->planetsVisited); + $this->assertCount(1, $planet->visitors); + } + + public function testBelongsToManySyncOid(): void + { + // create test instances + $explorer = SpaceExplorerOid::create(['name' => 'John Doe']); + $planet1 = PlanetOid::create(['name' => 'Mars']); + $planet2 = PlanetOid::create(['name' => 'Jupiter']); + + // Sync multiple + $explorer->planetsVisited()->sync([$planet1->_id, $planet2->_id]); + $this->assertCount(2, $explorer->planetsVisited); + + // Sync single wrapped by an array + $explorer->planetsVisited()->sync([$planet1->_id]); + $explorer->load('planetsVisited'); + + $this->assertCount(1, $explorer->planetsVisited); + self::assertTrue($explorer->planetsVisited->first()->is($planet1)); + + // Sync single model + $explorer->planetsVisited()->sync($planet2); + $explorer->load('planetsVisited'); + + $this->assertCount(1, $explorer->planetsVisited); + self::assertTrue($explorer->planetsVisited->first()->is($planet2)); + } } From 74a68c3febc5b2b4b727e9c6f937c3409df36609 Mon Sep 17 00:00:00 2001 From: florianJacques Date: Mon, 1 Jul 2024 09:01:44 +0200 Subject: [PATCH 08/10] Refactoring the model and relationship classes --- src/Eloquent/Model.php | 43 ++++++++++++++++++++++++--------- src/Relations/BelongsToMany.php | 12 ++++++--- 2 files changed, 41 insertions(+), 14 deletions(-) diff --git a/src/Eloquent/Model.php b/src/Eloquent/Model.php index 198190282..ac8855cec 100644 --- a/src/Eloquent/Model.php +++ b/src/Eloquent/Model.php @@ -773,26 +773,47 @@ public function refresh() } /** - * Determine if two models have the same ID and belong to the same table. + * Get a serialized attribute from the model. * - * @param \Illuminate\Database\Eloquent\Model|null $model - * @return bool + * @param string $key + * @return mixed */ - public function is($model) + public function getSerializedAttribute($key) { - $modelKey = $model?->getKey(); - $currentKey = $this->getKey(); + $value = $this->getAttribute($key); - if ($modelKey instanceof \MongoDB\BSON\ObjectId) { - $modelKey = (string) $modelKey; + // Convert ObjectID to string. + if ($value instanceof ObjectID) { + return (string) $value; } - if ($currentKey instanceof \MongoDB\BSON\ObjectId) { - $currentKey = (string) $currentKey; + if ($value instanceof Binary) { + return (string) $value->getData(); } + return $value; + } + + /** + * Get the serialized value of the model's primary key. + * + * @return mixed + */ + public function getSerializedKey() + { + return $this->getSerializedAttribute($this->getKeyName()); + } + + /** + * Determine if two models have the same ID and belong to the same table. + * + * @param \Illuminate\Database\Eloquent\Model|null $model + * @return bool + */ + public function is($model) + { return ! is_null($model) && - $currentKey === $modelKey && + $this->getSerializedKey() === $model->getSerializedKey() && $this->getTable() === $model->getTable() && $this->getConnectionName() === $model->getConnectionName(); } diff --git a/src/Relations/BelongsToMany.php b/src/Relations/BelongsToMany.php index 43922fdb9..acc38d549 100644 --- a/src/Relations/BelongsToMany.php +++ b/src/Relations/BelongsToMany.php @@ -11,6 +11,8 @@ use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsToMany as EloquentBelongsToMany; use Illuminate\Support\Arr; +use MongoDB\BSON\Binary; +use MongoDB\BSON\ObjectId; use function array_diff; use function array_map; @@ -304,7 +306,7 @@ public function attach($id, array $attributes = [], $touch = true) // Attach the new ids to the parent model. if ($this->parent instanceof \MongoDB\Laravel\Eloquent\Model) { - if ($id instanceof \MongoDB\BSON\ObjectId) { + if ($id instanceof ObjectId) { $id = [$id]; } else { $id = (array) $id; @@ -340,7 +342,7 @@ public function detach($ids = [], $touch = true) // If associated IDs were passed to the method we will only delete those // associations, otherwise all of the association ties will be broken. // We'll return the numbers of affected rows when we do the deletes. - if ($ids instanceof \MongoDB\BSON\ObjectId) { + if ($ids instanceof ObjectId) { $ids = [$ids]; } else { $ids = (array) $ids; @@ -388,10 +390,14 @@ protected function buildDictionary(Collection $results) foreach ($result->$foreign as $item) { //Prevent if id is non keyable - if ($item instanceof \MongoDB\BSON\ObjectId) { + if ($item instanceof ObjectId) { $item = (string) $item; } + if ($item instanceof Binary) { + $item = (string) $item->getData(); + } + $dictionary[$item][] = $result; } } From a4ab06a8c8f146875f1d677ee94fa8985e000cab Mon Sep 17 00:00:00 2001 From: florianJacques Date: Mon, 1 Jul 2024 11:26:12 +0200 Subject: [PATCH 09/10] remove is_null function --- src/Eloquent/Model.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Eloquent/Model.php b/src/Eloquent/Model.php index ac8855cec..57964bf23 100644 --- a/src/Eloquent/Model.php +++ b/src/Eloquent/Model.php @@ -812,7 +812,7 @@ public function getSerializedKey() */ public function is($model) { - return ! is_null($model) && + return $model !== null && $this->getSerializedKey() === $model->getSerializedKey() && $this->getTable() === $model->getTable() && $this->getConnectionName() === $model->getConnectionName(); From 003fbb5469bb5c10c34dc34d7026956d35f92f79 Mon Sep 17 00:00:00 2001 From: florianJacques Date: Tue, 2 Jul 2024 11:24:54 +0200 Subject: [PATCH 10/10] cs fixwq --- src/Eloquent/Model.php | 6 ++++-- src/Relations/BelongsToMany.php | 27 ++++++++++++++++----------- tests/RelationsTest.php | 1 - 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/src/Eloquent/Model.php b/src/Eloquent/Model.php index 57964bf23..f3031fb1e 100644 --- a/src/Eloquent/Model.php +++ b/src/Eloquent/Model.php @@ -775,7 +775,8 @@ public function refresh() /** * Get a serialized attribute from the model. * - * @param string $key + * @param string $key + * * @return mixed */ public function getSerializedAttribute($key) @@ -807,7 +808,8 @@ public function getSerializedKey() /** * Determine if two models have the same ID and belong to the same table. * - * @param \Illuminate\Database\Eloquent\Model|null $model + * @param \Illuminate\Database\Eloquent\Model|null $model + * * @return bool */ public function is($model) diff --git a/src/Relations/BelongsToMany.php b/src/Relations/BelongsToMany.php index acc38d549..0d0fdc6e9 100644 --- a/src/Relations/BelongsToMany.php +++ b/src/Relations/BelongsToMany.php @@ -7,17 +7,20 @@ use BackedEnum; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Collection; -use Illuminate\Support\Collection as BaseCollection; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsToMany as EloquentBelongsToMany; use Illuminate\Support\Arr; +use Illuminate\Support\Collection as BaseCollection; use MongoDB\BSON\Binary; use MongoDB\BSON\ObjectId; use function array_diff; +use function array_intersect; use function array_map; +use function array_merge; use function array_values; use function assert; +use function collect; use function count; use function in_array; use function is_numeric; @@ -112,7 +115,8 @@ public function create(array $attributes = [], array $joining = [], $touch = tru /** * Format the sync / toggle record list so that it is keyed by ID. * - * @param array $records + * @param array $records + * * @return array */ protected function formatRecordsList($records): array @@ -133,8 +137,9 @@ protected function formatRecordsList($records): array * * Each existing model is detached, and non existing ones are attached. * - * @param mixed $ids + * @param mixed $ids * @param bool $touch + * * @return array */ public function toggle($ids, $touch = true) @@ -193,9 +198,10 @@ public function toggle($ids, $touch = true) // Once we have finished attaching or detaching the records, we will see if we // have done any attaching or detaching, and if we have we will touch these // relationships if they are configured to touch on any database updates. - if ($touch && (count($changes['attached']) || - count($changes['detached']))) { - + if ( + $touch && (count($changes['attached']) || + count($changes['detached'])) + ) { $this->parent->touch(); $this->newRelatedQuery()->whereIn($this->relatedKey, $ids)->touch(); } @@ -203,12 +209,12 @@ public function toggle($ids, $touch = true) return $changes; } - /** * Sync the intermediate tables with a list of IDs or collection of models. * - * @param \Illuminate\Support\Collection|\Illuminate\Database\Eloquent\Model|array $ids - * @param bool $detaching + * @param \Illuminate\Support\Collection|Model|array $ids + * @param bool $detaching + * * @return array */ public function sync($ids, $detaching = true) @@ -259,7 +265,7 @@ public function sync($ids, $detaching = true) // ton of touch operations until we are totally done syncing the records. foreach ($records as $id) { // Only non strict check if exist no update s possible beacause no attributtes - if (!in_array($id, $current)) { + if (! in_array($id, $current)) { $this->attach($id, [], false); $changes['attached'][] = $this->castKey($id); } @@ -388,7 +394,6 @@ protected function buildDictionary(Collection $results) foreach ($results as $result) { foreach ($result->$foreign as $item) { - //Prevent if id is non keyable if ($item instanceof ObjectId) { $item = (string) $item; diff --git a/tests/RelationsTest.php b/tests/RelationsTest.php index 782c3459e..cf8f28218 100644 --- a/tests/RelationsTest.php +++ b/tests/RelationsTest.php @@ -1338,7 +1338,6 @@ public function testBelongsToManyOid(): void $this->assertCount(2, $explorer->planetsVisited); $this->assertCount(2, $planet->visitors); - // Detach planets from explorer $explorer->planetsVisited()->sync([]);