Merge pull request #3207 from wallabag/tag-rss

Add RSS for tags
This commit is contained in:
Jérémy Benoist 2017-06-21 14:51:46 +02:00 committed by GitHub
commit 8c68acff2a
31 changed files with 258 additions and 103 deletions

View file

@ -61,6 +61,7 @@ security:
- { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: /(unread|starred|archive).xml$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: /tags/(.*).xml$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/share, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/settings, roles: ROLE_SUPER_ADMIN }
- { path: ^/annotations, roles: ROLE_USER }

View file

@ -46,7 +46,7 @@ class CleanDuplicatesCommand extends ContainerAwareCommand
return 1;
}
} else {
$users = $this->getDoctrine()->getRepository('WallabagUserBundle:User')->findAll();
$users = $this->getContainer()->get('wallabag_user.user_repository')->findAll();
$output->writeln(sprintf('Cleaning through %d user accounts', count($users)));
@ -66,7 +66,7 @@ class CleanDuplicatesCommand extends ContainerAwareCommand
private function cleanDuplicates(User $user)
{
$em = $this->getContainer()->get('doctrine.orm.entity_manager');
$repo = $this->getDoctrine()->getRepository('WallabagCoreBundle:Entry');
$repo = $this->getContainer()->get('wallabag_core.entry_repository');
$entries = $repo->getAllEntriesIdAndUrl($user->getId());
@ -109,7 +109,7 @@ class CleanDuplicatesCommand extends ContainerAwareCommand
*/
private function getUser($username)
{
return $this->getDoctrine()->getRepository('WallabagUserBundle:User')->findOneByUserName($username);
return $this->getContainer()->get('wallabag_user.user_repository')->findOneByUserName($username);
}
private function getDoctrine()

View file

@ -32,15 +32,14 @@ class ExportCommand extends ContainerAwareCommand
protected function execute(InputInterface $input, OutputInterface $output)
{
try {
$user = $this->getDoctrine()->getRepository('WallabagUserBundle:User')->findOneByUserName($input->getArgument('username'));
$user = $this->getContainer()->get('wallabag_user.user_repository')->findOneByUserName($input->getArgument('username'));
} catch (NoResultException $e) {
$output->writeln(sprintf('<error>User "%s" not found.</error>', $input->getArgument('username')));
return 1;
}
$entries = $this->getDoctrine()
->getRepository('WallabagCoreBundle:Entry')
$entries = $this->getContainer()->get('wallabag_core.entry_repository')
->getBuilderForAllByUser($user->getId())
->getQuery()
->getResult();

View file

@ -67,7 +67,7 @@ class ShowUserCommand extends ContainerAwareCommand
*/
private function getUser($username)
{
return $this->getDoctrine()->getRepository('WallabagUserBundle:User')->findOneByUserName($username);
return $this->getContainer()->get('wallabag_user.user_repository')->findOneByUserName($username);
}
private function getDoctrine()

View file

@ -59,7 +59,7 @@ class TagAllCommand extends ContainerAwareCommand
*/
private function getUser($username)
{
return $this->getDoctrine()->getRepository('WallabagUserBundle:User')->findOneByUserName($username);
return $this->getContainer()->get('wallabag_user.user_repository')->findOneByUserName($username);
}
private function getDoctrine()

View file

@ -152,8 +152,7 @@ class ConfigController extends Controller
],
'twofactor_auth' => $this->getParameter('twofactor_auth'),
'wallabag_url' => $this->getParameter('domain_name'),
'enabled_users' => $this->getDoctrine()
->getRepository('WallabagUserBundle:User')
'enabled_users' => $this->get('wallabag_user.user_repository')
->getSumEnabledUsers(),
]);
}
@ -257,9 +256,7 @@ class ConfigController extends Controller
// manually remove tags to avoid orphan tag
$this->removeAllTagsByUserId($this->getUser()->getId());
$this->getDoctrine()
->getRepository('WallabagCoreBundle:Entry')
->removeAllByUserId($this->getUser()->getId());
$this->get('wallabag_core.entry_repository')->removeAllByUserId($this->getUser()->getId());
break;
case 'archived':
if ($this->get('doctrine')->getConnection()->getDatabasePlatform() instanceof \Doctrine\DBAL\Platforms\SqlitePlatform) {
@ -269,9 +266,7 @@ class ConfigController extends Controller
// manually remove tags to avoid orphan tag
$this->removeTagsForArchivedByUserId($this->getUser()->getId());
$this->getDoctrine()
->getRepository('WallabagCoreBundle:Entry')
->removeArchivedByUserId($this->getUser()->getId());
$this->get('wallabag_core.entry_repository')->removeArchivedByUserId($this->getUser()->getId());
break;
}
@ -295,8 +290,7 @@ class ConfigController extends Controller
return;
}
$this->getDoctrine()
->getRepository('WallabagCoreBundle:Entry')
$this->get('wallabag_core.entry_repository')
->removeTags($userId, $tags);
// cleanup orphan tags
@ -318,7 +312,7 @@ class ConfigController extends Controller
*/
private function removeAllTagsByUserId($userId)
{
$tags = $this->getDoctrine()->getRepository('WallabagCoreBundle:Tag')->findAllTags($userId);
$tags = $this->get('wallabag_core.tag_repository')->findAllTags($userId);
$this->removeAllTagsByStatusAndUserId($tags, $userId);
}
@ -329,7 +323,7 @@ class ConfigController extends Controller
*/
private function removeTagsForArchivedByUserId($userId)
{
$tags = $this->getDoctrine()->getRepository('WallabagCoreBundle:Tag')->findForArchivedArticlesByUser($userId);
$tags = $this->get('wallabag_core.tag_repository')->findForArchivedArticlesByUser($userId);
$this->removeAllTagsByStatusAndUserId($tags, $userId);
}
@ -393,8 +387,7 @@ class ConfigController extends Controller
*/
public function deleteAccountAction(Request $request)
{
$enabledUsers = $this->getDoctrine()
->getRepository('WallabagUserBundle:User')
$enabledUsers = $this->get('wallabag_user.user_repository')
->getSumEnabledUsers();
if ($enabledUsers <= 1) {

View file

@ -7,7 +7,6 @@ use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Wallabag\CoreBundle\Entity\Entry;
use Wallabag\CoreBundle\Entity\Tag;
/**
* The try/catch can be removed once all formats will be implemented.
@ -57,16 +56,17 @@ class ExportController extends Controller
{
$method = ucfirst($category);
$methodBuilder = 'getBuilderFor'.$method.'ByUser';
$repository = $this->get('wallabag_core.entry_repository');
if ($category == 'tag_entries') {
$tag = $this->getDoctrine()->getRepository('WallabagCoreBundle:Tag')->findOneBySlug($request->query->get('tag'));
$tag = $this->get('wallabag_core.tag_repository')->findOneBySlug($request->query->get('tag'));
$entries = $this->getDoctrine()
->getRepository('WallabagCoreBundle:Entry')
->findAllByTagId($this->getUser()->getId(), $tag->getId());
$entries = $repository->findAllByTagId(
$this->getUser()->getId(),
$tag->getId()
);
} else {
$entries = $this->getDoctrine()
->getRepository('WallabagCoreBundle:Entry')
$entries = $repository
->$methodBuilder($this->getUser()->getId())
->getQuery()
->getResult();

View file

@ -3,13 +3,16 @@
namespace Wallabag\CoreBundle\Controller;
use Pagerfanta\Adapter\DoctrineORMAdapter;
use Pagerfanta\Adapter\ArrayAdapter;
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\Component\HttpFoundation\Response;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Wallabag\CoreBundle\Entity\Entry;
use Wallabag\CoreBundle\Entity\Tag;
use Wallabag\UserBundle\Entity\User;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
@ -23,7 +26,7 @@ class RssController extends Controller
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function showUnreadAction(Request $request, User $user)
public function showUnreadRSSAction(Request $request, User $user)
{
return $this->showEntries('unread', $user, $request->query->get('page', 1));
}
@ -31,12 +34,12 @@ class RssController extends Controller
/**
* Shows read entries for current user.
*
* @Route("/{username}/{token}/archive.xml", name="archive_rss")
* @Route("/{username}/{token}/archive.xml", name="archive_rss", defaults={"_format"="xml"})
* @ParamConverter("user", class="WallabagUserBundle:User", converter="username_rsstoken_converter")
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function showArchiveAction(Request $request, User $user)
public function showArchiveRSSAction(Request $request, User $user)
{
return $this->showEntries('archive', $user, $request->query->get('page', 1));
}
@ -44,16 +47,88 @@ class RssController extends Controller
/**
* Shows starred entries for current user.
*
* @Route("/{username}/{token}/starred.xml", name="starred_rss")
* @Route("/{username}/{token}/starred.xml", name="starred_rss", defaults={"_format"="xml"})
* @ParamConverter("user", class="WallabagUserBundle:User", converter="username_rsstoken_converter")
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function showStarredAction(Request $request, User $user)
public function showStarredRSSAction(Request $request, User $user)
{
return $this->showEntries('starred', $user, $request->query->get('page', 1));
}
/**
* Shows all entries for current user.
*
* @Route("/{username}/{token}/all.xml", name="all_rss", defaults={"_format"="xml"})
* @ParamConverter("user", class="WallabagUserBundle:User", converter="username_rsstoken_converter")
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function showAllRSSAction(Request $request, User $user)
{
return $this->showEntries('all', $user, $request->query->get('page', 1));
}
/**
* Shows entries associated to a tag for current user.
*
* @Route("/{username}/{token}/tags/{slug}.xml", name="tag_rss", defaults={"_format"="xml"})
* @ParamConverter("user", class="WallabagUserBundle:User", converter="username_rsstoken_converter")
* @ParamConverter("tag", options={"mapping": {"slug": "slug"}})
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function showTagsAction(Request $request, User $user, Tag $tag)
{
$page = $request->query->get('page', 1);
$url = $this->generateUrl(
'tag_rss',
[
'username' => $user->getUsername(),
'token' => $user->getConfig()->getRssToken(),
'slug' => $tag->getSlug(),
],
UrlGeneratorInterface::ABSOLUTE_URL
);
$entriesByTag = $this->get('wallabag_core.entry_repository')->findAllByTagId(
$user->getId(),
$tag->getId()
);
$pagerAdapter = new ArrayAdapter($entriesByTag);
$entries = $this->get('wallabag_core.helper.prepare_pager_for_entries')->prepare(
$pagerAdapter,
$user
);
if (null === $entries) {
throw $this->createNotFoundException('No entries found?');
}
try {
$entries->setCurrentPage($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',
[
'url_html' => $this->generateUrl('tag_entries', ['slug' => $tag->getSlug()], UrlGeneratorInterface::ABSOLUTE_URL),
'type' => 'tag ('.$tag->getLabel().')',
'url' => $url,
'entries' => $entries,
],
new Response('', 200, ['Content-Type' => 'application/rss+xml'])
);
}
/**
* Global method to retrieve entries depending on the given type
* It returns the response to be send.
@ -66,7 +141,7 @@ class RssController extends Controller
*/
private function showEntries($type, User $user, $page = 1)
{
$repository = $this->getDoctrine()->getRepository('WallabagCoreBundle:Entry');
$repository = $this->get('wallabag_core.entry_repository');
switch ($type) {
case 'starred':
@ -81,6 +156,10 @@ class RssController extends Controller
$qb = $repository->getBuilderForUnreadByUser($user->getId());
break;
case 'all':
$qb = $repository->getBuilderForAllByUser($user->getId());
break;
default:
throw new \InvalidArgumentException(sprintf('Type "%s" is not implemented.', $type));
}
@ -108,10 +187,15 @@ class RssController extends Controller
}
}
return $this->render('@WallabagCore/themes/common/Entry/entries.xml.twig', [
'type' => $type,
'url' => $url,
'entries' => $entries,
]);
return $this->render(
'@WallabagCore/themes/common/Entry/entries.xml.twig',
[
'url_html' => $this->generateUrl($type, [], UrlGeneratorInterface::ABSOLUTE_URL),
'type' => $type,
'url' => $url,
'entries' => $entries,
],
new Response('', 200, ['Content-Type' => 'application/rss+xml'])
);
}
}

