Skip to content

Commit

Permalink
Merge pull request #36 from Stillat/fix-relationship-processing
Browse files Browse the repository at this point in the history
Fix relationship processing
  • Loading branch information
JohnathonKoster authored Mar 28, 2024
2 parents 5f8f632 + 1e8b5db commit 5b0908d
Show file tree
Hide file tree
Showing 14 changed files with 264 additions and 44 deletions.
1 change: 1 addition & 0 deletions .phpunit.cache/test-results
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"version":1,"defects":[],"times":{"Tests\\OneToManyTest::test_one_to_many_term_relationships":0.192,"Tests\\ManyToManyDeleteTest::test_many_to_many_delete":0.161,"Tests\\ManyToManyDeleteTest::test_many_to_many_user_delete":0.103,"Tests\\ManyToManyDeleteTest::test_many_to_many_term_delete":0.171,"Tests\\ManyToManyDisabledDeleteTest::test_many_to_many_deletes_can_be_disabled":0.085,"Tests\\ManyToManyDisabledDeleteTest::test_many_to_many_user_deletes_can_be_disabled":0.073,"Tests\\ManyToManyDisabledDeleteTest::test_many_to_many_term_deletes_can_be_disabled":0.109,"Tests\\ManyToManyTest::test_many_to_many_relationship":0.204,"Tests\\ManyToManyTest::test_many_to_many_user_relationships":0.094,"Tests\\ManyToManyTest::test_many_to_many_term_relationships":0.106,"Tests\\ManyToOneDeleteTest::test_many_to_one_delete":0.169,"Tests\\ManyToOneDeleteTest::test_many_to_one_user_delete":0.146,"Tests\\ManyToOneDeleteTest::test_many_to_one_term_delete":0.112,"Tests\\ManyToOneDisabledDeleteTest::test_many_to_one_delete_disabled":0.118,"Tests\\ManyToOneDisabledDeleteTest::test_many_to_one_user_delete_disabled":0.103,"Tests\\ManyToOneDisabledDeleteTest::test_many_to_one_term_delete_disabled":0.07,"Tests\\ManyToOneTest::test_many_to_one_relationship":0.18,"Tests\\ManyToOneTest::test_many_to_one_user_relationship":0.098,"Tests\\ManyToOneTest::test_many_to_one_term_relationship":0.137,"Tests\\OneToManyDeleteTest::test_one_to_many_delete":0.182,"Tests\\OneToManyDeleteTest::test_one_to_many_user_delete":0.115,"Tests\\OneToManyDeleteTest::test_one_to_many_term_delete":0.132,"Tests\\OneToManyDisabledDeleteTest::test_one_to_many_delete_disabled":0.139,"Tests\\OneToManyDisabledDeleteTest::test_one_to_many_user_delete_disabled":0.076,"Tests\\OneToManyDisabledDeleteTest::test_one_to_many_term_delete_disabled":0.08,"Tests\\OneToManyTest::test_one_to_many_relationships":0.197,"Tests\\OneToManyTest::test_explicit_one_to_many":0.2,"Tests\\OneToManyTest::test_one_to_many_user_relationships":0.18,"Tests\\OneToOneDeleteTest::test_one_to_one_delete":0.07,"Tests\\OneToOneDeleteTest::test_one_to_one_user_delete":0.066,"Tests\\OneToOneDeleteTest::test_one_to_one_term_delete":0.071,"Tests\\OneToOneDisabledDeleteTest::test_one_to_one_delete_disabled":0.047,"Tests\\OneToOneDisabledDeleteTest::test_one_to_one_user_disabled_delete":0.041,"Tests\\OneToOneDisabledDeleteTest::test_one_to_one_term_delete_disabled":0.044,"Tests\\OneToOneTest::test_one_to_one_relationship":0.079,"Tests\\OneToOneTest::test_one_to_one_user_relationship":0.069,"Tests\\OneToOneTest::test_one_to_one_term_relationship":0.072,"Tests\\SetNotationRelationshipsTest::test_it_extracts_collection_names":0.01,"Tests\\SetNotationRelationshipsTest::test_it_extracts_collection_names_without_sets":0.011}}
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) {
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) {
if (EventStack::count() > 1 || $this->manager->processor()->isProcessingRelationships()) {
return;
}

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

foreach ($results->added as $addedId) {
if (! $this->shouldProcessRelationship($relationship, $addedId)) {
continue;
Expand All @@ -24,5 +26,7 @@ protected function processManyToMany(ComparisonResult $results, EntryRelationshi

$this->removeItemFromEntry($relationship, $this->getEffectedEntity($relationship, $removedId));
}

$this->processingRelationships = false;
}
}
8 changes: 4 additions & 4 deletions src/Processors/Concerns/ProcessesManyToOne.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ trait ProcessesManyToOne
{
protected function processManyToOne(ComparisonResult $results, EntryRelationship $relationship)
{
if (! empty($results->added) && count($results->added) == 1 && $this->shouldProcessRelationship($relationship, $results->added[0])) {
$this->addItemToEntry($relationship, $this->getEffectedEntity($relationship, $results->added[0]));
}

foreach ($results->removed as $removedId) {
if ($this->shouldProcessRelationship($relationship, $removedId)) {
$this->removeItemFromEntry($relationship, $this->getEffectedEntity($relationship, $removedId));
}
}

if (! empty($results->added) && count($results->added) == 1 && $this->shouldProcessRelationship($relationship, $results->added[0])) {
$this->addItemToEntry($relationship, $this->getEffectedEntity($relationship, $results->added[0]));
}
}
}
30 changes: 24 additions & 6 deletions src/Processors/Concerns/ProcessesOneToMany.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,41 @@

namespace Stillat\Relationships\Processors\Concerns;

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

trait ProcessesOneToMany
{
protected function processOneToMany(ComparisonResult $results, EntryRelationship $relationship)
{
foreach ($results->added as $addedId) {
if ($this->shouldProcessRelationship($relationship, $addedId)) {
$this->setFieldValue($relationship, $this->getEffectedEntity($relationship, $addedId));
}
}

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));
}
}
}
}
49 changes: 36 additions & 13 deletions src/Processors/FillRelationshipsProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Stillat\Relationships\Processors;

