|
18 | 18 | use craft\elements\db\ElementRelationParamParser; |
19 | 19 | use craft\elements\ElementCollection; |
20 | 20 | use craft\events\ElementCriteriaEvent; |
| 21 | +use craft\fieldlayoutelements\BaseField; |
21 | 22 | use craft\fieldlayoutelements\CustomField; |
22 | 23 | use craft\fields\conditions\RelationalFieldConditionRule; |
23 | 24 | use craft\helpers\Cp; |
@@ -140,8 +141,33 @@ public static function modifyQuery(Builder $query, array $instances, mixed $valu |
140 | 141 | } |
141 | 142 |
|
142 | 143 | if (isset($value[0]) && in_array($value[0], [':notempty:', ':empty:', 'not :empty:'])) { |
143 | | - $emptyCondition = array_shift($value); |
144 | | - if (in_array($emptyCondition, [':notempty:', 'not :empty:'])) { |
| 144 | + $emptyParam = array_shift($value); |
| 145 | + |
| 146 | + if (self::isQueryConditionFieldMultiInstance($instances)) { |
| 147 | + // look at the JSON values rather than the `relations` table data |
| 148 | + // (see https://github.com/craftcms/cms/issues/17290 + https://github.com/craftcms/cms/pull/18092) |
| 149 | + if (in_array($emptyParam, [':notempty:', 'not :empty:'])) { |
| 150 | + $query->orWhere(function (Builder $query) use ($instances) { |
| 151 | + foreach ($instances as $instance) { |
| 152 | + $valueSql = $instance->getValueSql(); |
| 153 | + $query->orWhere(function (Builder $query) use ($valueSql) { |
| 154 | + $query->whereNotNull($valueSql) |
| 155 | + ->whereNot($valueSql, '[]'); |
| 156 | + }); |
| 157 | + } |
| 158 | + }); |
| 159 | + } else { |
| 160 | + $query->orWhere(function (Builder $query) use ($instances) { |
| 161 | + foreach ($instances as $instance) { |
| 162 | + $valueSql = $instance->getValueSql(); |
| 163 | + $query->where(function (Builder $query) use ($valueSql) { |
| 164 | + $query->whereNotNull($valueSql) |
| 165 | + ->whereNot($valueSql, '[]'); |
| 166 | + }); |
| 167 | + } |
| 168 | + }); |
| 169 | + } |
| 170 | + } elseif (in_array($emptyParam, [':notempty:', 'not :empty:'])) { |
145 | 171 | $query->orWhereExists(static::existsQuery($field)); |
146 | 172 | } else { |
147 | 173 | $query->orWhereNotExists(static::existsQuery($field)); |
@@ -173,6 +199,26 @@ public static function modifyQuery(Builder $query, array $instances, mixed $valu |
173 | 199 | return $query; |
174 | 200 | } |
175 | 201 |
|
| 202 | + /** |
| 203 | + * @param self[] $instances |
| 204 | + */ |
| 205 | + private static function isQueryConditionFieldMultiInstance(array $instances): bool |
| 206 | + { |
| 207 | + foreach ($instances as $instance) { |
| 208 | + // See if this instance is used multiple times within its field layout |
| 209 | + $allInstances = $instance->layoutElement?->getLayout()->getFields(fn (BaseField $field) => ( |
| 210 | + $field instanceof CustomField && |
| 211 | + $field->getFieldUid() === $instance->uid |
| 212 | + )); |
| 213 | + |
| 214 | + if ($allInstances && count($allInstances) > 1) { |
| 215 | + return true; |
| 216 | + } |
| 217 | + } |
| 218 | + |
| 219 | + return false; |
| 220 | + } |
| 221 | + |
176 | 222 | /** |
177 | 223 | * Returns a query builder-compatible condition for an element query, |
178 | 224 | * limiting the results to only elements where the given relation field has a value. |
@@ -441,7 +487,7 @@ public function validateSources(string $attribute): void |
441 | 487 | $inputSources = [$inputSources]; |
442 | 488 | } |
443 | 489 |
|
444 | | - $elementSources = app(ElementSources::class) |
| 490 | + $elementSources = resolve(ElementSources::class) |
445 | 491 | ->getSources(static::elementType()) |
446 | 492 | ->whereIn('key', $inputSources); |
447 | 493 |
|
@@ -1117,7 +1163,7 @@ public function getContentGqlMutationArgumentType(): array |
1117 | 1163 | */ |
1118 | 1164 | protected function gqlFieldArguments(): array |
1119 | 1165 | { |
1120 | | - $elementSourcesService = app(ElementSources::class); |
| 1166 | + $elementSourcesService = resolve(ElementSources::class); |
1121 | 1167 | $gqlService = Craft::$app->getGql(); |
1122 | 1168 | $fieldLayouts = []; |
1123 | 1169 | $arguments = []; |
@@ -1729,7 +1775,7 @@ protected function viewMode(): string |
1729 | 1775 | */ |
1730 | 1776 | protected function availableSources(): array |
1731 | 1777 | { |
1732 | | - return app(ElementSources::class) |
| 1778 | + return resolve(ElementSources::class) |
1733 | 1779 | ->getSources(static::elementType(), 'modal') |
1734 | 1780 | ->where('type', '!=', ElementSources::TYPE_HEADING) |
1735 | 1781 | ->values() |
|
0 commit comments