]> git.immae.eu Git - github/wallabag/wallabag.git/commitdiff
Merge pull request #1386 from wallabag/v2-refactor
authorNicolas Lœuillet <nicolas@loeuillet.org>
Thu, 20 Aug 2015 19:51:02 +0000 (21:51 +0200)
committerNicolas Lœuillet <nicolas@loeuillet.org>
Thu, 20 Aug 2015 19:51:02 +0000 (21:51 +0200)
WIP – Fixing things around :dash:

16 files changed:
app/config/config.yml
composer.json
src/Wallabag/ApiBundle/Tests/Controller/WallabagRestControllerTest.php
src/Wallabag/CoreBundle/Controller/EntryController.php
src/Wallabag/CoreBundle/Controller/RssController.php
src/Wallabag/CoreBundle/Controller/StaticController.php
src/Wallabag/CoreBundle/Entity/Entry.php
src/Wallabag/CoreBundle/Helper/Entry.php [deleted file]
src/Wallabag/CoreBundle/Helper/Tools.php [deleted file]
src/Wallabag/CoreBundle/Repository/EntryRepository.php
src/Wallabag/CoreBundle/Resources/config/routing.yml
src/Wallabag/CoreBundle/Resources/views/Static/about.html.twig
src/Wallabag/CoreBundle/Resources/views/base.html.twig
src/Wallabag/CoreBundle/Resources/views/themes/material/Static/about.html.twig
src/Wallabag/CoreBundle/Resources/views/themes/material/layout.html.twig
src/Wallabag/CoreBundle/Tools/Utils.php

index 5b26b06fecf0d20f2132a4d220ada94556592db5..efc815b8e9a3211e122649c73d5883795a89bc0e 100644 (file)
@@ -51,6 +51,7 @@ twig:
     form:
         resources:
             - LexikFormFilterBundle:Form:form_div_layout.html.twig
+
 # Assetic Configuration
 assetic:
     debug:          "%kernel.debug%"
index 709b23ac8168855da63593f5bdd0bccffc51f21c..2c5111fdecc87e601a88899946a1fd11243814f0 100644 (file)
@@ -19,6 +19,7 @@
         },
         {
             "name": "Jérémy Benoist",
+            "homepage": "http://www.j0k3r.net",
             "role": "Developer"
         }
     ],
index 86c8de1ed0eb8d5d5352d5289af535b972b15a45..7ae54b576d577014bb3f5348235986973fc2b439 100644 (file)
@@ -170,6 +170,31 @@ class WallabagRestControllerTest extends WebTestCase
         $client = $this->createClient();
         $headers = $this->generateHeaders('admin', 'mypassword');
 
