diff --git a/wire/core/Field.php b/wire/core/Field.php index 8529eb66..05a4c81c 100644 --- a/wire/core/Field.php +++ b/wire/core/Field.php @@ -38,6 +38,7 @@ * @property array $allowContexts Names of settings that are custom configured to be allowed for context. #pw-group-properties * @property bool|int|null $flagUnique Non-empty value indicates request for, or presence of, Field::flagUnique flag. #pw-internal * @property Fieldgroup|null $_contextFieldgroup Fieldgroup field is in context for or null if not in context. #pw-internal + * @property true|null $distinctAutojoin When true and flagAutojoin is set, a distinct autojoin will be used. 3.0.208+ #pw-internal * * Common Inputfield properties that Field objects store: * @property int|bool|null $required Whether or not this field is required during input #pw-group-properties @@ -812,7 +813,7 @@ class Field extends WireData implements Saveable, Exportable { $ids[] = (int) $role->id; } else if(is_string($role) && strlen($role)) { $rolePage = $this->wire()->roles->get($role); - if($rolePage && $rolePage->id) { + if($rolePage instanceof Role && $rolePage->id) { $ids[] = $rolePage->id; } else { $this->error("Unknown role '$role'"); diff --git a/wire/core/FieldtypeMulti.php b/wire/core/FieldtypeMulti.php index 3a47eb1b..c32eaa81 100644 --- a/wire/core/FieldtypeMulti.php +++ b/wire/core/FieldtypeMulti.php @@ -875,6 +875,7 @@ abstract class FieldtypeMulti extends Fieldtype { $schema = $this->trimDatabaseSchema($this->getDatabaseSchema($field)); $fieldName = $this->database->escapeCol($field->name); $separator = self::multiValueSeparator; + if($field->distinctAutojoin) $table = "DISTINCT $table"; foreach($schema as $key => $unused) { $query->select("GROUP_CONCAT($table.$key SEPARATOR '$separator') AS `{$fieldName}__$key`"); // QA } diff --git a/wire/core/PagesLoader.php b/wire/core/PagesLoader.php index 434e2c6d..20733d22 100644 --- a/wire/core/PagesLoader.php +++ b/wire/core/PagesLoader.php @@ -629,7 +629,8 @@ class PagesLoader extends Wire { $languages = $this->wire()->languages; $languageIds = array(); $templatesById = array(); - + $tmpAutojoinFields = array(); // fields to autojoin temporarily, just during this method call + if($languages) foreach($languages as $language) $languageIds[$language->id] = $language->id; $options['findIDs'] = $useCache ? 4 : 3; @@ -705,16 +706,22 @@ class PagesLoader extends Wire { $page->setForced($key, $value); } } - - // set blank values where joinField didn't appear on page row + foreach($joinFields as $joinField) { - if(isset($row["{$joinField}__data"])) continue; if(empty($joinResults[$joinField])) continue; // field did not support autojoin if(!$template->fieldgroup->hasField($joinField)) continue; $field = $page->getField($joinField); if(!$field || !$field->type) continue; - $blankValue = $field->type->getBlankValue($page, $field); - $page->setFieldValue($field->name, $blankValue, false); + if(isset($row["{$joinField}__data"])) { + if(!$field->hasFlag(Field::flagAutojoin)) { + $field->addFlag(Field::flagAutojoin); + $tmpAutojoinFields[$field->id] = $field; + } + } else { + // set blank values where joinField didn't appear on page row + $blankValue = $field->type->getBlankValue($page, $field); + $page->setFieldValue($field->name, $blankValue, false); + } } $page->setIsLoaded(true); @@ -731,6 +738,10 @@ class PagesLoader extends Wire { $pageArray->setTotal($paginationTotal); $pageArray->resetTrackChanges(true); + foreach($tmpAutojoinFields as $field) { /** @var Field $field */ + $field->removeFlag(Field::flagAutojoin)->untrackChange('flags'); + } + if($useCache) { $selectorString = $pageArray->getSelectors(true); $this->pages->cacher()->selectorCache($selectorString, $options, $pageArray); diff --git a/wire/modules/Fieldtype/FieldtypePage.module b/wire/modules/Fieldtype/FieldtypePage.module index 4a01d52a..5e7d5136 100644 --- a/wire/modules/Fieldtype/FieldtypePage.module +++ b/wire/modules/Fieldtype/FieldtypePage.module @@ -914,6 +914,19 @@ class FieldtypePage extends FieldtypeMulti implements Module, ConfigurableModule return $query; } + /** + * Return the query used for Autojoining this field + * + * @param Field $field + * @param DatabaseQuerySelect $query + * @return DatabaseQuerySelect|null + * + */ + public function getLoadQueryAutojoin(Field $field, DatabaseQuerySelect $query) { + $field->setQuietly('distinctAutojoin', true); + return parent::getLoadQueryAutojoin($field, $query); + } + /** * Update a DatabaseQuerySelect object to match a Page *