Skip to content

Using joinFields causes only one subpage to show in results #2079

@tuomassalo

Description

@tuomassalo

Short description of the issue

When a page has a Page fields that is joined with joinFields, only one of the subpages is returned.

Expected behavior

Adding joinFields should not affect the result, only performance.

Actual behavior

Adding joinFields misses other subpages.

Steps to reproduce the issue

The script below creates a parent and child template, p and c, and Page field c1_ref. Then it adds a parent page and two child pages that are added to the c1_ref field of the parent page.

If run without GET params, it show both child fields. If run with ?join, it shows only the first one.

Possible fix

This all seems quite messy, but I believe the following patch could fix the problem:

--- wire/modules/Fieldtype/FieldtypePage.module
+++ wire/modules/Fieldtype/FieldtypePage.module
@@ -219,7 +219,14 @@ class FieldtypePage extends FieldtypeMulti implements Module, ConfigurableModule
                if($value instanceof PageArray) {
                        $pageArray = $value;
                } else {
-                       if(!is_array($value)) $value = $this->wakeupValueToArray($value);
+
+                       if(!is_array($value)) {
+                               if(strrpos($value, FieldtypeMulti::multiValueSeparator)) {
+                                       $value = explode(FieldtypeMulti::multiValueSeparator, $value);
+                               } else {
+                                       $value = $this->wakeupValueToArray($value);
+                               }
+                       }
                        if(count($value)) {
                                $pageArray = $this->wire()->pages->getById($value, $template);
                        } else {

Setup/Environment

  • ProcessWire version: latest dev
  • (Optional) PHP version: 8.4
  • Database version: Mysql 8.0.39

The script:

<?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).
$wire->database->exec("DELETE FROM pages WHERE templates_id IN (SELECT id FROM templates WHERE name IN ('p', 'c'))");

// Remove templates
foreach(['p','c'] as $t) {
    $template = $templates->get($t);
    if ($template) $templates->delete($template);
}

// Remove fields
foreach(['c1_ref'] as $f) {
    $field = $fields->get($f);
    if ($field) $fields->delete($field);
}

// Create templates and field.
$pTemplate = $templates->add('p');
$pTemplate->save();

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

    $cField = $fields->makeItem();
    $cField->name = 'c1_ref';
    $cField->type = 'Page';
    $cField->label = 'c1_ref';;
    $cField->template_id = $cTemplate->id;
    $cField->parent_id = 1;
    $cField->save();
    $pTemplate->fields->add($cField);
    $pTemplate->save();

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

for($i=1; $i <= 2; $i++) {
    $c1 = $pages->add('c', '/', "child1-$i");
    $parent->c1_ref->add($c1);
}
$parent->save();

//////// Now everything is set up.

$loadOptions = isset($_GET['join']) ? ['joinFields' => ['c1_ref']] : [];

$result = $wire->pages->get($parent->id, ['loadOptions' => $loadOptions]);
echo "c1_ref count: " . count($result->c1_ref) . "\n";

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions