diff --git a/CHANGELOG-WIP.md b/CHANGELOG-WIP.md index 2ec5c4a165d..61ad62f9265 100644 --- a/CHANGELOG-WIP.md +++ b/CHANGELOG-WIP.md @@ -25,6 +25,7 @@ - Added the `affiliatedSite` and `affiliatedSiteId` user query and GraphQL params. ([#16174](https://github.com/craftcms/cms/pull/16174)) - Added the `affiliatedSiteHandle` and `affiliatedSiteId` user GraphQL field. ([#16174](https://github.com/craftcms/cms/pull/16174)) - It’s now possible to pass nested custom field value keys into element queries’ `orderBy` and `select` params (e.g. `myDateField.tz`). ([#16157](https://github.com/craftcms/cms/discussions/16157)) +- It’s now possible to set Link field values to arrays with `value` keys set to element instances or IDs. ([#16255](https://github.com/craftcms/cms/pull/16255)) ### Extensibility - Added `craft\base\conditions\BaseElementSelectConditionRule::allowMultiple()`. diff --git a/src/fields/Link.php b/src/fields/Link.php index 3ce074ed15f..763926607bb 100644 --- a/src/fields/Link.php +++ b/src/fields/Link.php @@ -479,7 +479,11 @@ public function normalizeValue(mixed $value, ?ElementInterface $element): mixed 'urlSuffix' => $this->showUrlSuffixField ? ($value['urlSuffix'] ?? null) : null, 'target' => $this->showTargetField ? ($value['target'] ?? null) : null, ]); - $value = trim($value['value'] ?? $value[$typeId]['value'] ?? ''); + $value = $value['value'] ?? $value[$typeId]['value'] ?? ''; + + if (is_string($value)) { + $value = trim($value); + } if (!$value) { return null; @@ -499,7 +503,11 @@ public function normalizeValue(mixed $value, ?ElementInterface $element): mixed $linkType = Component::createComponent($type, BaseLinkType::class); } - $value = $linkType->normalizeValue(str_replace(' ', '+', $value)); + if (is_string($value)) { + $value = str_replace(' ', '+', $value); + } + + $value = $linkType->normalizeValue($value); } else { if (!$value) { return null; diff --git a/src/fields/linktypes/BaseElementLinkType.php b/src/fields/linktypes/BaseElementLinkType.php index ab1aa124a3d..b8f9e0ca086 100644 --- a/src/fields/linktypes/BaseElementLinkType.php +++ b/src/fields/linktypes/BaseElementLinkType.php @@ -14,6 +14,7 @@ use craft\helpers\Html; use craft\services\ElementSources; use Illuminate\Support\Collection; +use yii\base\InvalidArgumentException; /** * Base element link type. @@ -198,11 +199,47 @@ protected function selectionCriteria(): array ]; } + /** + * @inheritdoc + */ public function validateValue(string $value, ?string &$error = null): bool { return true; } + /** + * @inheritdoc + */ + public function normalizeValue(ElementInterface|int|string $value): string + { + if ($value instanceof ElementInterface) { + if (!is_a($value, static::elementType())) { + throw new InvalidArgumentException(sprintf('$value must be an %s instance, ID, or reference tag.', static::elementType()::lowerDisplayName())); + } + $value = sprintf('{%s:%s@%s:url}', + static::elementType()::refHandle(), + $value->id, + $value->siteId, + ); + } + if (is_numeric($value)) { + $value = sprintf('{%s:%s@%s:url}', + static::elementType()::refHandle(), + $value, + Craft::$app->getSites()->getCurrentSite()->id, + ); + } + + return parent::normalizeValue($value); + } + + /** + * Returns an Element that the field is supposed to link to. + * + * @param string|null $value + * @return ElementInterface|null + * @throws \craft\errors\SiteNotFoundException + */ public function element(?string $value): ?ElementInterface { if (