Skip to content

Commit

Permalink
Get custom sources’ field layouts from an element query
Browse files Browse the repository at this point in the history
  • Loading branch information
brandonkelly committed Dec 13, 2024
1 parent feae518 commit 453950f
Show file tree
Hide file tree
Showing 9 changed files with 56 additions and 83 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG-WIP.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,15 @@

### Extensibility
- Added `craft\base\Element::EVENT_DEFINE_ALT_ACTIONS`. ([#16294](https://github.com/craftcms/cms/pull/16294))
- Added `craft\base\ElementInterface::fieldLayoutsForCustomSource()`.
- Added `craft\base\ElementInterface::getAltActions()`. ([#16294](https://github.com/craftcms/cms/pull/16294))
- Added `craft\base\conditions\BaseElementSelectConditionRule::allowMultiple()`.
- Added `craft\base\conditions\BaseElementSelectConditionRule::getElementIds()`.
- Added `craft\base\conditions\BaseElementSelectConditionRule::setElementIds()`.
- Added `craft\elements\User::$affiliatedSiteId`.
- Added `craft\elements\User::getAffiliatedSite()`.
- Added `craft\elements\conditions\entries\FieldConditionRule`.
- Added `craft\elements\db\ElementQueryInterface::getFieldLayouts()`.
- Added `craft\elements\db\NestedElementQueryTrait::fieldLayouts()`.
- Added `craft\events\DefineAltActionsEvent`.
- Added `craft\fields\BaseRelationField::gqlFieldArguments()`.
- Added `craft\fields\Color::$allowCustomColors`. ([#16249](https://github.com/craftcms/cms/pull/16249))
Expand Down
8 changes: 0 additions & 8 deletions src/base/Element.php
Original file line number Diff line number Diff line change
Expand Up @@ -1033,14 +1033,6 @@ protected static function defineFieldLayouts(?string $source): array
return Craft::$app->getFields()->getLayoutsByType(static::class);
}

/**
* @inheritdoc
*/
public static function fieldLayoutsForCustomSource(array $config): array
{
return Craft::$app->getFields()->getLayoutsByType(static::class);
}

/**
* @inheritdoc
*/
Expand Down
9 changes: 0 additions & 9 deletions src/base/ElementInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -333,15 +333,6 @@ public static function sourcePath(string $sourceKey, string $stepKey, ?string $c
*/
public static function fieldLayouts(?string $source): array;

/**
* Returns all the field layouts associated with elements from the given custom source.
*
* @param array $config The custom source config
* @return FieldLayout[]
* @since 5.6.0
*/
public static function fieldLayoutsForCustomSource(array $config): array;

/**
* Modifies a custom source’s config, before it’s returned by [[craft\services\ElementSources::getSources()]]
*
Expand Down
58 changes: 0 additions & 58 deletions src/elements/Entry.php
Original file line number Diff line number Diff line change
Expand Up @@ -393,64 +393,6 @@ protected static function defineFieldLayouts(?string $source): array
return array_map(fn(EntryType $entryType) => $entryType->getFieldLayout(), $entryTypes);
}

/**
* @interitdoc
*/
public static function fieldLayoutsForCustomSource(array $config): array
{
if (empty($config['condition']['conditionRules'])) {
return parent::fieldLayoutsForCustomSource($config);
}

// see if it specifies any entry types
/** @var TypeConditionRule|null $entryTypeRule */
$entryTypeRule = ArrayHelper::firstWhere(
$config['condition']['conditionRules'],
fn(array $rule) => $rule['class'] === TypeConditionRule::class,
);
$entryTypeOptions = $entryTypeRule['operator'] === 'in' && !empty($entryTypeRule['values'])
? $entryTypeRule['values']
: null;

if ($entryTypeOptions) {
$fieldLayouts = [];
$entriesService = Craft::$app->getEntries();
foreach ($entryTypeOptions as $entryTypeUid) {
$entryType = $entriesService->getEntryTypeByUid($entryTypeUid);
if ($entryType) {
$fieldLayout = $entryType->getFieldLayout();
$fieldLayouts[$fieldLayout->uid] = $fieldLayout;
}
}
return array_values($fieldLayouts);
}

/** @var SectionConditionRule|null $sectionRule */
$sectionRule = ArrayHelper::firstWhere(
$config['condition']['conditionRules'],
fn(array $rule) => $rule['class'] === SectionConditionRule::class,
);
$sectionOptions = $sectionRule['operator'] === 'in' && !empty($sectionRule['values'])
? $sectionRule['values']
: null;

if ($sectionOptions) {
$fieldLayouts = [];
foreach ($sectionOptions as $sectionUid) {
$section = Craft::$app->getEntries()->getSectionByUid($sectionUid);
if ($section) {
foreach ($section->getEntryTypes() as $entryType) {
$fieldLayout = $entryType->getFieldLayout();
$fieldLayouts[$fieldLayout->uid] = $fieldLayout;
}
}
}
return array_values($fieldLayouts);
}

return parent::fieldLayoutsForCustomSource($config);
}

/**
* @inheritdoc
*/
Expand Down
8 changes: 8 additions & 0 deletions src/elements/db/ElementQuery.php
Original file line number Diff line number Diff line change
Expand Up @@ -2521,6 +2521,14 @@ protected function customFields(): array
return $fields;
}

/**
* @inheritdoc
*/
public function getFieldLayouts(): array
{
return $this->fieldLayouts();
}

/**
* Returns the field layouts whose custom fields should be returned by [[customFields()]].
*
Expand Down
9 changes: 9 additions & 0 deletions src/elements/db/ElementQueryInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use craft\base\ElementInterface;
use craft\db\Query;
use craft\elements\ElementCollection;
use craft\models\FieldLayout;
use yii\base\Arrayable;
use yii\db\Connection;
use yii\db\QueryInterface;
Expand Down Expand Up @@ -1658,4 +1659,12 @@ public function createElement(array $row): ElementInterface;
* @since 3.6.0
*/
public function afterPopulate(array $elements): array;

/**
* Returns the field layouts that could be associated with the resulting elements.
*
* @return FieldLayout[]
* @since 5.6.0
*/
public function getFieldLayouts(): array;
}
6 changes: 5 additions & 1 deletion src/elements/db/EntryQuery.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ class EntryQuery extends ElementQuery implements NestedElementQueryInterface
use NestedElementQueryTrait {
__set as nestedTraitSet;
cacheTags as nestedTraitCacheTags;
fieldLayouts as nestedTraitFieldLayouts;
}

// General parameters
Expand Down Expand Up @@ -1245,6 +1246,9 @@ protected function cacheTags(): array
*/
protected function fieldLayouts(): array
{
$this->_normalizeTypeId();
$this->_normalizeSectionId();

if ($this->typeId || $this->sectionId) {
$fieldLayouts = [];
$sectionsService = Craft::$app->getEntries();
Expand All @@ -1268,6 +1272,6 @@ protected function fieldLayouts(): array
return $fieldLayouts;
}

return parent::fieldLayouts();
return $this->nestedTraitFieldLayouts();
}
}
23 changes: 23 additions & 0 deletions src/elements/db/NestedElementQueryTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -336,4 +336,27 @@ protected function cacheTags(): array

return $tags;
}

/**
* @inheritdoc
*/
protected function fieldLayouts(): array
{
$this->normalizeFieldId();

if ($this->fieldId) {
$fieldLayouts = [];
foreach ($this->fieldId as $fieldId) {
$field = Craft::$app->getFields()->getFieldById($fieldId);
if ($field instanceof ElementContainerFieldInterface) {
foreach ($field->getFieldLayoutProviders() as $provider) {
$fieldLayouts[] = $provider->getFieldLayout();
}
}
}
return $fieldLayouts;
}

return parent::fieldLayouts();
}
}
15 changes: 9 additions & 6 deletions src/services/ElementSources.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
use craft\base\PreviewableFieldInterface;
use craft\base\SortableFieldInterface;
use craft\db\CoalesceColumnsExpression;
use craft\elements\conditions\ElementConditionInterface;
use craft\errors\SiteNotFoundException;
use craft\events\DefineSourceSortOptionsEvent;
use craft\events\DefineSourceTableAttributesEvent;
Expand All @@ -21,7 +22,6 @@
use craft\helpers\Cp;
use craft\helpers\StringHelper;
use craft\models\FieldLayout;
use Illuminate\Support\Arr;
use Illuminate\Support\Collection;
use yii\base\Component;

Expand Down Expand Up @@ -278,12 +278,15 @@ public function getFieldLayoutsForSource(string $elementType, string $sourceKey)
{
// Don't bother the element type for custom sources
if (str_starts_with($sourceKey, 'custom:')) {
$sourceConfigs = $this->_sourceConfigs($elementType);
$sourceConfig = Arr::first($sourceConfigs, fn(array $config) => ($config['key'] ?? null) === $sourceKey);
if ($sourceConfig) {
return $elementType::fieldLayoutsForCustomSource($sourceConfig);
$source = $this->_sourceConfig($elementType, $sourceKey);
if (empty($source['condition'])) {
return Craft::$app->getFields()->getLayoutsByType($elementType);
}
return Craft::$app->getFields()->getLayoutsByType($elementType);
/** @var ElementConditionInterface $condition */
$condition = Craft::$app->getConditions()->createCondition($source['condition']);
$query = $elementType::find();
$condition->modifyQuery($query);
return $query->getFieldLayouts();
}

if (!isset($this->_fieldLayouts[$elementType][$sourceKey])) {
Expand Down

0 comments on commit 453950f

Please sign in to comment.