Skip to content

[5.x]: Empty "Uploaded By" condition rule throws InvalidArgumentException on asset index #19484

Description

@watarutmnh

What happened?

craft\elements\conditions\assets\UploaderConditionRule::modifyQuery() unconditionally passes the rule's element ID to AssetQuery::uploader():

public function modifyQuery(ElementQueryInterface $query): void
{
    /** @var AssetQuery $query */
    $query->uploader($this->getElementId());
}

When the rule is empty, BaseElementSelectConditionRule::getElementId() returns null. AssetQuery::uploader() declares int|User|null, but rejects null because is_numeric(null) is false:

public function uploader(int|User|null $value): static
{
    if ($value instanceof User) {
        $this->uploaderId = $value->id;
    } elseif (is_numeric($value)) {
        $this->uploaderId = $value;
    } else {
        throw new InvalidArgumentException('Invalid uploader value');
    }
    return $this;
}

The exception is not caught, so the control panel asset index returns HTTP 500.

Steps to reproduce

  1. Open an asset index in the control panel.
  2. Add an "Uploaded By" filter, but leave the user selection empty.
  3. Apply the filter.

The element-indexes/get-elements request responds with 500 and yii\base\InvalidArgumentException: Invalid uploader value. The same happens when a saved condition containing an empty uploader rule is restored.

Minimal reproduction (no Craft application boot required)

use craft\elements\conditions\assets\UploaderConditionRule;
use craft\elements\db\AssetQuery;

$rule = (new ReflectionClass(UploaderConditionRule::class))->newInstanceWithoutConstructor();
$query = (new ReflectionClass(AssetQuery::class))->newInstanceWithoutConstructor();

$rule->modifyQuery($query);
// yii\base\InvalidArgumentException: Invalid uploader value

Expected behaviour

An empty condition rule should be a no-op.

This would also make the query side consistent with the match side. BaseElementSelectConditionRule::matchValue() already returns true when no element IDs are set, so an empty rule matches every element rather than erroring:

$elementIds = $this->getElementIds();

if (empty($elementIds)) {
    return true;
}

Possible fixes

Guard in the condition rule:

public function modifyQuery(ElementQueryInterface $query): void
{
    if ($this->getElementId() === null) {
        return;
    }

    /** @var AssetQuery $query */
    $query->uploader($this->getElementId());
}

Or honour the declared signature in AssetQuery::uploader() and treat null as "no uploader filter".

Affected code

  • src/elements/conditions/assets/UploaderConditionRule.phpmodifyQuery()
  • src/elements/db/AssetQuery.phpuploader()

I reproduced this on 5.10.9. The same code is still present on the 5.10.14 tag and on the 5.x and 5.11 branches — both UploaderConditionRule::modifyQuery() and AssetQuery::uploader() are unchanged there. On 6.x the condition rule still calls $query->uploader(...), but AssetQuery appears to have been reworked and I could not find an uploader() method on it, so I have not verified the behaviour there.

I could not find an existing issue for this; apologies if I missed one.

Craft CMS version

5.10.9 (code unchanged on the 5.10.14 tag and on the 5.x and 5.11 branches)

PHP version

8.4

Database type and version

MySQL 8.0

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions