Skip to content

Commit 67867a2

Browse files
authored
Implement lampager-cakephp (#1)
* Implement lampager-cakephp * Update README.md * Update README.md
1 parent a5ee1d9 commit 67867a2

22 files changed

+3880
-0
lines changed

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
composer.lock
2+
/vendor/
3+
.php_cs.cache

.php_cs

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
3+
return \PhpCsFixer\Config::create()->setRules([
4+
'@Symfony' => true,
5+
'align_multiline_comment' => ['comment_type' => 'phpdocs_like'],
6+
'array_syntax' => ['syntax' => 'short'],
7+
'blank_line_before_statement' => false,
8+
'cast_spaces' => ['space' => 'none'],
9+
'combine_consecutive_unsets' => true,
10+
'concat_space' => ['spacing' => 'one'],
11+
'heredoc_to_nowdoc' => true,
12+
'list_syntax' => null,
13+
'no_extra_consecutive_blank_lines' => ['tokens' => ['continue', 'parenthesis_brace_block', 'extra', 'return']],
14+
'no_multiline_whitespace_before_semicolons' => true,
15+
'no_null_property_initialization' => true,
16+
'no_short_echo_tag' => false,
17+
'no_superfluous_elseif' => true,
18+
'no_unneeded_curly_braces' => true,
19+
'no_unneeded_final_method' => true,
20+
'no_useless_else' => true,
21+
'no_useless_return' => true,
22+
'not_operator_with_space' => false,
23+
'not_operator_with_successor_space' => false,
24+
'phpdoc_add_missing_param_annotation' => true,
25+
'phpdoc_annotation_without_dot' => null,
26+
'phpdoc_no_alias_tag' => false,
27+
'phpdoc_order' => true,
28+
'phpdoc_separation' => false,
29+
'phpdoc_summary' => null,
30+
'phpdoc_types_order' => true,
31+
'return_type_declaration' => true,
32+
'void_return' => false,
33+
'yoda_style' => false,
34+
]);

.scrutinizer.yml

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
checks:
2+
php:
3+
code_rating: true
4+
5+
filter:
6+
excluded_paths:
7+
- vendor/*
8+
9+
build:
10+
environment:
11+
php: '7.4'

.travis.yml

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
language: php
2+
3+
php:
4+
- 5.6
5+
- 7.0
6+
- 7.1
7+
- 7.2
8+
- 7.3
9+
- 7.4
10+
11+
services:
12+
- mysql
13+
14+
env:
15+
- DB_DSN=
16+
- DB_DSN=mysql://root:@localhost/lampager_test
17+
18+
cache:
19+
directories:
20+
- ./vendor
21+
- $HOME/.composer/cache
22+
23+
before_script:
24+
- composer install
25+
- mysql -e 'CREATE DATABASE lampager_test;'
26+
- mkdir -p build/logs
27+
28+
script:
29+
- vendor/bin/phpunit --coverage-clover build/logs/clover.xml
30+
31+
after_success:
32+
- travis_retry vendor/bin/coveralls

LICENSE

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2020 Chitoku
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

+194
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
<p align="center">
2+
<img width="320" alt="lampager-cakephp" src="https://user-images.githubusercontent.com/1351893/31820647-42c45c7a-b5dd-11e7-9ac8-f1000e961662.png">
3+
</p>
4+
<p align="center">
5+
<a href="https://travis-ci.com/lampager/lampager-cakephp"><img src="https://travis-ci.com/lampager/lampager-cakephp.svg?branch=master" alt="Build Status"></a>
6+
<a href="https://coveralls.io/github/lampager/lampager-cakephp?branch=master"><img src="https://coveralls.io/repos/github/lampager/lampager-cakephp/badge.svg?branch=master" alt="Coverage Status"></a>
7+
<a href="https://scrutinizer-ci.com/g/lampager/lampager-cakephp/?branch=master"><img src="https://scrutinizer-ci.com/g/lampager/lampager-cakephp/badges/quality-score.png?b=master" alt="Scrutinizer Code Quality"></a>
8+
</p>
9+
10+
# Lampager for CakePHP
11+
12+
Rapid pagination without using OFFSET
13+
14+
## Requirements
15+
16+
- PHP: ^5.6 || ^7.0
17+
- CakePHP: ^3.6
18+
- [lampager/lampager](https://github.com/lampager/lampager): ^0.4
19+
20+
## Installing
21+
22+
```bash
23+
composer require lampager/lampager-cakephp
24+
```
25+
26+
## Basic Usage
27+
28+
The `Plugin` is not provided. Simply install as a Composer package and use in
29+
one of the following methods:
30+
31+
- Use in Controller (via `Lampager\Cake\Datasource\Paginator`)
32+
- Use in Table (via `Lampager\Cake\Model\Behavior\LampagerBehavior`)
33+
34+
### Use in Controller
35+
36+
At first, load the default Paginator component with the Lampager `Paginator` in
37+
your Controller class (`AppController` is preferable).
38+
39+
Accept cursor parameters from a request and pass it through
40+
`PaginatorComponent::paginate()`. The `Paginator` also accepts `Query`
41+
expression that is created by `Table` classes.
42+
43+
```php
44+
namespace App\Controller;
45+
46+
use Cake\Controller\Controller;
47+
use Lampager\Cake\Datasource\Paginator;
48+
49+
class AppController extends Controller
50+
{
51+
public function initialize()
52+
{
53+
parent::initialize();
54+
55+
$this->loadComponent('Paginator', [
56+
'paginator' => new Paginator(),
57+
]);
58+
}
59+
60+
public function index()
61+
{
62+
// Get cursor parameters
63+
$previous = json_decode($this->request->getQuery('previous_cursor'), true);
64+
$next = json_decode($this->request->getQuery('next_cursor'), true);
65+
$cursor = $previous ?: $next ?: [];
66+
67+
/** @var \Lampager\PaginationResult<\Cake\ORM\Entity> $posts */
68+
$posts = $this->paginate('Posts', [
69+
// Lampager options
70+
// If the previous_cursor is not set, paginate forward; otherwise backward
71+
'forward' => !$previous,
72+
'cursor' => $cursor,
73+
'seekable' => true,
74+
75+
// PaginatorComponent config
76+
'order' => [
77+
'created' => 'DESC',
78+
'id' => 'DESC',
79+
],
80+
'limit' => 15,
81+
]);
82+
$this->set('posts', $posts);
83+
}
84+
85+
public function query()
86+
{
87+
// Get cursor parameters
88+
$previous = json_decode($this->request->getQuery('previous_cursor'), true);
89+
$next = json_decode($this->request->getQuery('next_cursor'), true);
90+
$cursor = $previous ?: $next ?: [];
91+
92+
// Query expression can also be passed to PaginatorComponent::paginate() as normal
93+
$query = TableRegistry::getTableLocator()->get('Posts')
94+
->where(['Posts.type' => 'public'])
95+
->orderDesc('created')
96+
->orderDesc('id')
97+
->limit(15);
98+
99+
/** @var \Lampager\PaginationResult<\Cake\ORM\Entity> $posts */
100+
$posts = $this->paginate($query, [
101+
// If the previous_cursor is not set, paginate forward; otherwise backward
102+
'forward' => !$previous,
103+
'cursor' => $cursor,
104+
'seekable' => true,
105+
]);
106+
$this->set('posts', $posts);
107+
}
108+
}
109+
```
110+
111+
And the pagination links can be output as follows:
112+
113+
```php
114+
// If there is a next page, print pagination link
115+
if ($posts->hasPrevious) {
116+
echo $this->Html->link('<< Previous', [
117+
'controller' => 'posts',
118+
'action' => 'index',
119+
'?' => [
120+
'previous_cursor' => json_encode($posts->previousCursor),
121+
],
122+
]);
123+
}
124+
125+
// If there is a next page, print pagination link
126+
if ($posts->hasNext) {
127+
echo $this->Html->link('Next >>', [
128+
'controller' => 'posts',
129+
'action' => 'index',
130+
'?' => [
131+
'next_cursor' => json_encode($posts->nextCursor),
132+
],
133+
]);
134+
}
135+
```
136+
137+
### Use in Table
138+
139+
Initialize `LampagerBehavior` in your Table class (`AppTable` is preferable)
140+
and simply use `lampager()` from the `Table` class. The query builder extends
141+
the plain old `\Cake\ORM\Query` and is mixed in with `\Lampager\Paginator`. Note
142+
that some of the methods in `\Lampager\Paginator`, viz., `orderBy()`,
143+
`orderByDesc()`, and `clearOrderBy()` are not exposed because their method
144+
signatures are not compatible with the CakePHP query builder.
145+
146+
```php
147+
namespace App\Model\Table;
148+
149+
use Cake\ORM\Table;
150+
use Lampager\Cake\Model\Behavior\LampagerBehavior;
151+
152+
class AppTable extends Table
153+
{
154+
public function initialize(array $config)
155+
{
156+
parent::initialize($config);
157+
158+
$this->addBehavior(LampagerBehavior::class);
159+
}
160+
161+
/**
162+
* @return \Lampager\PaginationResult
163+
*/
164+
public function latest(array $cursor = [])
165+
{
166+
return $this->lampager()
167+
->forward()
168+
->seekable()
169+
->cursor($cursor)
170+
->limit(10)
171+
->orderDesc('Post.modified')
172+
->orderDesc('Post.created')
173+
->orderDesc('Post.id');
174+
}
175+
176+
/**
177+
* @return \Lampager\PaginationResult
178+
*/
179+
public function draft(array $cursor = [])
180+
{
181+
// The methods from the CakePHP query builder, e.g., where(), are available.
182+
// \Cake\Database\Expression\QueryExpression can be accepted as well.
183+
return $this->lampager()
184+
->where(['type' => 'draft'])
185+
->forward()
186+
->seekable()
187+
->cursor($cursor)
188+
->limit(10)
189+
->orderDesc($this->query()->newExpr('modified'))
190+
->orderDesc($this->query()->newExpr('created'))
191+
->orderDesc($this->query()->newExpr('id'));
192+
}
193+
}
194+
```

composer.json

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
{
2+
"name": "lampager/lampager-cakephp",
3+
"description": "Rapid pagination for CakePHP 3",
4+
"type": "cakephp-plugin",
5+
"license": "MIT",
6+
"authors": [
7+
{
8+
"name": "Chitoku",
9+
"email": "[email protected]"
10+
}
11+
],
12+
"keywords": ["cakephp", "pagination", "paginator", "offset", "limit"],
13+
"autoload": {
14+
"psr-4": {
15+
"Lampager\\Cake\\": "src/"
16+
}
17+
},
18+
"autoload-dev": {
19+
"psr-4": {
20+
"Lampager\\Cake\\Test\\": "tests/",
21+
"Lampager\\Cake\\TestApp\\": "tests/test_app/"
22+
}
23+
},
24+
"require": {
25+
"php": "^5.6 || ^7.0",
26+
"lampager/lampager": "^0.4"
27+
},
28+
"require-dev": {
29+
"cakephp/cakephp": "^3.6",
30+
"phpunit/phpunit": "^5.7 || ^6.0"
31+
}
32+
}

phpunit.xml.dist

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<phpunit colors="true"
3+
processIsolation="false"
4+
stopOnFailure="false"
5+
syntaxCheck="false"
6+
bootstrap="tests/bootstrap.php">
7+
<testsuites>
8+
<testsuite name="Lampager CakePHP Test Suite">
9+
<directory>tests/TestCase/</directory>
10+
</testsuite>
11+
</testsuites>
12+
13+
<listeners>
14+
<listener class="\Cake\TestSuite\Fixture\FixtureInjector">
15+
<arguments>
16+
<object class="\Cake\TestSuite\Fixture\FixtureManager" />
17+
</arguments>
18+
</listener>
19+
</listeners>
20+
21+
<filter>
22+
<whitelist>
23+
<directory suffix=".php">src/</directory>
24+
</whitelist>
25+
</filter>
26+
</phpunit>

0 commit comments

Comments
 (0)