Skip to content

Commit

Permalink
Add eager-loaded fields to element recursively
Browse files Browse the repository at this point in the history
  • Loading branch information
bencroker committed Jul 23, 2024
1 parent 33c8591 commit 508ed44
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 9 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Release Notes for Blitz

## 4.21.0 - Unreleased

### Added

- Added the ability to track eager-loaded relation fields nested inside matrix blocks ([#657](https://github.com/putyourlightson/craft-blitz/issues/657)).

## 4.20.0 - 2024-07-22

### Added
Expand Down
35 changes: 29 additions & 6 deletions src/services/GenerateCacheService.php
Original file line number Diff line number Diff line change
Expand Up @@ -229,12 +229,7 @@ public function addElement(ElementInterface $element): void
$this->generateData->addElement($element);

// Add eager-loaded fields since they will be accessed directly on the element
$fieldHandles = array_keys(CustomFieldBehavior::$fieldHandles);
foreach ($fieldHandles as $handle) {
if ($element->hasEagerLoadedElements($handle)) {
$this->generateData->addElementTrackField($element, $handle);
}
}
$this->addEagerLoadedFields($element);

// Replace the custom field behavior with our own (only once)
$customFields = $element->getBehavior('customFields');
Expand Down Expand Up @@ -625,6 +620,31 @@ public function saveOutput(string $output, SiteUriModel $siteUri, int $duration
}
}

/**
* Adds eager-loaded fields to an element recursively.
* https://github.com/putyourlightson/craft-blitz/issues/657
*
* @since 4.21.0
*/
private function addEagerLoadedFields(ElementInterface $element): void
{
$fieldHandles = array_keys(CustomFieldBehavior::$fieldHandles);

foreach ($fieldHandles as $handle) {
if ($element->hasEagerLoadedElements($handle)) {
$this->generateData->addElementTrackField($element, $handle);
$eagerLoadedElements = $element->getEagerLoadedElements($handle);

foreach ($eagerLoadedElements as $eagerLoadedElement) {
$this->addEagerLoadedFields($eagerLoadedElement);
}
}
}
}

/**
* Returns whether elements of a given type should be tracked.
*/
private function shouldTrackElementsOfType(string $elementType): bool
{
// Don’t proceed if element tracking is disabled
Expand All @@ -646,6 +666,9 @@ private function shouldTrackElementsOfType(string $elementType): bool
return true;
}

/**
* Returns whether element queries of a given type should be tracked.
*/
private function shouldTrackElementQueriesOfType(string $elementType): bool
{
// Don’t proceed if element query tracking is disabled
Expand Down
2 changes: 2 additions & 0 deletions tests/TESTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ _Tests the saving of cached values, element cache records and element query reco
![Pass](https://raw.githubusercontent.com/putyourlightson/craft-generate-test-spec/main/icons/pass.svg) Element cache record is saved without custom fields.
![Pass](https://raw.githubusercontent.com/putyourlightson/craft-generate-test-spec/main/icons/pass.svg) Element cache record is saved with custom fields.
![Pass](https://raw.githubusercontent.com/putyourlightson/craft-generate-test-spec/main/icons/pass.svg) Element cache record is saved with eager-loaded custom fields.
![Pass](https://raw.githubusercontent.com/putyourlightson/craft-generate-test-spec/main/icons/pass.svg) Element cache record is saved with nested eager-loaded custom fields.
![Pass](https://raw.githubusercontent.com/putyourlightson/craft-generate-test-spec/main/icons/pass.svg) Element cache record is saved with eager-loaded matrix fields.
![Pass](https://raw.githubusercontent.com/putyourlightson/craft-generate-test-spec/main/icons/pass.svg) Element cache record is saved with eager-loaded custom fields in variable.
![Pass](https://raw.githubusercontent.com/putyourlightson/craft-generate-test-spec/main/icons/pass.svg) Element cache record is saved for preloaded single.
![Pass](https://raw.githubusercontent.com/putyourlightson/craft-generate-test-spec/main/icons/pass.svg) Element cache record is saved with eager-loaded custom fields for preloaded single.
Expand Down
45 changes: 43 additions & 2 deletions tests/pest/Feature/GenerateCacheTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@
});

test('Element cache record is saved with eager-loaded custom fields', function() {
createEntry();
$entry = Entry::find()->with(['relatedTo'])->one();
Blitz::$plugin->generateCache->addElement($entry);
Blitz::$plugin->generateCache->save(createOutput(), createSiteUri());
Expand All @@ -132,6 +133,46 @@
->toHaveRecordCount(1, ['elementId' => $entry->id]);
});

test('Element cache record is saved with nested eager-loaded custom fields', function() {
$childEntry = createEntryWithRelationship();
$entry = createEntryWithRelationship([$childEntry]);
Craft::$app->elements->eagerLoadElements(Entry::class, [$entry], ['relatedTo.relatedTo']);
Blitz::$plugin->generateCache->addElement($entry);
Blitz::$plugin->generateCache->save(createOutput(), createSiteUri());

expect(ElementCacheRecord::class)
->toHaveRecordCount(1, ['elementId' => $entry->id])
->toHaveRecordCount(1, ['elementId' => $childEntry->id])
->and(ElementFieldCacheRecord::class)
->toHaveRecordCount(1, ['elementId' => $entry->id])
->toHaveRecordCount(1, ['elementId' => $childEntry->id]);
});

test('Element cache record is saved with eager-loaded matrix fields', function() {
$childEntry = createEntryWithRelationship();
$entry = createEntry(customFields: [
'matrix' => [
[
'type' => 'test',
'fields' => [
'test' => '1',
'relatedTo' => [$childEntry->id],
],
],
],
]);
Craft::$app->elements->eagerLoadElements(Entry::class, [$entry], ['matrix.test:relatedTo.relatedTo']);
Blitz::$plugin->generateCache->addElement($entry);
Blitz::$plugin->generateCache->save(createOutput(), createSiteUri());

expect(ElementCacheRecord::class)
->toHaveRecordCount(1, ['elementId' => $entry->id])
->toHaveRecordCount(1, ['elementId' => $childEntry->id])
->and(ElementFieldCacheRecord::class)
->toHaveRecordCount(1, ['elementId' => $entry->id])
->toHaveRecordCount(1, ['elementId' => $childEntry->id]);
});

test('Element cache record is saved with eager-loaded custom fields in variable', function() {
$entry = createEntryWithRelationship();
Craft::$app->elements->eagerLoadElements(Entry::class, [$entry], ['relatedTo']);
Expand Down Expand Up @@ -197,8 +238,8 @@
});

test('Element cache records are saved respecting the criteria for eager-loaded relation field queries', function() {
$qualifyingEntry = createEntry(params: ['plainText' => '1']);
$nonQualifyingEntry = createEntry(params: ['plainText' => '2']);
$qualifyingEntry = createEntry(customFields: ['plainText' => '1']);
$nonQualifyingEntry = createEntry(customFields: ['plainText' => '2']);
$entry = createEntryWithRelationship([$qualifyingEntry, $nonQualifyingEntry]);

Blitz::$plugin->generateCache->reset();
Expand Down
6 changes: 5 additions & 1 deletion tests/pest/Helpers.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,19 @@ function createSiteUri(int $siteId = 1, string $uri = 'page'): SiteUriModel
]);
}

function createEntry(bool $enabled = true, array $params = [], bool $batchMode = false): Entry
function createEntry(bool $enabled = true, array $params = [], array $customFields = [], bool $batchMode = false): Entry
{
$originalBatchMode = Blitz::$plugin->refreshCache->batchMode;
Blitz::$plugin->refreshCache->batchMode = $batchMode;

/** @var Entry $entryFactory */
$entryFactory = EntryFactory::factory();
foreach ($params as $key => $value) {
$entryFactory->$key($value);
}
foreach ($customFields as $key => $value) {
$entryFactory->$key($value);
}

/** @var Entry $entry */
$entry = $entryFactory->section(App::env('TEST_CHANNEL_SECTION_HANDLE'))
Expand Down

0 comments on commit 508ed44

Please sign in to comment.