use Statamic\Contracts\Entries\EntryRepository;
use Statamic\Facades\Taxonomy;
use Stillat\Relationships\Comparisons\ComparisonResult;
use Stillat\Relationships\EntryRelationship;
use Stillat\Relationships\Processors\Concerns\GetsFieldValues;
Expand Down Expand Up @@ -61,19 +62,10 @@ protected function fillRelationships($relationships)
}
}

protected function fillRelationship(EntryRelationship $relationship)
protected function processData($data, EntryRelationship $relationship)
{
$collectionEntries = $this->entries->query()
->whereIn('collection', [$relationship->leftCollection])
->where($relationship->leftField, '!=', null)
->get();

if (count($collectionEntries) == 0) {
return;
}

foreach ($collectionEntries as $entry) {
$related = $this->getFieldValue($relationship->leftField, $entry, null);
foreach ($data as $item) {
$related = $this->getFieldValue($relationship->leftField, $item, null);

if ($related == null) {
continue;
Expand All @@ -86,8 +78,39 @@ protected function fillRelationship(EntryRelationship $relationship)
$mockResults = new ComparisonResult();
$mockResults->added = $related;

$this->manager->processor()->setEntryId($entry->id())
$this->manager->processor()->setEntryId($item->id())
->processRelationship($relationship, $mockResults);
}
}

protected function fillTaxonomyRelationship(EntryRelationship $relationship)
{
$terms = Taxonomy::find($relationship->taxonomyName)->queryTerms()->get();

if (count($terms) === 0) {
return;
}

$this->processData($terms, $relationship);
}

protected function fillRelationship(EntryRelationship $relationship)
{
if ($relationship->leftCollection === '[term]') {
$this->fillTaxonomyRelationship($relationship);

return;
}

$collectionEntries = $this->entries->query()
->whereIn('collection', [$relationship->leftCollection])
->where($relationship->leftField, '!=', null)
->get();

if (count($collectionEntries) == 0) {
return;
}

$this->processData($collectionEntries, $relationship);
}
}
68 changes: 60 additions & 8 deletions src/Processors/RelationshipProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@

class RelationshipProcessor
{
use ProcessesManyToMany,
ProcessesOneToOne,
use GetsFieldValues,
ProcessesManyToMany,
ProcessesManyToOne,
ProcessesOneToMany,
GetsFieldValues;
ProcessesOneToOne;

/**
* @var EntryRepository
Expand Down Expand Up @@ -85,6 +85,17 @@ class RelationshipProcessor

protected $isDry = false;

protected $observed = [];

protected $processingRelationships = false;

protected $dependencies = [];

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

public function setIsDeleting($isDeleting = true)
{
$this->isDelete = $isDeleting;
Expand Down Expand Up @@ -164,7 +175,11 @@ protected function updateEntry($entry, $relationship)

if (! $this->isDry) {
if ($relationship->withEvents) {
$entry->save();
if ($entry instanceof LocalizedTerm) {
$entry->term()->save();
} else {
$entry->save();
}
} else {
if ($entry instanceof LocalizedTerm) {
$entry->term()->saveQuietly();
Expand Down Expand Up @@ -222,15 +237,24 @@ protected function getEffectedEntries($relationship, $entryIds)
/** @var EntryCollection $entries */
$entries = $this->entries->query()->whereIn('id', $entryIds)->get();

$this->effectedEntries = $entries->keyBy('id')->all();
$this->effectedEntries = array_merge(
$this->effectedEntries,
$entries->keyBy('id')->all()
);
} elseif ($relationship->rightType == 'user') {
$users = $this->getUsersByIds($entryIds);

$this->effectedUsers = $users->keyBy('id')->all();
$this->effectedUsers = array_merge(
$this->effectedUsers,
$users->keyBy('id')->all()
);
} elseif ($relationship->rightType == 'term') {
$terms = $this->getTermsByIds($relationship, $entryIds);

$this->effectedTerms = $terms->keyBy('slug')->all();
$this->effectedTerms = array_merge(
$this->effectedTerms,
$terms->keyBy('slug')->all()
);
}
}

Expand Down Expand Up @@ -285,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 @@ -304,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 @@ -332,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 Expand Up @@ -446,7 +492,13 @@ protected function removeItemFromEntry($relationship, $entry)

$this->updateEntry($entry, $relationship);
} else {
$entry->set($relationship->rightField, null);
$value = null;

if (is_array($rightReference) && count($rightReference) > 0) {
$value = $rightReference;
}

$entry->set($relationship->rightField, $value);
$this->updateEntry($entry, $relationship);
}
}
Expand Down
Loading

0 comments on commit 5b0908d

Please sign in to comment.