From 53969121d20eab0f0d8a308761d493ab4e87732c Mon Sep 17 00:00:00 2001 From: brandonkelly Date: Mon, 22 Apr 2019 14:52:14 -0700 Subject: [PATCH] :empty: & :notempty: Matrix field query params must account for soft-deleted blocks Resolves #4161 --- CHANGELOG-v3.md | 1 + src/fields/Matrix.php | 21 +++++++++++++++------ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/CHANGELOG-v3.md b/CHANGELOG-v3.md index 07edd2e2794..9b21805dd80 100644 --- a/CHANGELOG-v3.md +++ b/CHANGELOG-v3.md @@ -11,6 +11,7 @@ - Fixed an error where re-saving a site would reset its sorting order. ([#4147](https://github.com/craftcms/cms/issues/4147)) - Fixed a SQL error that could occur when updating to Craft 3.1. ([#3663](https://github.com/craftcms/cms/issues/3663)) - Fixed an error that occurred when an SVG with `/` characters in its `id` attributes was passed to the `svg()` Twig function. ([#4155](https://github.com/craftcms/cms/issues/4155)) +- Fixed a bug where passing `:empty:` or `:notempty:` to a Matrix field param on an element query could return incorrect results for fields that had soft-deleted blocks. ([#4161](https://github.com/craftcms/cms/issues/4161)) - Fixed a bug where Craft wasn’t returning a `1` exit code for console requests if the server was running under PHP 7. ([#4153](https://github.com/craftcms/cms/issues/4153)) - Fixed a bug where `craft\services\Elements::duplicateElements()` would only ignore non-safe attributes passed to the `$newAttributes` argument. - Fixed a bug where `craft\elements\db\ElementQuery::exists()` and `offsetExists()` were ignoring cached query results. diff --git a/src/fields/Matrix.php b/src/fields/Matrix.php index 14ea4f55bd9..1946f9d48d5 100644 --- a/src/fields/Matrix.php +++ b/src/fields/Matrix.php @@ -437,13 +437,22 @@ public function modifyElementsQuery(ElementQueryInterface $query, $value) } if ($value === ':notempty:' || $value === ':empty:') { - $alias = 'matrixblocks_' . $this->handle; - $operator = ($value === ':notempty:' ? '!=' : '='); + $ns = $this->handle . '_' . StringHelper::randomString(5); + $condition = ['exists', (new Query()) + ->from(TableName::MATRIXBLOCKS . " matrixblocks_$ns") + ->innerJoin(TableName::ELEMENTS . " elements_$ns", "[[elements_$ns.id]] = [[matrixblocks_$ns.id]]") + ->where("[[matrixblocks_$ns.ownerId]] = [[elements.id]]") + ->andWhere([ + "matrixblocks_$ns.fieldId" => $this->id, + "elements_$ns.dateDeleted" => null, + ]) + ]; - $query->subQuery->andWhere( - "(select count([[{$alias}.id]]) from {{%matrixblocks}} {{{$alias}}} where [[{$alias}.ownerId]] = [[elements.id]] and [[{$alias}.fieldId]] = :fieldId) {$operator} 0", - [':fieldId' => $this->id] - ); + if ($value === ':notempty:') { + $query->subQuery->andWhere($condition); + } else { + $query->subQuery->andWhere(['not', $condition]); + } } else if ($value !== null) { return false; }