From df797c7019ad354607e4eb1f05a010940613a935 Mon Sep 17 00:00:00 2001 From: Septian Hari <5935057+LIQRGV@users.noreply.github.com> Date: Thu, 14 Jan 2021 21:12:11 +0800 Subject: [PATCH] Use fully qualified column name for filtering --- src/RequestParser.php | 1 + src/Struct/FilterStruct.php | 6 ++-- tests/RequestParserLaravelTest.php | 4 +-- tests/RequestParserLumenTest.php | 2 +- tests/RequestParserRelationTest.php | 6 ++-- tests/RequestParserTest.php | 45 +++++++++++++++-------------- 6 files changed, 35 insertions(+), 29 deletions(-) diff --git a/src/RequestParser.php b/src/RequestParser.php index 052d26f..d77b447 100644 --- a/src/RequestParser.php +++ b/src/RequestParser.php @@ -226,6 +226,7 @@ private function getModelFromNamespaces(string $modelName, array $modelNamespace private function applyFilter(Builder $builder, array $filters): Builder { + /** @var FilterStruct $filterStruct */ foreach ($filters as $filterStruct) { $builder = $filterStruct->apply($builder); } diff --git a/src/Struct/FilterStruct.php b/src/Struct/FilterStruct.php index c0ab4b7..295ee60 100644 --- a/src/Struct/FilterStruct.php +++ b/src/Struct/FilterStruct.php @@ -54,14 +54,16 @@ private function _apply(Builder $object, $fieldName, $boolean, $isChild = false) if ($this->isRelation($fieldName)) { return $this->_applyRelation($object, $fieldName, $boolean, $isChild); } + + $completeFieldName = $object->qualifyColumn($fieldName); if (array_key_exists($this->operator, self::$WHERE_QUERY_MAPPING)) { $whereQuery = self::$WHERE_QUERY_MAPPING[$this->operator]; $value = explode(",", $this->value); - return $object->$whereQuery($fieldName, $value, $boolean); + return $object->$whereQuery($completeFieldName, $value, $boolean); } - return $object->where($fieldName, $this->operator, $this->value, $boolean); + return $object->where($completeFieldName, $this->operator, $this->value, $boolean); } private function transformOperator($rawOperator) { diff --git a/tests/RequestParserLaravelTest.php b/tests/RequestParserLaravelTest.php index aa067c6..02d2807 100644 --- a/tests/RequestParserLaravelTest.php +++ b/tests/RequestParserLaravelTest.php @@ -33,7 +33,7 @@ function testFilterNormalViaController() $query = $builder->getQuery(); $this->assertEquals("mock_models", $query->from); - $this->assertEquals("x", $query->wheres[0]['column']); + $this->assertEquals("mock_models.x", $query->wheres[0]['column']); $this->assertEquals("=", $query->wheres[0]['operator']); $this->assertEquals([1], $builder->getBindings()); } @@ -61,7 +61,7 @@ function testFilterNormalViaClosure() $query = $builder->getQuery(); $this->assertEquals("mock_some_models", $query->from); - $this->assertEquals("x", $query->wheres[0]['column']); + $this->assertEquals("mock_some_models.x", $query->wheres[0]['column']); $this->assertEquals("=", $query->wheres[0]['operator']); $this->assertEquals([1], $builder->getBindings()); } diff --git a/tests/RequestParserLumenTest.php b/tests/RequestParserLumenTest.php index 6143048..c4a54ad 100644 --- a/tests/RequestParserLumenTest.php +++ b/tests/RequestParserLumenTest.php @@ -59,7 +59,7 @@ function() {} $query = $builder->getQuery(); $this->assertEquals("mock_models", $query->from); - $this->assertEquals("x", $query->wheres[0]['column']); + $this->assertEquals("mock_models.x", $query->wheres[0]['column']); $this->assertEquals("=", $query->wheres[0]['operator']); $this->assertEquals([1], $builder->getBindings()); } diff --git a/tests/RequestParserRelationTest.php b/tests/RequestParserRelationTest.php index 7d2f3c1..76552a4 100644 --- a/tests/RequestParserRelationTest.php +++ b/tests/RequestParserRelationTest.php @@ -47,7 +47,7 @@ function testFilterRelationOne() // assert relation query $this->assertEquals("Basic", $builder->getQuery()->wheres[0]["query"]->wheres[1]["type"]); - $this->assertEquals("id", $builder->getQuery()->wheres[0]["query"]->wheres[1]["column"]); + $this->assertEquals("mock_models.id", $builder->getQuery()->wheres[0]["query"]->wheres[1]["column"]); $this->assertEquals("=", $builder->getQuery()->wheres[0]["query"]->wheres[1]["operator"]); $this->assertEquals("2", $builder->getQuery()->wheres[0]["query"]->wheres[1]["value"]); $this->assertEquals("and", $builder->getQuery()->wheres[0]["query"]->wheres[1]["boolean"]); @@ -99,7 +99,7 @@ function testFilterOrRelationOne() // assert first relation query field $this->assertEquals("Basic", $firstInnerQuery->wheres[1]["type"]); - $this->assertEquals("id", $firstInnerQuery->wheres[1]["column"]); + $this->assertEquals("mock_models.id", $firstInnerQuery->wheres[1]["column"]); $this->assertEquals("=", $firstInnerQuery->wheres[1]["operator"]); $this->assertEquals("2", $firstInnerQuery->wheres[1]["value"]); $this->assertEquals("and", $firstInnerQuery->wheres[1]["boolean"]); @@ -113,7 +113,7 @@ function testFilterOrRelationOne() // assert second relation query field $this->assertEquals("Basic", $secondInnerQuery->wheres[1]["type"]); - $this->assertEquals("other_attr", $secondInnerQuery->wheres[1]["column"]); + $this->assertEquals("mock_models.other_attr", $secondInnerQuery->wheres[1]["column"]); $this->assertEquals("=", $secondInnerQuery->wheres[1]["operator"]); $this->assertEquals("2", $secondInnerQuery->wheres[1]["value"]); $this->assertEquals("and", $secondInnerQuery->wheres[1]["boolean"]); diff --git a/tests/RequestParserTest.php b/tests/RequestParserTest.php index 6957b40..9e0eeb5 100644 --- a/tests/RequestParserTest.php +++ b/tests/RequestParserTest.php @@ -186,7 +186,7 @@ function testFilterKeywordIn() $query = $builder->getQuery(); $this->assertEquals("mock_models", $query->from); - $this->assertEquals("y", $query->wheres[0]['column']); + $this->assertEquals("mock_models.y", $query->wheres[0]['column']); $this->assertEquals("in", strtolower($query->wheres[0]['type'])); $this->assertEquals(['2', '3', '4'], $builder->getBindings()); } @@ -261,15 +261,15 @@ function testFilterWithOr() $subquery = $query->wheres[0]['query']; //Assert subquery components - $this->assertEquals("x", $subquery->wheres[0]['column']); + $this->assertEquals("mock_models.x", $subquery->wheres[0]['column']); $this->assertEquals("=", strtolower($subquery->wheres[0]['operator'])); - $this->assertEquals("y", $subquery->wheres[1]['column']); + $this->assertEquals("mock_models.y", $subquery->wheres[1]['column']); $this->assertEquals("=", strtolower($subquery->wheres[1]['operator'])); $this->assertEquals("or", strtolower($subquery->wheres[1]['boolean'])); //Assert second where term of the main query - $this->assertEquals("z", $query->wheres[1]['column']); + $this->assertEquals("mock_models.z", $query->wheres[1]['column']); $this->assertEquals("in", strtolower($query->wheres[1]['type'])); $this->assertEquals(['1', '1', '1', '2', '3'], $builder->getBindings()); @@ -308,14 +308,14 @@ function testFilterWithOrUsingInQueryKeyword() $subquery1 = $query->wheres[0]['query']; - $this->assertEquals("c", $subquery1->wheres[0]['column']); + $this->assertEquals("mock_models.c", $subquery1->wheres[0]['column']); $this->assertEquals("in", strtolower($subquery1->wheres[0]['type'])); - $this->assertEquals("d", $subquery1->wheres[1]['column']); + $this->assertEquals("mock_models.d", $subquery1->wheres[1]['column']); $this->assertEquals("in", strtolower($subquery1->wheres[1]['type'])); $this->assertEquals("or", strtolower($subquery1->wheres[1]['boolean'])); - $this->assertEquals("i", $query->wheres[1]['column']); + $this->assertEquals("mock_models.i", $query->wheres[1]['column']); $this->assertEquals("between", strtolower($query->wheres[1]['type'])); $this->assertEquals( @@ -360,14 +360,14 @@ function testFilterWithOrUsingNotInQueryKeyword() $subquery1 = $query->wheres[0]['query']; - $this->assertEquals("e", $subquery1->wheres[0]['column']); + $this->assertEquals("mock_models.e", $subquery1->wheres[0]['column']); $this->assertEquals("NotIn", $subquery1->wheres[0]['type']); - $this->assertEquals("f", $subquery1->wheres[1]['column']); + $this->assertEquals("mock_models.f", $subquery1->wheres[1]['column']); $this->assertEquals("NotIn", $subquery1->wheres[1]['type']); $this->assertEquals("or", strtolower($subquery1->wheres[1]['boolean'])); - $this->assertEquals("i", $query->wheres[1]['column']); + $this->assertEquals("mock_models.i", $query->wheres[1]['column']); $this->assertEquals("between", strtolower($query->wheres[1]['type'])); $this->assertEquals( @@ -412,14 +412,14 @@ function testFilterWithOrUsingBetweenQueryKeyword() $subquery1 = $query->wheres[0]['query']; - $this->assertEquals("g", $subquery1->wheres[0]['column']); + $this->assertEquals("mock_models.g", $subquery1->wheres[0]['column']); $this->assertEquals("between", strtolower($subquery1->wheres[0]['type'])); - $this->assertEquals("h", $subquery1->wheres[1]['column']); + $this->assertEquals("mock_models.h", $subquery1->wheres[1]['column']); $this->assertEquals("between", strtolower($subquery1->wheres[1]['type'])); $this->assertEquals("or", strtolower($subquery1->wheres[1]['boolean'])); - $this->assertEquals("i", $query->wheres[1]['column']); + $this->assertEquals("mock_models.i", $query->wheres[1]['column']); $this->assertEquals("between", strtolower($query->wheres[1]['type'])); $this->assertEquals( @@ -508,6 +508,7 @@ function testFilterOnlyAllowedFilter() { $uri = 'some_model'; $controllerClass = MockModelController::class; + $tableName = 'mock_models'; $ignoredKey = "ignored_key"; $nameKey = "name"; $valueKey = "value"; @@ -542,8 +543,8 @@ function testFilterOnlyAllowedFilter() return $where["column"] == $ignoredKey; })); - $nameAndValueColumn = array_filter($query->wheres, function ($where) use ($nameKey, $valueKey) { - return in_array($where["column"], [$nameKey, $valueKey]); + $nameAndValueColumn = array_filter($query->wheres, function ($where) use ($tableName, $nameKey, $valueKey) { + return in_array($where["column"], [sprintf("%s.%s", $tableName, $nameKey), sprintf("%s.%s", $tableName, $valueKey)]); }); $this->assertEquals(2, count($nameAndValueColumn)); } @@ -552,6 +553,7 @@ function testFilterIgnoreIgnoredFilter() { $uri = 'some_model'; $controllerClass = MockModelController::class; + $tableName = 'mock_models'; $ignoredKey = "omnisearch"; $notIgnoredKey = "selected_value"; $query = new ParameterBag([ @@ -578,11 +580,11 @@ function testFilterIgnoreIgnoredFilter() $query = $builder->getQuery(); - $this->assertEmpty(array_filter($query->wheres, function ($where) use ($ignoredKey) { - return $where["column"] == $ignoredKey; + $this->assertEmpty(array_filter($query->wheres, function ($where) use ($tableName, $ignoredKey) { + return $where["column"] == sprintf("%s.%s", $tableName, $ignoredKey); })); - $this->assertNotEmpty(array_filter($query->wheres, function ($where) use ($notIgnoredKey) { - return $where["column"] == $notIgnoredKey; + $this->assertNotEmpty(array_filter($query->wheres, function ($where) use ($tableName, $notIgnoredKey) { + return $where["column"] == sprintf("%s.%s", $tableName, $notIgnoredKey); })); } @@ -590,6 +592,7 @@ function testFilterIgnoredFilterShouldTakePrecedenceOverAllowedFilter() { $uri = 'some_model'; $controllerClass = MockModelController::class; + $tableName = 'mock_models'; $ignoredKey = "ignored_key"; $nameKey = "name"; $valueKey = "value"; @@ -621,8 +624,8 @@ function testFilterIgnoredFilterShouldTakePrecedenceOverAllowedFilter() $query = $builder->getQuery(); - $nameAndValueColumn = array_filter($query->wheres, function ($where) use ($nameKey, $valueKey) { - return in_array($where["column"], [$nameKey, $valueKey]); + $nameAndValueColumn = array_filter($query->wheres, function ($where) use ($tableName, $nameKey, $valueKey) { + return in_array($where["column"], [sprintf("%s.%s", $tableName, $nameKey), sprintf("%s.%s", $tableName, $valueKey)]); }); $this->assertEquals(2, count($nameAndValueColumn)); $this->assertEmpty(array_filter($query->wheres, function ($where) use ($ignoredKey) {