CursorPaginateExtension::afterFind()   B
last analyzed

Complexity

Conditions 7
Paths 24

Size

Total Lines 56

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 43
CRAP Score 7

Importance

Changes 0
Metric Value
cc 7
nc 24
nop 1
dl 0
loc 56
rs 8.0266
c 0
b 0
f 0
ccs 43
cts 43
cp 1
crap 7

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * Copyright 2016 - 2018, Cake Development Corporation (http://cakedc.com)
4
 *
5
 * Licensed under The MIT License
6
 * Redistributions of files must retain the above copyright notice.
7
 *
8
 * @copyright Copyright 2016 - 2018, Cake Development Corporation (http://cakedc.com)
9
 * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
10
 */
11
12
namespace CakeDC\Api\Service\Action\Extension;
13
14
use CakeDC\Api\Service\Action\Action;
15
use CakeDC\Api\Service\Action\ExtensionRegistry;
16
use CakeDC\Api\Service\Utility\ReverseRouting;
17
use Cake\Event\Event;
18
use Cake\Event\EventListenerInterface;
19
use Cake\ORM\Entity;
20
21
/**
22
 * Class CursorPaginateExtension
23
 *
24
 * @package CakeDC\Api\Service\Action\Extension
25
 */
26
class CursorPaginateExtension extends Extension implements EventListenerInterface
27
{
28
29
    protected $_defaultConfig = [
30
        'cursorField' => 'id',
31
        'countField' => 'count',
32
        'defaultCount' => 20,
33
        'maxIdField' => 'max_id',
34
        'sinceIdField' => 'since_id',
35
    ];
36
37
    /**
38
     * @var ReverseRouting
39
     */
40
    protected $_reverseRouter;
41
42
    /**
43
     * CursorPaginateExtension constructor.
44
     *
45
     * @param ExtensionRegistry $registry An Extension Registry instance.
46
     * @param array $config Configuration.
47
     * @internal param array $options
48
     */
49 8
    public function __construct(ExtensionRegistry $registry, array $config = [])
50
    {
51 8
        parent::__construct($registry, $config);
52 8
        $this->_reverseRouter = new ReverseRouting();
53 8
    }
54
55
    /**
56
     * Returns a list of events this object is implementing. When the class is registered
57
     * in an event manager, each individual method will be associated with the respective event.
58
     *
59
     * @return array
60
     */
61 8
    public function implementedEvents()
62
    {
63
        return [
64 8
            'Action.Crud.onFindEntities' => 'findEntities',
65 8
            'Action.Crud.afterFindEntities' => 'afterFind',
66 8
        ];
67
    }
68
69
    /**
70
     * find entities
71
     *
72
     * @param Event $event An Event instance.
73
     * @return Entity
74
     */
75 8
    public function findEntities(Event $event)
76
    {
77 8
        $action = $event->getSubject();
78 8
        $query = $event->getData('query');
79 8
        if ($event->result) {
80
            $query = $event->result;
81
        }
82 8
        $query->limit($this->_count($action));
0 ignored issues
show
Documentation introduced by
$action is of type object|null, but the function expects a object<CakeDC\Api\Service\Action\Action>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
83 8
        $sinceId = $this->_sinceId($action);
0 ignored issues
show
Documentation introduced by
$action is of type object|null, but the function expects a object<CakeDC\Api\Service\Action\Action>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
84 8
        $maxId = $this->_maxId($action);
0 ignored issues
show
Documentation introduced by
$action is of type object|null, but the function expects a object<CakeDC\Api\Service\Action\Action>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
85 8
        $orderDirection = 'desc';
86 8
        $cursorField = $this->getConfig('cursorField');
87 8
        if ($maxId) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $maxId of type integer|null is loosely compared to true; this is ambiguous if the integer can be zero. 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...
88 2
            $orderDirection = 'desc';
89 2
            $query->where([$cursorField . ' <' => $maxId]);
90 8
        } elseif ($sinceId) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $sinceId of type integer|null is loosely compared to true; this is ambiguous if the integer can be zero. 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...
91 2
            $orderDirection = 'asc';
92 2
            $query->where([$cursorField . ' >' => $sinceId]);
93 2
        }
94 8
        $query->order([$cursorField => $orderDirection]);
95
96 8
        return $query;
97
    }
98
99
    /**
100
     * Returns since id.
101
     *
102
     * @param Action $action An Action instance.
103
     * @return int|null
104
     */
105 8
    protected function _sinceId(Action $action)
106
    {
107 8
        $data = $action->getData();
108 8
        $sinceIdField = $this->getConfig('sinceIdField');
109 8
        if (!empty($sinceIdField) && !empty($data[$sinceIdField]) && is_numeric($data[$sinceIdField])) {
110 2
            return (int)$data[$sinceIdField];
111
        } else {
112 6
            return null;
113
        }
114
    }
115
116
    /**
117
     * Returns max id.
118
     *
119
     * @param Action $action An Action instance.
120
     * @return int|null
121
     */
122 8
    protected function _maxId(Action $action)
123
    {
124 8
        $data = $action->getData();
125 8
        $maxIdField = $this->getConfig('maxIdField');
126 8
        if (!empty($maxIdField) && !empty($data[$maxIdField]) && is_numeric($data[$maxIdField])) {
127 2
            return (int)$data[$maxIdField];
128
        } else {
129 6
            return null;
130
        }
131
    }
132
133
    /**
134
     * Returns count.
135
     *
136
     * @param Action $action An Action instance.
137
     * @return int|null
138
     */
139 8
    protected function _count(Action $action)
140
    {
141 8
        $data = $action->getData();
142 8
        $countField = $this->getConfig('countField');
143 8
        $maxCount = $this->getConfig('defaultCount');
144 8
        if (!empty($countField) && !empty($data[$countField]) && is_numeric($data[$countField])) {
145 6
            $count = min((int)$data[$countField], $maxCount);
146
147 6
            return $count;
148
        } else {
149 2
            return $maxCount;
150
        }
151
    }
152
153
    /**
154
     * after find entities
155
     *
156
     * @param Event $event An Event instance.
157
     * @return Entity
158
     */
159 8
    public function afterFind(Event $event)
160
    {
161 8
        $action = $event->getSubject();
162 8
        $records = $event->getData('records');
163 8
        $result = $action->getService()->getResult();
164
165 8
        $newMaxId = null;
166 8
        $newSinceId = null;
167 8
        $cursorField = $this->getConfig('cursorField');
168 8
        foreach ($records as $item) {
169 7
            $value = $item[$cursorField];
170 7
            if ($value !== null) {
171 7
                $newMaxId = is_null($newMaxId) ? $value : min($value, $newMaxId);
172 7
                $newSinceId = is_null($newSinceId) ? $value : max($value, $newSinceId);
173 7
            }
174 8
        }
175
176 8
        $sinceId = $this->_sinceId($action);
0 ignored issues
show
Documentation introduced by
$action is of type object|null, but the function expects a object<CakeDC\Api\Service\Action\Action>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
177 8
        $maxId = $this->_maxId($action);
0 ignored issues
show
Documentation introduced by
$action is of type object|null, but the function expects a object<CakeDC\Api\Service\Action\Action>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
178
179 8
        if ($newSinceId === null) {
180 1
            $newSinceId = $sinceId;
181 1
        }
182
183 8
        if ($newMaxId === null) {
184 1
            $newMaxId = $maxId;
185 1
        }
186
187 8
        $indexRoute = $action->getRoute();
188
189 8
        $links = [];
190
        $path = $this->_reverseRouter->indexPath($action, function ($route) use ($newSinceId) {
0 ignored issues
show
Documentation introduced by
$action is of type object|null, but the function expects a object<CakeDC\Api\Service\Action\Action>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
191 8
            $route['?']['since_id'] = $newSinceId;
192
193 8
            return $route;
194 8
        });
195 8
        $link = $this->_reverseRouter->link('prev', $path, $indexRoute['_method']);
196 8
        $links[$link['name']] = $link['href'];
197
198 8
        $path = $this->_reverseRouter->indexPath($action, function ($route) use ($newMaxId) {
0 ignored issues
show
Documentation introduced by
$action is of type object|null, but the function expects a object<CakeDC\Api\Service\Action\Action>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
199 8
            $route['?']['max_id'] = $newMaxId;
200
201 8
            return $route;
202 8
        });
203 8
        $link = $this->_reverseRouter->link('next', $path, $indexRoute['_method']);
204 8
        $links[$link['name']] = $link['href'];
205
206 8
        $count = $this->_count($action);
0 ignored issues
show
Documentation introduced by
$action is of type object|null, but the function expects a object<CakeDC\Api\Service\Action\Action>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
207
        $pagination = [
208 8
            'links' => $links,
209 8
            'count' => $count,
210 8
            'since_id' => $sinceId,
211 8
            'max_id' => $maxId,
212 8
        ];
213 8
        $result->appendPayload('pagination', $pagination);
214 8
    }
215
}
216