+        $client->request('GET', '/api/entries', array('star' => 1, 'sort' => 'updated'), array(), $headers);
+
+        $this->assertEquals(200, $client->getResponse()->getStatusCode());
+
+        $content = json_decode($client->getResponse()->getContent(), true);
+
+        $this->assertGreaterThanOrEqual(1, count($content));
+        $this->assertNotEmpty($content['_embedded']['items']);
+        $this->assertGreaterThanOrEqual(1, $content['total']);
+        $this->assertEquals(1, $content['page']);
+        $this->assertGreaterThanOrEqual(1, $content['pages']);
+
+        $this->assertTrue(
+            $client->getResponse()->headers->contains(
+                'Content-Type',
+                'application/json'
+            )
+        );
+    }
+
+    public function testGetArchiveEntries()
+    {
+        $client = $this->createClient();
+        $headers = $this->generateHeaders('admin', 'mypassword');
+
         $client->request('GET', '/api/entries', array('archive' => 1), array(), $headers);
 
         $this->assertEquals(200, $client->getResponse()->getStatusCode());
index 006fa396476019c3055ed9c83da58b6f542acdba..dc399b8a3289ef58a9b835831eeb2d30b50b66c8 100644 (file)
@@ -113,34 +113,7 @@ class EntryController extends Controller
      */
     public function showUnreadAction(Request $request, $page)
     {
-        $form = $this->get('form.factory')->create(new EntryFilterType());
-
-        $filterBuilder = $this->getDoctrine()
-            ->getRepository('WallabagCoreBundle:Entry')
-            ->findUnreadByUser($this->getUser()->getId());
-
-        if ($request->query->has($form->getName())) {
-            // manually bind values from the request
-            $form->submit($request->query->get($form->getName()));
-
-            // build the query from the given form object
-            $this->get('lexik_form_filter.query_builder_updater')->addFilterConditions($form, $filterBuilder);
-        }
-
-        $pagerAdapter = new DoctrineORMAdapter($filterBuilder->getQuery());
-        $entries = new Pagerfanta($pagerAdapter);
-
-        $entries->setMaxPerPage($this->getUser()->getConfig()->getItemsPerPage());
-        $entries->setCurrentPage($page);
-
-        return $this->render(
-            'WallabagCoreBundle:Entry:entries.html.twig',
-            array(
-                'form' => $form->createView(),
-                'entries' => $entries,
-                'currentPage' => $page,
-            )
-        );
+        return $this->showEntries('unread', $request, $page);
     }
 
     /**
@@ -155,21 +128,66 @@ class EntryController extends Controller
      */
     public function showArchiveAction(Request $request, $page)
     {
-        $form = $this->get('form.factory')->create(new EntryFilterType());
+        return $this->showEntries('archive', $request, $page);
+    }
+
+    /**
+     * Shows starred entries for current user.
+     *
+     * @param Request $request
+     * @param int     $page
+     *
+     * @Route("/starred/list/{page}", name="starred", defaults={"page" = "1"})
+     *
+     * @return \Symfony\Component\HttpFoundation\Response
+     */
+    public function showStarredAction(Request $request, $page)
+    {
+        return $this->showEntries('starred', $request, $page);
+    }
 
-        $filterBuilder = $this->getDoctrine()
-            ->getRepository('WallabagCoreBundle:Entry')
-            ->findArchiveByUser($this->getUser()->getId());
+    /**
+     * Global method to retrieve entries depending on the given type
+     * It returns the response to be send.
+     *
+     * @param string  $type    Entries type: unread, starred or archive
+     * @param Request $request
+     * @param int     $page
+     *
+     * @return \Symfony\Component\HttpFoundation\Response
+     */
+    private function showEntries($type, Request $request, $page)
+    {
+        $repository = $this->getDoctrine()->getRepository('WallabagCoreBundle:Entry');
+
+        switch ($type) {
+            case 'starred':
+                $qb = $repository->getBuilderForStarredByUser($this->getUser()->getId());
+                break;
+
+            case 'archive':
+                $qb = $repository->getBuilderForArchiveByUser($this->getUser()->getId());
+                break;
+
+            case 'unread':
+                $qb = $repository->getBuilderForUnreadByUser($this->getUser()->getId());
+                break;
+
+            default:
+                throw new \InvalidArgumentException(sprintf('Type "%s" is not implemented.', $type));
+        }
+
+        $form = $this->get('form.factory')->create(new EntryFilterType());
 
         if ($request->query->has($form->getName())) {
             // manually bind values from the request
             $form->submit($request->query->get($form->getName()));
 
             // build the query from the given form object
-            $this->get('lexik_form_filter.query_builder_updater')->addFilterConditions($form, $filterBuilder);
+            $this->get('lexik_form_filter.query_builder_updater')->addFilterConditions($form, $qb);
         }
 
-        $pagerAdapter = new DoctrineORMAdapter($filterBuilder->getQuery());
+        $pagerAdapter = new DoctrineORMAdapter($qb->getQuery());
         $entries = new Pagerfanta($pagerAdapter);
 
         $entries->setMaxPerPage($this->getUser()->getConfig()->getItemsPerPage());
@@ -183,25 +201,6 @@ class EntryController extends Controller
                 'currentPage' => $page,
             )
         );
