Skip to content

Commit 28c06fa

Browse files
committed
We Are Still Here
0 parents  commit 28c06fa

13 files changed

+360
-0
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
vendor/
2+
composer.lock

composer.json

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
{
2+
"name": "devmakerlab/laravel-filters",
3+
"type": "library",
4+
"license": "WTFPL",
5+
"autoload": {
6+
"psr-4": {
7+
"DevMakerLab\\LaravelFilters\\": "src/"
8+
}
9+
},
10+
"autoload-dev": {
11+
"psr-4": {
12+
"Tests\\": "tests/",
13+
"Tests\\Example\\": "tests/Example"
14+
}
15+
},
16+
"authors": [
17+
{
18+
"name": "Valentin Leguy",
19+
"email": "[email protected]"
20+
},
21+
{
22+
"name": "Anthony Meinder",
23+
"email": "[email protected]"
24+
}
25+
],
26+
"require": {
27+
"illuminate/database": "^8.50"
28+
},
29+
"require-dev": {
30+
"symfony/var-dumper": "^5.3",
31+
"phpunit/phpunit": "^9.5",
32+
"orchestra/testbench": "^6.19",
33+
"devmakerlab/entities": "^3.0.1"
34+
},
35+
"scripts": {
36+
"post-autoload-dump": [
37+
"@php ./vendor/bin/testbench package:discover --ansi"
38+
]
39+
}
40+
}

phpunit.xml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<phpunit
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
bootstrap="vendor/autoload.php"
5+
backupGlobals="false"
6+
backupStaticAttributes="false"
7+
colors="true"
8+
verbose="true"
9+
convertErrorsToExceptions="true"
10+
convertNoticesToExceptions="true"
11+
convertWarningsToExceptions="true"
12+
processIsolation="false"
13+
stopOnFailure="false"
14+
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd"
15+
>
16+
<coverage>
17+
<include>
18+
<directory suffix=".php">src/</directory>
19+
</include>
20+
</coverage>
21+
<testsuites>
22+
<testsuite name="Unit">
23+
<directory suffix="Test.php">./tests/Unit</directory>
24+
</testsuite>
25+
<testsuite name="Feature">
26+
<directory suffix="Test.php">./tests/Feature</directory>
27+
</testsuite>
28+
</testsuites>
29+
<php>
30+
<env name="DB_CONNECTION" value="testing"/>
31+
<env name="APP_KEY" value="base64:bWVpbmRlci1hL2ZpbHRlcnMKc3RhciBpdCE="/>
32+
</php>
33+
</phpunit>
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace DevMakerLab\LaravelFilters;
6+
7+
use Illuminate\Database\Query\Builder;
8+
9+
abstract class AbstractFilterableRepository
10+
{
11+
protected array $filters;
12+
13+
protected ?int $limit = null;
14+
15+
/**
16+
* @throws FilterClassNotFound
17+
* @throws IncorrectFilterException
18+
*/
19+
public function addFilter(string $filter): self
20+
{
21+
if (! class_exists($filter)) {
22+
throw new FilterClassNotFound();
23+
}
24+
25+
if (! is_subclass_of($filter, FilterInterface::class)) {
26+
throw new IncorrectFilterException($filter);
27+
}
28+
29+
$this->filters[] = $filter;
30+
31+
return $this;
32+
}
33+
34+
public function resetFilters(): self
35+
{
36+
$this->filters = [];
37+
38+
return $this;
39+
}
40+
41+
public function limit(int $limit): self
42+
{
43+
$this->limit = $limit;
44+
45+
return $this;
46+
}
47+
48+
public function resetLimit(): self
49+
{
50+
$this->limit = null;
51+
52+
return $this;
53+
}
54+
55+
public function applyFilters(Builder &$builder, array $args): self
56+
{
57+
foreach ($this->filters as $filter) {
58+
$neededKeys = $filter::neededKeys();
59+
$neededArgs = $this->extractNeededArgs($neededKeys, $args);
60+
61+
if ($filter::isApplicable($neededArgs)) {
62+
(new $filter)->apply($builder, $neededArgs);
63+
}
64+
}
65+
66+
if ($this->limit) {
67+
$builder->limit($this->limit);
68+
}
69+
70+
$this->resetFilters();
71+
$this->resetLimit();
72+
73+
return $this;
74+
}
75+
76+
private function extractNeededArgs(array $neededKeys, array $args): array
77+
{
78+
return array_intersect_key($args, array_flip($neededKeys));
79+
}
80+
}

src/FilterClassNotFound.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace DevMakerLab\LaravelFilters;
6+
7+
use Exception;
8+
9+
class FilterClassNotFound extends Exception
10+
{
11+
public function __construct()
12+
{
13+
parent::__construct();
14+
}
15+
}

src/FilterInterface.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace DevMakerLab\LaravelFilters;
6+
7+
use Illuminate\Database\Query\Builder;
8+
9+
interface FilterInterface
10+
{
11+
public static function neededKeys(): array;
12+
13+
public static function isApplicable(... $args): bool;
14+
15+
public function apply(Builder &$queryBuilder, ... $args): void;
16+
}

src/IncorrectFilterException.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace DevMakerLab\LaravelFilters;
6+
7+
use Exception;
8+
9+
class IncorrectFilterException extends Exception
10+
{
11+
public function __construct(string $class)
12+
{
13+
parent::__construct(sprintf('Class `%s` does not extends FilterInterface.', $class));
14+
}
15+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tests\Example\Entities;
6+
7+
use DevMakerLab\Entity;
8+
9+
class PeopleEntity extends Entity
10+
{
11+
public string $name;
12+
public int $age;
13+
public string $gender;
14+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tests\Example\Entities;
6+
7+
use DevMakerLab\EntityList;
8+
9+
class PeopleEntityList extends EntityList
10+
{
11+
protected string $expectedType = PeopleEntity::class;
12+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tests\Example\Filters;
6+
7+
use Illuminate\Database\Query\Builder;
8+
use DevMakerLab\LaravelFilters\FilterInterface;
9+
10+
class OldPeopleFilter implements FilterInterface
11+
{
12+
public static function neededKeys(): array
13+
{
14+
return ['age'];
15+
}
16+
17+
public static function isApplicable(...$args): bool
18+
{
19+
return true;
20+
}
21+
22+
public function apply(Builder &$queryBuilder, ...$args): void
23+
{
24+
$age = $args[0][self::neededKeys()[0]];
25+
26+
$queryBuilder->where('age', '>=', $age);
27+
}
28+
}

0 commit comments

Comments
 (0)