diff options
author | Jeremy Benoist <j0k3r@users.noreply.github.com> | 2015-08-12 09:05:21 +0200 |
---|---|---|
committer | Jeremy Benoist <j0k3r@users.noreply.github.com> | 2015-08-12 09:05:21 +0200 |
commit | 930334cd6d486843b536412391a549815efd038e (patch) | |
tree | 485eeecc3bd3db3613d47de25662d5c9163e4afe /src/Wallabag | |
parent | fedaf005377e6d62ff0986f7f54afef3287a6451 (diff) | |
parent | 2686457448372543fdf4f1fc54c4fd20f0f02c2c (diff) | |
download | wallabag-930334cd6d486843b536412391a549815efd038e.tar.gz wallabag-930334cd6d486843b536412391a549815efd038e.tar.zst wallabag-930334cd6d486843b536412391a549815efd038e.zip |
Merge pull request #1297 from wallabag/v2-estimated-time
store estimated reading time in database (#393)
Diffstat (limited to 'src/Wallabag')
14 files changed, 184 insertions, 87 deletions
diff --git a/src/Wallabag/CoreBundle/Controller/EntryController.php b/src/Wallabag/CoreBundle/Controller/EntryController.php index 29e0ffb0..8894690c 100644 --- a/src/Wallabag/CoreBundle/Controller/EntryController.php +++ b/src/Wallabag/CoreBundle/Controller/EntryController.php | |||
@@ -9,6 +9,9 @@ use Wallabag\CoreBundle\Entity\Entry; | |||
9 | use Wallabag\CoreBundle\Service\Extractor; | 9 | use Wallabag\CoreBundle\Service\Extractor; |
10 | use Wallabag\CoreBundle\Form\Type\NewEntryType; | 10 | use Wallabag\CoreBundle\Form\Type\NewEntryType; |
11 | use Wallabag\CoreBundle\Form\Type\EditEntryType; | 11 | use Wallabag\CoreBundle\Form\Type\EditEntryType; |
12 | use Wallabag\CoreBundle\Filter\EntryFilterType; | ||
13 | use Pagerfanta\Adapter\DoctrineORMAdapter; | ||
14 | use Pagerfanta\Pagerfanta; | ||
12 | 15 | ||
13 | class EntryController extends Controller | 16 | class EntryController extends Controller |
14 | { | 17 | { |
@@ -89,22 +92,39 @@ class EntryController extends Controller | |||
89 | /** | 92 | /** |
90 | * Shows unread entries for current user. | 93 | * Shows unread entries for current user. |
91 | * | 94 | * |
95 | * @param Request $request | ||
96 | * @param int $page | ||
97 | * | ||
92 | * @Route("/unread/list/{page}", name="unread", defaults={"page" = "1"}) | 98 | * @Route("/unread/list/{page}", name="unread", defaults={"page" = "1"}) |
93 | * | 99 | * |
94 | * @return \Symfony\Component\HttpFoundation\Response | 100 | * @return \Symfony\Component\HttpFoundation\Response |
95 | */ | 101 | */ |
96 | public function showUnreadAction($page) | 102 | public function showUnreadAction(Request $request, $page) |
97 | { | 103 | { |
98 | $entries = $this->getDoctrine() | 104 | $form = $this->get('form.factory')->create(new EntryFilterType()); |
105 | |||
106 | $filterBuilder = $this->getDoctrine() | ||
99 | ->getRepository('WallabagCoreBundle:Entry') | 107 | ->getRepository('WallabagCoreBundle:Entry') |
100 | ->findUnreadByUser($this->getUser()->getId()); | 108 | ->findUnreadByUser($this->getUser()->getId()); |
101 | 109 | ||
110 | if ($request->query->has($form->getName())) { | ||
111 | // manually bind values from the request | ||
112 | $form->submit($request->query->get($form->getName())); | ||
113 | |||
114 | // build the query from the given form object | ||
115 | $this->get('lexik_form_filter.query_builder_updater')->addFilterConditions($form, $filterBuilder); | ||
116 | } | ||
117 | |||
118 | $pagerAdapter = new DoctrineORMAdapter($filterBuilder->getQuery()); | ||
119 | $entries = new Pagerfanta($pagerAdapter); | ||
120 | |||
102 | $entries->setMaxPerPage($this->getUser()->getConfig()->getItemsPerPage()); | 121 | $entries->setMaxPerPage($this->getUser()->getConfig()->getItemsPerPage()); |
103 | $entries->setCurrentPage($page); | 122 | $entries->setCurrentPage($page); |
104 | 123 | ||
105 | return $this->render( | 124 | return $this->render( |
106 | 'WallabagCoreBundle:Entry:entries.html.twig', | 125 | 'WallabagCoreBundle:Entry:entries.html.twig', |
107 | array( | 126 | array( |
127 | 'form' => $form->createView(), | ||
108 | 'entries' => $entries, | 128 | 'entries' => $entries, |
109 | 'currentPage' => $page | 129 | 'currentPage' => $page |
110 | ) | 130 | ) |
@@ -114,22 +134,39 @@ class EntryController extends Controller | |||
114 | /** | 134 | /** |
115 | * Shows read entries for current user. | 135 | * Shows read entries for current user. |
116 | * | 136 | * |
137 | * @param Request $request | ||
138 | * @param int $page | ||
139 | * | ||
117 | * @Route("/archive/list/{page}", name="archive", defaults={"page" = "1"}) | 140 | * @Route("/archive/list/{page}", name="archive", defaults={"page" = "1"}) |
118 | * | 141 | * |
119 | * @return \Symfony\Component\HttpFoundation\Response | 142 | * @return \Symfony\Component\HttpFoundation\Response |
120 | */ | 143 | */ |
121 | public function showArchiveAction($page) | 144 | public function showArchiveAction(Request $request, $page) |
122 | { | 145 | { |
123 | $entries = $this->getDoctrine() | 146 | $form = $this->get('form.factory')->create(new EntryFilterType()); |
147 | |||
148 | $filterBuilder = $this->getDoctrine() | ||
124 | ->getRepository('WallabagCoreBundle:Entry') | 149 | ->getRepository('WallabagCoreBundle:Entry') |
125 | ->findArchiveByUser($this->getUser()->getId()); | 150 | ->findArchiveByUser($this->getUser()->getId()); |
126 | 151 | ||
152 | if ($request->query->has($form->getName())) { | ||
153 | // manually bind values from the request | ||
154 | $form->submit($request->query->get($form->getName())); | ||
155 | |||
156 | // build the query from the given form object | ||
157 | $this->get('lexik_form_filter.query_builder_updater')->addFilterConditions($form, $filterBuilder); | ||
158 | } | ||
159 | |||
160 | $pagerAdapter = new DoctrineORMAdapter($filterBuilder->getQuery()); | ||
161 | $entries = new Pagerfanta($pagerAdapter); | ||
162 | |||
127 | $entries->setMaxPerPage($this->getUser()->getConfig()->getItemsPerPage()); | 163 | $entries->setMaxPerPage($this->getUser()->getConfig()->getItemsPerPage()); |
128 | $entries->setCurrentPage($page); | 164 | $entries->setCurrentPage($page); |
129 | 165 | ||
130 | return $this->render( | 166 | return $this->render( |
131 | 'WallabagCoreBundle:Entry:entries.html.twig', | 167 | 'WallabagCoreBundle:Entry:entries.html.twig', |
132 | array( | 168 | array( |
169 | 'form' => $form->createView(), | ||
133 | 'entries' => $entries, | 170 | 'entries' => $entries, |
134 | 'currentPage' => $page | 171 | 'currentPage' => $page |
135 | ) | 172 | ) |
@@ -139,22 +176,39 @@ class EntryController extends Controller | |||
139 | /** | 176 | /** |
140 | * Shows starred entries for current user. | 177 | * Shows starred entries for current user. |
141 | * | 178 | * |
179 | * @param Request $request | ||
180 | * @param int $page | ||
181 | * | ||
142 | * @Route("/starred/list/{page}", name="starred", defaults={"page" = "1"}) | 182 | * @Route("/starred/list/{page}", name="starred", defaults={"page" = "1"}) |
143 | * | 183 | * |
144 | * @return \Symfony\Component\HttpFoundation\Response | 184 | * @return \Symfony\Component\HttpFoundation\Response |
145 | */ | 185 | */ |
146 | public function showStarredAction($page) | 186 | public function showStarredAction(Request $request, $page) |
147 | { | 187 | { |
148 | $entries = $this->getDoctrine() | 188 | $form = $this->get('form.factory')->create(new EntryFilterType()); |
189 | |||
190 | $filterBuilder = $this->getDoctrine() | ||
149 | ->getRepository('WallabagCoreBundle:Entry') | 191 | ->getRepository('WallabagCoreBundle:Entry') |
150 | ->findStarredByUser($this->getUser()->getId()); | 192 | ->findStarredByUser($this->getUser()->getId()); |
151 | 193 | ||
194 | if ($request->query->has($form->getName())) { | ||
195 | // manually bind values from the request | ||
196 | $form->submit($request->query->get($form->getName())); | ||
197 | |||
198 | // build the query from the given form object | ||
199 | $this->get('lexik_form_filter.query_builder_updater')->addFilterConditions($form, $filterBuilder); | ||
200 | } | ||
201 | |||
202 | $pagerAdapter = new DoctrineORMAdapter($filterBuilder->getQuery()); | ||
203 | $entries = new Pagerfanta($pagerAdapter); | ||
204 | |||
152 | $entries->setMaxPerPage($this->getUser()->getConfig()->getItemsPerPage()); | 205 | $entries->setMaxPerPage($this->getUser()->getConfig()->getItemsPerPage()); |
153 | $entries->setCurrentPage($page); | 206 | $entries->setCurrentPage($page); |
154 | 207 | ||
155 | return $this->render( | 208 | return $this->render( |
156 | 'WallabagCoreBundle:Entry:entries.html.twig', | 209 | 'WallabagCoreBundle:Entry:entries.html.twig', |
157 | array( | 210 | array( |
211 | 'form' => $form->createView(), | ||
158 | 'entries' => $entries, | 212 | 'entries' => $entries, |
159 | 'currentPage' => $page | 213 | 'currentPage' => $page |
160 | ) | 214 | ) |
diff --git a/src/Wallabag/CoreBundle/Controller/RssController.php b/src/Wallabag/CoreBundle/Controller/RssController.php index 8428dce0..0558c53b 100644 --- a/src/Wallabag/CoreBundle/Controller/RssController.php +++ b/src/Wallabag/CoreBundle/Controller/RssController.php | |||
@@ -7,6 +7,8 @@ use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter; | |||
7 | use Symfony\Bundle\FrameworkBundle\Controller\Controller; | 7 | use Symfony\Bundle\FrameworkBundle\Controller\Controller; |
8 | use Wallabag\CoreBundle\Entity\User; | 8 | use Wallabag\CoreBundle\Entity\User; |
9 | use Wallabag\CoreBundle\Entity\Entry; | 9 | use Wallabag\CoreBundle\Entity\Entry; |
10 | use Pagerfanta\Adapter\DoctrineORMAdapter; | ||
11 | use Pagerfanta\Pagerfanta; | ||
10 | 12 | ||
11 | class RssController extends Controller | 13 | class RssController extends Controller |
12 | { | 14 | { |
@@ -20,12 +22,15 @@ class RssController extends Controller | |||
20 | */ | 22 | */ |
21 | public function showUnreadAction(User $user) | 23 | public function showUnreadAction(User $user) |
22 | { | 24 | { |
23 | $entries = $this->getDoctrine() | 25 | $qb = $this->getDoctrine() |
24 | ->getRepository('WallabagCoreBundle:Entry') | 26 | ->getRepository('WallabagCoreBundle:Entry') |
25 | ->findUnreadByUser( | 27 | ->findUnreadByUser( |
26 | $user->getId() | 28 | $user->getId() |
27 | ); | 29 | ); |
28 | 30 | ||
31 | $pagerAdapter = new DoctrineORMAdapter($qb->getQuery()); | ||
32 | $entries = new Pagerfanta($pagerAdapter); | ||
33 | |||
29 | $perPage = $user->getConfig()->getRssLimit() ?: $this->container->getParameter('rss_limit'); | 34 | $perPage = $user->getConfig()->getRssLimit() ?: $this->container->getParameter('rss_limit'); |
30 | $entries->setMaxPerPage($perPage); | 35 | $entries->setMaxPerPage($perPage); |
31 | 36 | ||
@@ -45,12 +50,15 @@ class RssController extends Controller | |||
45 | */ | 50 | */ |
46 | public function showArchiveAction(User $user) | 51 | public function showArchiveAction(User $user) |
47 | { | 52 | { |
48 | $entries = $this->getDoctrine() | 53 | $qb = $this->getDoctrine() |
49 | ->getRepository('WallabagCoreBundle:Entry') | 54 | ->getRepository('WallabagCoreBundle:Entry') |
50 | ->findArchiveByUser( | 55 | ->findArchiveByUser( |
51 | $user->getId() | 56 | $user->getId() |
52 | ); | 57 | ); |
53 | 58 | ||
59 | $pagerAdapter = new DoctrineORMAdapter($qb->getQuery()); | ||
60 | $entries = new Pagerfanta($pagerAdapter); | ||
61 | |||
54 | $perPage = $user->getConfig()->getRssLimit() ?: $this->container->getParameter('rss_limit'); | 62 | $perPage = $user->getConfig()->getRssLimit() ?: $this->container->getParameter('rss_limit'); |
55 | $entries->setMaxPerPage($perPage); | 63 | $entries->setMaxPerPage($perPage); |
56 | 64 | ||
@@ -70,12 +78,15 @@ class RssController extends Controller | |||
70 | */ | 78 | */ |
71 | public function showStarredAction(User $user) | 79 | public function showStarredAction(User $user) |
72 | { | 80 | { |
73 | $entries = $this->getDoctrine() | 81 | $qb = $this->getDoctrine() |
74 | ->getRepository('WallabagCoreBundle:Entry') | 82 | ->getRepository('WallabagCoreBundle:Entry') |
75 | ->findStarredByUser( | 83 | ->findStarredByUser( |
76 | $user->getId() | 84 | $user->getId() |
77 | ); | 85 | ); |
78 | 86 | ||
87 | $pagerAdapter = new DoctrineORMAdapter($qb->getQuery()); | ||
88 | $entries = new Pagerfanta($pagerAdapter); | ||
89 | |||
79 | $perPage = $user->getConfig()->getRssLimit() ?: $this->container->getParameter('rss_limit'); | 90 | $perPage = $user->getConfig()->getRssLimit() ?: $this->container->getParameter('rss_limit'); |
80 | $entries->setMaxPerPage($perPage); | 91 | $entries->setMaxPerPage($perPage); |
81 | 92 | ||
diff --git a/src/Wallabag/CoreBundle/Entity/Entry.php b/src/Wallabag/CoreBundle/Entity/Entry.php index f139bbac..9aebc55b 100644 --- a/src/Wallabag/CoreBundle/Entity/Entry.php +++ b/src/Wallabag/CoreBundle/Entity/Entry.php | |||
@@ -7,6 +7,7 @@ use Doctrine\ORM\Mapping as ORM; | |||
7 | use Symfony\Component\Validator\Constraints as Assert; | 7 | use Symfony\Component\Validator\Constraints as Assert; |
8 | use Hateoas\Configuration\Annotation as Hateoas; | 8 | use Hateoas\Configuration\Annotation as Hateoas; |
9 | use JMS\Serializer\Annotation\XmlRoot; | 9 | use JMS\Serializer\Annotation\XmlRoot; |
10 | use Wallabag\CoreBundle\Helper\Tools; | ||
10 | 11 | ||
11 | /** | 12 | /** |
12 | * Entry. | 13 | * Entry. |
@@ -96,7 +97,7 @@ class Entry | |||
96 | /** | 97 | /** |
97 | * @var int | 98 | * @var int |
98 | * | 99 | * |
99 | * @ORM\Column(name="reading_type", type="integer", nullable=true) | 100 | * @ORM\Column(name="reading_time", type="integer", nullable=true) |
100 | */ | 101 | */ |
101 | private $readingTime; | 102 | private $readingTime; |
102 | 103 | ||
@@ -264,6 +265,7 @@ class Entry | |||
264 | public function setContent($content) | 265 | public function setContent($content) |
265 | { | 266 | { |
266 | $this->content = $content; | 267 | $this->content = $content; |
268 | $this->readingTime = Tools::getReadingTime($content); | ||
267 | 269 | ||
268 | return $this; | 270 | return $this; |
269 | } | 271 | } |
diff --git a/src/Wallabag/CoreBundle/Filter/EntryFilterType.php b/src/Wallabag/CoreBundle/Filter/EntryFilterType.php new file mode 100644 index 00000000..636ba324 --- /dev/null +++ b/src/Wallabag/CoreBundle/Filter/EntryFilterType.php | |||
@@ -0,0 +1,28 @@ | |||
1 | <?php | ||
2 | |||
3 | namespace Wallabag\CoreBundle\Filter; | ||
4 | |||
5 | use Symfony\Component\Form\AbstractType; | ||
6 | use Symfony\Component\Form\FormBuilderInterface; | ||
7 | use Symfony\Component\OptionsResolver\OptionsResolver; | ||
8 | |||
9 | class EntryFilterType extends AbstractType | ||
10 | { | ||
11 | public function buildForm(FormBuilderInterface $builder, array $options) | ||
12 | { | ||
13 | $builder->add('readingTime', 'filter_number_range'); | ||
14 | } | ||
15 | |||
16 | public function getName() | ||
17 | { | ||
18 | return 'entry_filter'; | ||
19 | } | ||
20 | |||
21 | public function configureOptions(OptionsResolver $resolver) | ||
22 | { | ||
23 | $resolver->setDefaults(array( | ||
24 | 'csrf_protection' => false, | ||
25 | 'validation_groups' => array('filtering') | ||
26 | )); | ||
27 | } | ||
28 | } | ||
diff --git a/src/Wallabag/CoreBundle/Helper/Tools.php b/src/Wallabag/CoreBundle/Helper/Tools.php index be29ab99..d368ee71 100755 --- a/src/Wallabag/CoreBundle/Helper/Tools.php +++ b/src/Wallabag/CoreBundle/Helper/Tools.php | |||
@@ -118,4 +118,16 @@ final class Tools | |||
118 | 118 | ||
119 | return str_replace('+', '', $token); | 119 | return str_replace('+', '', $token); |
120 | } | 120 | } |
121 | |||
122 | /** | ||
123 | * For a given text, we calculate reading time for an article. | ||
124 | * | ||
125 | * @param $text | ||
126 | * | ||
127 | * @return float | ||
128 | */ | ||
129 | public static function getReadingTime($text) | ||
130 | { | ||
131 | return floor(str_word_count(strip_tags($text)) / 200); | ||
132 | } | ||
121 | } | 133 | } |
diff --git a/src/Wallabag/CoreBundle/Repository/EntryRepository.php b/src/Wallabag/CoreBundle/Repository/EntryRepository.php index a4514d9e..f885ee94 100644 --- a/src/Wallabag/CoreBundle/Repository/EntryRepository.php +++ b/src/Wallabag/CoreBundle/Repository/EntryRepository.php | |||
@@ -13,20 +13,15 @@ class EntryRepository extends EntityRepository | |||
13 | * | 13 | * |
14 | * @param int $userId | 14 | * @param int $userId |
15 | * | 15 | * |
16 | * @return Pagerfanta | 16 | * @return QueryBuilder |
17 | */ | 17 | */ |
18 | public function findUnreadByUser($userId) | 18 | public function findUnreadByUser($userId) |
19 | { | 19 | { |
20 | $qb = $this->createQueryBuilder('e') | 20 | return $this->createQueryBuilder('e') |
21 | ->leftJoin('e.user', 'u') | 21 | ->leftJoin('e.user', 'u') |
22 | ->where('e.isArchived = false') | 22 | ->where('e.isArchived = false') |
23 | ->andWhere('u.id =:userId')->setParameter('userId', $userId) | 23 | ->andWhere('u.id =:userId')->setParameter('userId', $userId) |
24 | ->orderBy('e.id', 'desc') | 24 | ->orderBy('e.id', 'desc'); |
25 | ->getQuery(); | ||
26 | |||
27 | $pagerAdapter = new DoctrineORMAdapter($qb); | ||
28 | |||
29 | return new Pagerfanta($pagerAdapter); | ||
30 | } | 25 | } |
31 | 26 | ||
32 | /** | 27 | /** |
@@ -34,21 +29,15 @@ class EntryRepository extends EntityRepository | |||
34 | * | 29 | * |
35 | * @param int $userId | 30 | * @param int $userId |
36 | * | 31 | * |
37 | * @return Pagerfanta | 32 | * @return QueryBuilder |
38 | */ | 33 | */ |
39 | public function findArchiveByUser($userId) | 34 | public function findArchiveByUser($userId) |
40 | { | 35 | { |
41 | $qb = $this->createQueryBuilder('e') | 36 | return $this->createQueryBuilder('e') |
42 | ->select('e') | ||
43 | ->leftJoin('e.user', 'u') | 37 | ->leftJoin('e.user', 'u') |
44 | ->where('e.isArchived = true') | 38 | ->where('e.isArchived = true') |
45 | ->andWhere('u.id =:userId')->setParameter('userId', $userId) | 39 | ->andWhere('u.id =:userId')->setParameter('userId', $userId) |
46 | ->orderBy('e.id', 'desc') | 40 | ->orderBy('e.id', 'desc'); |
47 | ->getQuery(); | ||
48 | |||
49 | $pagerAdapter = new DoctrineORMAdapter($qb); | ||
50 | |||
51 | return new Pagerfanta($pagerAdapter); | ||
52 | } | 41 | } |
53 | 42 | ||
54 | /** | 43 | /** |
@@ -56,22 +45,15 @@ class EntryRepository extends EntityRepository | |||
56 | * | 45 | * |
57 | * @param int $userId | 46 | * @param int $userId |
58 | * | 47 | * |
59 | * @return Pagerfanta | 48 | * @return QueryBuilder |
60 | */ | 49 | */ |
61 | public function findStarredByUser($userId) | 50 | public function findStarredByUser($userId) |
62 | { | 51 | { |
63 | 52 | return $this->createQueryBuilder('e') | |
64 | $qb = $this->createQueryBuilder('e') | ||
65 | ->select('e') | ||
66 | ->leftJoin('e.user', 'u') | 53 | ->leftJoin('e.user', 'u') |
67 | ->where('e.isStarred = true') | 54 | ->where('e.isStarred = true') |
68 | ->andWhere('u.id =:userId')->setParameter('userId', $userId) | 55 | ->andWhere('u.id =:userId')->setParameter('userId', $userId) |
69 | ->orderBy('e.id', 'desc') | 56 | ->orderBy('e.id', 'desc'); |
70 | ->getQuery(); | ||
71 | |||
72 | $pagerAdapter = new DoctrineORMAdapter($qb); | ||
73 | |||
74 | return new Pagerfanta($pagerAdapter); | ||
75 | } | 57 | } |
76 | 58 | ||
77 | /** | 59 | /** |
diff --git a/src/Wallabag/CoreBundle/Resources/views/Entry/entries.html.twig b/src/Wallabag/CoreBundle/Resources/views/Entry/entries.html.twig index bf3caf09..7629ef35 100644 --- a/src/Wallabag/CoreBundle/Resources/views/Entry/entries.html.twig +++ b/src/Wallabag/CoreBundle/Resources/views/Entry/entries.html.twig | |||
@@ -21,11 +21,12 @@ | |||
21 | {% if entries is empty %} | 21 | {% if entries is empty %} |
22 | <div class="messages warning"><p>{% trans %}No articles found.{% endtrans %}</p></div> | 22 | <div class="messages warning"><p>{% trans %}No articles found.{% endtrans %}</p></div> |
23 | {% else %} | 23 | {% else %} |
24 | <div><form>{{ form_rest(form) }}<button class="btn waves-effect waves-light" type="submit" id="submit-filter" value="filter">Filter</button></form></div> | ||
24 | {% for entry in entries %} | 25 | {% for entry in entries %} |
25 | <div id="entry-{{ entry.id|e }}" class="entrie"> | 26 | <div id="entry-{{ entry.id|e }}" class="entry"> |
26 | <h2><a href="{{ path('view', { 'id': entry.id }) }}">{{ entry.title|raw }}</a></h2> | 27 | <h2><a href="{{ path('view', { 'id': entry.id }) }}">{{ entry.title|raw }}</a></h2> |
27 | {% if entry.content| readingTime > 0 %} | 28 | {% if entry.readingTime > 0 %} |
28 | <div class="estimatedTime"><span class="tool reading-time">{% trans %}estimated reading time :{% endtrans %} {{ entry.content| readingTime }} min</span></div> | 29 | <div class="estimatedTime"><span class="tool reading-time">{% trans %}estimated reading time :{% endtrans %} {{ entry.readingTime }} min</span></div> |
29 | {% else %} | 30 | {% else %} |
30 | <div class="estimatedTime"><span class="tool reading-time">{% trans %}estimated reading time :{% endtrans %} <small class="inferieur"><</small> 1 min</span></div> | 31 | <div class="estimatedTime"><span class="tool reading-time">{% trans %}estimated reading time :{% endtrans %} <small class="inferieur"><</small> 1 min</span></div> |
31 | {% endif %} | 32 | {% endif %} |
diff --git a/src/Wallabag/CoreBundle/Resources/views/Entry/entries.xml.twig b/src/Wallabag/CoreBundle/Resources/views/Entry/entries.xml.twig index 5ec9bc03..a39a8dc3 100644 --- a/src/Wallabag/CoreBundle/Resources/views/Entry/entries.xml.twig +++ b/src/Wallabag/CoreBundle/Resources/views/Entry/entries.xml.twig | |||
@@ -17,8 +17,8 @@ | |||
17 | <pubDate>{{ entry.createdAt|date('D, d M Y H:i:s') }}</pubDate> | 17 | <pubDate>{{ entry.createdAt|date('D, d M Y H:i:s') }}</pubDate> |
18 | <description> | 18 | <description> |
19 | <![CDATA[ | 19 | <![CDATA[ |
20 | {%- if entry.content|readingTime > 0 -%} | 20 | {%- if entry.readingTime > 0 -%} |
21 | {% trans %}estimated reading time :{% endtrans %} {{ entry.content|readingTime }} min | 21 | {% trans %}estimated reading time :{% endtrans %} {{ entry.readingTime }} min |
22 | {%- else -%} | 22 | {%- else -%} |
23 | {% trans %}estimated reading time :{% endtrans %} < 1 min | 23 | {% trans %}estimated reading time :{% endtrans %} < 1 min |
24 | {%- endif %} | 24 | {%- endif %} |
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/_global/public/css/style.css b/src/Wallabag/CoreBundle/Resources/views/themes/_global/public/css/style.css index e3069b86..ffd9d022 100644 --- a/src/Wallabag/CoreBundle/Resources/views/themes/_global/public/css/style.css +++ b/src/Wallabag/CoreBundle/Resources/views/themes/_global/public/css/style.css | |||
@@ -121,7 +121,7 @@ a:visited { | |||
121 | font-size: 1.3em; | 121 | font-size: 1.3em; |
122 | } | 122 | } |
123 | 123 | ||
124 | #main #content .entrie { | 124 | #main #content .entry { |
125 | margin-top: 15px; | 125 | margin-top: 15px; |
126 | padding-bottom: 15px; | 126 | padding-bottom: 15px; |
127 | border-bottom: 1px dashed #222; | 127 | border-bottom: 1px dashed #222; |
@@ -129,19 +129,19 @@ a:visited { | |||
129 | } | 129 | } |
130 | 130 | ||
131 | /* First entry */ | 131 | /* First entry */ |
132 | #main #content .results + .entrie { | 132 | #main #content .results + .entry { |
133 | clear: both; | 133 | clear: both; |
134 | margin-top: 0; | 134 | margin-top: 0; |
135 | } | 135 | } |
136 | 136 | ||
137 | #main .entrie .tools { | 137 | #main .entry .tools { |
138 | float: right; | 138 | float: right; |
139 | text-align: right; | 139 | text-align: right; |
140 | list-style-type: none; | 140 | list-style-type: none; |
141 | opacity: 0.5; | 141 | opacity: 0.5; |
142 | } | 142 | } |
143 | 143 | ||
144 | #main .entrie .tools .tool span { | 144 | #main .entry .tools .tool span { |
145 | display: inline-block; | 145 | display: inline-block; |
146 | width: 16px; | 146 | width: 16px; |
147 | height: 16px; | 147 | height: 16px; |
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 e2844ccc..6090face 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 | |||
@@ -322,7 +322,7 @@ footer a { | |||
322 | letter-spacing:-5px; | 322 | letter-spacing:-5px; |
323 | } | 323 | } |
324 | 324 | ||
325 | .listmode .entrie { | 325 | .listmode .entry { |
326 | width: 100%!important; | 326 | width: 100%!important; |
327 | margin-left: 0!important; | 327 | margin-left: 0!important; |
328 | } | 328 | } |
@@ -343,7 +343,7 @@ footer a { | |||
343 | top: -1px; | 343 | top: -1px; |
344 | } | 344 | } |
345 | 345 | ||
346 | .entrie { | 346 | .entry { |
347 | background-color: #FFF; | 347 | background-color: #FFF; |
348 | letter-spacing:normal; | 348 | letter-spacing:normal; |
349 | box-shadow: 0 3px 7px rgba(0,0,0,0.3); | 349 | box-shadow: 0 3px 7px rgba(0,0,0,0.3); |
@@ -366,7 +366,7 @@ footer a { | |||
366 | /* transition: all 0.5s ease; */ | 366 | /* transition: all 0.5s ease; */ |
367 | } | 367 | } |
368 | 368 | ||
369 | .entrie:before { | 369 | .entry:before { |
370 | content: ""; | 370 | content: ""; |
371 | width: 0; | 371 | width: 0; |
372 | height: 0; | 372 | height: 0; |
@@ -384,7 +384,7 @@ footer a { | |||
384 | transition: all 0.5s ease; | 384 | transition: all 0.5s ease; |
385 | } | 385 | } |
386 | 386 | ||
387 | .entrie:after { | 387 | .entry:after { |
388 | content: ""; | 388 | content: ""; |
389 | position: absolute; | 389 | position: absolute; |
390 | height: 7px; | 390 | height: 7px; |
@@ -399,34 +399,34 @@ footer a { | |||
399 | transition: all 0.5s ease; | 399 | transition: all 0.5s ease; |
400 | } | 400 | } |
401 | 401 | ||
402 | .entrie:hover { | 402 | .entry:hover { |
403 | box-shadow: 0 3px 10px rgba(0,0,0,1); | 403 | box-shadow: 0 3px 10px rgba(0,0,0,1); |
404 | } | 404 | } |
405 | 405 | ||
406 | .entrie:hover:after { | 406 | .entry:hover:after { |
407 | height: 40px; | 407 | height: 40px; |
408 | } | 408 | } |
409 | 409 | ||
410 | .entrie:hover:before { | 410 | .entry:hover:before { |
411 | bottom: 2.4em; | 411 | bottom: 2.4em; |
412 | } | 412 | } |
413 | 413 | ||
414 | .entrie:hover h2 a { | 414 | .entry:hover h2 a { |
415 | color: #666; | 415 | color: #666; |
416 | } | 416 | } |
417 | 417 | ||
418 | .entrie h2 { | 418 | .entry h2 { |
419 | text-transform: none; | 419 | text-transform: none; |
420 | margin-bottom: 0; | 420 | margin-bottom: 0; |
421 | line-height: 1.2; | 421 | line-height: 1.2; |
422 | } | 422 | } |
423 | 423 | ||
424 | .entrie h2:after { | 424 | .entry h2:after { |
425 | content: none; | 425 | content: none; |
426 | } | 426 | } |
427 | 427 | ||
428 | 428 | ||
429 | .entrie h2 a { | 429 | .entry h2 a { |
430 | display: block; | 430 | display: block; |
431 | text-decoration: none; | 431 | text-decoration: none; |
432 | color: #000; | 432 | color: #000; |
@@ -438,7 +438,7 @@ footer a { | |||
438 | transition: all 0.5s ease; | 438 | transition: all 0.5s ease; |
439 | } | 439 | } |
440 | /* | 440 | /* |
441 | .entrie h2 a:after { | 441 | .entry h2 a:after { |
442 | content: ""; | 442 | content: ""; |
443 | position: absolute; | 443 | position: absolute; |
444 | top: 0; | 444 | top: 0; |
@@ -448,21 +448,21 @@ footer a { | |||
448 | } | 448 | } |
449 | */ | 449 | */ |
450 | 450 | ||
451 | .entrie p { | 451 | .entry p { |
452 | color: #666; | 452 | color: #666; |
453 | font-size: 0.9em; | 453 | font-size: 0.9em; |
454 | line-height: 1.7; | 454 | line-height: 1.7; |
455 | } | 455 | } |
456 | 456 | ||
457 | .entrie h2 a:first-letter { | 457 | .entry h2 a:first-letter { |
458 | text-transform: uppercase; | 458 | text-transform: uppercase; |
459 | } | 459 | } |
460 | 460 | ||
461 | .entrie:hover .tools { | 461 | .entry:hover .tools { |
462 | bottom: 0; | 462 | bottom: 0; |
463 | } | 463 | } |
464 | 464 | ||
465 | .entrie .tools { | 465 | .entry .tools { |
466 | position: absolute; | 466 | position: absolute; |
467 | bottom: -50px; | 467 | bottom: -50px; |
468 | left: 0; | 468 | left: 0; |
@@ -477,22 +477,22 @@ footer a { | |||
477 | transition: all 0.5s ease; | 477 | transition: all 0.5s ease; |
478 | } | 478 | } |
479 | 479 | ||
480 | .entrie .tools a { | 480 | .entry .tools a { |
481 | color: #666; | 481 | color: #666; |
482 | text-decoration: none; | 482 | text-decoration: none; |
483 | display: block; | 483 | display: block; |
484 | padding: 0.4em; | 484 | padding: 0.4em; |
485 | } | 485 | } |
486 | 486 | ||
487 | .entrie .tools a:hover { | 487 | .entry .tools a:hover { |
488 | color: #FFF; | 488 | color: #FFF; |
489 | } | 489 | } |
490 | 490 | ||
491 | .entrie .tools li { | 491 | .entry .tools li { |
492 | display: inline-block; | 492 | display: inline-block; |
493 | } | 493 | } |
494 | 494 | ||
495 | .entrie:nth-child(3n+1) { | 495 | .entry:nth-child(3n+1) { |
496 | margin-left: 0; | 496 | margin-left: 0; |
497 | } | 497 | } |
498 | 498 | ||
@@ -941,13 +941,13 @@ pre code { | |||
941 | ========================================================================== */ | 941 | ========================================================================== */ |
942 | 942 | ||
943 | @media screen and (max-width: 1050px) { | 943 | @media screen and (max-width: 1050px) { |
944 | .entrie { | 944 | .entry { |
945 | width: 49%; | 945 | width: 49%; |
946 | } | 946 | } |
947 | .entrie:nth-child(3n+1) { | 947 | .entry:nth-child(3n+1) { |
948 | margin-left: 1.5%; | 948 | margin-left: 1.5%; |
949 | } | 949 | } |
950 | .entrie:nth-child(2n+1) { | 950 | .entry:nth-child(2n+1) { |
951 | margin-left: 0; | 951 | margin-left: 0; |
952 | } | 952 | } |
953 | } | 953 | } |
@@ -962,7 +962,7 @@ pre code { | |||
962 | } | 962 | } |
963 | 963 | ||
964 | @media screen and (max-width: 700px) { | 964 | @media screen and (max-width: 700px) { |
965 | .entrie { | 965 | .entry { |
966 | width: 100%; | 966 | width: 100%; |
967 | margin-left: 0; | 967 | margin-left: 0; |
968 | } | 968 | } |
@@ -972,7 +972,7 @@ pre code { | |||
972 | } | 972 | } |
973 | 973 | ||
974 | @media screen and (max-width: 500px) { | 974 | @media screen and (max-width: 500px) { |
975 | .entrie { | 975 | .entry { |
976 | width: 100%; | 976 | width: 100%; |
977 | margin-left: 0; | 977 | margin-left: 0; |
978 | } | 978 | } |
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/entries.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/entries.html.twig index fbdc1ffd..b9f1be49 100644 --- a/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/entries.html.twig +++ b/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/entries.html.twig | |||
@@ -18,6 +18,7 @@ | |||
18 | {% if entries is not empty %} | 18 | {% if entries is not empty %} |
19 | <div class="results clearfix"> | 19 | <div class="results clearfix"> |
20 | <div class="nb-results left">{{ entries.count }} {% trans %}entries{% endtrans %}</div> | 20 | <div class="nb-results left">{{ entries.count }} {% trans %}entries{% endtrans %}</div> |
21 | <div class="left"><form>{{ form_rest(form) }}<button class="btn waves-effect waves-light" type="submit" id="submit-filter" value="filter">Filter</button></form></div> | ||
21 | <ul class="pagination right"> | 22 | <ul class="pagination right"> |
22 | {% for p in range(1, entries.nbPages) %} | 23 | {% for p in range(1, entries.nbPages) %} |
23 | <li class="{{ currentPage == p ? 'active':'waves-effect'}}"> | 24 | <li class="{{ currentPage == p ? 'active':'waves-effect'}}"> |
@@ -38,8 +39,8 @@ | |||
38 | <div class="card"> | 39 | <div class="card"> |
39 | <div class="card-content"> | 40 | <div class="card-content"> |
40 | <span class="card-title"><a href="{{ path('view', { 'id': entry.id }) }}">{{ entry.title|raw }}</a></span> | 41 | <span class="card-title"><a href="{{ path('view', { 'id': entry.id }) }}">{{ entry.title|raw }}</a></span> |
41 | {% if entry.content| readingTime > 0 %} | 42 | {% if entry.readingTime > 0 %} |
42 | <div class="estimatedTime grey-text"><span class="tool reading-time">{% trans %}estimated reading time: {% endtrans %} {{ entry.content| readingTime }} min</span></div> | 43 | <div class="estimatedTime grey-text"><span class="tool reading-time">{% trans %}estimated reading time: {% endtrans %} {{ entry.readingTime }} min</span></div> |
43 | {% else %} | 44 | {% else %} |
44 | <div class="estimatedTime grey-text"><span class="tool reading-time">{% trans %}estimated reading time: {% endtrans %} <small class="inferieur"><</small> 1 min</span></div> | 45 | <div class="estimatedTime grey-text"><span class="tool reading-time">{% trans %}estimated reading time: {% endtrans %} <small class="inferieur"><</small> 1 min</span></div> |
45 | {% endif %} | 46 | {% endif %} |
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/material/public/css/print.css b/src/Wallabag/CoreBundle/Resources/views/themes/material/public/css/print.css index 9dd6d295..2a799c44 100755 --- a/src/Wallabag/CoreBundle/Resources/views/themes/material/public/css/print.css +++ b/src/Wallabag/CoreBundle/Resources/views/themes/material/public/css/print.css | |||
@@ -25,7 +25,7 @@ body > footer, | |||
25 | div.tools, | 25 | div.tools, |
26 | header div, | 26 | header div, |
27 | .messages, | 27 | .messages, |
28 | .entrie + .results { | 28 | .entry + .results { |
29 | display: none !important; | 29 | display: none !important; |
30 | } | 30 | } |
31 | 31 | ||
diff --git a/src/Wallabag/CoreBundle/Tests/Controller/EntryControllerTest.php b/src/Wallabag/CoreBundle/Tests/Controller/EntryControllerTest.php index 2cd50130..24848eb2 100644 --- a/src/Wallabag/CoreBundle/Tests/Controller/EntryControllerTest.php +++ b/src/Wallabag/CoreBundle/Tests/Controller/EntryControllerTest.php | |||
@@ -240,4 +240,23 @@ class EntryControllerTest extends WallabagCoreTestCase | |||
240 | 240 | ||
241 | $this->assertEquals(403, $client->getResponse()->getStatusCode()); | 241 | $this->assertEquals(403, $client->getResponse()->getStatusCode()); |
242 | } | 242 | } |
243 | |||
244 | public function testFilterOnUnreadeView() | ||
245 | { | ||
246 | $this->logInAs('admin'); | ||
247 | $client = $this->getClient(); | ||
248 | |||
249 | $crawler = $client->request('GET', '/unread/list'); | ||
250 | |||
251 | $form = $crawler->filter('button[id=submit-filter]')->form(); | ||
252 | |||
253 | $data = array( | ||
254 | 'entry_filter[readingTime][right_number]' => 11, | ||
255 | 'entry_filter[readingTime][left_number]' => 11 | ||
256 | ); | ||
257 | |||
258 | $crawler = $client->submit($form, $data); | ||
259 | |||
260 | $this->assertCount(1, $crawler->filter('div[class=entry]')); | ||
261 | } | ||
243 | } | 262 | } |
diff --git a/src/Wallabag/CoreBundle/Twig/Extension/WallabagExtension.php b/src/Wallabag/CoreBundle/Twig/Extension/WallabagExtension.php index 18388948..5f0a9643 100644 --- a/src/Wallabag/CoreBundle/Twig/Extension/WallabagExtension.php +++ b/src/Wallabag/CoreBundle/Twig/Extension/WallabagExtension.php | |||
@@ -7,7 +7,6 @@ class WallabagExtension extends \Twig_Extension | |||
7 | public function getFilters() | 7 | public function getFilters() |
8 | { | 8 | { |
9 | return array( | 9 | return array( |
10 | new \Twig_SimpleFilter('readingTime', array($this, 'getReadingTime')), | ||
11 | new \Twig_SimpleFilter('domainName', array($this, 'getDomainName')), | 10 | new \Twig_SimpleFilter('domainName', array($this, 'getDomainName')), |
12 | ); | 11 | ); |
13 | } | 12 | } |
@@ -24,18 +23,6 @@ class WallabagExtension extends \Twig_Extension | |||
24 | return parse_url($url, PHP_URL_HOST); | 23 | return parse_url($url, PHP_URL_HOST); |
25 | } | 24 | } |
26 | 25 | ||
27 | /** | ||
28 | * For a given text, we calculate reading time for an article. | ||
29 | * | ||
30 | * @param $text | ||
31 | * | ||
32 | * @return float | ||
33 | */ | ||
34 | public static function getReadingTime($text) | ||
35 | { | ||
36 | return floor(str_word_count(strip_tags($text)) / 200); | ||
37 | } | ||
38 | |||
39 | public function getName() | 26 | public function getName() |
40 | { | 27 | { |
41 | return 'wallabag_extension'; | 28 | return 'wallabag_extension'; |