-    }
-
-    /**
-     * Shows starred entries for current user.
-     *
-     * @param Request $request
-     * @param int     $page
-     *
-     * @Route("/starred/list/{page}", name="starred", defaults={"page" = "1"})
-     *
-     * @return \Symfony\Component\HttpFoundation\Response
-     */
-    public function showStarredAction(Request $request, $page)
-    {
-        $form = $this->get('form.factory')->create(new EntryFilterType());
-
-        $filterBuilder = $this->getDoctrine()
-            ->getRepository('WallabagCoreBundle:Entry')
-            ->findStarredByUser($this->getUser()->getId());
 
         if ($request->query->has($form->getName())) {
             // manually bind values from the request
index 0558c53b0fcbe4ba84572366523702a30aac35d7..6121f36142ab730b503933f657c9a1700e7fabf2 100644 (file)
@@ -22,22 +22,7 @@ class RssController extends Controller
      */
     public function showUnreadAction(User $user)
     {
-        $qb = $this->getDoctrine()
-            ->getRepository('WallabagCoreBundle:Entry')
-            ->findUnreadByUser(
-                $user->getId()
-            );
-
-        $pagerAdapter = new DoctrineORMAdapter($qb->getQuery());
-        $entries = new Pagerfanta($pagerAdapter);
-
-        $perPage = $user->getConfig()->getRssLimit() ?: $this->container->getParameter('rss_limit');
-        $entries->setMaxPerPage($perPage);
-
-        return $this->render('WallabagCoreBundle:Entry:entries.xml.twig', array(
-            'type' => 'unread',
-            'entries' => $entries,
-        ));
+        return $this->showEntries('unread', $user);
     }
 
     /**
@@ -50,22 +35,7 @@ class RssController extends Controller
      */
     public function showArchiveAction(User $user)
     {
-        $qb = $this->getDoctrine()
-            ->getRepository('WallabagCoreBundle:Entry')
-            ->findArchiveByUser(
-                $user->getId()
-            );
-
-        $pagerAdapter = new DoctrineORMAdapter($qb->getQuery());
-        $entries = new Pagerfanta($pagerAdapter);
-
-        $perPage = $user->getConfig()->getRssLimit() ?: $this->container->getParameter('rss_limit');
-        $entries->setMaxPerPage($perPage);
-
-        return $this->render('WallabagCoreBundle:Entry:entries.xml.twig', array(
-            'type' => 'archive',
-            'entries' => $entries,
-        ));
+        return $this->showEntries('archive', $user);
     }
 
     /**
@@ -78,11 +48,38 @@ class RssController extends Controller
      */
     public function showStarredAction(User $user)
     {
-        $qb = $this->getDoctrine()
-            ->getRepository('WallabagCoreBundle:Entry')
-            ->findStarredByUser(
-                $user->getId()
-            );
+        return $this->showEntries('starred', $user);
+    }
+
+    /**
+     * Global method to retrieve entries depending on the given type
+     * It returns the response to be send.
+     *
+     * @param string $type Entries type: unread, starred or archive
+     * @param User   $user
+     *
+     * @return \Symfony\Component\HttpFoundation\Response
+     */
+    private function showEntries($type, User $user)
+    {
+        $repository = $this->getDoctrine()->getRepository('WallabagCoreBundle:Entry');
+
+        switch ($type) {
+            case 'starred':
+                $qb = $repository->getBuilderForStarredByUser($user->getId());
+                break;
+
+            case 'archive':
+                $qb = $repository->getBuilderForArchiveByUser($user->getId());
+                break;
+
+            case 'unread':
+                $qb = $repository->getBuilderForUnreadByUser($user->getId());
+                break;
+
+            default:
+                throw new \InvalidArgumentException(sprintf('Type "%s" is not implemented.', $type));
+        }
 
         $pagerAdapter = new DoctrineORMAdapter($qb->getQuery());
         $entries = new Pagerfanta($pagerAdapter);
@@ -91,7 +88,7 @@ class RssController extends Controller
         $entries->setMaxPerPage($perPage);
 
         return $this->render('WallabagCoreBundle:Entry:entries.xml.twig', array(
-            'type' => 'starred',
+            'type' => $type,
             'entries' => $entries,
         ));
     }
index 3b844b44c500054cb47bd1412d9c7215399941d2..64875a6654c3723de9facd382a7f4552b8eee90d 100644 (file)
@@ -28,12 +28,4 @@ class StaticController extends Controller
             array()
         );
     }
-
-    /**
-     * @Route("/", name="homepage")
-     */
-    public function apiAction()
-    {
-        return $this->redirect($this->generateUrl('nelmio_api_doc_index'));
-    }
 }
index 7d2d2027f1bbf43478db1887339a2ed8a38cef56..f88d189d3f6e376f08fec5851999d478c0dede8d 100644 (file)
@@ -7,7 +7,7 @@ use Doctrine\ORM\Mapping as ORM;
 use Symfony\Component\Validator\Constraints as Assert;
 use Hateoas\Configuration\Annotation as Hateoas;
 use JMS\Serializer\Annotation\XmlRoot;