View file

@ -84,16 +84,17 @@ class TagController extends Controller
*/
public function showTagAction()
{
$tags = $this->getDoctrine()
->getRepository('WallabagCoreBundle:Tag')
$repository = $this->get('wallabag_core.entry_repository');
$tags = $this->get('wallabag_core.tag_repository')
->findAllTags($this->getUser()->getId());
$flatTags = [];
foreach ($tags as $tag) {
$nbEntries = $this->getDoctrine()
->getRepository('WallabagCoreBundle:Entry')
->countAllEntriesByUserIdAndTagId($this->getUser()->getId(), $tag->getId());
$nbEntries = $repository->countAllEntriesByUserIdAndTagId(
$this->getUser()->getId(),
$tag->getId()
);
$flatTags[] = [
'id' => $tag->getId(),
@ -119,9 +120,10 @@ class TagController extends Controller
*/
public function showEntriesForTagAction(Tag $tag, $page, Request $request)
{
$entriesByTag = $this->getDoctrine()
->getRepository('WallabagCoreBundle:Entry')
->findAllByTagId($this->getUser()->getId(), $tag->getId());
$entriesByTag = $this->get('wallabag_core.entry_repository')->findAllByTagId(
$this->getUser()->getId(),
$tag->getId()
);
$pagerAdapter = new ArrayAdapter($entriesByTag);
@ -142,7 +144,7 @@ class TagController extends Controller
'form' => null,
'entries' => $entries,
'currentPage' => $page,
'tag' => $tag->getSlug(),
'tag' => $tag,
]);
}
}

