diff --git a/composer.json b/composer.json index 34f9996..38db1b6 100755 --- a/composer.json +++ b/composer.json @@ -24,8 +24,8 @@ "illuminate/http": "5.5.*|5.6.*" }, "require-dev": { - "phpunit/phpunit": "~6.0|~7.0", - "orchestra/testbench": "3.5.*|3.6.*" + "orchestra/testbench": "^3.6", + "phpunit/phpunit": "~6.0|~7.0" }, "autoload": { "psr-4": { diff --git a/src/Filter.php b/src/Filter.php index a3cce94..5cc5f86 100644 --- a/src/Filter.php +++ b/src/Filter.php @@ -24,6 +24,14 @@ abstract class Filter implements FilterContract */ protected $filterMap; + /** + * @var array + */ + protected $joins = []; + /** + * @return Filter + */ + public function __construct(Request $request) { @@ -76,6 +84,68 @@ protected function builderPresent() } } + /** + * @param \Illuminate\Database\Eloquent\Builder $builder + * @param String $join + * @param String $key + * @param String $joinKey + * @param String $joinType + * + * @return Filter + */ + public function addJoin($join,$key,$joinKey,$joinType = null) + { + if(in_array($join, $this->joins)){ + return $this; + } + array_push($this->joins,$join); + if($joinType == "left"){ + $this->builder->leftJoin($join,$key,$joinKey); + }else if($joinType == "right"){ + $this->builder->rightJoin($join,$key,$joinKey); + }else{ + $this->builder->join($join,$key,$joinKey); + } + return $this; + } + + /** + * @param String $join + * @param String $key + * @param String $joinKey + * @param String $joinType + * + * @return Builder + */ + public function setJoin($join,$key,$joinKey,$joinType = null) + { + $this->addJoin($join,$key,$joinKey,$joinType); + return $this->builder; + } + + /** + * @param String $join + * @param String $key + * @param String $joinKey + * + * @return Builder + */ + public function setLeftJoin($join,$key,$joinKey) + { + return $this->setJoin($join,$key,$joinKey,"left"); + } + + /** + * @param String $join + * @param String $key + * @param String $joinKey + * + * @return Builder + */ + public function setRightJoin($join,$key,$joinKey) + { + return $this->setJoin($join,$key,$joinKey,"right"); + } /** * @return $this @@ -115,4 +185,4 @@ private function filters(): array return $filters ?? []; } -} \ No newline at end of file +} diff --git a/tests/JoinTest.php b/tests/JoinTest.php new file mode 100644 index 0000000..9b52891 --- /dev/null +++ b/tests/JoinTest.php @@ -0,0 +1,85 @@ +assertJoinQuery('select * inner join "user" on "role"."user_id" = "user"."id" where "user"."username" = \'name\'', + ['name' => 'name']); + } + + function test_join_and_other_filter(){ + $this->assertJoinQuery('select * inner join "user" on "role"."user_id" = "user"."id" where "user"."username" = \'name\' '. + 'and "user"."email" = \'email@example.com\'', + ['name' => 'name', 'email' => "email@example.com"]); + + } + + function test_left_right_joins() + { + $this->assertJoinQuery('select * left join "user" on "role"."user_id" = "user"."id" where "user"."username" = \'name\'', + ['left' => 'name']); + $this->assertJoinQuery('select * right join "user" on "role"."user_id" = "user"."id" where "user"."username" = \'name\'', + ['right' => 'name']); + } + + function test_multiple_joins(){ + $this->assertJoinQuery('select * '. + 'inner join "user" on "role"."user_id" = "user"."id" '. + 'inner join "permission" on "role"."id" = "permission"."role_id" '. + 'where "user"."username" = \'name\' '. + 'and "permission"."level" = \'6\'', + [ 'permission' => '6', "name" => "name"]); + } + + function test_join_through_tables(){ + $this->assertJoinQuery('select * '. + 'inner join "permission" on "role"."id" = "permission"."role_id" '. + 'inner join "permissiontype" on "permission"."id" = "permissiontype"."permission_id" '. + 'where "permissiontype"."type" = \'admin\'', + [ "permissiontype" => "admin"]); + } + + function test_join_though_tables_and_other_filter(){ + $this->assertJoinQuery('select * '. + 'inner join "permission" on "role"."id" = "permission"."role_id" '. + 'inner join "permissiontype" on "permission"."id" = "permissiontype"."permission_id" '. + 'where "permissiontype"."type" = \'admin\' '. + 'and "permissiontype"."active" = \'1\'' , + [ "permissiontype" => "admin",'permissiontype_active' => 1]); + } + + function test_join_though_multiple_tables_and_other_filter(){ + $this->assertJoinQuery('select * '. + 'inner join "user" on "role"."user_id" = "user"."id" '. + 'inner join "permission" on "role"."id" = "permission"."role_id" '. + 'inner join "permissiontype" on "permission"."id" = "permissiontype"."permission_id" '. + 'where "user"."username" = \'name\' '. + 'and "permissiontype"."type" = \'admin\' '. + 'and "permissiontype"."active" = \'1\'' , + ["name" => "name", "permissiontype" => "admin",'permissiontype_active' => 1]); + } + + private function assertJoinQuery($expectedQuery, $builderQuery) + { + $filter = $this->buildCustomFilter(http_build_query($builderQuery)); + $this->assertEquals($expectedQuery,$this->dumpQuery($filter->apply($this->builder))); + $this->resetBuilder(); + } + + + private function assertQuery($expectedQuery, $params) + { + $filter = $this->buildFilter(http_build_query($params)); + $this->assertEquals($expectedQuery, $this->dumpQuery($filter->apply($this->builder))); + $this->resetBuilder(); + } +} diff --git a/tests/Stubs/Permission.php b/tests/Stubs/Permission.php new file mode 100644 index 0000000..cf27782 --- /dev/null +++ b/tests/Stubs/Permission.php @@ -0,0 +1,27 @@ + ['name'], + 'email' => ['email'], + 'name_left' => ['left'], + 'name_right' => ['right'], + 'permission' => ['permission'], + 'permissiontype' => ['permissiontype'], + 'permissiontype_active' => ['permissiontype_active'], + + ]; + } + + public function name($username){ + return $this->setJoin("user","role.user_id","user.id")->where("user.username",$username); + } + + public function email($email){ + return $this->setJoin("user","role.user_id","user.id")->where("user.email",$email); + } + + public function name_left($username){ + return $this->setLeftJoin("user","role.user_id","user.id")->where("user.username",$username); + } + + public function name_right($username){ + return $this->setRightJoin("user","role.user_id","user.id")->where("user.username",$username); + } + + public function permission($level){ + return $this->setJoin("permission","role.id","permission.role_id")->where("permission.level",$level); + } + + public function permissiontype($permission_type){ + return $this->addJoin("permission","role.id","permission.role_id") + ->setJoin("permissiontype","permission.id","permissiontype.permission_id") + ->where("permissiontype.type",$permission_type); + } + + public function permissiontype_active($permission_type_active){ + return $this->addJoin("permission","role.id","permission.role_id") + ->setJoin("permissiontype","permission.id","permissiontype.permission_id") + ->where("permissiontype.active",$permission_type_active); + } + +} diff --git a/tests/Stubs/UserFilter.php b/tests/Stubs/UserFilter.php index 314ce60..55b4a90 100644 --- a/tests/Stubs/UserFilter.php +++ b/tests/Stubs/UserFilter.php @@ -27,4 +27,8 @@ public function getGroupingOperator() { return $this->groupingOperator; } + + // public function role($role){ + // return $this->setJoin("roles","user.id","roles.user_id")->where("roles.role",$role); + // } } diff --git a/tests/TestCase.php b/tests/TestCase.php index cfda8e8..764d482 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -7,6 +7,7 @@ use Kyslik\LaravelFilterable\FilterableServiceProvider; use Kyslik\LaravelFilterable\Generic\Templater; use Kyslik\LaravelFilterable\Test\Stubs\UserFilter; +use Kyslik\LaravelFilterable\Test\Stubs\RoleFilter; use Orchestra\Testbench\TestCase as Orchestra; abstract class TestCase extends Orchestra @@ -54,8 +55,16 @@ protected function buildFilter($requestQuery) } + protected function buildCustomFilter($requestQuery) + { + /** @var Request $request */ + $request = resolve(Request::class)->create('http://test.dev?'.$requestQuery); + return new RoleFilter($request); + } + + protected function dumpQuery(Builder $builder) { return vsprintf(str_replace(['?'], ['\'%s\''], $builder->toSql()), $builder->getBindings()); } -} \ No newline at end of file +}