Skip to content

Commit e869d22

Browse files
committed
Almost all primary keys are related to their tables
1 parent 40f93b7 commit e869d22

15 files changed

+80
-6
lines changed

src/Config/ModelConfig.php

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,25 @@ class ModelConfig
2020
public function __construct(Model $model)
2121
{
2222
$this->model = $model;
23-
$this->config = $this->hasConfig() ? $this->getConfig() : [];
23+
$this->config = $this->hasConfig() ? $this->getConfig() : [];
24+
25+
}
26+
27+
28+
public function getPrimaryColumn(): string {
29+
$table = $this->model->getTable();
30+
$primaryKey = $this->model->getKeyName();
31+
return $table. '.'. $primaryKey;
32+
}
33+
34+
/**
35+
* @param string $column
36+
*
37+
* @return bool
38+
*/
39+
public function isPrimaryKey($column): bool
40+
{
41+
return $this->model->getKeyName() === $column;
2442
}
2543

2644
public function hasConfig(): bool

src/SearchCallbacks/AbstractCallback.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public function __construct(Builder $builder, SearchParserInterface $searchParse
3838
$this->categorizedValues = new CategorizedValues($this->searchParser);
3939

4040
$this->builder->when(
41-
str_contains($this->searchParser->column, '.'),
41+
$this->searchParser->isModelRelation(),
4242
function (Builder $builder) {
4343
// Hack for whereDoesntHave relation, doesn't work recursively.
4444
if (str_contains($this->searchParser->column, '!') !== false) {

src/SearchParser.php

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ class SearchParser implements SearchParserInterface
4040
public function __construct(ModelConfig $modelConfig, OperatorsConfig $operatorsConfig, string $column, string $argument)
4141
{
4242
$this->modelConfig = $modelConfig;
43-
$this->column = $column;
43+
$this->column = $modelConfig->isPrimaryKey($column) ?
44+
$modelConfig->getPrimaryColumn() : $column;
4445
$this->argument = $argument;
4546

4647
$this->checkForForbiddenColumns();
@@ -51,6 +52,20 @@ public function __construct(ModelConfig $modelConfig, OperatorsConfig $operators
5152
$this->type = $this->getColumnType();
5253
}
5354

55+
/**
56+
* @return bool
57+
*
58+
* @throws JsonQueryBuilderException
59+
*/
60+
public function isModelRelation(): bool
61+
{
62+
if (!str_contains($this->column, '.')) {
63+
return false;
64+
}
65+
$relation = explode('.', $this->column)[0];
66+
return in_array($relation, $this->modelConfig->getRelations());
67+
}
68+
5469
/**
5570
* @param $operators
5671
* @param string $argument

tests/TestModel.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,17 @@
66

77
use Illuminate\Database\Eloquent\Model;
88

9+
class Tag extends Model
10+
{
11+
}
12+
13+
14+
915
class TestModel extends Model
1016
{
1117
protected $table = 'test';
18+
19+
public function tags() {
20+
return $this->morphToMany(Tag::class, "taggable");
21+
}
1222
}

tests/Unit/JsonQueryTest.php

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ public function searches_with_or_micro_operator()
139139
$jsonQuery = new JsonQuery($this->builder, $input);
140140
$jsonQuery->search();
141141

142-
$sql = 'select * from "test" where ((("id" in (?)) or ("id" in (?))))';
142+
$sql = 'select * from "test" where ((("test"."id" in (?)) or ("test"."id" in (?))))';
143143

144144
$this->assertEquals($sql, $this->builder->toSql());
145145
}
@@ -156,7 +156,7 @@ public function searches_with_and_micro_operator()
156156
$jsonQuery = new JsonQuery($this->builder, $input);
157157
$jsonQuery->search();
158158

159-
$sql = 'select * from "test" where ((("id" in (?) and "id" in (?))))';
159+
$sql = 'select * from "test" where ((("test"."id" in (?) and "test"."id" in (?))))';
160160

161161
$this->assertEquals($sql, $this->builder->toSql());
162162
}
@@ -317,7 +317,28 @@ public function can_recurse_absurdly_deep()
317317
$jsonQuery = new JsonQuery($this->builder, $input);
318318
$jsonQuery->search();
319319

320-
$sql = 'select * from "test" where ((((("id" in (?)) or ("id" in (?))) and (("name" in (?)))) or ((("id" in (?))) and (("name" LIKE ? and "name" LIKE ?)))) and ((("we" in (?)))) or (("love" < ?)) or (("recursion" in (?))))';
320+
$sql = 'select * from "test" where ((((("test"."id" in (?)) or ("test"."id" in (?))) and (("name" in (?)))) or ((("test"."id" in (?))) and (("name" LIKE ? and "name" LIKE ?)))) and ((("we" in (?)))) or (("love" < ?)) or (("recursion" in (?))))';
321+
322+
$this->assertEquals($sql, $this->builder->toSql());
323+
}
324+
325+
/** @test */
326+
public function can_query_by_many_to_many_relationships()
327+
{
328+
$input = [
329+
'search' => [
330+
'tags' => [
331+
"search" => [
332+
"id" => "=1",
333+
],
334+
],
335+
],
336+
];
337+
338+
$jsonQuery = new JsonQuery($this->builder, $input);
339+
$jsonQuery->search();
340+
341+
$sql = 'select * from "test" where (exists (select * from "tags" inner join "taggables" on "tags"."id" = "taggables"."tag_id" where "test"."id" = "taggables"."taggable_id" and "taggables"."taggable_type" = ? and ((("tags"."id" in (?))))))';
321342

322343
$this->assertEquals($sql, $this->builder->toSql());
323344
}

tests/Unit/RequestParameters/SearchParameterTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ public function setUp(): void
2727
$this->modelConfig = Mockery::mock(ModelConfig::class);
2828
$this->modelConfig->shouldReceive('getForbidden')->andReturn([]);
2929
$this->modelConfig->shouldReceive('getModelColumns')->andReturn([]);
30+
$this->modelConfig->shouldReceive('isPrimaryKey')->andReturn(false);
3031
}
3132

3233
protected function createSearchParameter(array $arguments): SearchParameter

tests/Unit/SearchCallbacks/BetweenTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ public function setUp(): void
2828
$this->searchParser = Mockery::mock(SearchParser::class);
2929
$this->searchParser->type = 'test';
3030
$this->searchParser->column = 'test';
31+
$this->searchParser->shouldReceive('isModelRelation')->andReturn(false);
3132
}
3233

3334
/** @test */

tests/Unit/SearchCallbacks/EqualsTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ public function setUp(): void
2727
$this->searchParser = Mockery::mock(SearchParser::class);
2828
$this->searchParser->type = 'test';
2929
$this->searchParser->column = 'test';
30+
$this->searchParser->shouldReceive('isModelRelation')->andReturn(false);
3031
}
3132

3233
/** @test */

tests/Unit/SearchCallbacks/GreaterThanOrEqualTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ public function setUp(): void
2727
$this->searchParser = Mockery::mock(SearchParser::class);
2828
$this->searchParser->type = 'test';
2929
$this->searchParser->column = 'test';
30+
$this->searchParser->shouldReceive('isModelRelation')->andReturn(false);
3031
}
3132

3233
/** @test */

tests/Unit/SearchCallbacks/GreaterThanTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ public function setUp(): void
2727
$this->searchParser = Mockery::mock(SearchParser::class);
2828
$this->searchParser->type = 'test';
2929
$this->searchParser->column = 'test';
30+
$this->searchParser->shouldReceive('isModelRelation')->andReturn(false);
3031
}
3132

3233
/** @test */

0 commit comments

Comments
 (0)