aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJeremy Benoist <jeremy.benoist@gmail.com>2016-11-19 14:53:28 +0100
committerJeremy Benoist <jeremy.benoist@gmail.com>2016-11-20 09:39:26 +0100
commit8670250a2674b6b388f3d40a8ba291a4dca41b82 (patch)
tree47f07b0ff474f361a5527fb2aed8d31040805c77
parent3c969d39906dbfb9711caee9f115a1d06d06ad36 (diff)
downloadwallabag-8670250a2674b6b388f3d40a8ba291a4dca41b82.tar.gz
wallabag-8670250a2674b6b388f3d40a8ba291a4dca41b82.tar.zst
wallabag-8670250a2674b6b388f3d40a8ba291a4dca41b82.zip
Add RSS pagination
Following https://tools.ietf.org/html/rfc5005#page-4
-rw-r--r--src/Wallabag/CoreBundle/Controller/RssController.php36
-rw-r--r--src/Wallabag/CoreBundle/Resources/views/themes/common/Entry/entries.xml.twig10
-rw-r--r--tests/Wallabag/CoreBundle/Controller/RssControllerTest.php57
3 files changed, 91 insertions, 12 deletions
diff --git a/src/Wallabag/CoreBundle/Controller/RssController.php b/src/Wallabag/CoreBundle/Controller/RssController.php
index 38e3b5a0..2290386f 100644
--- a/src/Wallabag/CoreBundle/Controller/RssController.php
+++ b/src/Wallabag/CoreBundle/Controller/RssController.php
@@ -3,12 +3,15 @@
3namespace Wallabag\CoreBundle\Controller; 3namespace Wallabag\CoreBundle\Controller;
4 4
5use Pagerfanta\Adapter\DoctrineORMAdapter; 5use Pagerfanta\Adapter\DoctrineORMAdapter;
6use Pagerfanta\Exception\OutOfRangeCurrentPageException;
6use Pagerfanta\Pagerfanta; 7use Pagerfanta\Pagerfanta;
7use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter; 8use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
8use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; 9use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
10use Symfony\Component\HttpFoundation\Request;
9use Symfony\Bundle\FrameworkBundle\Controller\Controller; 11use Symfony\Bundle\FrameworkBundle\Controller\Controller;
10use Wallabag\CoreBundle\Entity\Entry; 12use Wallabag\CoreBundle\Entity\Entry;
11use Wallabag\UserBundle\Entity\User; 13use Wallabag\UserBundle\Entity\User;
14use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
12 15
13class RssController extends Controller 16class RssController extends Controller
14{ 17{
@@ -20,9 +23,9 @@ class RssController extends Controller
20 * 23 *
21 * @return \Symfony\Component\HttpFoundation\Response 24 * @return \Symfony\Component\HttpFoundation\Response
22 */ 25 */
23 public function showUnreadAction(User $user) 26 public function showUnreadAction(Request $request, User $user)
24 { 27 {
25 return $this->showEntries('unread', $user); 28 return $this->showEntries('unread', $user, $request->query->get('page', 1));
26 } 29 }
27 30
28 /** 31 /**
@@ -33,9 +36,9 @@ class RssController extends Controller
33 * 36 *
34 * @return \Symfony\Component\HttpFoundation\Response 37 * @return \Symfony\Component\HttpFoundation\Response
35 */ 38 */
36 public function showArchiveAction(User $user) 39 public function showArchiveAction(Request $request, User $user)
37 { 40 {
38 return $this->showEntries('archive', $user); 41 return $this->showEntries('archive', $user, $request->query->get('page', 1));
39 } 42 }
40 43
41 /** 44 /**
@@ -46,9 +49,9 @@ class RssController extends Controller
46 * 49 *
47 * @return \Symfony\Component\HttpFoundation\Response 50 * @return \Symfony\Component\HttpFoundation\Response
48 */ 51 */
49 public function showStarredAction(User $user) 52 public function showStarredAction(Request $request, User $user)
50 { 53 {
51 return $this->showEntries('starred', $user); 54 return $this->showEntries('starred', $user, $request->query->get('page', 1));
52 } 55 }
53 56
54 /** 57 /**
@@ -57,10 +60,11 @@ class RssController extends Controller
57 * 60 *
58 * @param string $type Entries type: unread, starred or archive 61 * @param string $type Entries type: unread, starred or archive
59 * @param User $user 62 * @param User $user
63 * @param int $page
60 * 64 *
61 * @return \Symfony\Component\HttpFoundation\Response 65 * @return \Symfony\Component\HttpFoundation\Response
62 */ 66 */
63 private function showEntries($type, User $user) 67 private function showEntries($type, User $user, $page = 1)
64 { 68 {
65 $repository = $this->getDoctrine()->getRepository('WallabagCoreBundle:Entry'); 69 $repository = $this->getDoctrine()->getRepository('WallabagCoreBundle:Entry');
66 70
@@ -87,8 +91,26 @@ class RssController extends Controller
87 $perPage = $user->getConfig()->getRssLimit() ?: $this->getParameter('wallabag_core.rss_limit'); 91 $perPage = $user->getConfig()->getRssLimit() ?: $this->getParameter('wallabag_core.rss_limit');
88 $entries->setMaxPerPage($perPage); 92 $entries->setMaxPerPage($perPage);
89 93
94 $url = $this->generateUrl(
95 $type.'_rss',
96 [
97 'username' => $user->getUsername(),
98 'token' => $user->getConfig()->getRssToken(),
99 ],
100 UrlGeneratorInterface::ABSOLUTE_URL
101 );
102
103 try {
104 $entries->setCurrentPage((int) $page);
105 } catch (OutOfRangeCurrentPageException $e) {
106 if ($page > 1) {
107 return $this->redirect($url.'?page='.$entries->getNbPages(), 302);
108 }
109 }
110
90 return $this->render('@WallabagCore/themes/common/Entry/entries.xml.twig', [ 111 return $this->render('@WallabagCore/themes/common/Entry/entries.xml.twig', [
91 'type' => $type, 112 'type' => $type,
113 'url' => $url,
92 'entries' => $entries, 114 'entries' => $entries,
93 ]); 115 ]);
94 } 116 }
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/common/Entry/entries.xml.twig b/src/Wallabag/CoreBundle/Resources/views/themes/common/Entry/entries.xml.twig
index 288bb54f..16ecaa97 100644
--- a/src/Wallabag/CoreBundle/Resources/views/themes/common/Entry/entries.xml.twig
+++ b/src/Wallabag/CoreBundle/Resources/views/themes/common/Entry/entries.xml.twig
@@ -2,7 +2,15 @@
2<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:media="http://search.yahoo.com/mrss/"> 2<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:media="http://search.yahoo.com/mrss/">
3 <channel> 3 <channel>
4 <title>wallabag — {{type}} feed</title> 4 <title>wallabag — {{type}} feed</title>
5 <link>{{ url('unread') }}</link> 5 <link>{{ url(type) }}</link>
6 <link rel="self" href="{{ app.request.uri }}"/>
7 {% if entries.hasPreviousPage -%}
8 <link rel="previous" href="{{ url }}?page={{ entries.previousPage }}"/>
9 {% endif -%}
10 {% if entries.hasNextPage -%}
11 <link rel="next" href="{{ url }}?page={{ entries.nextPage }}"/>
12 {% endif -%}
13 <link rel="last" href="{{ url }}?page={{ entries.nbPages }}"/>
6 <pubDate>{{ "now"|date('D, d M Y H:i:s') }}</pubDate> 14 <pubDate>{{ "now"|date('D, d M Y H:i:s') }}</pubDate>
7 <generator>wallabag</generator> 15 <generator>wallabag</generator>
8 <description>wallabag {{type}} elements</description> 16 <description>wallabag {{type}} elements</description>
diff --git a/tests/Wallabag/CoreBundle/Controller/RssControllerTest.php b/tests/Wallabag/CoreBundle/Controller/RssControllerTest.php
index fb6fe06a..1d6c02b2 100644
--- a/tests/Wallabag/CoreBundle/Controller/RssControllerTest.php
+++ b/tests/Wallabag/CoreBundle/Controller/RssControllerTest.php
@@ -6,7 +6,7 @@ use Tests\Wallabag\CoreBundle\WallabagCoreTestCase;
6 6
7class RssControllerTest extends WallabagCoreTestCase 7class RssControllerTest extends WallabagCoreTestCase
8{ 8{
9 public function validateDom($xml, $nb = null) 9 public function validateDom($xml, $type, $nb = null)
10 { 10 {
11 $doc = new \DOMDocument(); 11 $doc = new \DOMDocument();
12 $doc->loadXML($xml); 12 $doc->loadXML($xml);
@@ -22,6 +22,23 @@ class RssControllerTest extends WallabagCoreTestCase
22 $this->assertEquals(1, $xpath->query('/rss')->length); 22 $this->assertEquals(1, $xpath->query('/rss')->length);
23 $this->assertEquals(1, $xpath->query('/rss/channel')->length); 23 $this->assertEquals(1, $xpath->query('/rss/channel')->length);
24 24
25 $this->assertEquals(1, $xpath->query('/rss/channel/title')->length);
26 $this->assertEquals('wallabag — '.$type.' feed', $xpath->query('/rss/channel/title')->item(0)->nodeValue);
27
28 $this->assertEquals(1, $xpath->query('/rss/channel/pubDate')->length);
29
30 $this->assertEquals(1, $xpath->query('/rss/channel/generator')->length);
31 $this->assertEquals('wallabag', $xpath->query('/rss/channel/generator')->item(0)->nodeValue);
32
33 $this->assertEquals(1, $xpath->query('/rss/channel/description')->length);
34 $this->assertEquals('wallabag '.$type.' elements', $xpath->query('/rss/channel/description')->item(0)->nodeValue);
35
36 $this->assertEquals(1, $xpath->query('/rss/channel/link[@rel="self"]')->length);
37 $this->assertContains($type.'.xml', $xpath->query('/rss/channel/link[@rel="self"]')->item(0)->getAttribute('href'));
38
39 $this->assertEquals(1, $xpath->query('/rss/channel/link[@rel="last"]')->length);
40 $this->assertContains($type.'.xml?page=', $xpath->query('/rss/channel/link[@rel="last"]')->item(0)->getAttribute('href'));
41
25 foreach ($xpath->query('//item') as $item) { 42 foreach ($xpath->query('//item') as $item) {
26 $this->assertEquals(1, $xpath->query('title', $item)->length); 43 $this->assertEquals(1, $xpath->query('title', $item)->length);
27 $this->assertEquals(1, $xpath->query('source', $item)->length); 44 $this->assertEquals(1, $xpath->query('source', $item)->length);
@@ -77,7 +94,7 @@ class RssControllerTest extends WallabagCoreTestCase
77 94
78 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 95 $this->assertEquals(200, $client->getResponse()->getStatusCode());
79 96
80 $this->validateDom($client->getResponse()->getContent(), 2); 97 $this->validateDom($client->getResponse()->getContent(), 'unread', 2);
81 } 98 }
82 99
83 public function testStarred() 100 public function testStarred()
@@ -99,7 +116,7 @@ class RssControllerTest extends WallabagCoreTestCase
99 116
100 $this->assertEquals(200, $client->getResponse()->getStatusCode(), 1); 117 $this->assertEquals(200, $client->getResponse()->getStatusCode(), 1);
101 118
102 $this->validateDom($client->getResponse()->getContent()); 119 $this->validateDom($client->getResponse()->getContent(), 'starred');
103 } 120 }
104 121
105 public function testArchives() 122 public function testArchives()
@@ -121,6 +138,38 @@ class RssControllerTest extends WallabagCoreTestCase
121 138
122 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 139 $this->assertEquals(200, $client->getResponse()->getStatusCode());
123 140
124 $this->validateDom($client->getResponse()->getContent()); 141 $this->validateDom($client->getResponse()->getContent(), 'archive');
142 }
143
144 public function testPagination()
145 {
146 $client = $this->getClient();
147 $em = $client->getContainer()->get('doctrine.orm.entity_manager');
148 $user = $em
149 ->getRepository('WallabagUserBundle:User')
150 ->findOneByUsername('admin');
151
152 $config = $user->getConfig();
153 $config->setRssToken('SUPERTOKEN');
154 $config->setRssLimit(1);
155 $em->persist($config);
156 $em->flush();
157
158 $client = $this->getClient();
159
160 $client->request('GET', '/admin/SUPERTOKEN/archive.xml');
161 $this->assertEquals(200, $client->getResponse()->getStatusCode());
162 $this->validateDom($client->getResponse()->getContent(), 'archive');
163
164 $client->request('GET', '/admin/SUPERTOKEN/archive.xml?page=2');
165 $this->assertEquals(200, $client->getResponse()->getStatusCode());
166 $this->validateDom($client->getResponse()->getContent(), 'archive');
167
168 $client->request('GET', '/admin/SUPERTOKEN/archive.xml?page=3');
169 $this->assertEquals(200, $client->getResponse()->getStatusCode());
170 $this->validateDom($client->getResponse()->getContent(), 'archive');
171
172 $client->request('GET', '/admin/SUPERTOKEN/archive.xml?page=3000');
173 $this->assertEquals(302, $client->getResponse()->getStatusCode());
125 } 174 }
126} 175}