View file

@ -4,6 +4,7 @@ namespace Wallabag\CoreBundle\Helper;
use Pagerfanta\Adapter\AdapterInterface;
use Pagerfanta\Pagerfanta;
use Wallabag\UserBundle\Entity\User;
use Symfony\Component\Routing\Router;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
@ -20,12 +21,15 @@ class PreparePagerForEntries
/**
* @param AdapterInterface $adapter
* @param User $user If user isn't logged in, we can force it (like for rss)
*
* @return null|Pagerfanta
*/
public function prepare(AdapterInterface $adapter)
public function prepare(AdapterInterface $adapter, User $user = null)
{
$user = $this->tokenStorage->getToken() ? $this->tokenStorage->getToken()->getUser() : null;
if (null === $user) {
$user = $this->tokenStorage->getToken() ? $this->tokenStorage->getToken()->getUser() : null;
}
if (null === $user || !is_object($user)) {
return;

View file

@ -90,9 +90,10 @@ config:
token_reset: 'Nulstil token'
rss_links: 'RSS-Links'
rss_link:
unread: 'ulæst'
starred: 'favoritter'
archive: 'arkiv'
unread: 'Ulæst'
starred: 'Favoritter'
archive: 'Arkiv'
# all: 'All'
# rss_limit: 'Number of items in the feed'
form_user:
# two_factor_description: "Enabling two factor authentication means you'll receive an email with a code on every new untrusted connexion"

View file

@ -93,6 +93,7 @@ config:
unread: 'Ungelesene'
starred: 'Favoriten'
archive: 'Archivierte'
# all: 'All'
rss_limit: 'Anzahl der Einträge pro Feed'
form_user:
two_factor_description: "Wenn du die Zwei-Faktor-Authentifizierung aktivierst, erhältst du eine E-Mail mit einem Code bei jeder nicht vertrauenswürdigen Verbindung"

View file

@ -90,9 +90,10 @@ config:
token_reset: 'Regenerate your token'
rss_links: 'RSS links'
rss_link:
unread: 'unread'
starred: 'starred'
archive: 'archived'
unread: 'Unread'
starred: 'Starred'
archive: 'Archived'
all: 'All'
rss_limit: 'Number of items in the feed'
form_user:
two_factor_description: "Enabling two factor authentication means you'll receive an email with a code on every new untrusted connection."

View file

@ -93,6 +93,7 @@ config:
unread: 'sin leer'
starred: 'favoritos'
archive: 'archivados'
# all: 'All'
rss_limit: 'Límite de artículos en feed RSS'
form_user:
two_factor_description: "Con la autenticación en dos pasos recibirá código por e-mail en cada nueva conexión que no sea de confianza."

View file

@ -93,6 +93,7 @@ config:
unread: 'خوانده‌نشده'
starred: 'برگزیده'
archive: 'بایگانی'
# all: 'All'
rss_limit: 'محدودیت آر-اس-اس'
form_user:
two_factor_description: "با فعال‌کردن تأیید ۲مرحله‌ای هر بار که اتصال تأییدنشده‌ای برقرار شد، به شما یک کد از راه ایمیل فرستاده می‌شود"

View file

@ -88,11 +88,12 @@ config:
no_token: "Aucun jeton généré"
token_create: "Créez votre jeton"
token_reset: "Réinitialisez votre jeton"
rss_links: "Adresse de vos flux RSS"
rss_links: "Adresses de vos flux RSS"
rss_link:
unread: "non lus"
starred: "favoris"
archive: "lus"
unread: "Non lus"
starred: "Favoris"
archive: "Lus"
all: "Tous"
rss_limit: "Nombre darticles dans le flux"
form_user:
two_factor_description: "Activer lauthentification double-facteur veut dire que vous allez recevoir un code par courriel à chaque nouvelle connexion non approuvée."

View file

@ -90,9 +90,10 @@ config:
token_reset: 'Rigenera il tuo token'
rss_links: 'Collegamenti RSS'
rss_link:
unread: 'non letti'
starred: 'preferiti'
archive: 'archiviati'
unread: 'Non letti'
starred: 'Preferiti'
archive: 'Archiviati'
# all: 'All'
rss_limit: 'Numero di elementi nel feed'
form_user:
two_factor_description: "Abilitando l'\autenticazione a due fattori riceverai una e-mail con un codice per ogni nuova connesione non verificata"

View file

@ -88,11 +88,12 @@ config:
no_token: 'Pas cap de geton generat'
token_create: 'Creatz vòstre geton'
token_reset: 'Reïnicializatz vòstre geton'
rss_links: 'URL de vòstres fluxes RSS'
rss_links: 'URLs de vòstres fluxes RSS'
rss_link:
unread: 'pas legits'
starred: 'favorits'
archive: 'legits'
unread: 'Pas legits'
starred: 'Favorits'
archive: 'Legits'
# all: 'All'
rss_limit: "Nombre d'articles dins un flux RSS"
form_user:
two_factor_description: "Activar l'autentificacion doble-factor vòl dire que recebretz un còdi per corrièl per cada novèla connexion pas aprovada."

View file

@ -90,9 +90,10 @@ config:
token_reset: 'Zresetuj swojego tokena'
rss_links: 'RSS links'
rss_link:
unread: 'nieprzeczytane'
starred: 'oznaczone gwiazdką'
archive: 'archiwum'
unread: 'Nieprzeczytane'
starred: 'Oznaczone gwiazdką'
archive: 'Archiwum'
# all: 'All'
rss_limit: 'Link do RSS'
form_user:
two_factor_description: "Włączenie autoryzacji dwuetapowej oznacza, że będziesz otrzymywał maile z kodem przy każdym nowym, niezaufanym połączeniu"

View file

@ -90,9 +90,10 @@ config:
token_reset: 'Gerar novamente seu token'
rss_links: 'Links RSS'
rss_link:
unread: 'não lido'
starred: 'destacado'
archive: 'arquivado'
unread: 'Não lido'
starred: 'Destacado'
archive: 'Arquivado'
# all: 'All'
rss_limit: 'Número de itens no feed'
form_user:
two_factor_description: 'Habilitar autenticação de dois passos significa que você receberá um e-mail com um código a cada nova conexão desconhecida.'

View file

@ -90,9 +90,10 @@ config:
token_reset: 'Resetează-ți token-ul'
rss_links: 'Link-uri RSS'
rss_link:
unread: 'unread'
starred: 'starred'
archive: 'archived'
unread: 'Unread'
starred: 'Starred'
archive: 'Archived'
# all: 'All'
rss_limit: 'Limită RSS'
form_user:
# two_factor_description: "Enabling two factor authentication means you'll receive an email with a code on every new untrusted connexion"

View file

@ -90,9 +90,10 @@ config:
token_reset: 'Belirteci (token) sıfırla'
rss_links: 'RSS akış bağlantıları'
rss_link:
unread: 'okunmayan'
starred: 'favoriler'
archive: 'arşiv'
unread: 'Okunmayan'
starred: 'Favoriler'
archive: 'Arşiv'
# all: 'All'
rss_limit: 'RSS içeriğinden talep edilecek makale limiti'
form_user:
two_factor_description: "İki adımlı doğrulamayı aktifleştirdiğinizde, her yeni güvenilmeyen bağlantılarda size e-posta ile bir kod alacaksınız."

View file

@ -82,7 +82,7 @@
<fieldset class="w500p inline">
<div class="row">
<h3>{{ 'config.form_settings.android_configuration'|trans }}</h3>
<a href="wallabag://{{ app.user.username }}@{{ wallabag_url }}" >Touch here to prefill your Android application</a>
<a href="wallabag://{{ app.user.username }}@{{ wallabag_url }}">Touch here to prefill your Android application</a>
<br/>
<img id="androidQrcode" />
<script>
@ -106,7 +106,7 @@
<fieldset class="w500p inline">
<div class="row">
<label>Rss token</label>
<label>{{ 'config.form_rss.token_label'|trans }}</label>
{% if rss.token %}
{{ rss.token }}
{% else %}
@ -128,9 +128,10 @@
<div class="row">
<label>{{ 'config.form_rss.rss_links'|trans }}</label>
<ul>
<li><a href="{{ path('unread_rss', {'username': rss.username, 'token': rss.token}) }}">unread</a></li>
<li><a href="{{ path('starred_rss', {'username': rss.username, 'token': rss.token}) }}">fav</a></li>
<li><a href="{{ path('archive_rss', {'username': rss.username, 'token': rss.token}) }}">archives</a></li>
<li><a href="{{ path('unread_rss', {'username': rss.username, 'token': rss.token}) }}">{{ 'config.form_rss.rss_link.unread'|trans }}</a></li>
<li><a href="{{ path('starred_rss', {'username': rss.username, 'token': rss.token}) }}">{{ 'config.form_rss.rss_link.starred'|trans }}</a></li>
<li><a href="{{ path('archive_rss', {'username': rss.username, 'token': rss.token}) }}">{{ 'config.form_rss.rss_link.archive'|trans }}</a></li>
<li><a href="{{ path('all_rss', {'username': rss.username, 'token': rss.token}) }}">{{ 'config.form_rss.rss_link.all'|trans }}</a></li>
</ul>
</div>
</fieldset>

View file

@ -1,5 +1,12 @@
{% extends "WallabagCoreBundle::layout.html.twig" %}
{% block head %}
{{ parent() }}
{% if tag is defined and app.user.config.rssToken %}
<link rel="alternate" type="application/rss+xml" href="{{ path('tag_rss', {'username': app.user.username, 'token': app.user.config.rssToken, 'slug': tag.slug}) }}" />
{% endif %}
{% endblock %}
{% block title %}
{% set filter = '' %}
{% if tag is defined %}
@ -12,12 +19,15 @@
{% endblock %}
{% block content %}
{% set currentRoute = app.request.attributes.get('_route') %}
{% set listMode = app.user.config.listMode %}
<div class="results">
<div class="nb-results">{{ 'entry.list.number_on_the_page'|transchoice(entries.count) }}</div>
<div class="pagination">
<a href="{{ path('switch_view_mode') }}"><i class="listMode-btn material-icons md-24">{% if listMode == 0 %}list{% else %}view_module{% endif %}</i></a>
{% if app.user.config.rssToken %}
{% include "@WallabagCore/themes/common/Entry/_rss_link.html.twig" %}
{% endif %}
<i class="btn-clickable download-btn material-icons md-24 js-export-action">file_download</i>
<i class="btn-clickable filter-btn material-icons md-24 js-filters-action">filter_list</i>
{% if entries.getNbPages > 1 %}
@ -76,7 +86,6 @@
<!-- Export -->
<aside id="download-form">
{% set currentRoute = app.request.attributes.get('_route') %}
{% set currentTag = '' %}
{% if tag is defined %}
{% set currentTag = tag %}

View file

@ -9,7 +9,12 @@
<ul>
{% for tag in tags %}
<li id="tag-{{ tag.id|e }}"><a href="{{ path('tag_entries', {'slug': tag.slug}) }}">{{tag.label}} ({{ tag.nbEntries }})</a></li>
<li id="tag-{{ tag.id|e }}">
<a href="{{ path('tag_entries', {'slug': tag.slug}) }}">{{tag.label}} ({{ tag.nbEntries }})</a>
<a rel="alternate" type="application/rss+xml" href="{{ path('tag_rss', {'username': app.user.username, 'token': app.user.config.rssToken, 'slug': tag.slug}) }}" class="right">
<i class="material-icons md-24">rss_feed</i>
</a>
</li>
{% endfor %}
</ul>

View file

@ -0,0 +1,6 @@
{% if tag is defined %}
<a rel="alternate" type="application/rss+xml" href="{{ path('tag_rss', {'username': app.user.username, 'token': app.user.config.rssToken, 'slug': tag.slug}) }}" class="right"><i class="material-icons md-24">rss_feed</i></a>
{% elseif currentRoute in ['unread', 'starred', 'archive', 'all'] %}
<a rel="alternate" type="application/rss+xml" href="{{ path(currentRoute ~ '_rss', {'username': app.user.username, 'token': app.user.config.rssToken}) }}" class="right"><i class="material-icons">rss_feed</i></a>
{% endif %}

View file

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<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(type) }}</link>
<title>wallabag - {{ type }} feed</title>
<link>{{ url_html }}</link>
<link rel="self" href="{{ app.request.uri }}"/>
{% if entries.hasPreviousPage -%}
<link rel="previous" href="{{ url }}?page={{ entries.previousPage }}"/>
@ -13,7 +13,7 @@
<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>
<description>wallabag {{ type }} elements</description>
{% for entry in entries %}

