Skip to content

Commit

Permalink
Entry condition rule improvements
Browse files Browse the repository at this point in the history
Resolves #16270
  • Loading branch information
brandonkelly committed Dec 5, 2024
1 parent 51d40ab commit b8fe7e1
Show file tree
Hide file tree
Showing 7 changed files with 146 additions and 61 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG-WIP.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
- Added support for setting site-specific email setting overrides. ([#16187](https://github.com/craftcms/cms/pull/16187))
- Added the “View users” user permission. ([#16206](https://github.com/craftcms/cms/pull/16206))
- Added the “GraphQL Mode” Link field setting. ([#16237](https://github.com/craftcms/cms/pull/16237))
- Added the “Field” entry condition rule, which replaces “Matrix field”, includes a “has a value” operator. ([#16270](https://github.com/craftcms/cms/discussions/16270))
- Section condition rules now have a “has a value” operator. ([#16270](https://github.com/craftcms/cms/discussions/16270))
- The Queue Manager utility now shows jobs’ class names. ([#16228](https://github.com/craftcms/cms/pull/16228))

### Development
Expand All @@ -42,9 +44,11 @@
- Added `craft\mail\Mailer::$siteId`.
- Added `craft\mail\Mailer::$siteOverrides`.
- Added `craft\models\MailSettings::$siteOverrides`.
- Added `craft\elements\conditions\entries\FieldConditionRule`.
- `craft\elements\NestedElementManager::getIndexHtml()` now supports passing `defaultSort` in the `$config` array. ([#16236](https://github.com/craftcms/cms/discussions/16236))
- `craft\helpers\Cp::elementIndexHtml()` now supports passing `defaultSort` in the `$config` array, when `sources` is `null`. ([#16236](https://github.com/craftcms/cms/discussions/16236))
- `craft\models\Site` now implements `craft\base\Chippable`.
- `craft\elements\conditions\entries\MatrixFieldConditionRule` is now an alias of `FieldConditionRule`.
- Sortable checkbox selects now always display the selected options first on initial render.

### System
Expand Down
4 changes: 4 additions & 0 deletions src/base/conditions/BaseMultiSelectConditionRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ abstract protected function options(): array;
*/
protected function inputHtml(): string
{
if (!in_array($this->operator, [self::OPERATOR_IN, self::OPERATOR_NOT_IN])) {
return '';
}

$multiSelectId = 'multiselect';

return
Expand Down
2 changes: 1 addition & 1 deletion src/elements/conditions/entries/EntryCondition.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ protected function selectableConditionRules(): array
PostDateConditionRule::class,
SavableConditionRule::class,
SectionConditionRule::class,
MatrixFieldConditionRule::class,
FieldConditionRule::class,
TypeConditionRule::class,
ViewableConditionRule::class,
]);
Expand Down
103 changes: 103 additions & 0 deletions src/elements/conditions/entries/FieldConditionRule.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
<?php

namespace craft\elements\conditions\entries;

use Craft;
use craft\base\conditions\BaseMultiSelectConditionRule;
use craft\base\ElementContainerFieldInterface;
use craft\base\ElementInterface;
use craft\elements\conditions\ElementConditionRuleInterface;
use craft\elements\db\ElementQueryInterface;
use craft\elements\db\EntryQuery;
use craft\elements\Entry;
use Illuminate\Support\Collection;

/**
* Field condition rule.
*
* @author Pixel & Tonic, Inc. <[email protected]>
* @since 5.6.0
*/
class FieldConditionRule extends BaseMultiSelectConditionRule implements ElementConditionRuleInterface
{
/**
* @inheritdoc
*/
protected bool $reloadOnOperatorChange = true;

/**
* @inheritdoc
*/
public function getLabel(): string
{
return Craft::t('app', 'Field');
}

/**
* @inheritdoc
*/
public function getExclusiveQueryParams(): array
{
return ['field', 'fieldId'];
}

/**
* @inheritdoc
*/
protected function operators(): array
{
return [
...parent::operators(),
self::OPERATOR_NOT_EMPTY,
];
}

/**
* @inheritdoc
*/
protected function options(): array
{
return $this->nestedEntryFields()
->keyBy(fn(ElementContainerFieldInterface $field) => $field->uid)
->map(fn(ElementContainerFieldInterface $field) => $field->getUiLabel())
->all();
}

/**
* @inheritdoc
*/
public function modifyQuery(ElementQueryInterface $query): void
{
/** @var EntryQuery $query */
if ($this->operator === self::OPERATOR_NOT_EMPTY) {
$query->field($this->nestedEntryFields()->all());
} else {
$fieldsService = Craft::$app->getFields();
$query->fieldId($this->paramValue(fn($uid) => $fieldsService->getFieldByUid($uid)->id ?? null));
}
}

/**
* @inheritdoc
*/
public function matchElement(ElementInterface $element): bool
{
/** @var Entry $element */
if ($this->operator === self::OPERATOR_NOT_EMPTY) {
return $element->getField() !== null;
}

return $this->matchValue($element->getField()?->uid);
}

/**
* @return Collection<ElementContainerFieldInterface>
*/
private function nestedEntryFields(): Collection
{
$fieldsService = Craft::$app->getFields();
return Collection::make($fieldsService->getNestedEntryFieldTypes())
->map(fn(string $class) => $fieldsService->getFieldsByType($class))
->flatten(1);
}
}
64 changes: 7 additions & 57 deletions src/elements/conditions/entries/MatrixFieldConditionRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,65 +2,15 @@

namespace craft\elements\conditions\entries;

use Craft;
use craft\base\conditions\BaseMultiSelectConditionRule;
use craft\base\ElementInterface;
use craft\elements\conditions\ElementConditionRuleInterface;
use craft\elements\db\ElementQueryInterface;
use craft\elements\db\EntryQuery;
use craft\elements\Entry;
use craft\fields\Matrix;
use craft\helpers\ArrayHelper;

/**
* Matrix field condition rule.
*
* @author Pixel & Tonic, Inc. <[email protected]>
* @since 5.0.0
*/
class MatrixFieldConditionRule extends BaseMultiSelectConditionRule implements ElementConditionRuleInterface
{
/**
* @inheritdoc
*/
public function getLabel(): string
{
return Craft::t('app', 'Matrix field');
}

/**
* @inheritdoc
*/
public function getExclusiveQueryParams(): array
{
return ['field', 'fieldId'];
}

/** @phpstan-ignore-next-line */
if (false) {
/**
* @inheritdoc
* @since 5.0.0
* @deprecated in 5.6.0
*/
protected function options(): array
class MatrixFieldConditionRule
{
$fields = Craft::$app->getFields()->getFieldsByType(Matrix::class);
return ArrayHelper::map($fields, 'uid', 'name');
}

/**
* @inheritdoc
*/
public function modifyQuery(ElementQueryInterface $query): void
{
/** @var EntryQuery $query */
$fieldsService = Craft::$app->getFields();
$query->fieldId($this->paramValue(fn($uid) => $fieldsService->getFieldByUid($uid)->id ?? null));
}

/**
* @inheritdoc
*/
public function matchElement(ElementInterface $element): bool
{
/** @var Entry $element */
return $this->matchValue($element->getField()?->uid);
}
}

class_alias(FieldConditionRule::class, MatrixFieldConditionRule::class);
28 changes: 26 additions & 2 deletions src/elements/conditions/entries/SectionConditionRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@
*/
class SectionConditionRule extends BaseMultiSelectConditionRule implements ElementConditionRuleInterface
{
/**
* @inheritdoc
*/
protected bool $reloadOnOperatorChange = true;

/**
* @inheritdoc
*/
Expand All @@ -35,6 +40,17 @@ public function getExclusiveQueryParams(): array
return ['section', 'sectionId'];
}

/**
* @inheritdoc
*/
protected function operators(): array
{
return [
...parent::operators(),
self::OPERATOR_NOT_EMPTY,
];
}

/**
* @inheritdoc
*/
Expand All @@ -50,8 +66,12 @@ protected function options(): array
public function modifyQuery(ElementQueryInterface $query): void
{
/** @var EntryQuery $query */
$sections = Craft::$app->getEntries();
$query->sectionId($this->paramValue(fn($uid) => $sections->getSectionByUid($uid)->id ?? null));
if ($this->operator === self::OPERATOR_NOT_EMPTY) {
$query->section('*');
} else {
$sections = Craft::$app->getEntries();
$query->sectionId($this->paramValue(fn($uid) => $sections->getSectionByUid($uid)->id ?? null));
}
}

/**
Expand All @@ -60,6 +80,10 @@ public function modifyQuery(ElementQueryInterface $query): void
public function matchElement(ElementInterface $element): bool
{
/** @var Entry $element */
if ($this->operator === self::OPERATOR_NOT_EMPTY) {
return $element->getSection() !== null;
}

return $this->matchValue($element->getSection()?->uid);
}
}
2 changes: 1 addition & 1 deletion src/translations/en/app.php
Original file line number Diff line number Diff line change
Expand Up @@ -682,6 +682,7 @@
'Field Limit' => 'Field Limit',
'Field Type' => 'Field Type',
'Field saved.' => 'Field saved.',
'Field' => 'Field',
'Fields' => 'Fields',
'File Kind' => 'File Kind',
'File Modification Date' => 'File Modification Date',
Expand Down Expand Up @@ -942,7 +943,6 @@
'Manage categories' => 'Manage categories',
'Manage your Craft Console account' => 'Manage your Craft Console account',
'Manipulated SVG image rasterizing is unreliable. See \\craft\\services\\Images::loadImage()' => 'Manipulated SVG image rasterizing is unreliable. See \\craft\\services\\Images::loadImage()',
'Matrix field' => 'Matrix field',
'Matrix' => 'Matrix',
'Max Authors' => 'Max Authors',
'Max Date' => 'Max Date',
Expand Down

0 comments on commit b8fe7e1

Please sign in to comment.