processwire / processwire-issues

ProcessWire issue reports.
45 stars 2 forks source link

preload() incorrectly includes a Page field as preloadable when preceded by a different kind of Page field #1992

Open tuomassalo opened 1 week ago

tuomassalo commented 1 week ago

Short description of the issue

preload(['pagefield2']) works as expected (ignoring pagefield2), but preload(['pagefield1', 'pagefield2']) breaks pagefield2 value.

Expected behavior

preload(['pagefield1', 'pagefield2'] should only affect performance.

Actual behavior

Ater preload(['pagefield1', 'pagefield2'], $page->pagefield2 only includes one value even when the field has multiple values.

Optional: Suggestion for a possible fix

I believe the problem is with caching by only field type here, while additional field attributes (derefAsPage) should also be taken into account.

Also, the experimental useFieldtypeMulti option fixes the problem.

Steps to reproduce the issue

Run this script with ?bug to trigger the problem: only child1 is printed.

<?php

$processwirePath = '/var/www/html/';
include($processwirePath . 'index.php');
header('Content-Type: text/plain');

////// Install fixture templates, field and pages.
////// First, clean up previous run (if any).

// Remove pages with template 'p' or 'c'.
$pagesToRemove = $pages->find("template=p|c");
foreach ($pagesToRemove as $page) $pages->delete($page, true);

// Remove templates 'p' and 'c'.
$pTemplate = $templates->get('p');
if ($pTemplate) $templates->delete($pTemplate);

$cTemplate = $templates->get('c');
if ($cTemplate) $templates->delete($cTemplate);

// Remove fields 'pagefield1' and 'pagefield2' if they exist.
$field = $fields->get('pagefield1');
if ($field) $fields->delete($field);

$field = $fields->get('pagefield2');
if ($field) $fields->delete($field);

// Create templates and fields.

$pTemplate = $templates->add('p');
$pTemplate->save();

$cTemplate = $templates->add('c');
$cTemplate->save();

$field = $fields->makeItem();
$field->name = 'pagefield1';
$field->type = 'Page';
$field->label = "pagefield1";
$field->derefAsPage = 2; // <-------------------------------- NB!
$field->template_id = [$cTemplate->id];
$field->inputfield = "InputfieldPage";
$field->parent_id = 1;
$field->save();
$pTemplate->fields->add($field);
$pTemplate->save();

$field = $fields->makeItem();
$field->name = 'pagefield2';
$field->type = 'Page';
$field->label = "pagefield2";
$field->template_id = [$cTemplate->id];
$field->inputfield = "InputfieldPage";
$field->parent_id = 1;
$field->save();
$pTemplate->fields->add($field);
$pTemplate->save();

// Create pages.
$parent = $pages->add('p', '/', 'parent-a');

$child_a1 = $pages->add('c', '/', 'child-a1');
$parent->pagefield2->add($child_a1);
$parent->save();

$child_a2 = $pages->add('c', '/', 'child-a2');
$parent->pagefield2->add($child_a2);
$parent->save();

$parent = $wire->pages->get("id=" . $parent->id);

$preloadFields = isset($_GET['bug']) ? ['pagefield1','pagefield2'] : ['pagefield2'];
$ret = $parent->preload($preloadFields, ['debug' => true]);
echo "Preload: " . json_encode($ret) . "\n";

foreach ($parent->pagefield2 as $child) {
    echo "  Child: " . $child->name . "\n";
}

Setup/Environment

ryancramerdesign commented 1 week ago

@tuomassalo

I believe the problem is with caching by only field type here, while additional field attributes (derefAsPage) should also be taken into account.

You are right, I can see that would be an issue without attempting further. I have updated it so correct that, though please let me know if you still experience any issues with it. Thanks!