-use Wallabag\CoreBundle\Helper\Tools;
+use Wallabag\CoreBundle\Tools\Utils;
 
 /**
  * Entry.
@@ -265,7 +265,7 @@ class Entry
     public function setContent($content)
     {
         $this->content = $content;
-        $this->readingTime = Tools::getReadingTime($content);
+        $this->readingTime = Utils::getReadingTime($content);
         $this->domainName = parse_url($this->url, PHP_URL_HOST);
 
         return $this;
diff --git a/src/Wallabag/CoreBundle/Helper/Entry.php b/src/Wallabag/CoreBundle/Helper/Entry.php
deleted file mode 100644 (file)
index 219711b..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-<?php
-
-namespace Wallabag\CoreBundle\Helper;
-
-class Entry
-{
-}
diff --git a/src/Wallabag/CoreBundle/Helper/Tools.php b/src/Wallabag/CoreBundle/Helper/Tools.php
deleted file mode 100755 (executable)
index d368ee7..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-<?php
-
-namespace Wallabag\CoreBundle\Helper;
-
-final class Tools
-{
-    /**
-     * Download a file (typically, for downloading pictures on web server).
-     *
-     * @param $url
-     *
-     * @return bool|mixed|string
-     */
-    public static function getFile($url)
-    {
-        $timeout = 15;
-        $useragent = 'Mozilla/5.0 (Windows NT 5.1; rv:18.0) Gecko/20100101 Firefox/18.0';
-
-        if (in_array('curl', get_loaded_extensions())) {
-            # Fetch feed from URL
-            $curl = curl_init();
-            curl_setopt($curl, CURLOPT_URL, $url);
-            curl_setopt($curl, CURLOPT_TIMEOUT, $timeout);
-            if (!ini_get('open_basedir') && !ini_get('safe_mode')) {
-                curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
-            }
-            curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
-            curl_setopt($curl, CURLOPT_HEADER, false);
-
-            # for ssl, do not verified certificate
-            curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
-            curl_setopt($curl, CURLOPT_AUTOREFERER, true);
-
-            # FeedBurner requires a proper USER-AGENT...
-            curl_setopt($curl, CURL_HTTP_VERSION_1_1, true);
-            curl_setopt($curl, CURLOPT_ENCODING, 'gzip, deflate');
-            curl_setopt($curl, CURLOPT_USERAGENT, $useragent);
-
-            $data = curl_exec($curl);
-            $httpcode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
-            $httpcodeOK = isset($httpcode) and ($httpcode == 200 or $httpcode == 301);
-            curl_close($curl);
-        } else {
-            # create http context and add timeout and user-agent
-            $context = stream_context_create(
-                array(
-                    'http' => array(
-                        'timeout' => $timeout,
-                        'header' => 'User-Agent: '.$useragent,
-                        'follow_location' => true,
-                    ),
-                    'ssl' => array(
-                        'verify_peer' => false,
-                        'allow_self_signed' => true,
-                    ),
-                )
-            );
-
-            # only download page lesser than 4MB
-            $data = @file_get_contents($url, false, $context, -1, 4000000);
-
-            if (isset($http_response_header) and isset($http_response_header[0])) {
-                $httpcodeOK = isset($http_response_header) and isset($http_response_header[0]) and ((strpos($http_response_header[0], '200 OK') !== false) or (strpos($http_response_header[0], '301 Moved Permanently') !== false));
-            }
-        }
-
-        # if response is not empty and response is OK
-        if (isset($data) and isset($httpcodeOK) and $httpcodeOK) {
-            # take charset of page and get it
-            preg_match('#<meta .*charset=.*>#Usi', $data, $meta);
-
-            # if meta tag is found
-            if (!empty($meta[0])) {
-                preg_match('#charset="?(.*)"#si', $meta[0], $encoding);
-                # if charset is found set it otherwise, set it to utf-8
-                $html_charset = (!empty($encoding[1])) ? strtolower($encoding[1]) : 'utf-8';
-                if (empty($encoding[1])) {
-                    $encoding[1] = 'utf-8';
-                }
-            } else {
-                $html_charset = 'utf-8';
-                $encoding[1] = '';
-            }
-
-            # replace charset of url to charset of page
-            $data = str_replace('charset='.$encoding[1], 'charset='.$html_charset, $data);
-
-            return $data;
-        } else {
-            return false;
-        }
-    }
-
-    /**
-     * Encode a URL by using a salt.
-     *
-     * @param $string
-     *
-     * @return string
-     */
-    public static function encodeString($string)
-    {
-        return sha1($string.SALT);
-    }
-
-    public static function generateToken()
-    {
-        if (ini_get('open_basedir') === '') {
-            if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
-                // alternative to /dev/urandom for Windows
-                $token = substr(base64_encode(uniqid(mt_rand(), true)), 0, 20);
-            } else {
-                $token = substr(base64_encode(file_get_contents('/dev/urandom', false, null, 0, 20)), 0, 15);
-            }
-        } else {
-            $token = substr(base64_encode(uniqid(mt_rand(), true)), 0, 20);
-        }
-
-        return str_replace('+', '', $token);
-    }
-
-    /**
-     * For a given text, we calculate reading time for an article.
-     *
-     * @param $text
-     *
-     * @return float
-     */
-    public static function getReadingTime($text)
-    {
-        return floor(str_word_count(strip_tags($text)) / 200);
-    }
-}
index f885ee94fd09a98cae60c6c7ccbd86c9b957dda4..5538ae82b40081101d2482271a7b0b290039bfbf 100644 (file)
@@ -9,19 +9,34 @@ use Pagerfanta\Pagerfanta;
 class EntryRepository extends EntityRepository
 {
     /**
-     * Retrieves unread entries for a user.
+     * Return a query builder to used by other getBuilderFor* method.
      *
      * @param int $userId
      *
      * @return QueryBuilder
      */
-    public function findUnreadByUser($userId)
+    private function getBuilderByUser($userId)
     {
         return $this->createQueryBuilder('e')
             ->leftJoin('e.user', 'u')
-            ->where('e.isArchived = false')
-            ->andWhere('u.id =:userId')->setParameter('userId', $userId)
-            ->orderBy('e.id', 'desc');
+            ->andWhere('u.id = :userId')->setParameter('userId', $userId)
+            ->orderBy('e.id', 'desc')
+        ;
+    }
+
+    /**
+     * Retrieves unread entries for a user.
+     *
+     * @param int $userId
+     *
+     * @return QueryBuilder
+     */
+    public function getBuilderForUnreadByUser($userId)
+    {
+        return $this
+            ->getBuilderByUser($userId)
+            ->andWhere('e.isArchived = false')
+        ;
     }
 
     /**
@@ -31,13 +46,12 @@ class EntryRepository extends EntityRepository
      *
      * @return QueryBuilder
      */
-    public function findArchiveByUser($userId)
+    public function getBuilderForArchiveByUser($userId)
     {
-        return $this->createQueryBuilder('e')
-            ->leftJoin('e.user', 'u')
-            ->where('e.isArchived = true')
-            ->andWhere('u.id =:userId')->setParameter('userId', $userId)
-            ->orderBy('e.id', 'desc');
+        return $this
+            ->getBuilderByUser($userId)
+            ->andWhere('e.isArchived = true')
+        ;
     }
 
     /**
@@ -47,13 +61,12 @@ class EntryRepository extends EntityRepository
      *
      * @return QueryBuilder
      */
-    public function findStarredByUser($userId)
+    public function getBuilderForStarredByUser($userId)
     {
-        return $this->createQueryBuilder('e')
-            ->leftJoin('e.user', 'u')
-            ->where('e.isStarred = true')
-            ->andWhere('u.id =:userId')->setParameter('userId', $userId)
-            ->orderBy('e.id', 'desc');
+        return $this
+            ->getBuilderByUser($userId)
+            ->andWhere('e.isStarred = true')
+        ;
     }
 
     /**
index f3502e156e6c80e884e9beb89bd42f76ec55bdd7..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1,7 +0,0 @@
-entry:
-    resource: "@WallabagCoreBundle/Controller/EntryController.php"
-    type:     annotation
-
-config:
-    resource: "@WallabagCoreBundle/Controller/ConfigController.php"
-    type:     annotation
index 9e188cd92d51bf368d2a8785a469bf333cd6835b..311b5067a21ad72d9839a07a09a3d86f4f8bcd4f 100755 (executable)
@@ -3,38 +3,34 @@
 {% block title %}{% trans %}About{% endtrans %}{% endblock %}
 
 {% block content %}
-    <h2>{% trans %}About wallabag{% endtrans %}</h2>
+    <h2>{% trans %}Who is behind wallabag{% endtrans %}</h2>
 
     <dl>
-        <dt>{% trans %}Project website{% endtrans %}</dt>
-        <dd><a href="https://www.wallabag.org">https://www.wallabag.org</a></dd>
-
-        <dt>{% trans %}Main developer{% endtrans %}</dt>
+        <dt>{% trans %}Developed by{% endtrans %}</dt>
         <dd><a href="mailto:nicolas@loeuillet.org">Nicolas Lœuillet</a> — <a href="http://cdetc.fr">{% trans %}website{% endtrans %}</a></dd>
+        <dd>Thomas Citharel — <a href="https://tcit.fr">{% trans %}website{% endtrans %}</a></dd>
+        <dd>Jérémy Benoist — <a href="http://www.j0k3r.net">{% trans %}website{% endtrans %}</a></dd>
 
-        <dt>{% trans %}Contributors ♥:{% endtrans %}</dt>
-        <dd><a href="https://github.com/wallabag/wallabag/graphs/contributors">{% trans %}on Github{% endtrans %}</a></dd>
+        <dt>{% trans %}And many others contributors ♥{% endtrans %} <a href="https://github.com/wallabag/wallabag/graphs/contributors">{% trans %}on Github{% endtrans %}</a></dt>
 
-        <dt>{% trans %}Bug reports{% endtrans %}</dt>
-        <dd><a href="https://support.wallabag.org">{% trans %}On our support website{% endtrans %}</a> {% trans %}or{% endtrans %} <a href="https://github.com/wallabag/wallabag/issues">{% trans %}on Github{% endtrans %}</a></dd>
+        <dt>{% trans %}Project website{% endtrans %}</dt>
+        <dd><a href="https://www.wallabag.org">https://www.wallabag.org</a></dd>
 
-        <dt>{% trans %}License{% endtrans %}</dt>
-        <dd><a href="http://en.wikipedia.org/wiki/MIT_License">MIT</a></dd>
+        <dt>{% trans %}License{% endtrans %}: <a href="http://en.wikipedia.org/wiki/MIT_License">MIT</a></dt>
 
-        <dt>{% trans %}Version{% endtrans %}</dt>
-        <dd>{{ version }}</dd>
+        <dt>{% trans %}Version{% endtrans %}: {{ version }}</dt>
     </dl>
 
-    <p>{% trans %}wallabag is a read-it-later application: you can save a web page by keeping only content. Elements like ads or menus are deleted.{% endtrans %}</p>
-
     <h2>{% trans %}Getting help{% endtrans %}</h2>
 
     <dl>
         <dt>{% trans %}Documentation{% endtrans %}</dt>
-        <dd><a href="https://doc.wallabag.org/">Online documentation</a></dd>
+        <dd><a href="https://doc.wallabag.org/en">english</a></dd>
+        <dd><a href="https://doc.wallabag.org/fr">français</a></dd>
+        <dd><a href="https://doc.wallabag.org/de">deutsch</a></dd>
 
-        <dt>{% trans %}Support{% endtrans %}</dt>
-        <dd><a href="http://support.wallabag.org/">http://support.wallabag.org/</a></dd>
+        <dt>{% trans %}Bug reports{% endtrans %}</dt>
+        <dd><a href="https://support.wallabag.org">{% trans %}On our support website{% endtrans %}</a> {% trans %}or{% endtrans %} <a href="https://github.com/wallabag/wallabag/issues">{% trans %}on Github{% endtrans %}</a></dd>
     </dl>
 
     <h2>{% trans %}Helping wallabag{% endtrans %}</h2>
     <p>{% trans %}wallabag is free and opensource. You can help us:{% endtrans %}</p>
 
     <dl>
-        <dt><a href="{{ paypal_url }}">{% trans %}via Paypal{% endtrans %}</a></dt>
+        <dt>{% trans %}wallabag is free and opensource. You can help us:{% endtrans %}</dt>
+        <dd>by contributing to the project: <a href="https://github.com/wallabag/wallabag/issues/1254">an issue lists all our needs</a></dd>
+        <dd><a href="{{ paypal_url }}">{% trans %}via Paypal{% endtrans %}</a></dd>
 
-        <dt><a href="{{ flattr_url }}">{% trans %}via Flattr{% endtrans %}</a></dt>
+        <dd><a href="{{ flattr_url }}">{% trans %}via Flattr{% endtrans %}</a></dd>
     </dl>
 {% endblock %}
index e27aceae492e658ade3ff47f2ed08802f3410836..ac5d2bf9c307778cc6f70319e0f1c939af70d93a 100644 (file)
@@ -71,7 +71,7 @@
                     <li><a href="{{ path('unread') }}">{% trans %}unread{% endtrans %}</a></li>
                     <li><a href="{{ path('starred') }}">{% trans %}favorites{% endtrans %}</a></li>
                     <li><a href="{{ path('archive') }}"}>{% trans %}archive{% endtrans %}</a></li>
-                    <li><a href="{{ path ('tag') }}">{% trans %}tags{% endtrans %}</a></li>
+                    <li><a href="{{ path('tag') }}">{% trans %}tags{% endtrans %}</a></li>
                     <li><a href="{{ path('new') }}">{% trans %}save a link{% endtrans %}</a></li>
                     <li style="position: relative;"><a href="javascript: void(null);" id="search">{% trans %}search{% endtrans %}</a>
                         <div id="search-form" class="messages info popup-form">
index 8c6269eca172f9107b9dbf637bb3e79c75c1d230..5de71d77c37f4c78c26f0a83c97432cf0b725bb9 100755 (executable)
@@ -21,7 +21,7 @@
                         <dt>{% trans %}Developed by{% endtrans %}</dt>
                         <dd><a href="mailto:nicolas@loeuillet.org">Nicolas Lœuillet</a> — <a href="http://cdetc.fr">{% trans %}website{% endtrans %}</a></dd>
                         <dd>Thomas Citharel — <a href="https://tcit.fr">{% trans %}website{% endtrans %}</a></dd>
-                        <dd>Jérémy Besnoit — <a href="http://wildtrip.net">{% trans %}website{% endtrans %}</a></dd>
+                        <dd>Jérémy Benoist — <a href="http://www.j0k3r.net">{% trans %}website{% endtrans %}</a></dd>
                         <dt>{% trans %}And many others contributors ♥{% endtrans %} <a href="https://github.com/wallabag/wallabag/graphs/contributors">{% trans %}on Github{% endtrans %}</a></dt>
                         <dt>{% trans %}Project website{% endtrans %}</dt>
                         <dd><a href="https://www.wallabag.org">https://www.wallabag.org</a></dd>
index 554865d7fa1d56049bfcde7987d771a25f6a41ce..1456d5dd620646d0544fae3555d4c7d05b9e8a3f 100644 (file)
@@ -55,9 +55,9 @@
             </div>
             <div class="input-field nav-panel-buttom">
                 <ul>
-                    <li class="bold"><a class="waves-effect" href="{{ path('new') }}" id="nav-btn-add"><i class="mdi-content-add"></i></a></li>
-                    <li><a class="waves-effect" href="javascript: void(null);" id="nav-btn-search"><i class="mdi-action-search"></i></a>
-                    <li id="button_filters"><a href="#" data-activates="filters" class="nav-panel-menu button-collapse-right"><i class="mdi-content-filter-list"></i></a></li>
+                    <li class="bold"><a title="{% trans %}Add a new entry{% endtrans %}" class="waves-effect" href="{{ path('new') }}" id="nav-btn-add"><i class="mdi-content-add"></i></a></li>
+                    <li><a title="{% trans %}Search{% endtrans %}" class="waves-effect" href="javascript: void(null);" id="nav-btn-search"><i class="mdi-action-search"></i></a>
+                    <li id="button_filters"><a title="{% trans %}Filter entries{% endtrans %}" href="#" data-activates="filters" class="nav-panel-menu button-collapse-right"><i class="mdi-content-filter-list"></i></a></li>
                 </ul>
             </div>
             <form method="get" action="index.php">
index 7e2968e77f45153fc55178fd9bac190450a7bb5a..a16baca97e0a09e27e7c35e7ecafdfdf0131416e 100644 (file)
@@ -25,4 +25,17 @@ class Utils
         // remove character which can broken the url
         return str_replace(array('+', '/'), '', $token);
     }
+
+    /**
+     * For a given text, we calculate reading time for an article
+     * based on 200 words per minute.
+     *
+     * @param $text
+     *
+     * @return float
+     */
+    public static function getReadingTime($text)
+    {
+        return floor(str_word_count(strip_tags($text)) / 200);
+    }
 }