Passed
Push — master ( dc3688...f2f34e )
by Pavel
02:13
created

CollectionAction::applyFilter()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 2
dl 0
loc 7
ccs 4
cts 4
cp 1
crap 1
rs 9.4285
c 0
b 0
f 0
1
<?php namespace Pz\Doctrine\Rest\Action;
2
3
use Doctrine\Common\Collections\Criteria;
4
use Doctrine\ORM\QueryBuilder;
5
use Doctrine\ORM\Tools\Pagination\Paginator;
6
use League\Fractal\Pagination\DoctrinePaginatorAdapter;
7
use League\Fractal\Resource\Collection;
8
use Pz\Doctrine\Rest\BuilderChain\CriteriaChain;
9
use Pz\Doctrine\Rest\QueryParser\ArrayFilterParser;
10
use Pz\Doctrine\Rest\QueryParser\FilterParserAbstract;
11
use Pz\Doctrine\Rest\QueryParser\StringFilterParser;
12
use Pz\Doctrine\Rest\RestAction;
13
use Pz\Doctrine\Rest\Contracts\RestRequestContract;
14
use Pz\Doctrine\Rest\RestResponse;
15
16
/**
17
 * Action for providing collection (list or array) of data with API.
18
 */
19
class CollectionAction extends RestAction
20
{
21
    /**
22
     * Field that can be filtered if filter is string.
23
     *
24
     * @var string
25
     */
26
    protected $filterProperty;
27
28
    /**
29
     * Get list of filterable entity fields.
30
     *
31
     * @var array
32
     */
33
    protected $filterable = [];
34
35
    /**
36
     * @param string $property
37
     *
38
     * @return $this
39
     */
40 1
    public function setFilterProperty($property)
41
    {
42 1
        $this->filterProperty = $property;
43 1
        return $this;
44
    }
45
46
    /**
47
     * @param array $filterable
48
     *
49
     * @return $this
50
     */
51 1
    public function setFilterable(array $filterable)
52
    {
53 1
        $this->filterable = $filterable;
54 1
        return $this;
55
    }
56
57
    /**
58
     * Param that can be filtered if query is string.
59
     *
60
     * @return null|string
61
     */
62 7
    public function getStringFilterField()
63
    {
64 7
        return $this->filterProperty;
65
    }
66
67
    /**
68
     * Get list of filterable entity properties.
69
     *
70
     * @return array
71
     */
72 7
    public function getArrayFilterFields()
73
    {
74 7
        return $this->filterable;
75
    }
76
77
    /**
78
     * @param RestRequestContract $request
79
     *
80
     * @return RestResponse
81
     */
82 7
    protected function handle(RestRequestContract $request)
83
    {
84 7
        $resourceKey = $this->repository()->getResourceKey();
85 7
        $this->authorize($request, $this->repository()->getClassName());
86
87 7
        $qb = $this->repository()->sourceQueryBuilder();
88 7
        $this->applyPagination($request, $qb);
89 7
        $this->applyFilter($request, $qb);
90
91 7
         $paginator = new Paginator($qb, false);
92 7
         $collection = new Collection($paginator, $this->transformer(), $resourceKey);
93
94 7
        if ($qb->getMaxResults()) {
95 2
            $collection->setPaginator(
96 2
                new DoctrinePaginatorAdapter(
97 2
                    $paginator,
98 2
                    $this->paginatorUrlGenerator($request, $resourceKey)
99
                )
100
            );
101
        }
102
103 7
        return $this->response()->resource($request, $collection);
104
    }
105
106
    /**
107
     * @param RestRequestContract $request
108
     * @param QueryBuilder        $qb
109
     *
110
     * @return QueryBuilder
111
     */
112 7
    protected function applyPagination(RestRequestContract $request, QueryBuilder $qb)
113
    {
114 7
        $qb->addCriteria(
115 7
            new Criteria(null,
116 7
                $request->getOrderBy(),
117 7
                $request->getStart(),
118 7
                $request->getLimit()
119
            )
120
        );
121
122 7
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this returns the type Pz\Doctrine\Rest\Action\CollectionAction which is incompatible with the documented return type Doctrine\ORM\QueryBuilder.
Loading history...
123
    }
124
125
    /**
126
     * @param RestRequestContract $request
127
     * @param QueryBuilder        $qb
128
     *
129
     * @return QueryBuilder
130
     * @throws \Doctrine\ORM\Query\QueryException
131
     */
132 7
    protected function applyFilter(RestRequestContract $request, QueryBuilder $qb)
133
    {
134 7
        $qb->addCriteria(
135 7
            CriteriaChain::create($this->filterParsers($request))->process()
136
        );
137
138 7
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this returns the type Pz\Doctrine\Rest\Action\CollectionAction which is incompatible with the documented return type Doctrine\ORM\QueryBuilder.
Loading history...
139
    }
140
141
    /**
142
     * @param RestRequestContract $request
143
     *
144
     * @return array|FilterParserAbstract[]
145
     */
146 7
    protected function filterParsers(RestRequestContract $request)
147
    {
148
        return [
149 7
            new StringFilterParser($request, $this->getStringFilterField()),
150 7
            new ArrayFilterParser($request, $this->getArrayFilterFields()),
151
        ];
152
    }
153
154
    /**
155
     * @param RestRequestContract $request
156
     * @param             $resourceKey
157
     *
158
     * @return \Closure
159
     */
160
    protected function paginatorUrlGenerator(RestRequestContract $request, $resourceKey)
161
    {
162 2
        return function(int $page) use ($resourceKey, $request) {
163 1
            return !$resourceKey ? null : "{$request->getBaseUrl()}/$resourceKey?".http_build_query([
164
                'page' => [
165 1
                    'number'    => $page,
166 1
                    'size'      => $request->getLimit()
167
                ]
168
            ]);
169 2
        };
170
    }
171
}
172