+# settings_changed: Configuration updated
download_pictures: Download billeder på din server
carrot: Aktiver deling til Carrot
diaspora_url: Diaspora URL, hvis tjenesten er aktiv
+# settings_changed: Configuration updated
download_pictures: Bilder auf den Server herunterladen
carrot: Teilen zu Carrot aktivieren
diaspora_url: Diaspora-URL, sofern der Service aktiviert ist
+settings_changed: Configuration updated
download_pictures: Download pictures on your server
carrot: Enable share to Carrot
diaspora_url: Diaspora URL, if the service is enabled
+# settings_changed: Configuration updated
download_pictures: Descargar imágenes
carrot: Activar compartir con Carrot
diaspora_url: Diaspora URL, si el servicio está activado
+# settings_changed: Configuration updated
download_pictures: تصاویر را در کارگزار خودتان باربگیرید
carrot: فعالسازی همرسانی به Carrot
diaspora_url: نشانی Diaspora، اگر فعال بود
+settings_changed: Configuration mise à jour
download_pictures: Télécharger les images sur le serveur
carrot: Activer le partage vers Carrot
diaspora_url: URL de Diaspora, si le service Diaspora est activé
+# settings_changed: Configuration updated
download_pictures: Scarica le immagini sul tuo server
carrot: Abilita la condivisione con Carrot
diaspora_url: Diaspora URL, se il servizio è abilitato
+# settings_changed: Configuration updated
download_pictures: Telecargar los imatges sul servidor
carrot: Activar lo partatge cap a Carrot
diaspora_url: URL de Diaspora, se lo servici Diaspora es activat
+# settings_changed: Configuration updated
download_pictures: Pobierz obrazy na swój serwer
carrot: Włącz udostępnianie dla Carrot
diaspora_url: Adres URL Diaspora, jeżeli usługa jest włączona
+# settings_changed: Configuration updated
download_pictures: Download imagens no seu servidor
carrot: Habilitar compartilhamento para o Carrot
diaspora_url: URL Diaspora, se o serviço está habilitado
export_json: Habilita exportação para JSON
export_txt: Habilita exportação para TXT
export_xml: Habilita exportação para XML
-pocket_consumer_key: Chave de consumidor do Pocket para importar conteúdo (https://getpocket.com/developer/docs/authentication)
+# import_with_rabbitmq: Enable RabbitMQ to import data asynchronously
+# import_with_redis: Enable Redis to import data asynchronously
shaarli_url: URL Shaarli, se o serviço está habilitado
share_diaspora: Habilitar compartilhamento para o Diaspora
share_mail: Habilitar compartilhamento por e-mail
piwik_enabled: Habilitar Piwik
demo_mode_enabled: "Habilitar modo demo? (somente usado para o demo público do wallabag)"
demo_mode_username: "Usuário demo"
+# share_public: Allow public url for entries
+# download_images_enabled: Download images locally
+# settings_changed: Configuration updated
download_pictures: Descarcă poze pe server
carrot: Permite share către Carrot
diaspora_url: Diaspora URL, dacă serviciul este permis
+# settings_changed: Configuration updated
# download_pictures: Download pictures on your server
# carrot: Enable share to Carrot
# diaspora_url: Diaspora URL, if the service is enabled
Du kannst auch definieren wie viele Artikel du in deinem RSS Feed (Standardwert: 50) haben willst.
+There is also a pagination available for these feeds. You can add ``?page=2`` to jump to the second page.
+The pagination follow `the RFC <https://tools.ietf.org/html/rfc5005#page-4>`_ about that, which means you'll find the ``next``, ``previous`` & ``last`` page link inside the `<channel>` tag of each RSS feed.
+
Benutzer-Informationen
----------------------
You can also define how many articles you want in each RSS feed (default value: 50).
+There is also a pagination available for these feeds. You can add ``?page=2`` to jump to the second page.
+The pagination follow `the RFC <https://tools.ietf.org/html/rfc5005#page-4>`_ about that, which means you'll find the ``next``, ``previous`` & ``last`` page link inside the `<channel>` tag of each RSS feed.
+
User information
----------------
Vous pouvez aussi définir combien d'articles vous souhaitez dans vos flux RSS
(50 est la valeur par défaut).
+Une pagination est aussi disponible pour ces flux. Il suffit de rajouter ``?page=2`` pour aller à la seconde page, par exemple.
+Cette pagination suit `la RFC <https://tools.ietf.org/html/rfc5005#page-4>`_, ce qui signifie que vous trouverez la page suivante (``next``), précédente (``previous``) et la dernière (``last``) dans la balise `<channel>` de chaque flux RSS.
+
Mon compte
----------
namespace Wallabag\CoreBundle\Controller;
use Pagerfanta\Adapter\DoctrineORMAdapter;
+use Pagerfanta\Exception\OutOfRangeCurrentPageException;
use Pagerfanta\Pagerfanta;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
+use Symfony\Component\HttpFoundation\Request;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Wallabag\CoreBundle\Entity\Entry;
use Wallabag\UserBundle\Entity\User;
+use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
class RssController extends Controller
{
*
* @return \Symfony\Component\HttpFoundation\Response
*/
- public function showUnreadAction(User $user)
+ public function showUnreadAction(Request $request, User $user)
{
- return $this->showEntries('unread', $user);
+ return $this->showEntries('unread', $user, $request->query->get('page', 1));
}
/**
*
* @return \Symfony\Component\HttpFoundation\Response
*/
- public function showArchiveAction(User $user)
+ public function showArchiveAction(Request $request, User $user)
{
- return $this->showEntries('archive', $user);
+ return $this->showEntries('archive', $user, $request->query->get('page', 1));
}
/**
*
* @return \Symfony\Component\HttpFoundation\Response
*/
- public function showStarredAction(User $user)
+ public function showStarredAction(Request $request, User $user)
{
- return $this->showEntries('starred', $user);
+ return $this->showEntries('starred', $user, $request->query->get('page', 1));
}
/**
*
* @param string $type Entries type: unread, starred or archive
* @param User $user
+ * @param int $page
*
* @return \Symfony\Component\HttpFoundation\Response
*/
- private function showEntries($type, User $user)
+ private function showEntries($type, User $user, $page = 1)
{
$repository = $this->getDoctrine()->getRepository('WallabagCoreBundle:Entry');
$perPage = $user->getConfig()->getRssLimit() ?: $this->getParameter('wallabag_core.rss_limit');
$entries->setMaxPerPage($perPage);
+ $url = $this->generateUrl(
+ $type.'_rss',
+ [
+ 'username' => $user->getUsername(),
+ 'token' => $user->getConfig()->getRssToken(),
+ ],
+ UrlGeneratorInterface::ABSOLUTE_URL
+ );
+
+ try {
+ $entries->setCurrentPage((int) $page);
+ } catch (OutOfRangeCurrentPageException $e) {
+ if ($page > 1) {
+ return $this->redirect($url.'?page='.$entries->getNbPages(), 302);
+ }
+ }
+
return $this->render('@WallabagCore/themes/common/Entry/entries.xml.twig', [
'type' => $type,
+ 'url' => $url,
'entries' => $entries,
]);
}
<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/">
<channel>
<title>wallabag — {{type}} feed</title>
- <link>{{ url('unread') }}</link>
+ <link>{{ url(type) }}</link>
+ <link rel="self" href="{{ app.request.uri }}"/>
+ {% if entries.hasPreviousPage -%}
+ <link rel="previous" href="{{ url }}?page={{ entries.previousPage }}"/>
+ {% endif -%}
+ {% if entries.hasNextPage -%}
+ <link rel="next" href="{{ url }}?page={{ entries.nextPage }}"/>
+ {% endif -%}
+ <link rel="last" href="{{ url }}?page={{ entries.nbPages }}"/>
<pubDate>{{ "now"|date('D, d M Y H:i:s') }}</pubDate>
<generator>wallabag</generator>
<description>wallabag {{type}} elements</description>
class RssControllerTest extends WallabagCoreTestCase
{
- public function validateDom($xml, $nb = null)
+ public function validateDom($xml, $type, $nb = null)
{
$doc = new \DOMDocument();
$doc->loadXML($xml);
$this->assertEquals(1, $xpath->query('/rss')->length);
$this->assertEquals(1, $xpath->query('/rss/channel')->length);
+ $this->assertEquals(1, $xpath->query('/rss/channel/title')->length);
+ $this->assertEquals('wallabag — '.$type.' feed', $xpath->query('/rss/channel/title')->item(0)->nodeValue);
+
+ $this->assertEquals(1, $xpath->query('/rss/channel/pubDate')->length);
+
+ $this->assertEquals(1, $xpath->query('/rss/channel/generator')->length);
+ $this->assertEquals('wallabag', $xpath->query('/rss/channel/generator')->item(0)->nodeValue);
+
+ $this->assertEquals(1, $xpath->query('/rss/channel/description')->length);
+ $this->assertEquals('wallabag '.$type.' elements', $xpath->query('/rss/channel/description')->item(0)->nodeValue);
+
+ $this->assertEquals(1, $xpath->query('/rss/channel/link[@rel="self"]')->length);
+ $this->assertContains($type.'.xml', $xpath->query('/rss/channel/link[@rel="self"]')->item(0)->getAttribute('href'));
+
+ $this->assertEquals(1, $xpath->query('/rss/channel/link[@rel="last"]')->length);
+ $this->assertContains($type.'.xml?page=', $xpath->query('/rss/channel/link[@rel="last"]')->item(0)->getAttribute('href'));
+
foreach ($xpath->query('//item') as $item) {
$this->assertEquals(1, $xpath->query('title', $item)->length);
$this->assertEquals(1, $xpath->query('source', $item)->length);
$this->assertEquals(200, $client->getResponse()->getStatusCode());
- $this->validateDom($client->getResponse()->getContent(), 2);
+ $this->validateDom($client->getResponse()->getContent(), 'unread', 2);
}
public function testStarred()
$this->assertEquals(200, $client->getResponse()->getStatusCode(), 1);
- $this->validateDom($client->getResponse()->getContent());
+ $this->validateDom($client->getResponse()->getContent(), 'starred');
}
public function testArchives()
$this->assertEquals(200, $client->getResponse()->getStatusCode());
- $this->validateDom($client->getResponse()->getContent());
+ $this->validateDom($client->getResponse()->getContent(), 'archive');
+ }
+
+ public function testPagination()
+ {
+ $client = $this->getClient();
+ $em = $client->getContainer()->get('doctrine.orm.entity_manager');
+ $user = $em
+ ->getRepository('WallabagUserBundle:User')
+ ->findOneByUsername('admin');
+
+ $config = $user->getConfig();
+ $config->setRssToken('SUPERTOKEN');
+ $config->setRssLimit(1);
+ $em->persist($config);
+ $em->flush();
+
+ $client = $this->getClient();
+
+ $client->request('GET', '/admin/SUPERTOKEN/unread.xml');
+ $this->assertEquals(200, $client->getResponse()->getStatusCode());
+ $this->validateDom($client->getResponse()->getContent(), 'unread');
+
+ $client->request('GET', '/admin/SUPERTOKEN/unread.xml?page=2');
+ $this->assertEquals(200, $client->getResponse()->getStatusCode());
+ $this->validateDom($client->getResponse()->getContent(), 'unread');
+
+ $client->request('GET', '/admin/SUPERTOKEN/unread.xml?page=3000');
+ $this->assertEquals(302, $client->getResponse()->getStatusCode());
}
}