diff options
author | Nicolas LÅ“uillet <nicolas@loeuillet.org> | 2015-04-01 21:08:56 +0200 |
---|---|---|
committer | Nicolas LÅ“uillet <nicolas@loeuillet.org> | 2015-04-01 21:08:56 +0200 |
commit | 1a93ee423b072ec3bcb0c437cbf9b488bdea245c (patch) | |
tree | 1466dcb1b465f9ead71c4dcbefe380853c5d846b /src/Wallabag | |
parent | f98a2a0fc3ae8a5955bb811f083c3d2535f96791 (diff) | |
parent | 7d74a2f32b55fa9c33f5ecff57785e8d9e4de8ae (diff) | |
download | wallabag-1a93ee423b072ec3bcb0c437cbf9b488bdea245c.tar.gz wallabag-1a93ee423b072ec3bcb0c437cbf9b488bdea245c.tar.zst wallabag-1a93ee423b072ec3bcb0c437cbf9b488bdea245c.zip |
Merge pull request #1166 from wallabag/v2-rss
Add RSS feeds
Diffstat (limited to 'src/Wallabag')
23 files changed, 1068 insertions, 85 deletions
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..dbae3ea7 100644 --- a/src/Wallabag/CoreBundle/Controller/ConfigController.php +++ b/src/Wallabag/CoreBundle/Controller/ConfigController.php | |||
@@ -5,11 +5,14 @@ namespace Wallabag\CoreBundle\Controller; | |||
5 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; | 5 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; |
6 | use Symfony\Bundle\FrameworkBundle\Controller\Controller; | 6 | use Symfony\Bundle\FrameworkBundle\Controller\Controller; |
7 | use Symfony\Component\HttpFoundation\Request; | 7 | use Symfony\Component\HttpFoundation\Request; |
8 | use Symfony\Component\HttpFoundation\JsonResponse; | ||
8 | use Wallabag\CoreBundle\Entity\Config; | 9 | use Wallabag\CoreBundle\Entity\Config; |
9 | use Wallabag\CoreBundle\Entity\User; | 10 | use Wallabag\CoreBundle\Entity\User; |
10 | use Wallabag\CoreBundle\Form\Type\ChangePasswordType; | 11 | use Wallabag\CoreBundle\Form\Type\ChangePasswordType; |
11 | use Wallabag\CoreBundle\Form\Type\UserType; | 12 | use Wallabag\CoreBundle\Form\Type\UserType; |
12 | use Wallabag\CoreBundle\Form\Type\NewUserType; | 13 | use Wallabag\CoreBundle\Form\Type\NewUserType; |
14 | use Wallabag\CoreBundle\Form\Type\RssType; | ||
15 | use Wallabag\CoreBundle\Tools\Utils; | ||
13 | 16 | ||
14 | class ConfigController extends Controller | 17 | class 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->container->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..14f1dcb2 --- /dev/null +++ b/src/Wallabag/CoreBundle/Controller/RssController.php | |||
@@ -0,0 +1,84 @@ | |||
1 | <?php | ||
2 | |||
3 | namespace Wallabag\CoreBundle\Controller; | ||
4 | |||
5 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; | ||
6 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter; | ||
7 | use Symfony\Bundle\FrameworkBundle\Controller\Controller; | ||
8 | use Wallabag\CoreBundle\Entity\User; | ||
9 | use Wallabag\CoreBundle\Entity\Entry; | ||
10 | |||
11 | class 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->container->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->container->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->container->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/DataFixtures/ORM/LoadEntryData.php b/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadEntryData.php index ce12ec5d..54d0d6b6 100644 --- a/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadEntryData.php +++ b/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadEntryData.php | |||
@@ -67,6 +67,26 @@ class LoadEntryData extends AbstractFixture implements OrderedFixtureInterface | |||
67 | 67 | ||
68 | $this->addReference('entry4', $entry4); | 68 | $this->addReference('entry4', $entry4); |
69 | 69 | ||
70 | $entry5 = new Entry($this->getReference('admin-user')); | ||
71 | $entry5->setUrl('http://0.0.0.0'); | ||
72 | $entry5->setTitle('test title entry5'); | ||
73 | $entry5->setContent('This is my content /o/'); | ||
74 | $entry5->setStarred(true); | ||
75 | |||
76 | $manager->persist($entry5); | ||
77 | |||
78 | $this->addReference('entry5', $entry5); | ||
79 | |||
80 | $entry6 = new Entry($this->getReference('admin-user')); | ||
81 | $entry6->setUrl('http://0.0.0.0'); | ||
82 | $entry6->setTitle('test title entry6'); | ||
83 | $entry6->setContent('This is my content /o/'); | ||
84 | $entry6->setArchived(true); | ||
85 | |||
86 | $manager->persist($entry6); | ||
87 | |||
88 | $this->addReference('entry6', $entry6); | ||
89 | |||
70 | $manager->flush(); | 90 | $manager->flush(); |
71 | } | 91 | } |
72 | 92 | ||
diff --git a/src/Wallabag/CoreBundle/Entity/Config.php b/src/Wallabag/CoreBundle/Entity/Config.php index 91f9bfe8..9f079656 100644 --- a/src/Wallabag/CoreBundle/Entity/Config.php +++ b/src/Wallabag/CoreBundle/Entity/Config.php | |||
@@ -32,12 +32,17 @@ 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 | * @Assert\Range( | ||
39 | * min = 1, | ||
40 | * max = 100000, | ||
41 | * maxMessage = "This will certainly kill the app" | ||
42 | * ) | ||
38 | * @ORM\Column(name="items_per_page", type="integer", nullable=false) | 43 | * @ORM\Column(name="items_per_page", type="integer", nullable=false) |
39 | */ | 44 | */ |
40 | private $items_per_page; | 45 | private $itemsPerPage; |
41 | 46 | ||
42 | /** | 47 | /** |
43 | * @var string | 48 | * @var string |
@@ -48,6 +53,25 @@ class Config | |||
48 | private $language; | 53 | private $language; |
49 | 54 | ||
50 | /** | 55 | /** |
56 | * @var string | ||
57 | * | ||
58 | * @ORM\Column(name="rss_token", type="string", nullable=true) | ||
59 | */ | ||
60 | private $rssToken; | ||
61 | |||
62 | /** | ||
63 | * @var integer | ||
64 | * | ||
65 | * @ORM\Column(name="rss_limit", type="integer", nullable=true) | ||
66 | * @Assert\Range( | ||
67 | * min = 1, | ||
68 | * max = 100000, | ||
69 | * maxMessage = "This will certainly kill the app" | ||
70 | * ) | ||
71 | */ | ||
72 | private $rssLimit; | ||
73 | |||
74 | /** | ||
51 | * @ORM\OneToOne(targetEntity="User", inversedBy="config") | 75 | * @ORM\OneToOne(targetEntity="User", inversedBy="config") |
52 | */ | 76 | */ |
53 | private $user; | 77 | private $user; |
@@ -58,8 +82,6 @@ class Config | |||
58 | public function __construct(User $user) | 82 | public function __construct(User $user) |
59 | { | 83 | { |
60 | $this->user = $user; | 84 | $this->user = $user; |
61 | $this->items_per_page = 12; | ||
62 | $this->language = 'en_US'; | ||
63 | } | 85 | } |
64 | 86 | ||
65 | /** | 87 | /** |
@@ -96,26 +118,26 @@ class Config | |||
96 | } | 118 | } |
97 | 119 | ||
98 | /** | 120 | /** |
99 | * Set items_per_page | 121 | * Set itemsPerPage |
100 | * | 122 | * |
101 | * @param integer $itemsPerPage | 123 | * @param integer $itemsPerPage |
102 | * @return Config | 124 | * @return Config |
103 | */ | 125 | */ |
104 | public function setItemsPerPage($itemsPerPage) | 126 | public function setItemsPerPage($itemsPerPage) |
105 | { | 127 | { |
106 | $this->items_per_page = $itemsPerPage; | 128 | $this->itemsPerPage = $itemsPerPage; |
107 | 129 | ||
108 | return $this; | 130 | return $this; |
109 | } | 131 | } |
110 | 132 | ||
111 | /** | 133 | /** |
112 | * Get items_per_page | 134 | * Get itemsPerPage |
113 | * | 135 | * |
114 | * @return integer | 136 | * @return integer |
115 | */ | 137 | */ |
116 | public function getItemsPerPage() | 138 | public function getItemsPerPage() |
117 | { | 139 | { |
118 | return $this->items_per_page; | 140 | return $this->itemsPerPage; |
119 | } | 141 | } |
120 | 142 | ||
121 | /** | 143 | /** |
@@ -163,4 +185,50 @@ class Config | |||
163 | { | 185 | { |
164 | return $this->user; | 186 | return $this->user; |
165 | } | 187 | } |
188 | |||
189 | /** | ||
190 | * Set rssToken | ||
191 | * | ||
192 | * @param string $rssToken | ||
193 | * @return Config | ||
194 | */ | ||
195 | public function setRssToken($rssToken) | ||
196 | { | ||
197 | $this->rssToken = $rssToken; | ||
198 | |||
199 | return $this; | ||
200 | } | ||
201 | |||
202 | /** | ||
203 | * Get rssToken | ||
204 | * | ||
205 | * @return string | ||
206 | */ | ||
207 | public function getRssToken() | ||
208 | { | ||
209 | return $this->rssToken; | ||
210 | } | ||
211 | |||
212 | /** | ||
213 | * Set rssLimit | ||
214 | * | ||
215 | * @param string $rssLimit | ||
216 | * @return Config | ||
217 | */ | ||
218 | public function setRssLimit($rssLimit) | ||
219 | { | ||
220 | $this->rssLimit = $rssLimit; | ||
221 | |||
222 | return $this; | ||
223 | } | ||
224 | |||
225 | /** | ||
226 | * Get rssLimit | ||
227 | * | ||
228 | * @return string | ||
229 | */ | ||
230 | public function getRssLimit() | ||
231 | { | ||
232 | return $this->rssLimit; | ||
233 | } | ||
166 | } | 234 | } |
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/ConfigType.php b/src/Wallabag/CoreBundle/Form/Type/ConfigType.php index 0c8706e2..0fcf020a 100644 --- a/src/Wallabag/CoreBundle/Form/Type/ConfigType.php +++ b/src/Wallabag/CoreBundle/Form/Type/ConfigType.php | |||
@@ -24,7 +24,7 @@ class ConfigType extends AbstractType | |||
24 | { | 24 | { |
25 | $builder | 25 | $builder |
26 | ->add('theme', 'choice', array('choices' => $this->themes)) | 26 | ->add('theme', 'choice', array('choices' => $this->themes)) |
27 | ->add('items_per_page', 'text') | 27 | ->add('items_per_page') |
28 | ->add('language') | 28 | ->add('language') |
29 | ->add('save', 'submit') | 29 | ->add('save', 'submit') |
30 | ; | 30 | ; |
diff --git a/src/Wallabag/CoreBundle/Form/Type/RssType.php b/src/Wallabag/CoreBundle/Form/Type/RssType.php new file mode 100644 index 00000000..a1ab990f --- /dev/null +++ b/src/Wallabag/CoreBundle/Form/Type/RssType.php | |||
@@ -0,0 +1,29 @@ | |||
1 | <?php | ||
2 | namespace Wallabag\CoreBundle\Form\Type; | ||
3 | |||
4 | use Symfony\Component\Form\AbstractType; | ||
5 | use Symfony\Component\Form\FormBuilderInterface; | ||
6 | use Symfony\Component\OptionsResolver\OptionsResolverInterface; | ||
7 | |||
8 | class RssType extends AbstractType | ||
9 | { | ||
10 | public function buildForm(FormBuilderInterface $builder, array $options) | ||
11 | { | ||
12 | $builder | ||
13 | ->add('rss_limit') | ||
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 | |||
3 | namespace Wallabag\CoreBundle\ParamConverter; | ||
4 | |||
5 | use Sensio\Bundle\FrameworkExtraBundle\Request\ParamConverter\ParamConverterInterface; | ||
6 | use Doctrine\Common\Persistence\ManagerRegistry; | ||
7 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter; | ||
8 | use Symfony\Component\HttpFoundation\Request; | ||
9 | use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; | ||
10 | use 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 | */ | ||
18 | class 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/EntryRepository.php b/src/Wallabag/CoreBundle/Repository/EntryRepository.php index 53e8e2ba..a8c138a9 100644 --- a/src/Wallabag/CoreBundle/Repository/EntryRepository.php +++ b/src/Wallabag/CoreBundle/Repository/EntryRepository.php | |||
@@ -26,7 +26,7 @@ class EntryRepository extends EntityRepository | |||
26 | ->leftJoin('e.user', 'u') | 26 | ->leftJoin('e.user', 'u') |
27 | ->where('e.isArchived = false') | 27 | ->where('e.isArchived = false') |
28 | ->andWhere('u.id =:userId')->setParameter('userId', $userId) | 28 | ->andWhere('u.id =:userId')->setParameter('userId', $userId) |
29 | ->orderBy('e.createdAt', 'desc') | 29 | ->orderBy('e.id', 'desc') |
30 | ->getQuery(); | 30 | ->getQuery(); |
31 | 31 | ||
32 | $paginator = new Paginator($qb); | 32 | $paginator = new Paginator($qb); |
@@ -52,7 +52,7 @@ class EntryRepository extends EntityRepository | |||
52 | ->leftJoin('e.user', 'u') | 52 | ->leftJoin('e.user', 'u') |
53 | ->where('e.isArchived = true') | 53 | ->where('e.isArchived = true') |
54 | ->andWhere('u.id =:userId')->setParameter('userId', $userId) | 54 | ->andWhere('u.id =:userId')->setParameter('userId', $userId) |
55 | ->orderBy('e.createdAt', 'desc') | 55 | ->orderBy('e.id', 'desc') |
56 | ->getQuery(); | 56 | ->getQuery(); |
57 | 57 | ||
58 | $paginator = new Paginator($qb); | 58 | $paginator = new Paginator($qb); |
@@ -78,7 +78,7 @@ class EntryRepository extends EntityRepository | |||
78 | ->leftJoin('e.user', 'u') | 78 | ->leftJoin('e.user', 'u') |
79 | ->where('e.isStarred = true') | 79 | ->where('e.isStarred = true') |
80 | ->andWhere('u.id =:userId')->setParameter('userId', $userId) | 80 | ->andWhere('u.id =:userId')->setParameter('userId', $userId) |
81 | ->orderBy('e.createdAt', 'desc') | 81 | ->orderBy('e.id', 'desc') |
82 | ->getQuery(); | 82 | ->getQuery(); |
83 | 83 | ||
84 | $paginator = new Paginator($qb); | 84 | $paginator = new Paginator($qb); |
@@ -111,7 +111,7 @@ class EntryRepository extends EntityRepository | |||
111 | } | 111 | } |
112 | 112 | ||
113 | if ('created' === $sort) { | 113 | if ('created' === $sort) { |
114 | $qb->orderBy('e.createdAt', $order); | 114 | $qb->orderBy('e.id', $order); |
115 | } elseif ('updated' === $sort) { | 115 | } elseif ('updated' === $sort) { |
116 | $qb->orderBy('e.updatedAt', $order); | 116 | $qb->orderBy('e.updatedAt', $order); |
117 | } | 117 | } |
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 | |||
3 | namespace Wallabag\CoreBundle\Repository; | ||
4 | |||
5 | use Doctrine\ORM\EntityRepository; | ||
6 | |||
7 | class 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..f2a98dfb 100644 --- a/src/Wallabag/CoreBundle/Resources/views/Config/index.html.twig +++ b/src/Wallabag/CoreBundle/Resources/views/Config/index.html.twig | |||
@@ -5,129 +5,173 @@ | |||
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 | {% if rss.token %} | ||
60 | <ul> | ||
61 | <li><a href="{{ path('unread_rss', {'username': rss.username, 'token': rss.token}) }}">unread</a></li> | ||
62 | <li><a href="{{ path('starred_rss', {'username': rss.username, 'token': rss.token}) }}">fav</a></li> | ||
63 | <li><a href="{{ path('archive_rss', {'username': rss.username, 'token': rss.token}) }}">archives</a></li> | ||
64 | </ul> | ||
65 | {% else %} | ||
66 | <strong>You need to generate a token first.</strong> | ||
67 | {% endif %} | ||
68 | </div> | ||
69 | </fieldset> | ||
70 | |||
71 | <fieldset class="w500p inline"> | ||
72 | <div class="row"> | ||
73 | {{ form_label(form.rss.rss_limit) }} | ||
74 | {{ form_errors(form.rss.rss_limit) }} | ||
75 | {{ form_widget(form.rss.rss_limit) }} | ||
76 | </div> | ||
77 | </fieldset> | ||
78 | |||
79 | {{ form_rest(form.rss) }} | ||
36 | </form> | 80 | </form> |
37 | 81 | ||
38 | <h2>{% trans %}User information{% endtrans %}</h2> | 82 | <h2>{% trans %}User information{% endtrans %}</h2> |
39 | 83 | ||
40 | <form action="{{ path('config') }}" method="post" {{ form_enctype(userForm) }}> | 84 | <form action="{{ path('config') }}" method="post" {{ form_enctype(form.user) }}> |
41 | {{ form_errors(userForm) }} | 85 | {{ form_errors(form.user) }} |
42 | 86 | ||
43 | <fieldset class="w500p inline"> | 87 | <fieldset class="w500p inline"> |
44 | <div class="row"> | 88 | <div class="row"> |
45 | {{ form_label(userForm.username) }} | 89 | {{ form_label(form.user.username) }} |
46 | {{ form_errors(userForm.username) }} | 90 | {{ form_errors(form.user.username) }} |
47 | {{ form_widget(userForm.username) }} | 91 | {{ form_widget(form.user.username) }} |
48 | </div> | 92 | </div> |
49 | </fieldset> | 93 | </fieldset> |
50 | 94 | ||
51 | <fieldset class="w500p inline"> | 95 | <fieldset class="w500p inline"> |
52 | <div class="row"> | 96 | <div class="row"> |
53 | {{ form_label(userForm.name) }} | 97 | {{ form_label(form.user.name) }} |
54 | {{ form_errors(userForm.name) }} | 98 | {{ form_errors(form.user.name) }} |
55 | {{ form_widget(userForm.name) }} | 99 | {{ form_widget(form.user.name) }} |
56 | </div> | 100 | </div> |
57 | </fieldset> | 101 | </fieldset> |
58 | 102 | ||
59 | <fieldset class="w500p inline"> | 103 | <fieldset class="w500p inline"> |
60 | <div class="row"> | 104 | <div class="row"> |
61 | {{ form_label(userForm.email) }} | 105 | {{ form_label(form.user.email) }} |
62 | {{ form_errors(userForm.email) }} | 106 | {{ form_errors(form.user.email) }} |
63 | {{ form_widget(userForm.email) }} | 107 | {{ form_widget(form.user.email) }} |
64 | </div> | 108 | </div> |
65 | </fieldset> | 109 | </fieldset> |
66 | 110 | ||
67 | {{ form_rest(userForm) }} | 111 | {{ form_rest(form.user) }} |
68 | </form> | 112 | </form> |
69 | 113 | ||
70 | <h2>{% trans %}Change your password{% endtrans %}</h2> | 114 | <h2>{% trans %}Change your password{% endtrans %}</h2> |
71 | 115 | ||
72 | <form action="{{ path('config') }}" method="post" {{ form_enctype(pwdForm) }}> | 116 | <form action="{{ path('config') }}" method="post" {{ form_enctype(form.pwd) }}> |
73 | {{ form_errors(pwdForm) }} | 117 | {{ form_errors(form.pwd) }} |
74 | 118 | ||
75 | <fieldset class="w500p inline"> | 119 | <fieldset class="w500p inline"> |
76 | <div class="row"> | 120 | <div class="row"> |
77 | {{ form_label(pwdForm.old_password) }} | 121 | {{ form_label(form.pwd.old_password) }} |
78 | {{ form_errors(pwdForm.old_password) }} | 122 | {{ form_errors(form.pwd.old_password) }} |
79 | {{ form_widget(pwdForm.old_password) }} | 123 | {{ form_widget(form.pwd.old_password) }} |
80 | </div> | 124 | </div> |
81 | </fieldset> | 125 | </fieldset> |
82 | 126 | ||
83 | <fieldset class="w500p inline"> | 127 | <fieldset class="w500p inline"> |
84 | <div class="row"> | 128 | <div class="row"> |
85 | {{ form_label(pwdForm.new_password.first) }} | 129 | {{ form_label(form.pwd.new_password.first) }} |
86 | {{ form_errors(pwdForm.new_password.first) }} | 130 | {{ form_errors(form.pwd.new_password.first) }} |
87 | {{ form_widget(pwdForm.new_password.first) }} | 131 | {{ form_widget(form.pwd.new_password.first) }} |
88 | </div> | 132 | </div> |
89 | </fieldset> | 133 | </fieldset> |
90 | 134 | ||
91 | <fieldset class="w500p inline"> | 135 | <fieldset class="w500p inline"> |
92 | <div class="row"> | 136 | <div class="row"> |
93 | {{ form_label(pwdForm.new_password.second) }} | 137 | {{ form_label(form.pwd.new_password.second) }} |
94 | {{ form_errors(pwdForm.new_password.second) }} | 138 | {{ form_errors(form.pwd.new_password.second) }} |
95 | {{ form_widget(pwdForm.new_password.second) }} | 139 | {{ form_widget(form.pwd.new_password.second) }} |
96 | </div> | 140 | </div> |
97 | </fieldset> | 141 | </fieldset> |
98 | 142 | ||
99 | {{ form_rest(pwdForm) }} | 143 | {{ form_rest(form.pwd) }} |
100 | </form> | 144 | </form> |
101 | 145 | ||
102 | <h2>{% trans %}Add a user{% endtrans %}</h2> | 146 | <h2>{% trans %}Add a user{% endtrans %}</h2> |
103 | 147 | ||
104 | <form action="{{ path('config') }}" method="post" {{ form_enctype(newUserForm) }}> | 148 | <form action="{{ path('config') }}" method="post" {{ form_enctype(form.new_user) }}> |
105 | {{ form_errors(newUserForm) }} | 149 | {{ form_errors(form.new_user) }} |
106 | 150 | ||
107 | <fieldset class="w500p inline"> | 151 | <fieldset class="w500p inline"> |
108 | <div class="row"> | 152 | <div class="row"> |
109 | {{ form_label(newUserForm.username) }} | 153 | {{ form_label(form.new_user.username) }} |
110 | {{ form_errors(newUserForm.username) }} | 154 | {{ form_errors(form.new_user.username) }} |
111 | {{ form_widget(newUserForm.username) }} | 155 | {{ form_widget(form.new_user.username) }} |
112 | </div> | 156 | </div> |
113 | </fieldset> | 157 | </fieldset> |
114 | 158 | ||
115 | <fieldset class="w500p inline"> | 159 | <fieldset class="w500p inline"> |
116 | <div class="row"> | 160 | <div class="row"> |
117 | {{ form_label(newUserForm.password) }} | 161 | {{ form_label(form.new_user.password) }} |
118 | {{ form_errors(newUserForm.password) }} | 162 | {{ form_errors(form.new_user.password) }} |
119 | {{ form_widget(newUserForm.password) }} | 163 | {{ form_widget(form.new_user.password) }} |
120 | </div> | 164 | </div> |
121 | </fieldset> | 165 | </fieldset> |
122 | 166 | ||
123 | <fieldset class="w500p inline"> | 167 | <fieldset class="w500p inline"> |
124 | <div class="row"> | 168 | <div class="row"> |
125 | {{ form_label(newUserForm.email) }} | 169 | {{ form_label(form.new_user.email) }} |
126 | {{ form_errors(newUserForm.email) }} | 170 | {{ form_errors(form.new_user.email) }} |
127 | {{ form_widget(newUserForm.email) }} | 171 | {{ form_widget(form.new_user.email) }} |
128 | </div> | 172 | </div> |
129 | </fieldset> | 173 | </fieldset> |
130 | 174 | ||
131 | {{ form_rest(newUserForm) }} | 175 | {{ form_rest(form.new_user) }} |
132 | </form> | 176 | </form> |
133 | {% endblock %} | 177 | {% 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..5ec9bc03 --- /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 %} < 1 min | ||
24 | {%- endif %} | ||
25 | |||
26 | {{ entry.content|raw -}} | ||
27 | ]]> | ||
28 | </description> | ||
29 | </item> | ||
30 | |||
31 | {% endfor %} | ||
32 | |||
33 | </channel> | ||
34 | </rss> | ||
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/baggy/public/css/main.css b/src/Wallabag/CoreBundle/Resources/views/themes/baggy/public/css/main.css index 1df82910..ff1a36a1 100755 --- a/src/Wallabag/CoreBundle/Resources/views/themes/baggy/public/css/main.css +++ b/src/Wallabag/CoreBundle/Resources/views/themes/baggy/public/css/main.css | |||
@@ -7,7 +7,7 @@ | |||
7 | 4 = Messages | 7 | 4 = Messages |
8 | 5 = Article | 8 | 5 = Article |
9 | 6 = Media queries | 9 | 6 = Media queries |
10 | 10 | ||
11 | ========================================================================== */ | 11 | ========================================================================== */ |
12 | 12 | ||
13 | html { | 13 | html { |
@@ -42,17 +42,17 @@ body { | |||
42 | position: absolute; | 42 | position: absolute; |
43 | top: 2em; | 43 | top: 2em; |
44 | left: 50%; | 44 | left: 50%; |
45 | margin-left: -55px; | 45 | margin-left: -55px; |
46 | } | 46 | } |
47 | 47 | ||
48 | /* ========================================================================== | 48 | /* ========================================================================== |
49 | 1 = Style Guide | 49 | 1 = Style Guide |
50 | ========================================================================== */ | 50 | ========================================================================== */ |
51 | 51 | ||
52 | ::selection { | 52 | ::selection { |
53 | color: #FFF; | 53 | color: #FFF; |
54 | background-color: #000; | 54 | background-color: #000; |
55 | } | 55 | } |
56 | 56 | ||
57 | .desktopHide { | 57 | .desktopHide { |
58 | display: none; | 58 | display: none; |
@@ -62,7 +62,7 @@ body { | |||
62 | position: fixed; | 62 | position: fixed; |
63 | z-index: 20; | 63 | z-index: 20; |
64 | top: 0.4em; | 64 | top: 0.4em; |
65 | left: 0.6em; | 65 | left: 0.6em; |
66 | } | 66 | } |
67 | 67 | ||
68 | h2, h3, h4 { | 68 | h2, h3, h4 { |
@@ -89,7 +89,7 @@ form fieldset { | |||
89 | margin: 0; | 89 | margin: 0; |
90 | } | 90 | } |
91 | 91 | ||
92 | form input[type="text"], select, form input[type="password"], form input[type="url"], form input[type="email"] { | 92 | form input[type="text"], form input[type="number"], select, form input[type="password"], form input[type="url"], form input[type="email"] { |
93 | border: 1px solid #999; | 93 | border: 1px solid #999; |
94 | padding: 0.5em 1em; | 94 | padding: 0.5em 1em; |
95 | min-width: 12em; | 95 | min-width: 12em; |
@@ -149,7 +149,7 @@ form button, input[type="submit"] { | |||
149 | 149 | ||
150 | #bookmarklet { | 150 | #bookmarklet { |
151 | cursor: move; | 151 | cursor: move; |
152 | } | 152 | } |
153 | 153 | ||
154 | h2:after { | 154 | h2:after { |
155 | content: ""; | 155 | content: ""; |
@@ -296,7 +296,7 @@ h2:after { | |||
296 | /* ========================================================================== | 296 | /* ========================================================================== |
297 | 2 = Layout | 297 | 2 = Layout |
298 | ========================================================================== */ | 298 | ========================================================================== */ |
299 | 299 | ||
300 | #content { | 300 | #content { |
301 | margin-top: 5em; | 301 | margin-top: 5em; |
302 | min-height: 30em; | 302 | min-height: 30em; |
@@ -653,7 +653,7 @@ a.add-to-wallabag-link-after:after { | |||
653 | /* ========================================================================== | 653 | /* ========================================================================== |
654 | 3 = Pictos | 654 | 3 = Pictos |
655 | ========================================================================== */ | 655 | ========================================================================== */ |
656 | 656 | ||
657 | @font-face { | 657 | @font-face { |
658 | font-family: 'icomoon'; | 658 | font-family: 'icomoon'; |
659 | src:url('../fonts/icomoon.eot?-s0mcsx'); | 659 | src:url('../fonts/icomoon.eot?-s0mcsx'); |
@@ -866,7 +866,7 @@ blockquote { | |||
866 | color: #FFF; | 866 | color: #FFF; |
867 | text-decoration: none; | 867 | text-decoration: none; |
868 | } | 868 | } |
869 | 869 | ||
870 | #article_toolbar a:hover, #article_toolbar a:focus { | 870 | #article_toolbar a:hover, #article_toolbar a:focus { |
871 | background-color: #999; | 871 | background-color: #999; |
872 | } | 872 | } |
@@ -1052,7 +1052,7 @@ pre code { | |||
1052 | #article_toolbar a { | 1052 | #article_toolbar a { |
1053 | padding: 0.3em 0.4em 0.2em; | 1053 | padding: 0.3em 0.4em 0.2em; |
1054 | } | 1054 | } |
1055 | 1055 | ||
1056 | #display-mode { | 1056 | #display-mode { |
1057 | display: none; | 1057 | display: none; |
1058 | } | 1058 | } |
diff --git a/src/Wallabag/CoreBundle/Tests/Command/InstallCommandTest.php b/src/Wallabag/CoreBundle/Tests/Command/InstallCommandTest.php index 64f6c329..f689b532 100644 --- a/src/Wallabag/CoreBundle/Tests/Command/InstallCommandTest.php +++ b/src/Wallabag/CoreBundle/Tests/Command/InstallCommandTest.php | |||
@@ -4,6 +4,7 @@ namespace Wallabag\CoreBundle\Tests\Command; | |||
4 | 4 | ||
5 | use Wallabag\CoreBundle\Tests\WallabagTestCase; | 5 | use Wallabag\CoreBundle\Tests\WallabagTestCase; |
6 | use Wallabag\CoreBundle\Command\InstallCommand; | 6 | use Wallabag\CoreBundle\Command\InstallCommand; |
7 | use Wallabag\CoreBundle\Tests\Mock\InstallCommandMock; | ||
7 | use Symfony\Bundle\FrameworkBundle\Console\Application; | 8 | use Symfony\Bundle\FrameworkBundle\Console\Application; |
8 | use Symfony\Component\Console\Tester\CommandTester; | 9 | use Symfony\Component\Console\Tester\CommandTester; |
9 | use Symfony\Component\Console\Input\ArrayInput; | 10 | use Symfony\Component\Console\Input\ArrayInput; |
@@ -30,7 +31,7 @@ class InstallCommandTest extends WallabagTestCase | |||
30 | $this->container = static::$kernel->getContainer(); | 31 | $this->container = static::$kernel->getContainer(); |
31 | 32 | ||
32 | $application = new Application(static::$kernel); | 33 | $application = new Application(static::$kernel); |
33 | $application->add(new InstallCommand()); | 34 | $application->add(new InstallCommandMock()); |
34 | 35 | ||
35 | $command = $application->find('wallabag:install'); | 36 | $command = $application->find('wallabag:install'); |
36 | 37 | ||
@@ -64,7 +65,7 @@ class InstallCommandTest extends WallabagTestCase | |||
64 | $this->container = static::$kernel->getContainer(); | 65 | $this->container = static::$kernel->getContainer(); |
65 | 66 | ||
66 | $application = new Application(static::$kernel); | 67 | $application = new Application(static::$kernel); |
67 | $application->add(new InstallCommand()); | 68 | $application->add(new InstallCommandMock()); |
68 | 69 | ||
69 | $command = $application->find('wallabag:install'); | 70 | $command = $application->find('wallabag:install'); |
70 | 71 | ||
@@ -97,6 +98,9 @@ class InstallCommandTest extends WallabagTestCase | |||
97 | $this->assertContains('Droping database, creating database and schema', $tester->getDisplay()); | 98 | $this->assertContains('Droping database, creating database and schema', $tester->getDisplay()); |
98 | } | 99 | } |
99 | 100 | ||
101 | /** | ||
102 | * @group command-doctrine | ||
103 | */ | ||
100 | public function testRunInstallCommandWithDatabaseRemoved() | 104 | public function testRunInstallCommandWithDatabaseRemoved() |
101 | { | 105 | { |
102 | $this->container = static::$kernel->getContainer(); | 106 | $this->container = static::$kernel->getContainer(); |
@@ -148,7 +152,7 @@ class InstallCommandTest extends WallabagTestCase | |||
148 | $this->container = static::$kernel->getContainer(); | 152 | $this->container = static::$kernel->getContainer(); |
149 | 153 | ||
150 | $application = new Application(static::$kernel); | 154 | $application = new Application(static::$kernel); |
151 | $application->add(new InstallCommand()); | 155 | $application->add(new InstallCommandMock()); |
152 | 156 | ||
153 | $command = $application->find('wallabag:install'); | 157 | $command = $application->find('wallabag:install'); |
154 | 158 | ||
@@ -181,6 +185,9 @@ class InstallCommandTest extends WallabagTestCase | |||
181 | $this->assertContains('Droping schema and creating schema', $tester->getDisplay()); | 185 | $this->assertContains('Droping schema and creating schema', $tester->getDisplay()); |
182 | } | 186 | } |
183 | 187 | ||
188 | /** | ||
189 | * @group command-doctrine | ||
190 | */ | ||
184 | public function testRunInstallCommandChooseNothing() | 191 | public function testRunInstallCommandChooseNothing() |
185 | { | 192 | { |
186 | $this->container = static::$kernel->getContainer(); | 193 | $this->container = static::$kernel->getContainer(); |
@@ -242,7 +249,7 @@ class InstallCommandTest extends WallabagTestCase | |||
242 | $this->container = static::$kernel->getContainer(); | 249 | $this->container = static::$kernel->getContainer(); |
243 | 250 | ||
244 | $application = new Application(static::$kernel); | 251 | $application = new Application(static::$kernel); |
245 | $application->add(new InstallCommand()); | 252 | $application->add(new InstallCommandMock()); |
246 | 253 | ||
247 | $command = $application->find('wallabag:install'); | 254 | $command = $application->find('wallabag:install'); |
248 | 255 | ||
diff --git a/src/Wallabag/CoreBundle/Tests/Controller/ConfigControllerTest.php b/src/Wallabag/CoreBundle/Tests/Controller/ConfigControllerTest.php index d7d341aa..11c86423 100644 --- a/src/Wallabag/CoreBundle/Tests/Controller/ConfigControllerTest.php +++ b/src/Wallabag/CoreBundle/Tests/Controller/ConfigControllerTest.php | |||
@@ -28,6 +28,8 @@ class ConfigControllerTest extends WallabagTestCase | |||
28 | $this->assertCount(1, $crawler->filter('button[id=config_save]')); | 28 | $this->assertCount(1, $crawler->filter('button[id=config_save]')); |
29 | $this->assertCount(1, $crawler->filter('button[id=change_passwd_save]')); | 29 | $this->assertCount(1, $crawler->filter('button[id=change_passwd_save]')); |
30 | $this->assertCount(1, $crawler->filter('button[id=user_save]')); | 30 | $this->assertCount(1, $crawler->filter('button[id=user_save]')); |
31 | $this->assertCount(1, $crawler->filter('button[id=new_user_save]')); | ||
32 | $this->assertCount(1, $crawler->filter('button[id=rss_config_save]')); | ||
31 | } | 33 | } |
32 | 34 | ||
33 | public function testUpdate() | 35 | public function testUpdate() |
@@ -347,4 +349,128 @@ class ConfigControllerTest extends WallabagTestCase | |||
347 | $this->assertGreaterThan(1, $alert = $crawler->filter('div.messages.success')->extract(array('_text'))); | 349 | $this->assertGreaterThan(1, $alert = $crawler->filter('div.messages.success')->extract(array('_text'))); |
348 | $this->assertContains('User "wallace" added', $alert[0]); | 350 | $this->assertContains('User "wallace" added', $alert[0]); |
349 | } | 351 | } |
352 | |||
353 | public function testRssUpdateResetToken() | ||
354 | { | ||
355 | $this->logInAs('admin'); | ||
356 | $client = $this->getClient(); | ||
357 | |||
358 | // reset the token | ||
359 | $em = $client->getContainer()->get('doctrine.orm.entity_manager'); | ||
360 | $user = $em | ||
361 | ->getRepository('WallabagCoreBundle:User') | ||
362 | ->findOneByUsername('admin'); | ||
363 | |||
364 | if (!$user) { | ||
365 | $this->markTestSkipped('No user found in db.'); | ||
366 | } | ||
367 | |||
368 | $config = $user->getConfig(); | ||
369 | $config->setRssToken(null); | ||
370 | $em->persist($config); | ||
371 | $em->flush(); | ||
372 | |||
373 | $crawler = $client->request('GET', '/config'); | ||
374 | |||
375 | $this->assertEquals(200, $client->getResponse()->getStatusCode()); | ||
376 | |||
377 | $this->assertGreaterThan(1, $body = $crawler->filter('body')->extract(array('_text'))); | ||
378 | $this->assertContains('You need to generate a token first.', $body[0]); | ||
379 | |||
380 | $client->request('GET', '/generate-token'); | ||
381 | $this->assertEquals(302, $client->getResponse()->getStatusCode()); | ||
382 | |||
383 | $crawler = $client->followRedirect(); | ||
384 | |||
385 | $this->assertGreaterThan(1, $body = $crawler->filter('body')->extract(array('_text'))); | ||
386 | $this->assertNotContains('You need to generate a token first.', $body[0]); | ||
387 | } | ||
388 | |||
389 | public function testGenerateTokenAjax() | ||
390 | { | ||
391 | $this->logInAs('admin'); | ||
392 | $client = $this->getClient(); | ||
393 | |||
394 | $client->request( | ||
395 | 'GET', | ||
396 | '/generate-token', | ||
397 | array(), | ||
398 | array(), | ||
399 | array('HTTP_X-Requested-With' => 'XMLHttpRequest') | ||
400 | ); | ||
401 | |||
402 | $this->assertEquals(200, $client->getResponse()->getStatusCode()); | ||
403 | $content = json_decode($client->getResponse()->getContent(), true);; | ||
404 | $this->assertArrayHasKey('token', $content); | ||
405 | } | ||
406 | |||
407 | public function testRssUpdate() | ||
408 | { | ||
409 | $this->logInAs('admin'); | ||
410 | $client = $this->getClient(); | ||
411 | |||
412 | $crawler = $client->request('GET', '/config'); | ||
413 | |||
414 | if (500 == $client->getResponse()->getStatusCode()) { | ||
415 | var_export($client->getResponse()->getContent()); | ||
416 | die(); | ||
417 | } | ||
418 | |||
419 | $this->assertEquals(200, $client->getResponse()->getStatusCode()); | ||
420 | |||
421 | $form = $crawler->filter('button[id=rss_config_save]')->form(); | ||
422 | |||
423 | $data = array( | ||
424 | 'rss_config[rss_limit]' => 12, | ||
425 | ); | ||
426 | |||
427 | $client->submit($form, $data); | ||
428 | |||
429 | $this->assertEquals(302, $client->getResponse()->getStatusCode()); | ||
430 | |||
431 | $crawler = $client->followRedirect(); | ||
432 | |||
433 | $this->assertGreaterThan(1, $alert = $crawler->filter('div.messages.success')->extract(array('_text'))); | ||
434 | $this->assertContains('RSS information updated', $alert[0]); | ||
435 | } | ||
436 | |||
437 | public function dataForRssFailed() | ||
438 | { | ||
439 | return array( | ||
440 | array( | ||
441 | array( | ||
442 | 'rss_config[rss_limit]' => 0, | ||
443 | ), | ||
444 | 'This value should be 1 or more.', | ||
445 | ), | ||
446 | array( | ||
447 | array( | ||
448 | 'rss_config[rss_limit]' => 1000000000000, | ||
449 | ), | ||
450 | 'This will certainly kill the app', | ||
451 | ), | ||
452 | ); | ||
453 | } | ||
454 | |||
455 | /** | ||
456 | * @dataProvider dataForRssFailed | ||
457 | */ | ||
458 | public function testRssFailed($data, $expectedMessage) | ||
459 | { | ||
460 | $this->logInAs('admin'); | ||
461 | $client = $this->getClient(); | ||
462 | |||
463 | $crawler = $client->request('GET', '/config'); | ||
464 | |||
465 | $this->assertEquals(200, $client->getResponse()->getStatusCode()); | ||
466 | |||
467 | $form = $crawler->filter('button[id=rss_config_save]')->form(); | ||
468 | |||
469 | $crawler = $client->submit($form, $data); | ||
470 | |||
471 | $this->assertEquals(200, $client->getResponse()->getStatusCode()); | ||
472 | |||
473 | $this->assertGreaterThan(1, $alert = $crawler->filter('body')->extract(array('_text'))); | ||
474 | $this->assertContains($expectedMessage, $alert[0]); | ||
475 | } | ||
350 | } | 476 | } |
diff --git a/src/Wallabag/CoreBundle/Tests/Controller/EntryControllerTest.php b/src/Wallabag/CoreBundle/Tests/Controller/EntryControllerTest.php index 99a3a945..1a0d586c 100644 --- a/src/Wallabag/CoreBundle/Tests/Controller/EntryControllerTest.php +++ b/src/Wallabag/CoreBundle/Tests/Controller/EntryControllerTest.php | |||
@@ -60,7 +60,7 @@ class EntryControllerTest extends WallabagTestCase | |||
60 | $form = $crawler->filter('button[type=submit]')->form(); | 60 | $form = $crawler->filter('button[type=submit]')->form(); |
61 | 61 | ||
62 | $data = array( | 62 | $data = array( |
63 | 'entry[url]' => 'https://www.mailjet.com/blog/mailjet-zapier-integrations-made-easy/', | 63 | 'entry[url]' => 'http://www.lemonde.fr/pixels/article/2015/03/28/plongee-dans-l-univers-d-ingress-le-jeu-de-google-aux-frontieres-du-reel_4601155_4408996.html', |
64 | ); | 64 | ); |
65 | 65 | ||
66 | $client->submit($form, $data); | 66 | $client->submit($form, $data); |
@@ -70,7 +70,7 @@ class EntryControllerTest extends WallabagTestCase | |||
70 | $crawler = $client->followRedirect(); | 70 | $crawler = $client->followRedirect(); |
71 | 71 | ||
72 | $this->assertGreaterThan(1, $alert = $crawler->filter('h2 a')->extract(array('_text'))); | 72 | $this->assertGreaterThan(1, $alert = $crawler->filter('h2 a')->extract(array('_text'))); |
73 | $this->assertContains('Mailjet', $alert[0]); | 73 | $this->assertContains('Google', $alert[0]); |
74 | } | 74 | } |
75 | 75 | ||
76 | public function testArchive() | 76 | public function testArchive() |
diff --git a/src/Wallabag/CoreBundle/Tests/Controller/RssControllerTest.php b/src/Wallabag/CoreBundle/Tests/Controller/RssControllerTest.php new file mode 100644 index 00000000..8f627b4b --- /dev/null +++ b/src/Wallabag/CoreBundle/Tests/Controller/RssControllerTest.php | |||
@@ -0,0 +1,126 @@ | |||
1 | <?php | ||
2 | |||
3 | namespace Wallabag\CoreBundle\Tests\Controller; | ||
4 | |||
5 | use Wallabag\CoreBundle\Tests\WallabagTestCase; | ||
6 | |||
7 | class RssControllerTest extends WallabagTestCase | ||
8 | { | ||
9 | public function validateDom($xml, $nb = null) | ||
10 | { | ||
11 | $doc = new \DOMDocument(); | ||
12 | $doc->loadXML($xml); | ||
13 | |||
14 | $xpath = new \DOMXpath($doc); | ||
15 | |||
16 | if (null === $nb) { | ||
17 | $this->assertGreaterThan(0, $xpath->query('//item')->length); | ||
18 | } else { | ||
19 | $this->assertEquals($nb, $xpath->query('//item')->length); | ||
20 | } | ||
21 | |||
22 | $this->assertEquals(1, $xpath->query('/rss')->length); | ||
23 | $this->assertEquals(1, $xpath->query('/rss/channel')->length); | ||
24 | |||
25 | foreach ($xpath->query('//item') as $item) { | ||
26 | $this->assertEquals(1, $xpath->query('title', $item)->length); | ||
27 | $this->assertEquals(1, $xpath->query('source', $item)->length); | ||
28 | $this->assertEquals(1, $xpath->query('link', $item)->length); | ||
29 | $this->assertEquals(1, $xpath->query('guid', $item)->length); | ||
30 | $this->assertEquals(1, $xpath->query('pubDate', $item)->length); | ||
31 | $this->assertEquals(1, $xpath->query('description', $item)->length); | ||
32 | } | ||
33 | } | ||
34 | |||
35 | public function dataForBadUrl() | ||
36 | { | ||
37 | return array( | ||
38 | array( | ||
39 | '/admin/YZIOAUZIAO/unread.xml' | ||
40 | ), | ||
41 | array( | ||
42 | '/wallace/YZIOAUZIAO/starred.xml' | ||
43 | ), | ||
44 | array( | ||
45 | '/wallace/YZIOAUZIAO/archives.xml' | ||
46 | ), | ||
47 | ); | ||
48 | } | ||
49 | |||
50 | /** | ||
51 | * @dataProvider dataForBadUrl | ||
52 | */ | ||
53 | public function testBadUrl($url) | ||
54 | { | ||
55 | $client = $this->getClient(); | ||
56 | |||
57 | $client->request('GET', $url); | ||
58 | |||
59 | $this->assertEquals(404, $client->getResponse()->getStatusCode()); | ||
60 | } | ||
61 | |||
62 | public function testUnread() | ||
63 | { | ||
64 | $client = $this->getClient(); | ||
65 | $em = $client->getContainer()->get('doctrine.orm.entity_manager'); | ||
66 | $user = $em | ||
67 | ->getRepository('WallabagCoreBundle:User') | ||
68 | ->findOneByUsername('admin'); | ||
69 | |||
70 | $config = $user->getConfig(); | ||
71 | $config->setRssToken('SUPERTOKEN'); | ||
72 | $config->setRssLimit(2); | ||
73 | $em->persist($config); | ||
74 | $em->flush(); | ||
75 | |||
76 | $client->request('GET', '/admin/SUPERTOKEN/unread.xml'); | ||
77 | |||
78 | $this->assertEquals(200, $client->getResponse()->getStatusCode()); | ||
79 | |||
80 | $this->validateDom($client->getResponse()->getContent(), 2); | ||
81 | } | ||
82 | |||
83 | public function testStarred() | ||
84 | { | ||
85 | $client = $this->getClient(); | ||
86 | $em = $client->getContainer()->get('doctrine.orm.entity_manager'); | ||
87 | $user = $em | ||
88 | ->getRepository('WallabagCoreBundle:User') | ||
89 | ->findOneByUsername('admin'); | ||
90 | |||
91 | $config = $user->getConfig(); | ||
92 | $config->setRssToken('SUPERTOKEN'); | ||
93 | $config->setRssLimit(1); | ||
94 | $em->persist($config); | ||
95 | $em->flush(); | ||
96 | |||
97 | $client = $this->getClient(); | ||
98 | $client->request('GET', '/admin/SUPERTOKEN/starred.xml'); | ||
99 | |||
100 | $this->assertEquals(200, $client->getResponse()->getStatusCode(), 1); | ||
101 | |||
102 | $this->validateDom($client->getResponse()->getContent()); | ||
103 | } | ||
104 | |||
105 | public function testArchives() | ||
106 | { | ||
107 | $client = $this->getClient(); | ||
108 | $em = $client->getContainer()->get('doctrine.orm.entity_manager'); | ||
109 | $user = $em | ||
110 | ->getRepository('WallabagCoreBundle:User') | ||
111 | ->findOneByUsername('admin'); | ||
112 | |||
113 | $config = $user->getConfig(); | ||
114 | $config->setRssToken('SUPERTOKEN'); | ||
115 | $config->setRssLimit(null); | ||
116 | $em->persist($config); | ||
117 | $em->flush(); | ||
118 | |||
119 | $client = $this->getClient(); | ||
120 | $client->request('GET', '/admin/SUPERTOKEN/archive.xml'); | ||
121 | |||
122 | $this->assertEquals(200, $client->getResponse()->getStatusCode()); | ||
123 | |||
124 | $this->validateDom($client->getResponse()->getContent()); | ||
125 | } | ||
126 | } | ||
diff --git a/src/Wallabag/CoreBundle/Tests/Controller/WallabagRestControllerTest.php b/src/Wallabag/CoreBundle/Tests/Controller/WallabagRestControllerTest.php index 0eca7cde..c9907065 100644 --- a/src/Wallabag/CoreBundle/Tests/Controller/WallabagRestControllerTest.php +++ b/src/Wallabag/CoreBundle/Tests/Controller/WallabagRestControllerTest.php | |||
@@ -105,7 +105,7 @@ class WallabagRestControllerTest extends WallabagTestCase | |||
105 | 105 | ||
106 | $this->assertGreaterThanOrEqual(1, count(json_decode($client->getResponse()->getContent()))); | 106 | $this->assertGreaterThanOrEqual(1, count(json_decode($client->getResponse()->getContent()))); |
107 | 107 | ||
108 | $this->assertContains('Mailjet', $client->getResponse()->getContent()); | 108 | $this->assertContains('Google', $client->getResponse()->getContent()); |
109 | 109 | ||
110 | $this->assertTrue( | 110 | $this->assertTrue( |
111 | $client->getResponse()->headers->contains( | 111 | $client->getResponse()->headers->contains( |
diff --git a/src/Wallabag/CoreBundle/Tests/Mock/InstallCommandMock.php b/src/Wallabag/CoreBundle/Tests/Mock/InstallCommandMock.php new file mode 100644 index 00000000..69bc48e0 --- /dev/null +++ b/src/Wallabag/CoreBundle/Tests/Mock/InstallCommandMock.php | |||
@@ -0,0 +1,22 @@ | |||
1 | <?php | ||
2 | |||
3 | namespace Wallabag\CoreBundle\Tests\Mock; | ||
4 | |||
5 | use Wallabag\CoreBundle\Command\InstallCommand; | ||
6 | |||
7 | /** | ||
8 | * This mock aims to speed the test of InstallCommand by avoid calling external command | ||
9 | * like all doctrine commands. | ||
10 | * | ||
11 | * This speed the test but as a downside, it doesn't allow to fully test the InstallCommand | ||
12 | * | ||
13 | * Launching tests to avoid doctrine command: | ||
14 | * phpunit --exclude-group command-doctrine | ||
15 | */ | ||
16 | class InstallCommandMock extends InstallCommand | ||
17 | { | ||
18 | protected function runCommand($command, $parameters = array()) | ||
19 | { | ||
20 | return $this; | ||
21 | } | ||
22 | } | ||
diff --git a/src/Wallabag/CoreBundle/Tests/ParamConverter/UsernameRssTokenConverterTest.php b/src/Wallabag/CoreBundle/Tests/ParamConverter/UsernameRssTokenConverterTest.php new file mode 100644 index 00000000..ebb550b5 --- /dev/null +++ b/src/Wallabag/CoreBundle/Tests/ParamConverter/UsernameRssTokenConverterTest.php | |||
@@ -0,0 +1,220 @@ | |||
1 | <?php | ||
2 | |||
3 | namespace Wallabag\CoreBundle\Tests\Command; | ||
4 | |||
5 | use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; | ||
6 | use Wallabag\CoreBundle\ParamConverter\UsernameRssTokenConverter; | ||
7 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter; | ||
8 | use Symfony\Component\HttpFoundation\Request; | ||
9 | use Wallabag\CoreBundle\Entity\User; | ||
10 | |||
11 | class UsernameRssTokenConverterTest extends KernelTestCase | ||
12 | { | ||
13 | public function testSupportsWithNoRegistry() | ||
14 | { | ||
15 | $params = new ParamConverter(array()); | ||
16 | $converter = new UsernameRssTokenConverter(); | ||
17 | |||
18 | $this->assertFalse($converter->supports($params)); | ||
19 | } | ||
20 | |||
21 | public function testSupportsWithNoRegistryManagers() | ||
22 | { | ||
23 | $registry = $this->getMockBuilder('Doctrine\Common\Persistence\ManagerRegistry') | ||
24 | ->disableOriginalConstructor() | ||
25 | ->getMock(); | ||
26 | |||
27 | $registry->expects($this->once()) | ||
28 | ->method('getManagers') | ||
29 | ->will($this->returnValue(array())); | ||
30 | |||
31 | $params = new ParamConverter(array()); | ||
32 | $converter = new UsernameRssTokenConverter($registry); | ||
33 | |||
34 | $this->assertFalse($converter->supports($params)); | ||
35 | } | ||
36 | |||
37 | public function testSupportsWithNoConfigurationClass() | ||
38 | { | ||
39 | $registry = $this->getMockBuilder('Doctrine\Common\Persistence\ManagerRegistry') | ||
40 | ->disableOriginalConstructor() | ||
41 | ->getMock(); | ||
42 | |||
43 | $registry->expects($this->once()) | ||
44 | ->method('getManagers') | ||
45 | ->will($this->returnValue(array('default' => null))); | ||
46 | |||
47 | $params = new ParamConverter(array()); | ||
48 | $converter = new UsernameRssTokenConverter($registry); | ||
49 | |||
50 | $this->assertFalse($converter->supports($params)); | ||
51 | } | ||
52 | |||
53 | public function testSupportsWithNotTheGoodClass() | ||
54 | { | ||
55 | $meta = $this->getMockBuilder('Doctrine\Common\Persistence\Mapping\ClassMetadata') | ||
56 | ->disableOriginalConstructor() | ||
57 | ->getMock(); | ||
58 | |||
59 | $meta->expects($this->once()) | ||
60 | ->method('getName') | ||
61 | ->will($this->returnValue('nothingrelated')); | ||
62 | |||
63 | $em = $this->getMockBuilder('Doctrine\Common\Persistence\ObjectManager') | ||
64 | ->disableOriginalConstructor() | ||
65 | ->getMock(); | ||
66 | |||
67 | $em->expects($this->once()) | ||
68 | ->method('getClassMetadata') | ||
69 | ->with('superclass') | ||
70 | ->will($this->returnValue($meta)); | ||
71 | |||
72 | $registry = $this->getMockBuilder('Doctrine\Common\Persistence\ManagerRegistry') | ||
73 | ->disableOriginalConstructor() | ||
74 | ->getMock(); | ||
75 | |||
76 | $registry->expects($this->once()) | ||
77 | ->method('getManagers') | ||
78 | ->will($this->returnValue(array('default' => null))); | ||
79 | |||
80 | $registry->expects($this->once()) | ||
81 | ->method('getManagerForClass') | ||
82 | ->with('superclass') | ||
83 | ->will($this->returnValue($em)); | ||
84 | |||
85 | $params = new ParamConverter(array('class' => 'superclass')); | ||
86 | $converter = new UsernameRssTokenConverter($registry); | ||
87 | |||
88 | $this->assertFalse($converter->supports($params)); | ||
89 | } | ||
90 | |||
91 | public function testSupportsWithGoodClass() | ||
92 | { | ||
93 | $meta = $this->getMockBuilder('Doctrine\Common\Persistence\Mapping\ClassMetadata') | ||
94 | ->disableOriginalConstructor() | ||
95 | ->getMock(); | ||
96 | |||
97 | $meta->expects($this->once()) | ||
98 | ->method('getName') | ||
99 | ->will($this->returnValue('Wallabag\CoreBundle\Entity\User')); | ||
100 | |||
101 | $em = $this->getMockBuilder('Doctrine\Common\Persistence\ObjectManager') | ||
102 | ->disableOriginalConstructor() | ||
103 | ->getMock(); | ||
104 | |||
105 | $em->expects($this->once()) | ||
106 | ->method('getClassMetadata') | ||
107 | ->with('WallabagCoreBundle:User') | ||
108 | ->will($this->returnValue($meta)); | ||
109 | |||
110 | $registry = $this->getMockBuilder('Doctrine\Common\Persistence\ManagerRegistry') | ||
111 | ->disableOriginalConstructor() | ||
112 | ->getMock(); | ||
113 | |||
114 | $registry->expects($this->once()) | ||
115 | ->method('getManagers') | ||
116 | ->will($this->returnValue(array('default' => null))); | ||
117 | |||
118 | $registry->expects($this->once()) | ||
119 | ->method('getManagerForClass') | ||
120 | ->with('WallabagCoreBundle:User') | ||
121 | ->will($this->returnValue($em)); | ||
122 | |||
123 | $params = new ParamConverter(array('class' => 'WallabagCoreBundle:User')); | ||
124 | $converter = new UsernameRssTokenConverter($registry); | ||
125 | |||
126 | $this->assertTrue($converter->supports($params)); | ||
127 | } | ||
128 | |||
129 | /** | ||
130 | * @expectedException InvalidArgumentException | ||
131 | * @expectedExceptionMessage Route attribute is missing | ||
132 | */ | ||
133 | public function testApplyEmptyRequest() | ||
134 | { | ||
135 | $params = new ParamConverter(array()); | ||
136 | $converter = new UsernameRssTokenConverter(); | ||
137 | |||
138 | $converter->apply(new Request(), $params); | ||
139 | } | ||
140 | |||
141 | /** | ||
142 | * @expectedException Symfony\Component\HttpKernel\Exception\NotFoundHttpException | ||
143 | * @expectedExceptionMessage User not found | ||
144 | */ | ||
145 | public function testApplyUserNotFound() | ||
146 | { | ||
147 | $repo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\UserRepository') | ||
148 | ->disableOriginalConstructor() | ||
149 | ->getMock(); | ||
150 | |||
151 | $repo->expects($this->once()) | ||
152 | ->method('findOneByUsernameAndRsstoken') | ||
153 | ->with('test', 'test') | ||
154 | ->will($this->returnValue(null)); | ||
155 | |||
156 | $em = $this->getMockBuilder('Doctrine\Common\Persistence\ObjectManager') | ||
157 | ->disableOriginalConstructor() | ||
158 | ->getMock(); | ||
159 | |||
160 | $em->expects($this->once()) | ||
161 | ->method('getRepository') | ||
162 | ->with('WallabagCoreBundle:User') | ||
163 | ->will($this->returnValue($repo)); | ||
164 | |||
165 | $registry = $this->getMockBuilder('Doctrine\Common\Persistence\ManagerRegistry') | ||
166 | ->disableOriginalConstructor() | ||
167 | ->getMock(); | ||
168 | |||
169 | $registry->expects($this->once()) | ||
170 | ->method('getManagerForClass') | ||
171 | ->with('WallabagCoreBundle:User') | ||
172 | ->will($this->returnValue($em)); | ||
173 | |||
174 | $params = new ParamConverter(array('class' => 'WallabagCoreBundle:User')); | ||
175 | $converter = new UsernameRssTokenConverter($registry); | ||
176 | $request = new Request(array(), array(), array('username' => 'test', 'token' => 'test')); | ||
177 | |||
178 | $converter->apply($request, $params); | ||
179 | } | ||
180 | |||
181 | public function testApplyUserFound() | ||
182 | { | ||
183 | $user = new User(); | ||
184 | |||
185 | $repo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\UserRepository') | ||
186 | ->disableOriginalConstructor() | ||
187 | ->getMock(); | ||
188 | |||
189 | $repo->expects($this->once()) | ||
190 | ->method('findOneByUsernameAndRsstoken') | ||
191 | ->with('test', 'test') | ||
192 | ->will($this->returnValue($user)); | ||
193 | |||
194 | $em = $this->getMockBuilder('Doctrine\Common\Persistence\ObjectManager') | ||
195 | ->disableOriginalConstructor() | ||
196 | ->getMock(); | ||
197 | |||
198 | $em->expects($this->once()) | ||
199 | ->method('getRepository') | ||
200 | ->with('WallabagCoreBundle:User') | ||
201 | ->will($this->returnValue($repo)); | ||
202 | |||
203 | $registry = $this->getMockBuilder('Doctrine\Common\Persistence\ManagerRegistry') | ||
204 | ->disableOriginalConstructor() | ||
205 | ->getMock(); | ||
206 | |||
207 | $registry->expects($this->once()) | ||
208 | ->method('getManagerForClass') | ||
209 | ->with('WallabagCoreBundle:User') | ||
210 | ->will($this->returnValue($em)); | ||
211 | |||
212 | $params = new ParamConverter(array('class' => 'WallabagCoreBundle:User', 'name' => 'user')); | ||
213 | $converter = new UsernameRssTokenConverter($registry); | ||
214 | $request = new Request(array(), array(), array('username' => 'test', 'token' => 'test')); | ||
215 | |||
216 | $converter->apply($request, $params); | ||
217 | |||
218 | $this->assertEquals($user, $request->attributes->get('user')); | ||
219 | } | ||
220 | } | ||
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 | |||
3 | namespace Wallabag\CoreBundle\Tools; | ||
4 | |||
5 | class 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 | } | ||