View file

@ -157,6 +157,7 @@
<li><a href="{{ path('unread_rss', {'username': rss.username, 'token': rss.token}) }}">{{ 'config.form_rss.rss_link.unread'|trans }}</a></li>
<li><a href="{{ path('starred_rss', {'username': rss.username, 'token': rss.token}) }}">{{ 'config.form_rss.rss_link.starred'|trans }}</a></li>
<li><a href="{{ path('archive_rss', {'username': rss.username, 'token': rss.token}) }}">{{ 'config.form_rss.rss_link.archive'|trans }}</a></li>
<li><a href="{{ path('all_rss', {'username': rss.username, 'token': rss.token}) }}">{{ 'config.form_rss.rss_link.all'|trans }}</a></li>
</ul>
</div>
</div>

View file

@ -1,9 +1,16 @@
{% extends "WallabagCoreBundle::layout.html.twig" %}
{% block head %}
{{ parent() }}
{% if tag is defined and app.user.config.rssToken %}
<link rel="alternate" type="application/rss+xml" href="{{ path('tag_rss', {'username': app.user.username, 'token': app.user.config.rssToken, 'slug': tag.slug}) }}" />
{% endif %}
{% endblock %}
{% block title %}
{% set filter = '' %}
{% if tag is defined %}
{% set filter = tag %}
{% set filter = tag.slug %}
{% endif %}
{% if searchTerm is defined and searchTerm is not empty %}
{% set filter = searchTerm %}
@ -13,10 +20,14 @@
{% block content %}
{% set listMode = app.user.config.listMode %}
{% set currentRoute = app.request.attributes.get('_route') %}
<div class="results clearfix">
<div class="nb-results left">
{{ 'entry.list.number_on_the_page'|transchoice(entries.count) }}
<a href="{{ path('switch_view_mode') }}"><i class="material-icons">{% if listMode == 0 %}view_list{% else %}view_module{% endif %}</i></a>
{% if app.user.config.rssToken %}
{% include "@WallabagCore/themes/common/Entry/_rss_link.html.twig" %}
{% endif %}
</div>
{% if entries.getNbPages > 1 %}
{{ pagerfanta(entries, 'twitter_bootstrap_translated', {'proximity': 1}) }}
@ -46,10 +57,9 @@
<!-- Export -->
<div id="export" class="side-nav right-aligned">
{% set currentRoute = app.request.attributes.get('_route') %}
{% set currentTag = '' %}
{% if tag is defined %}
{% set currentTag = tag %}
{% set currentTag = tag.slug %}
{% endif %}
{% if currentRoute == 'homepage' %}
{% set currentRoute = 'unread' %}

