Passed
Push — master ( 08900f...b14429 )
by Pavel
02:14
created

CollectionAction::prepareCollection()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 23
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 12
nc 2
nop 2
dl 0
loc 23
ccs 13
cts 13
cp 1
crap 2
rs 9.8666
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 Pz\Doctrine\Rest\BuilderChain\CriteriaChain;
8
use Pz\Doctrine\Rest\QueryParser\ArrayFilterParser;
9
use Pz\Doctrine\Rest\QueryParser\FilterParserAbstract;
10
use Pz\Doctrine\Rest\QueryParser\StringFilterParser;
11
use Pz\Doctrine\Rest\Resource\Collection;
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 12
    public function getStringFilterField()
63
    {
64 12
        return $this->filterProperty;
65
    }
66
67
    /**
68
     * Get list of filterable entity properties.
69
     *
70
     * @return array
71
     */
72 12
    public function getArrayFilterFields()
73
    {
74 12
        return $this->filterable;
75
    }
76
77
    /**
78
     * @param RestRequestContract $request
79
     *
80
     * @return RestResponse
81
     */
82 12
    protected function handle($request)
83
    {
84 12
        $this->authorize($request, $this->repository()->getClassName());
85
86 12
        $qb = $this->repository()->sourceQueryBuilder($request);
87 12
        $this->applyPagination($request, $qb);
88 12
        $this->applyFilter($request, $qb);
89
90 12
        return $this->response()->resource($request, $this->prepareCollection($request, $qb));
91
    }
92
93
    /**
94
     * @param RestRequestContract   $request
95
     * @param QueryBuilder          $qb
96
     * @return Collection
97
     */
98 12
    protected function prepareCollection($request, QueryBuilder $qb)
99
    {
100 12
        $paginator = new Paginator($qb, false);
101 12
        $collection = new Collection($paginator, $this->transformer(), $this->repository()->getResourceKey());
102
103 12
        if ($qb->getMaxResults()) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $qb->getMaxResults() of type null|integer is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
104 2
            $collection->setPaginator(
105 2
                new DoctrinePaginatorAdapter(
106 2
                    $paginator,
107 2
                    function(int $page) use ($request) {
108
                        // return !$resourceKey ? null : "{$request->getBaseUrl()}/$resourceKey?".http_build_query([
109 2
                        return $request->getBasePath().'?'.http_build_query([
110
                            'page' => [
111 2
                                'number'    => $page,
112 2
                                'size'      => $request->getLimit()
113
                            ]
114
                        ]);
115 2
                    }
116
                )
117
            );
118
        }
119
120 12
        return $collection;
121
    }
122
123
    /**
124
     * @param RestRequestContract $request
125
     * @param QueryBuilder        $qb
126
     *
127
     * @return $this
128
     */
129 12
    protected function applyPagination(RestRequestContract $request, QueryBuilder $qb)
130
    {
131 12
        $qb->addCriteria(
132 12
            new Criteria(null,
133 12
                $request->getOrderBy(),
134 12
                $request->getStart(),
135 12
                $request->getLimit()
136
            )
137
        );
138
139 12
        return $this;
140
    }
141
142
    /**
143
     * @param RestRequestContract $request
144
     * @param QueryBuilder        $qb
145
     *
146
     * @return $this
147
     */
148 12
    protected function applyFilter(RestRequestContract $request, QueryBuilder $qb)
149
    {
150 12
        $qb->addCriteria(
151 12
            CriteriaChain::create($this->filterParsers($request))->process()
152
        );
153
154 12
        return $this;
155
    }
156
157
    /**
158
     * @param RestRequestContract $request
159
     *
160
     * @return array|FilterParserAbstract[]
161
     */
162 12
    protected function filterParsers(RestRequestContract $request)
163
    {
164
        return [
165 12
            new StringFilterParser($request, $this->getStringFilterField()),
166 12
            new ArrayFilterParser($request, $this->getArrayFilterFields()),
167
        ];
168
    }
169
}
170