Completed
Branch develop (f7dc53)
by Anton
05:49
created

PaginatorTrait::applyPagination()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 1
Metric Value
c 2
b 0
f 1
dl 0
loc 8
rs 9.4286
cc 2
eloc 4
nc 2
nop 0
1
<?php
2
/**
3
 * Spiral Framework.
4
 *
5
 * @license   MIT
6
 * @author    Anton Titov (Wolfy-J)
7
 */
8
namespace Spiral\Pagination\Traits;
9
10
use Interop\Container\ContainerInterface;
11
use Psr\Http\Message\ServerRequestInterface;
12
use Spiral\Core\Exceptions\SugarException;
13
use Spiral\Core\FactoryInterface;
14
use Spiral\Pagination\Exceptions\PaginationException;
15
use Spiral\Pagination\Paginator;
16
use Spiral\Pagination\PaginatorInterface;
17
18
/**
19
 * Provides ability to paginate associated instance. Will work with default Paginator or fetch one
20
 * from container.
21
 *
22
 * Compatible with PaginatorAwareInterface.
23
 */
24
trait PaginatorTrait
25
{
26
    /**
27
     * @var PaginatorInterface
28
     */
29
    private $paginator = null;
30
31
    /**
32
     * @var int
33
     */
34
    protected $limit = 0;
35
36
    /**
37
     * @var int
38
     */
39
    protected $offset = 0;
40
41
    /**
42
     * Count elements of an object.
43
     *
44
     * @link http://php.net/manual/en/countable.count.php
45
     * @return int
46
     */
47
    abstract public function count();
48
49
    /**
50
     * Set selection limit.
51
     *
52
     * @param int $limit
53
     * @return mixed
54
     */
55
    public function limit($limit = 0)
56
    {
57
        $this->limit = $limit;
58
59
        return $this;
60
    }
61
62
    /**
63
     * @return int
64
     */
65
    public function getLimit()
66
    {
67
        return $this->limit;
68
    }
69
70
    /**
71
     * Set selection offset.
72
     *
73
     * @param int $offset
74
     * @return mixed
75
     */
76
    public function offset($offset = 0)
77
    {
78
        $this->offset = $offset;
79
80
        return $this;
81
    }
82
83
    /**
84
     * @return int
85
     */
86
    public function getOffset()
87
    {
88
        return $this->offset;
89
    }
90
91
    /**
92
     * Manually set paginator instance for specific object.
93
     *
94
     * @param PaginatorInterface $paginator
95
     * @return $this
96
     */
97
    public function setPaginator(PaginatorInterface $paginator)
98
    {
99
        $this->paginator = $paginator;
100
101
        return $this;
102
    }
103
104
    /**
105
     * Get paginator for the current selection. Paginate method should be already called.
106
     *
107
     * @see isPaginated()
108
     * @see paginate()
109
     * @return PaginatorInterface|Paginator|null
110
     */
111
    public function paginator()
112
    {
113
        return $this->paginator;
114
    }
115
116
    /**
117
     * Indication that object was paginated.
118
     *
119
     * @return bool
120
     */
121
    public function isPaginated()
122
    {
123
        return !empty($this->paginator);
124
    }
125
126
    /**
127
     * Paginate current selection using Paginator class.
128
     *
129
     * @param int                    $limit         Pagination limit.
130
     * @param string                 $pageParameter Name of parameter in request query which is
131
     *                                              used to store the current page number. "page"
132
     *                                              by default.
133
     * @param ServerRequestInterface $request       Has to be specified if no global container set.
134
     * @return $this
135
     * @throws PaginationException
136
     */
137
    public function paginate(
138
        $limit = Paginator::DEFAULT_LIMIT,
139
        $pageParameter = Paginator::DEFAULT_PARAMETER,
140
        ServerRequestInterface $request = null
141
    ) {
142
        //Will be used in two places
143
        $container = $this->container();
144
145
        if (empty($request)) {
146
            if (empty($container) || !$container->has(ServerRequestInterface::class)) {
147
                throw new SugarException(
148
                    "Unable to create pagination without specified request."
149
                );
150
            }
151
152
            //Getting request from container scope
153
            $request = $container->get(ServerRequestInterface::class);
154
        }
155
156
        if (empty($container) || !$container->has(PaginatorInterface::class)) {
157
            //Let's use default paginator
158
            $this->paginator = new Paginator($request, $pageParameter);
159
        } else {
160
            //We need constructor
161
            if ($container instanceof FactoryInterface) {
162
                $constructor = $container;
163
            } else {
164
                $constructor = $container->get(FactoryInterface::class);
165
            }
166
167
            //We can also create paginator using container
168
            $this->paginator = $constructor->make(PaginatorInterface::class, compact(
169
                'request', 'pageParameter'
170
            ));
171
        }
172
173
        $this->paginator->setLimit($limit);
174
175
        return $this;
176
    }
177
178
    /**
179
     * Apply pagination to current object. Will be applied only if internal paginator already
180
     * constructed.
181
     *
182
     * @return $this
183
     * @throws PaginationException
184
     */
185
    protected function applyPagination()
186
    {
187
        if (empty($this->paginator)) {
188
            return $this;
189
        }
190
191
        return $this->paginator->paginate($this);
192
    }
193
194
    /**
195
     * @return ContainerInterface
196
     */
197
    abstract protected function container();
198
}