View file

@ -14,6 +14,9 @@
{% for tag in tags %}
<li title="{{tag.label}} ({{ tag.nbEntries }})" id="tag-{{ tag.id }}" class="col l2 m2 s5">
<a href="{{ path('tag_entries', {'slug': tag.slug}) }}">{{tag.label}} ({{ tag.nbEntries }})</a>
{% if app.user.config.rssToken %}
<a rel="alternate" type="application/rss+xml" href="{{ path('tag_rss', {'username': app.user.username, 'token': app.user.config.rssToken, 'slug': tag.slug}) }}" class="right"><i class="material-icons">rss_feed</i></a>
{% endif %}
</li>
{% endfor %}
</ul>

View file

@ -6,7 +6,7 @@ use Tests\Wallabag\CoreBundle\WallabagCoreTestCase;
class RssControllerTest extends WallabagCoreTestCase
{
public function validateDom($xml, $type, $nb = null)
public function validateDom($xml, $type, $urlPagination, $nb = null)
{
$doc = new \DOMDocument();
$doc->loadXML($xml);
@ -23,7 +23,7 @@ class RssControllerTest extends WallabagCoreTestCase
$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('wallabag - '.$type.' feed', $xpath->query('/rss/channel/title')->item(0)->nodeValue);
$this->assertEquals(1, $xpath->query('/rss/channel/pubDate')->length);
@ -34,10 +34,10 @@ class RssControllerTest extends WallabagCoreTestCase
$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->assertContains($urlPagination.'.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'));
$this->assertContains($urlPagination.'.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);
@ -94,7 +94,7 @@ class RssControllerTest extends WallabagCoreTestCase
$this->assertEquals(200, $client->getResponse()->getStatusCode());
$this->validateDom($client->getResponse()->getContent(), 'unread', 2);
$this->validateDom($client->getResponse()->getContent(), 'unread', 'unread', 2);
}
public function testStarred()
@ -116,7 +116,7 @@ class RssControllerTest extends WallabagCoreTestCase
$this->assertEquals(200, $client->getResponse()->getStatusCode(), 1);
$this->validateDom($client->getResponse()->getContent(), 'starred');
$this->validateDom($client->getResponse()->getContent(), 'starred', 'starred');
}
public function testArchives()
@ -138,7 +138,7 @@ class RssControllerTest extends WallabagCoreTestCase
$this->assertEquals(200, $client->getResponse()->getStatusCode());
$this->validateDom($client->getResponse()->getContent(), 'archive');
$this->validateDom($client->getResponse()->getContent(), 'archive', 'archive');
}
public function testPagination()
@ -159,13 +159,38 @@ class RssControllerTest extends WallabagCoreTestCase
$client->request('GET', '/admin/SUPERTOKEN/unread.xml');
$this->assertEquals(200, $client->getResponse()->getStatusCode());
$this->validateDom($client->getResponse()->getContent(), 'unread');
$this->validateDom($client->getResponse()->getContent(), 'unread', 'unread');
$client->request('GET', '/admin/SUPERTOKEN/unread.xml?page=2');
$this->assertEquals(200, $client->getResponse()->getStatusCode());
$this->validateDom($client->getResponse()->getContent(), 'unread');
$this->validateDom($client->getResponse()->getContent(), 'unread', 'unread');
$client->request('GET', '/admin/SUPERTOKEN/unread.xml?page=3000');
$this->assertEquals(302, $client->getResponse()->getStatusCode());
}
public function testTags()
{
$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(null);
$em->persist($config);
$em->flush();
$client = $this->getClient();
$client->request('GET', '/admin/SUPERTOKEN/tags/foo-bar.xml');
$this->assertEquals(200, $client->getResponse()->getStatusCode());
$this->validateDom($client->getResponse()->getContent(), 'tag (foo bar)', 'tags/foo-bar');
$client->request('GET', '/admin/SUPERTOKEN/tags/foo-bar.xml?page=3000');
$this->assertEquals(302, $client->getResponse()->getStatusCode());
}
}