Skip to content

Commit

Permalink
Make field condition rules more defensive about their field type
Browse files Browse the repository at this point in the history
Fixes #15850
  • Loading branch information
brandonkelly committed Oct 8, 2024
1 parent 071ae84 commit e8e67bf
Show file tree
Hide file tree
Showing 7 changed files with 48 additions and 7 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
- Fixed an error that could occur when saving an element, if a Date field’s time zone input was focused.
- Fixed a bug where the time zones listed in Date fields weren’t labelled properly based on the selected date. ([#15805](https://github.com/craftcms/cms/issues/15805))
- Fixed an error that could occur if a native element property was attempted to be eager-loaded. ([#15822](https://github.com/craftcms/cms/issues/15822))
- Fixed errors that could occur if a custom source or field condition referenced a custom field whose type had changed. ([#15850](https://github.com/craftcms/cms/issues/15850))
- Fixed a missing authorization vulnerability.

## 4.12.5 - 2024-09-27
Expand Down
6 changes: 6 additions & 0 deletions src/fields/conditions/CountryFieldConditionRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Craft;
use craft\base\conditions\BaseMultiSelectConditionRule;
use craft\fields\Country;

/**
* Options field condition rule.
Expand Down Expand Up @@ -33,6 +34,11 @@ protected function elementQueryParam(): ?array
*/
protected function matchFieldValue($value): bool
{
if (!$this->field() instanceof Country) {
// No longer a Country field
return false;
}

return $this->matchValue($value);
}
}
6 changes: 6 additions & 0 deletions src/fields/conditions/DateFieldConditionRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace craft\fields\conditions;

use craft\base\conditions\BaseDateRangeConditionRule;
use craft\fields\Date;
use DateTime;

/**
Expand All @@ -28,6 +29,11 @@ protected function elementQueryParam(): array|string|null
*/
protected function matchFieldValue($value): bool
{
if (!$this->field() instanceof Date) {
// No longer a Date field
return false;
}

/** @var DateTime|null $value */
return $this->matchValue($value);
}
Expand Down
2 changes: 1 addition & 1 deletion src/fields/conditions/EmptyFieldConditionRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public function matchElement(ElementInterface $element): bool
return false;
}

$isEmpty = $this->field()->isValueEmpty($value, $element);
$isEmpty = $field->isValueEmpty($value, $element);

if ($this->operator === self::OPERATOR_EMPTY) {
return $isEmpty;
Expand Down
6 changes: 6 additions & 0 deletions src/fields/conditions/LightswitchFieldConditionRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace craft\fields\conditions;

use craft\base\conditions\BaseLightswitchConditionRule;
use craft\fields\Lightswitch;

/**
* Lightswitch field condition rule.
Expand All @@ -27,6 +28,11 @@ protected function elementQueryParam(): bool
*/
protected function matchFieldValue($value): bool
{
if (!$this->field() instanceof Lightswitch) {
// No longer a Lightswitch field
return false;
}

/** @var bool $value */
return $this->matchValue($value);
}
Expand Down
5 changes: 5 additions & 0 deletions src/fields/conditions/OptionsFieldConditionRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ protected function elementQueryParam(): ?array
*/
protected function matchFieldValue($value): bool
{
if (!$this->field() instanceof BaseOptionsField) {
// No longer an options field
return false;
}

if ($value instanceof MultiOptionsFieldData) {
/** @phpstan-ignore-next-line */
$value = array_map(fn(OptionData $option) => $option->value, (array)$value);
Expand Down
29 changes: 23 additions & 6 deletions src/fields/conditions/RelationalFieldConditionRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use craft\elements\db\ElementQueryInterface;
use craft\fields\BaseRelationField;
use Illuminate\Support\Collection;
use yii\base\InvalidConfigException;
use yii\db\QueryInterface;

/**
Expand Down Expand Up @@ -40,8 +41,10 @@ class RelationalFieldConditionRule extends BaseElementSelectConditionRule implem
*/
protected function elementType(): string
{
/** @var BaseRelationField $field */
$field = $this->field();
if (!$field instanceof BaseRelationField) {
throw new InvalidConfigException();
}
return $field::elementType();
}

Expand All @@ -50,8 +53,10 @@ protected function elementType(): string
*/
protected function sources(): ?array
{
/** @var BaseRelationField $field */
$field = $this->field();
if (!$field instanceof BaseRelationField) {
throw new InvalidConfigException();
}
return (array)$field->getInputSources();
}

Expand All @@ -60,8 +65,10 @@ protected function sources(): ?array
*/
protected function selectionCondition(): ?ElementConditionInterface
{
/** @var BaseRelationField $field */
$field = $this->field();
if (!$field instanceof BaseRelationField) {
throw new InvalidConfigException();
}
return $field->getSelectionCondition();
}

Expand All @@ -70,8 +77,10 @@ protected function selectionCondition(): ?ElementConditionInterface
*/
protected function criteria(): ?array
{
/** @var BaseRelationField $field */
$field = $this->field();
if (!$field instanceof BaseRelationField) {
throw new InvalidConfigException();
}
return $field->getInputSelectionCriteria();
}

Expand Down Expand Up @@ -114,13 +123,16 @@ protected function inputHtml(): string
*/
public function modifyQuery(QueryInterface $query): void
{
$field = $this->field();
if (!$field instanceof BaseRelationField) {
return;
}

if ($this->operator === self::OPERATOR_RELATED_TO) {
$this->traitModifyQuery($query);
} else {
// Add the condition manually so we can ignore the related elements’ statuses and the field’s target site
// so conditions reflect what authors see in the UI
/** @var BaseRelationField $field */
$field = $this->field();
$query->andWhere(
$this->operator === self::OPERATOR_NOT_EMPTY
? $field::existsQueryCondition($field, false, false)
Expand All @@ -143,6 +155,11 @@ protected function elementQueryParam(): int|string|null
*/
protected function matchFieldValue($value): bool
{
if (!$this->field() instanceof BaseRelationField) {
// No longer a relation field
return false;
}

if ($value instanceof ElementQueryInterface) {
// Ignore the related elements’ statuses and target site
// so conditions reflect what authors see in the UI
Expand Down

0 comments on commit e8e67bf

Please sign in to comment.