Skip to content

Commit

Permalink
Refactors
Browse files Browse the repository at this point in the history
  • Loading branch information
JohnathonKoster committed Mar 28, 2024
1 parent a8f6394 commit 1e8b5db
Show file tree
Hide file tree
Showing 9 changed files with 145 additions and 11 deletions.
21 changes: 21 additions & 0 deletions src/EntryRelationship.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ class EntryRelationship

const TYPE_MANY_TO_ONE = 4;

public ?EntryRelationship $origin = null;

public ?EntryRelationship $inverted = null;

public $leftType = '';

public $rightType = '';
Expand Down Expand Up @@ -115,6 +119,14 @@ public function withEvents($withEvents = true)
return $this;
}

public function withOriginRelationship(EntryRelationship $relationship)
{
$this->origin = $relationship;
$relationship->inverted = $this;

return $this;
}

public function isAutomaticInverse($isInverse = true, $inverseIndex = null)
{
$this->isAutomaticInverse = $isInverse;
Expand All @@ -128,6 +140,15 @@ public function isAutomaticInverse($isInverse = true, $inverseIndex = null)
return $this;
}

public function getInverse()
{
if ($this->isAutomaticInverse) {
return $this->origin;
}

return $this->inverted;
}

/**
* Sets whether affected entries will be updated when deleting related entries.
*
Expand Down
2 changes: 1 addition & 1 deletion src/Listeners/EntrySavedListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public function handle(EntrySaved $event)
return;
}

if (EventStack::count() > 0 || $this->manager->processor()->isProcessingManyToMany()) {
if (EventStack::count() > 0 || $this->manager->processor()->isProcessingRelationships()) {
return;
}

Expand Down
2 changes: 1 addition & 1 deletion src/Listeners/EntrySavingListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public function handle(EntrySaving $event)
return;
}

if (EventStack::count() > 1 || $this->manager->processor()->isProcessingManyToMany()) {
if (EventStack::count() > 1 || $this->manager->processor()->isProcessingRelationships()) {
return;
}

Expand Down
4 changes: 2 additions & 2 deletions src/Processors/Concerns/ProcessesManyToMany.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ trait ProcessesManyToMany
{
protected function processManyToMany(ComparisonResult $results, EntryRelationship $relationship)
{
$this->processingManyToMany = true;
$this->processingRelationships = true;

foreach ($results->added as $addedId) {
if (! $this->shouldProcessRelationship($relationship, $addedId)) {
Expand All @@ -27,6 +27,6 @@ protected function processManyToMany(ComparisonResult $results, EntryRelationshi
$this->removeItemFromEntry($relationship, $this->getEffectedEntity($relationship, $removedId));
}

$this->processingManyToMany = false;
$this->processingRelationships = false;
}
}
18 changes: 18 additions & 0 deletions src/Processors/Concerns/ProcessesOneToMany.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Stillat\Relationships\Processors\Concerns;

use Statamic\Facades\Data;
use Stillat\Relationships\Comparisons\ComparisonResult;
use Stillat\Relationships\EntryRelationship;

Expand All @@ -11,12 +12,29 @@ protected function processOneToMany(ComparisonResult $results, EntryRelationship
{
foreach ($results->removed as $removedId) {
if ($this->shouldProcessRelationship($relationship, $removedId)) {
$this->dependencies[] = $removedId;
$this->dependencies[] = $this->getDependency($relationship, $removedId);
$this->removeFieldValue($relationship, $this->getEffectedEntity($relationship, $removedId));
}
}

foreach ($results->added as $addedId) {
if ($this->shouldProcessRelationship($relationship, $addedId)) {
$this->dependencies[] = $addedId;
$dependent = Data::find($this->getDependency($relationship, $addedId));

if ($dependent !== null && $inverse = $relationship->getInverse()) {
$leftReference = $dependent->get($relationship->leftField);

if (($key = array_search($addedId, $leftReference)) !== false) {
unset($leftReference[$key]);

$dependent->set($relationship->leftField, array_values($leftReference));

$dependent->saveQuietly();
}
}

$this->setFieldValue($relationship, $this->getEffectedEntity($relationship, $addedId));
}
}
Expand Down
30 changes: 27 additions & 3 deletions src/Processors/RelationshipProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,13 @@ class RelationshipProcessor

protected $observed = [];

protected $processingManyToMany = false;
protected $processingRelationships = false;

public function isProcessingManyToMany()
protected $dependencies = [];

public function isProcessingRelationships()
{
return $this->processingManyToMany;
return $this->processingRelationships;
}

public function setIsDeleting($isDeleting = true)
Expand Down Expand Up @@ -307,9 +309,11 @@ public function process($relationships)

public function processRelationship($relationship, $results)
{
$this->processingRelationships = true;
UpdatingRelationshipsEvent::dispatch($relationship, $results);

if (! $results->hasChanges()) {
$this->processingRelationships = false;
UpdatedRelationshipsEvent::dispatch($relationship, $results);

return;
Expand All @@ -326,6 +330,7 @@ public function processRelationship($relationship, $results)
} elseif ($relationship->type == EntryRelationship::TYPE_MANY_TO_ONE) {
$this->processManyToOne($results, $relationship);
}
$this->processingRelationships = false;

UpdatedRelationshipsEvent::dispatch($relationship, $results);
}
Expand Down Expand Up @@ -354,6 +359,25 @@ protected function shouldProcessRelationship(EntryRelationship $relationship, $i
return true;
}

protected function getDependency(EntryRelationship $relationship, $id)
{
$data = null;

if ($relationship->rightType == 'entry') {
$data = $this->effectedEntries[$id];
} elseif ($relationship->rightType == 'user') {
$data = $this->effectedUsers[$id];
} elseif ($relationship->rightType == 'term') {
$data = $this->effectedTerms[$id];
}

if ($data === null || ! method_exists($data, 'get')) {
return null;
}

return $data->get($relationship->rightField);
}

protected function getEffectedEntity(EntryRelationship $relationship, $id)
{
if ($relationship->rightType == 'entry') {
Expand Down
20 changes: 16 additions & 4 deletions src/RelationshipManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,10 @@ private function buildOneToOneRelationships($relationships)
$right = $this->getFieldDetails($relationship[1]);

$builtRelationships[] = $this->getRelationship($left, $right)->oneToOne();
$builtRelationships[] = $this->getRelationship($right, $left)->oneToOne()->isAutomaticInverse();
$builtRelationships[] = $this->getRelationship($right, $left)
->oneToOne()
->isAutomaticInverse()
->withOriginRelationship($builtRelationships[0]);
}

return new RelationshipProxy($builtRelationships);
Expand All @@ -150,7 +153,10 @@ private function buildOneToManyRelationships($relationships)
$right = $this->getFieldDetails($relationship[1]);

$builtRelationships[] = $this->getRelationship($left, $right)->manyToOne();
$builtRelationships[] = $this->getRelationship($right, $left)->oneToMany()->isAutomaticInverse();
$builtRelationships[] = $this->getRelationship($right, $left)
->oneToMany()
->isAutomaticInverse()
->withOriginRelationship($builtRelationships[0]);
}

return new RelationshipProxy($builtRelationships);
Expand All @@ -175,7 +181,10 @@ private function buildManyToOneRelationships($relationships)
$right = $this->getFieldDetails($relationship[1]);

$builtRelationships[] = $this->getRelationship($left, $right)->oneToOne();
$builtRelationships[] = $this->getRelationship($right, $left)->manyToOne()->isAutomaticInverse();
$builtRelationships[] = $this->getRelationship($right, $left)
->manyToOne()
->isAutomaticInverse()
->withOriginRelationship($builtRelationships[0]);
}

return new RelationshipProxy($builtRelationships);
Expand Down Expand Up @@ -254,7 +263,10 @@ private function buildManyToManyRelationships($relationships)
$right = $this->getFieldDetails($relationship[1]);

$builtRelationships[] = $this->getRelationship($left, $right)->manyToMany();
$builtRelationships[] = $this->getRelationship($right, $left)->manyToMany()->isAutomaticInverse();
$builtRelationships[] = $this->getRelationship($right, $left)
->manyToMany()
->isAutomaticInverse()
->withOriginRelationship($builtRelationships[0]);
}

return new RelationshipProxy($builtRelationships);
Expand Down
50 changes: 50 additions & 0 deletions tests/OneToManyTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -117,4 +117,54 @@ public function test_one_to_many_term_relationships()
$this->assertSame([], $this->getTerm('topics-one')->get('posts', []));
$this->assertSame([], $this->getTerm('topics-two')->get('posts', []));
}

public function test_one_to_many_updates_dependents()
{
Relate::clear();
Relate::oneToMany(
'books.author',
'authors.books'
);

Entry::find('books-1')->set('author', 'authors-1')->save();
Entry::find('books-2')->set('author', 'authors-1')->save();
Entry::find('books-3')->set('author', 'authors-1')->save();

Entry::find('books-4')->set('author', 'authors-1')->save();
Entry::find('books-5')->set('author', 'authors-2')->save();

Entry::find('authors-1')->set('books', [
'books-1',
'books-2',
'books-3',
])->save();

Entry::find('authors-2')->set('books', [
'books-4',
'books-5',
])->save();

Entry::find('authors-1')->set('books', [
'books-1',
'books-2',
'books-3',
'books-4',
])->save();

$this->assertSame(['books-5'], Entry::find('authors-2')->get('books'));

$this->assertSame([
'books-1',
'books-2',
'books-3',
'books-4',
], Entry::find('authors-1')->get('books'));

$this->assertSame('authors-1', Entry::find('books-1')->get('author'));
$this->assertSame('authors-1', Entry::find('books-2')->get('author'));
$this->assertSame('authors-1', Entry::find('books-3')->get('author'));
$this->assertSame('authors-1', Entry::find('books-4')->get('author'));

$this->assertSame('authors-2', Entry::find('books-5')->get('author'));
}
}
9 changes: 9 additions & 0 deletions tests/RelationshipTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,15 @@ protected function createCollectionEntries()
[
'title' => 'Book Two',
],
[
'title' => 'Book Three',
],
[
'title' => 'Book Four',
],
[
'title' => 'Book Five',
],
]);

$this->createEntries('conferences', [
Expand Down

0 comments on commit 1e8b5db

Please sign in to comment.