aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJeremy <jeremy.benoist@gmail.com>2015-03-28 14:27:45 +0100
committerJeremy <jeremy.benoist@gmail.com>2015-03-31 22:47:43 +0200
commit0c83fd5994861efa728097dd151c994796c39ae1 (patch)
tree925520c0bb62d2b9ba7270020fc2ebcebb520f8c
parentf98a2a0fc3ae8a5955bb811f083c3d2535f96791 (diff)
downloadwallabag-0c83fd5994861efa728097dd151c994796c39ae1.tar.gz
wallabag-0c83fd5994861efa728097dd151c994796c39ae1.tar.zst
wallabag-0c83fd5994861efa728097dd151c994796c39ae1.zip
Add rss for entries
will fix #1000
-rw-r--r--app/config/parameters.yml.dist1
-rw-r--r--src/Wallabag/CoreBundle/Command/InstallCommand.php1
-rw-r--r--src/Wallabag/CoreBundle/Controller/ConfigController.php58
-rw-r--r--src/Wallabag/CoreBundle/Controller/RssController.php84
-rw-r--r--src/Wallabag/CoreBundle/Entity/Config.php74
-rw-r--r--src/Wallabag/CoreBundle/Entity/User.php2
-rw-r--r--src/Wallabag/CoreBundle/Form/Type/RssType.php29
-rw-r--r--src/Wallabag/CoreBundle/ParamConverter/UsernameRssTokenConverter.php92
-rw-r--r--src/Wallabag/CoreBundle/Repository/UserRepository.php26
-rw-r--r--src/Wallabag/CoreBundle/Resources/config/services.yml7
-rw-r--r--src/Wallabag/CoreBundle/Resources/views/Config/index.html.twig136
-rw-r--r--src/Wallabag/CoreBundle/Resources/views/Entry/entries.xml.twig34
-rw-r--r--src/Wallabag/CoreBundle/Tools/Utils.php27
13 files changed, 510 insertions, 61 deletions
diff --git a/app/config/parameters.yml.dist b/app/config/parameters.yml.dist
index 8f967011..73318013 100644
--- a/app/config/parameters.yml.dist
+++ b/app/config/parameters.yml.dist
@@ -42,3 +42,4 @@ parameters:
42 theme: baggy 42 theme: baggy
43 language: en_US 43 language: en_US
44 from_email: no-reply@wallabag.org 44 from_email: no-reply@wallabag.org
45 rss_limit: 50
diff --git a/src/Wallabag/CoreBundle/Command/InstallCommand.php b/src/Wallabag/CoreBundle/Command/InstallCommand.php
index ac7583ea..bba2607d 100644
--- a/src/Wallabag/CoreBundle/Command/InstallCommand.php
+++ b/src/Wallabag/CoreBundle/Command/InstallCommand.php
@@ -198,6 +198,7 @@ class InstallCommand extends ContainerAwareCommand
198 $config = new Config($user); 198 $config = new Config($user);
199 $config->setTheme($this->getContainer()->getParameter('theme')); 199 $config->setTheme($this->getContainer()->getParameter('theme'));
200 $config->setItemsPerPage($this->getContainer()->getParameter('items_on_page')); 200 $config->setItemsPerPage($this->getContainer()->getParameter('items_on_page'));
201 $config->setRssLimit($this->getContainer()->getParameter('rss_limit'));
201 $config->setLanguage($this->getContainer()->getParameter('language')); 202 $config->setLanguage($this->getContainer()->getParameter('language'));
202 203
203 $em->persist($config); 204 $em->persist($config);
diff --git a/src/Wallabag/CoreBundle/Controller/ConfigController.php b/src/Wallabag/CoreBundle/Controller/ConfigController.php
index 4e895875..1622f348 100644
--- a/src/Wallabag/CoreBundle/Controller/ConfigController.php
+++ b/src/Wallabag/CoreBundle/Controller/ConfigController.php
@@ -5,11 +5,14 @@ namespace Wallabag\CoreBundle\Controller;
5use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; 5use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
6use Symfony\Bundle\FrameworkBundle\Controller\Controller; 6use Symfony\Bundle\FrameworkBundle\Controller\Controller;
7use Symfony\Component\HttpFoundation\Request; 7use Symfony\Component\HttpFoundation\Request;
8use Symfony\Component\HttpFoundation\JsonResponse;
8use Wallabag\CoreBundle\Entity\Config; 9use Wallabag\CoreBundle\Entity\Config;
9use Wallabag\CoreBundle\Entity\User; 10use Wallabag\CoreBundle\Entity\User;
10use Wallabag\CoreBundle\Form\Type\ChangePasswordType; 11use Wallabag\CoreBundle\Form\Type\ChangePasswordType;
11use Wallabag\CoreBundle\Form\Type\UserType; 12use Wallabag\CoreBundle\Form\Type\UserType;
12use Wallabag\CoreBundle\Form\Type\NewUserType; 13use Wallabag\CoreBundle\Form\Type\NewUserType;
14use Wallabag\CoreBundle\Form\Type\RssType;
15use Wallabag\CoreBundle\Tools\Utils;
13 16
14class ConfigController extends Controller 17class ConfigController extends Controller
15{ 18{
@@ -77,6 +80,22 @@ class ConfigController extends Controller
77 return $this->redirect($this->generateUrl('config')); 80 return $this->redirect($this->generateUrl('config'));
78 } 81 }
79 82
83 // handle rss information
84 $rssForm = $this->createForm(new RssType(), $config);
85 $rssForm->handleRequest($request);
86
87 if ($rssForm->isValid()) {
88 $em->persist($config);
89 $em->flush();
90
91 $this->get('session')->getFlashBag()->add(
92 'notice',
93 'RSS information updated'
94 );
95
96 return $this->redirect($this->generateUrl('config'));
97 }
98
80 // handle adding new user 99 // handle adding new user
81 $newUser = new User(); 100 $newUser = new User();
82 $newUserForm = $this->createForm(new NewUserType(), $newUser); 101 $newUserForm = $this->createForm(new NewUserType(), $newUser);
@@ -88,6 +107,7 @@ class ConfigController extends Controller
88 $config = new Config($newUser); 107 $config = new Config($newUser);
89 $config->setTheme($this->container->getParameter('theme')); 108 $config->setTheme($this->container->getParameter('theme'));
90 $config->setItemsPerPage($this->container->getParameter('items_on_page')); 109 $config->setItemsPerPage($this->container->getParameter('items_on_page'));
110 $config->setRssLimit($this->getContainer()->getParameter('rss_limit'));
91 $config->setLanguage($this->container->getParameter('language')); 111 $config->setLanguage($this->container->getParameter('language'));
92 112
93 $em->persist($config); 113 $em->persist($config);
@@ -103,14 +123,44 @@ class ConfigController extends Controller
103 } 123 }
104 124
105 return $this->render('WallabagCoreBundle:Config:index.html.twig', array( 125 return $this->render('WallabagCoreBundle:Config:index.html.twig', array(
106 'configForm' => $configForm->createView(), 126 'form' => array(
107 'pwdForm' => $pwdForm->createView(), 127 'config' => $configForm->createView(),
108 'userForm' => $userForm->createView(), 128 'rss' => $rssForm->createView(),
109 'newUserForm' => $newUserForm->createView(), 129 'pwd' => $pwdForm->createView(),
130 'user' => $userForm->createView(),
131 'new_user' => $newUserForm->createView(),
132 ),
133 'rss' => array(
134 'username' => $user->getUsername(),
135 'token' => $config->getRssToken(),
136 )
110 )); 137 ));
111 } 138 }
112 139
113 /** 140 /**
141 * @param Request $request
142 *
143 * @Route("/generate-token", name="generate_token")
144 *
145 * @return JsonResponse
146 */
147 public function generateTokenAction(Request $request)
148 {
149 $config = $this->getConfig();
150 $config->setRssToken(Utils::generateToken());
151
152 $em = $this->getDoctrine()->getManager();
153 $em->persist($config);
154 $em->flush();
155
156 if ($request->isXmlHttpRequest()) {
157 return new JsonResponse(array('token' => $config->getRssToken()));
158 }
159
160 return $request->headers->get('referer') ? $this->redirect($request->headers->get('referer')) : $this->redirectToRoute('config');
161 }
162
163 /**
114 * Retrieve config for the current user. 164 * Retrieve config for the current user.
115 * If no config were found, create a new one. 165 * If no config were found, create a new one.
116 * 166 *
diff --git a/src/Wallabag/CoreBundle/Controller/RssController.php b/src/Wallabag/CoreBundle/Controller/RssController.php
new file mode 100644
index 00000000..f2f8dd65
--- /dev/null
+++ b/src/Wallabag/CoreBundle/Controller/RssController.php
@@ -0,0 +1,84 @@
1<?php
2
3namespace Wallabag\CoreBundle\Controller;
4
5use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
6use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
7use Symfony\Bundle\FrameworkBundle\Controller\Controller;
8use Wallabag\CoreBundle\Entity\User;
9use Wallabag\CoreBundle\Entity\Entry;
10
11class RssController extends Controller
12{
13 /**
14 * Shows unread entries for current user
15 *
16 * @Route("/{username}/{token}/unread.xml", name="unread_rss", defaults={"_format"="xml"})
17 * @ParamConverter("user", class="WallabagCoreBundle:User", converter="username_rsstoken_converter")
18 *
19 * @return \Symfony\Component\HttpFoundation\Response
20 */
21 public function showUnreadAction(User $user)
22 {
23 $entries = $this->getDoctrine()
24 ->getRepository('WallabagCoreBundle:Entry')
25 ->findUnreadByUser(
26 $user->getId(),
27 0,
28 $user->getConfig()->getRssLimit() ?: $this->getContainer()->getParameter('rss_limit')
29 );
30
31 return $this->render('WallabagCoreBundle:Entry:entries.xml.twig', array(
32 'type' => 'unread',
33 'entries' => $entries,
34 ));
35 }
36
37 /**
38 * Shows read entries for current user
39 *
40 * @Route("/{username}/{token}/archive.xml", name="archive_rss")
41 * @ParamConverter("user", class="WallabagCoreBundle:User", converter="username_rsstoken_converter")
42 *
43 * @return \Symfony\Component\HttpFoundation\Response
44 */
45 public function showArchiveAction(User $user)
46 {
47 $entries = $this->getDoctrine()
48 ->getRepository('WallabagCoreBundle:Entry')
49 ->findArchiveByUser(
50 $user->getId(),
51 0,
52 $user->getConfig()->getRssLimit() ?: $this->getContainer()->getParameter('rss_limit')
53 );
54
55 return $this->render('WallabagCoreBundle:Entry:entries.xml.twig', array(
56 'type' => 'archive',
57 'entries' => $entries,
58 ));
59 }
60
61 /**
62 * Shows starred entries for current user
63 *
64 * @Route("/{username}/{token}/starred.xml", name="starred_rss")
65 * @ParamConverter("user", class="WallabagCoreBundle:User", converter="username_rsstoken_converter")
66 *
67 * @return \Symfony\Component\HttpFoundation\Response
68 */
69 public function showStarredAction(User $user)
70 {
71 $entries = $this->getDoctrine()
72 ->getRepository('WallabagCoreBundle:Entry')
73 ->findStarredByUser(
74 $user->getId(),
75 0,
76 $user->getConfig()->getRssLimit() ?: $this->getContainer()->getParameter('rss_limit')
77 );
78
79 return $this->render('WallabagCoreBundle:Entry:entries.xml.twig', array(
80 'type' => 'starred',
81 'entries' => $entries,
82 ));
83 }
84}
diff --git a/src/Wallabag/CoreBundle/Entity/Config.php b/src/Wallabag/CoreBundle/Entity/Config.php
index 91f9bfe8..56eff30c 100644
--- a/src/Wallabag/CoreBundle/Entity/Config.php
+++ b/src/Wallabag/CoreBundle/Entity/Config.php
@@ -32,12 +32,12 @@ class Config
32 private $theme; 32 private $theme;
33 33
34 /** 34 /**
35 * @var string 35 * @var integer
36 * 36 *
37 * @Assert\NotBlank() 37 * @Assert\NotBlank()
38 * @ORM\Column(name="items_per_page", type="integer", nullable=false) 38 * @ORM\Column(name="items_per_page", type="integer", nullable=false)
39 */ 39 */
40 private $items_per_page; 40 private $itemsPerPage;
41 41
42 /** 42 /**
43 * @var string 43 * @var string
@@ -48,6 +48,20 @@ class Config
48 private $language; 48 private $language;
49 49
50 /** 50 /**
51 * @var string
52 *
53 * @ORM\Column(name="rss_token", type="string", nullable=true)
54 */
55 private $rssToken;
56
57 /**
58 * @var integer
59 *
60 * @ORM\Column(name="rss_limit", type="integer", nullable=true)
61 */
62 private $rssLimit;
63
64 /**
51 * @ORM\OneToOne(targetEntity="User", inversedBy="config") 65 * @ORM\OneToOne(targetEntity="User", inversedBy="config")
52 */ 66 */
53 private $user; 67 private $user;
@@ -58,8 +72,6 @@ class Config
58 public function __construct(User $user) 72 public function __construct(User $user)
59 { 73 {
60 $this->user = $user; 74 $this->user = $user;
61 $this->items_per_page = 12;
62 $this->language = 'en_US';
63 } 75 }
64 76
65 /** 77 /**
@@ -96,26 +108,26 @@ class Config
96 } 108 }
97 109
98 /** 110 /**
99 * Set items_per_page 111 * Set itemsPerPage
100 * 112 *
101 * @param integer $itemsPerPage 113 * @param integer $itemsPerPage
102 * @return Config 114 * @return Config
103 */ 115 */
104 public function setItemsPerPage($itemsPerPage) 116 public function setItemsPerPage($itemsPerPage)
105 { 117 {
106 $this->items_per_page = $itemsPerPage; 118 $this->itemsPerPage = $itemsPerPage;
107 119
108 return $this; 120 return $this;
109 } 121 }
110 122
111 /** 123 /**
112 * Get items_per_page 124 * Get itemsPerPage
113 * 125 *
114 * @return integer 126 * @return integer
115 */ 127 */
116 public function getItemsPerPage() 128 public function getItemsPerPage()
117 { 129 {
118 return $this->items_per_page; 130 return $this->itemsPerPage;
119 } 131 }
120 132
121 /** 133 /**
@@ -163,4 +175,50 @@ class Config
163 { 175 {
164 return $this->user; 176 return $this->user;
165 } 177 }
178
179 /**
180 * Set rssToken
181 *
182 * @param string $rssToken
183 * @return Config
184 */
185 public function setRssToken($rssToken)
186 {
187 $this->rssToken = $rssToken;
188
189 return $this;
190 }
191
192 /**
193 * Get rssToken
194 *
195 * @return string
196 */
197 public function getRssToken()
198 {
199 return $this->rssToken;
200 }
201
202 /**
203 * Set rssLimit
204 *
205 * @param string $rssLimit
206 * @return Config
207 */
208 public function setRssLimit($rssLimit)
209 {
210 $this->rssLimit = $rssLimit;
211
212 return $this;
213 }
214
215 /**
216 * Get rssLimit
217 *
218 * @return string
219 */
220 public function getRssLimit()
221 {
222 return $this->rssLimit;
223 }
166} 224}
diff --git a/src/Wallabag/CoreBundle/Entity/User.php b/src/Wallabag/CoreBundle/Entity/User.php
index 6a7619ac..e75e3a83 100644
--- a/src/Wallabag/CoreBundle/Entity/User.php
+++ b/src/Wallabag/CoreBundle/Entity/User.php
@@ -14,7 +14,7 @@ use JMS\Serializer\Annotation\Expose;
14 * User 14 * User
15 * 15 *
16 * @ORM\Table(name="user") 16 * @ORM\Table(name="user")
17 * @ORM\Entity 17 * @ORM\Entity(repositoryClass="Wallabag\CoreBundle\Repository\UserRepository")
18 * @ORM\HasLifecycleCallbacks() 18 * @ORM\HasLifecycleCallbacks()
19 * @ExclusionPolicy("all") 19 * @ExclusionPolicy("all")
20 */ 20 */
diff --git a/src/Wallabag/CoreBundle/Form/Type/RssType.php b/src/Wallabag/CoreBundle/Form/Type/RssType.php
new file mode 100644
index 00000000..5edb38ba
--- /dev/null
+++ b/src/Wallabag/CoreBundle/Form/Type/RssType.php
@@ -0,0 +1,29 @@
1<?php
2namespace Wallabag\CoreBundle\Form\Type;
3
4use Symfony\Component\Form\AbstractType;
5use Symfony\Component\Form\FormBuilderInterface;
6use Symfony\Component\OptionsResolver\OptionsResolverInterface;
7
8class RssType extends AbstractType
9{
10 public function buildForm(FormBuilderInterface $builder, array $options)
11 {
12 $builder
13 ->add('rss_limit', 'text')
14 ->add('save', 'submit')
15 ;
16 }
17
18 public function setDefaultOptions(OptionsResolverInterface $resolver)
19 {
20 $resolver->setDefaults(array(
21 'data_class' => 'Wallabag\CoreBundle\Entity\Config',
22 ));
23 }
24
25 public function getName()
26 {
27 return 'rss_config';
28 }
29}
diff --git a/src/Wallabag/CoreBundle/ParamConverter/UsernameRssTokenConverter.php b/src/Wallabag/CoreBundle/ParamConverter/UsernameRssTokenConverter.php
new file mode 100644
index 00000000..ea2bda17
--- /dev/null
+++ b/src/Wallabag/CoreBundle/ParamConverter/UsernameRssTokenConverter.php
@@ -0,0 +1,92 @@
1<?php
2
3namespace Wallabag\CoreBundle\ParamConverter;
4
5use Sensio\Bundle\FrameworkExtraBundle\Request\ParamConverter\ParamConverterInterface;
6use Doctrine\Common\Persistence\ManagerRegistry;
7use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
8use Symfony\Component\HttpFoundation\Request;
9use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
10use Wallabag\CoreBundle\Entity\User;
11
12/**
13 * ParamConverter used in the RSS controller to retrieve the right user according to
14 * username & token given in the url.
15 *
16 * @see http://stfalcon.com/en/blog/post/symfony2-custom-paramconverter
17 */
18class UsernameRssTokenConverter implements ParamConverterInterface
19{
20 private $registry;
21
22 /**
23 * @param ManagerRegistry $registry Manager registry
24 */
25 public function __construct(ManagerRegistry $registry = null)
26 {
27 $this->registry = $registry;
28 }
29
30 /**
31 * {@inheritdoc}
32 *
33 * Check, if object supported by our converter
34 */
35 public function supports(ParamConverter $configuration)
36 {
37 // If there is no manager, this means that only Doctrine DBAL is configured
38 // In this case we can do nothing and just return
39 if (null === $this->registry || !count($this->registry->getManagers())) {
40 return false;
41 }
42
43 // Check, if option class was set in configuration
44 if (null === $configuration->getClass()) {
45 return false;
46 }
47
48 // Get actual entity manager for class
49 $em = $this->registry->getManagerForClass($configuration->getClass());
50
51 // Check, if class name is what we need
52 if ('Wallabag\CoreBundle\Entity\User' !== $em->getClassMetadata($configuration->getClass())->getName()) {
53 return false;
54 }
55
56 return true;
57 }
58
59 /**
60 * {@inheritdoc}
61 *
62 * Applies converting
63 *
64 * @throws \InvalidArgumentException When route attributes are missing
65 * @throws NotFoundHttpException When object not found
66 */
67 public function apply(Request $request, ParamConverter $configuration)
68 {
69 $username = $request->attributes->get('username');
70 $rssToken = $request->attributes->get('token');
71
72 // Check, if route attributes exists
73 if (null === $username || null === $rssToken) {
74 throw new \InvalidArgumentException('Route attribute is missing');
75 }
76
77 // Get actual entity manager for class
78 $em = $this->registry->getManagerForClass($configuration->getClass());
79
80 $userRepository = $em->getRepository($configuration->getClass());
81
82 // Try to find user by its username and config rss_token
83 $user = $userRepository->findOneByUsernameAndRsstoken($username, $rssToken);
84
85 if (null === $user || !($user instanceof User)) {
86 throw new NotFoundHttpException(sprintf('%s not found.', $configuration->getClass()));
87 }
88
89 // Map found user to the route's parameter
90 $request->attributes->set($configuration->getName(), $user);
91 }
92}
diff --git a/src/Wallabag/CoreBundle/Repository/UserRepository.php b/src/Wallabag/CoreBundle/Repository/UserRepository.php
new file mode 100644
index 00000000..aab3dedc
--- /dev/null
+++ b/src/Wallabag/CoreBundle/Repository/UserRepository.php
@@ -0,0 +1,26 @@
1<?php
2
3namespace Wallabag\CoreBundle\Repository;
4
5use Doctrine\ORM\EntityRepository;
6
7class UserRepository extends EntityRepository
8{
9 /**
10 * Find a user by its username and rss roken
11 *
12 * @param string $username
13 * @param string $rssToken
14 *
15 * @return User|null
16 */
17 public function findOneByUsernameAndRsstoken($username, $rssToken)
18 {
19 return $this->createQueryBuilder('u')
20 ->leftJoin('u.config', 'c')
21 ->where('c.rssToken = :rss_token')->setParameter('rss_token', $rssToken)
22 ->andWhere('u.username = :username')->setParameter('username', $username)
23 ->getQuery()
24 ->getOneOrNullResult();
25 }
26}
diff --git a/src/Wallabag/CoreBundle/Resources/config/services.yml b/src/Wallabag/CoreBundle/Resources/config/services.yml
index 062e1651..0f4db94e 100644
--- a/src/Wallabag/CoreBundle/Resources/config/services.yml
+++ b/src/Wallabag/CoreBundle/Resources/config/services.yml
@@ -36,3 +36,10 @@ services:
36 - @doctrine 36 - @doctrine
37 tags: 37 tags:
38 - { name: form.type, alias: forgot_password } 38 - { name: form.type, alias: forgot_password }
39
40 wallabag_core.param_converter.username_rsstoken_converter:
41 class: Wallabag\CoreBundle\ParamConverter\UsernameRssTokenConverter
42 tags:
43 - { name: request.param_converter, converter: username_rsstoken_converter }
44 arguments:
45 - @doctrine
diff --git a/src/Wallabag/CoreBundle/Resources/views/Config/index.html.twig b/src/Wallabag/CoreBundle/Resources/views/Config/index.html.twig
index 1835d26e..b134b6ca 100644
--- a/src/Wallabag/CoreBundle/Resources/views/Config/index.html.twig
+++ b/src/Wallabag/CoreBundle/Resources/views/Config/index.html.twig
@@ -5,129 +5,169 @@
5{% block content %} 5{% block content %}
6 <h2>{% trans %}Wallabag configuration{% endtrans %}</h2> 6 <h2>{% trans %}Wallabag configuration{% endtrans %}</h2>
7 7
8 <form action="{{ path('config') }}" method="post" {{ form_enctype(configForm) }}> 8 <form action="{{ path('config') }}" method="post" {{ form_enctype(form.config) }}>
9 {{ form_errors(configForm) }} 9 {{ form_errors(form.config) }}
10 10
11 <fieldset class="w500p inline"> 11 <fieldset class="w500p inline">
12 <div class="row"> 12 <div class="row">
13 {{ form_label(configForm.theme) }} 13 {{ form_label(form.config.theme) }}
14 {{ form_errors(configForm.theme) }} 14 {{ form_errors(form.config.theme) }}
15 {{ form_widget(configForm.theme) }} 15 {{ form_widget(form.config.theme) }}
16 </div> 16 </div>
17 </fieldset> 17 </fieldset>
18 18
19 <fieldset class="w500p inline"> 19 <fieldset class="w500p inline">
20 <div class="row"> 20 <div class="row">
21 {{ form_label(configForm.items_per_page) }} 21 {{ form_label(form.config.items_per_page) }}
22 {{ form_errors(configForm.items_per_page) }} 22 {{ form_errors(form.config.items_per_page) }}
23 {{ form_widget(configForm.items_per_page) }} 23 {{ form_widget(form.config.items_per_page) }}
24 </div> 24 </div>
25 </fieldset> 25 </fieldset>
26 26
27 <fieldset class="w500p inline"> 27 <fieldset class="w500p inline">
28 <div class="row"> 28 <div class="row">
29 {{ form_label(configForm.language) }} 29 {{ form_label(form.config.language) }}
30 {{ form_errors(configForm.language) }} 30 {{ form_errors(form.config.language) }}
31 {{ form_widget(configForm.language) }} 31 {{ form_widget(form.config.language) }}
32 </div> 32 </div>
33 </fieldset> 33 </fieldset>
34 34
35 {{ form_rest(configForm) }} 35 {{ form_rest(form.config) }}
36 </form>
37
38 <h2>{% trans %}RSS configuration{% endtrans %}</h2>
39
40 <form action="{{ path('config') }}" method="post" {{ form_enctype(form.rss) }}>
41 {{ form_errors(form.rss) }}
42
43 <fieldset class="w500p inline">
44 <div class="row">
45 <label>Rss token</label>
46 {% if rss.token %}
47 {{ rss.token }}
48 {% else %}
49 <em>No token</em>
50 {% endif %}
51
52 <a href="{{ path('generate_token') }}">Regenerate ?</a>
53 </div>
54 </fieldset>
55
56 <fieldset class="w500p inline">
57 <div class="row">
58 <label>Rss links:</label>
59 <ul>
60 <li><a href="{{ path('unread_rss', {'username': rss.username, 'token': rss.token}) }}">unread</a></li>
61 <li><a href="{{ path('starred_rss', {'username': rss.username, 'token': rss.token}) }}">fav</a></li>
62 <li><a href="{{ path('archive_rss', {'username': rss.username, 'token': rss.token}) }}">archives</a></li>
63 </ul>
64 </div>
65 </fieldset>
66
67 <fieldset class="w500p inline">
68 <div class="row">
69 {{ form_label(form.rss.rss_limit) }}
70 {{ form_errors(form.rss.rss_limit) }}
71 {{ form_widget(form.rss.rss_limit) }}
72 </div>
73 </fieldset>
74
75 {{ form_rest(form.rss) }}
36 </form> 76 </form>
37 77
38 <h2>{% trans %}User information{% endtrans %}</h2> 78 <h2>{% trans %}User information{% endtrans %}</h2>
39 79
40 <form action="{{ path('config') }}" method="post" {{ form_enctype(userForm) }}> 80 <form action="{{ path('config') }}" method="post" {{ form_enctype(form.user) }}>
41 {{ form_errors(userForm) }} 81 {{ form_errors(form.user) }}
42 82
43 <fieldset class="w500p inline"> 83 <fieldset class="w500p inline">
44 <div class="row"> 84 <div class="row">
45 {{ form_label(userForm.username) }} 85 {{ form_label(form.user.username) }}
46 {{ form_errors(userForm.username) }} 86 {{ form_errors(form.user.username) }}
47 {{ form_widget(userForm.username) }} 87 {{ form_widget(form.user.username) }}
48 </div> 88 </div>
49 </fieldset> 89 </fieldset>
50 90
51 <fieldset class="w500p inline"> 91 <fieldset class="w500p inline">
52 <div class="row"> 92 <div class="row">
53 {{ form_label(userForm.name) }} 93 {{ form_label(form.user.name) }}
54 {{ form_errors(userForm.name) }} 94 {{ form_errors(form.user.name) }}
55 {{ form_widget(userForm.name) }} 95 {{ form_widget(form.user.name) }}
56 </div> 96 </div>
57 </fieldset> 97 </fieldset>
58 98
59 <fieldset class="w500p inline"> 99 <fieldset class="w500p inline">
60 <div class="row"> 100 <div class="row">
61 {{ form_label(userForm.email) }} 101 {{ form_label(form.user.email) }}
62 {{ form_errors(userForm.email) }} 102 {{ form_errors(form.user.email) }}
63 {{ form_widget(userForm.email) }} 103 {{ form_widget(form.user.email) }}
64 </div> 104 </div>
65 </fieldset> 105 </fieldset>
66 106
67 {{ form_rest(userForm) }} 107 {{ form_rest(form.user) }}
68 </form> 108 </form>
69 109
70 <h2>{% trans %}Change your password{% endtrans %}</h2> 110 <h2>{% trans %}Change your password{% endtrans %}</h2>
71 111
72 <form action="{{ path('config') }}" method="post" {{ form_enctype(pwdForm) }}> 112 <form action="{{ path('config') }}" method="post" {{ form_enctype(form.pwd) }}>
73 {{ form_errors(pwdForm) }} 113 {{ form_errors(form.pwd) }}
74 114
75 <fieldset class="w500p inline"> 115 <fieldset class="w500p inline">
76 <div class="row"> 116 <div class="row">
77 {{ form_label(pwdForm.old_password) }} 117 {{ form_label(form.pwd.old_password) }}
78 {{ form_errors(pwdForm.old_password) }} 118 {{ form_errors(form.pwd.old_password) }}
79 {{ form_widget(pwdForm.old_password) }} 119 {{ form_widget(form.pwd.old_password) }}
80 </div> 120 </div>
81 </fieldset> 121 </fieldset>
82 122
83 <fieldset class="w500p inline"> 123 <fieldset class="w500p inline">
84 <div class="row"> 124 <div class="row">
85 {{ form_label(pwdForm.new_password.first) }} 125 {{ form_label(form.pwd.new_password.first) }}
86 {{ form_errors(pwdForm.new_password.first) }} 126 {{ form_errors(form.pwd.new_password.first) }}
87 {{ form_widget(pwdForm.new_password.first) }} 127 {{ form_widget(form.pwd.new_password.first) }}
88 </div> 128 </div>
89 </fieldset> 129 </fieldset>
90 130
91 <fieldset class="w500p inline"> 131 <fieldset class="w500p inline">
92 <div class="row"> 132 <div class="row">
93 {{ form_label(pwdForm.new_password.second) }} 133 {{ form_label(form.pwd.new_password.second) }}
94 {{ form_errors(pwdForm.new_password.second) }} 134 {{ form_errors(form.pwd.new_password.second) }}
95 {{ form_widget(pwdForm.new_password.second) }} 135 {{ form_widget(form.pwd.new_password.second) }}
96 </div> 136 </div>
97 </fieldset> 137 </fieldset>
98 138
99 {{ form_rest(pwdForm) }} 139 {{ form_rest(form.pwd) }}
100 </form> 140 </form>
101 141
102 <h2>{% trans %}Add a user{% endtrans %}</h2> 142 <h2>{% trans %}Add a user{% endtrans %}</h2>
103 143
104 <form action="{{ path('config') }}" method="post" {{ form_enctype(newUserForm) }}> 144 <form action="{{ path('config') }}" method="post" {{ form_enctype(form.new_user) }}>
105 {{ form_errors(newUserForm) }} 145 {{ form_errors(form.new_user) }}
106 146
107 <fieldset class="w500p inline"> 147 <fieldset class="w500p inline">
108 <div class="row"> 148 <div class="row">
109 {{ form_label(newUserForm.username) }} 149 {{ form_label(form.new_user.username) }}
110 {{ form_errors(newUserForm.username) }} 150 {{ form_errors(form.new_user.username) }}
111 {{ form_widget(newUserForm.username) }} 151 {{ form_widget(form.new_user.username) }}
112 </div> 152 </div>
113 </fieldset> 153 </fieldset>
114 154
115 <fieldset class="w500p inline"> 155 <fieldset class="w500p inline">
116 <div class="row"> 156 <div class="row">
117 {{ form_label(newUserForm.password) }} 157 {{ form_label(form.new_user.password) }}
118 {{ form_errors(newUserForm.password) }} 158 {{ form_errors(form.new_user.password) }}
119 {{ form_widget(newUserForm.password) }} 159 {{ form_widget(form.new_user.password) }}
120 </div> 160 </div>
121 </fieldset> 161 </fieldset>
122 162
123 <fieldset class="w500p inline"> 163 <fieldset class="w500p inline">
124 <div class="row"> 164 <div class="row">
125 {{ form_label(newUserForm.email) }} 165 {{ form_label(form.new_user.email) }}
126 {{ form_errors(newUserForm.email) }} 166 {{ form_errors(form.new_user.email) }}
127 {{ form_widget(newUserForm.email) }} 167 {{ form_widget(form.new_user.email) }}
128 </div> 168 </div>
129 </fieldset> 169 </fieldset>
130 170
131 {{ form_rest(newUserForm) }} 171 {{ form_rest(form.new_user) }}
132 </form> 172 </form>
133{% endblock %} 173{% endblock %}
diff --git a/src/Wallabag/CoreBundle/Resources/views/Entry/entries.xml.twig b/src/Wallabag/CoreBundle/Resources/views/Entry/entries.xml.twig
new file mode 100644
index 00000000..6eebc80d
--- /dev/null
+++ b/src/Wallabag/CoreBundle/Resources/views/Entry/entries.xml.twig
@@ -0,0 +1,34 @@
1<?xml version="1.0" encoding="utf-8"?>
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>
4 <title>wallabag — {{type}} feed</title>
5 <link>{{ url('unread') }}</link>
6 <pubDate>{{ "now"|date('D, d M Y H:i:s') }}</pubDate>
7 <generator>wallabag</generator>
8 <description>wallabag {{type}} elements</description>
9
10 {% for entry in entries %}
11
12 <item>
13 <title><![CDATA[{{ entry.title }}]]></title>
14 <source url="{{ url('view', { 'id': entry.id }) }}">wallabag</source>
15 <link>{{ url('view', { 'id': entry.id }) }}</link>
16 <guid>{{ url('view', { 'id': entry.id }) }}</guid>
17 <pubDate>{{ entry.createdAt|date('D, d M Y H:i:s') }}</pubDate>
18 <description>
19 <![CDATA[
20 {%- if entry.content| readingTime > 0 %}
21 {% trans %}estimated reading time :{% endtrans %} {{ entry.content| readingTime }} min
22 {% else -%}
23 {% trans %}estimated reading time :{% endtrans %} &lt; 1 min
24 {% endif -%}
25
26 {{ entry.content -}}
27 ]]>
28 </description>
29 </item>
30
31 {% endfor %}
32
33 </channel>
34</rss>
diff --git a/src/Wallabag/CoreBundle/Tools/Utils.php b/src/Wallabag/CoreBundle/Tools/Utils.php
new file mode 100644
index 00000000..de97c796
--- /dev/null
+++ b/src/Wallabag/CoreBundle/Tools/Utils.php
@@ -0,0 +1,27 @@
1<?php
2
3namespace Wallabag\CoreBundle\Tools;
4
5class Utils
6{
7 /**
8 * Generate a token used for RSS
9 *
10 * @return string
11 */
12 public static function generateToken()
13 {
14 if (ini_get('open_basedir') === '') {
15 if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
16 // alternative to /dev/urandom for Windows
17 $token = substr(base64_encode(uniqid(mt_rand(), true)), 0, 20);
18 } else {
19 $token = substr(base64_encode(file_get_contents('/dev/urandom', false, null, 0, 20)), 0, 15);
20 }
21 } else {
22 $token = substr(base64_encode(uniqid(mt_rand(), true)), 0, 20);
23 }
24
25 return str_replace('+', '', $token);
26 }
27}