From 1f4408de9ed08f3b0fda45a93f1585c80feeb21d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20L=C5=93uillet?= Date: Tue, 20 Oct 2015 13:58:13 +0200 Subject: 1st draft for Pocket import via API --- app/AppKernel.php | 1 + app/config/parameters.yml.dist | 3 + app/config/routing.yml | 5 + composer.json | 3 +- composer.lock | 66 +++++----- src/Wallabag/CoreBundle/Tools/Utils.php | 11 +- .../ImportBundle/Controller/PocketController.php | 139 +++++++++++++++++++++ .../Resources/views/Pocket/index.html.twig | 16 +++ src/Wallabag/ImportBundle/WallabagImportBundle.php | 9 ++ 9 files changed, 219 insertions(+), 34 deletions(-) create mode 100644 src/Wallabag/ImportBundle/Controller/PocketController.php create mode 100644 src/Wallabag/ImportBundle/Resources/views/Pocket/index.html.twig create mode 100644 src/Wallabag/ImportBundle/WallabagImportBundle.php diff --git a/app/AppKernel.php b/app/AppKernel.php index 85edc14a..93b0201a 100644 --- a/app/AppKernel.php +++ b/app/AppKernel.php @@ -31,6 +31,7 @@ class AppKernel extends Kernel new Stof\DoctrineExtensionsBundle\StofDoctrineExtensionsBundle(), new Scheb\TwoFactorBundle\SchebTwoFactorBundle(), new KPhoen\RulerZBundle\KPhoenRulerZBundle(), + new Wallabag\ImportBundle\WallabagImportBundle(), ); if (in_array($this->getEnvironment(), array('dev', 'test'))) { diff --git a/app/config/parameters.yml.dist b/app/config/parameters.yml.dist index 149179c2..c0d57aa1 100644 --- a/app/config/parameters.yml.dist +++ b/app/config/parameters.yml.dist @@ -60,3 +60,6 @@ parameters: language: en from_email: no-reply@wallabag.org rss_limit: 50 + + # pocket import + pocket_consumer_key: 47025-85ed5e6cfd72abbb49d12db1 diff --git a/app/config/routing.yml b/app/config/routing.yml index 0f7b61fb..91a5705f 100644 --- a/app/config/routing.yml +++ b/app/config/routing.yml @@ -1,3 +1,8 @@ +wallabag_import: + resource: "@WallabagImportBundle/Controller/" + type: annotation + prefix: / + wallabag_api: resource: "@WallabagApiBundle/Resources/config/routing.yml" prefix: / diff --git a/composer.json b/composer.json index bf519faf..0ba42a3e 100644 --- a/composer.json +++ b/composer.json @@ -59,7 +59,8 @@ "scheb/two-factor-bundle": "~1.4.0", "grandt/phpepub": "~4.0", "wallabag/php-mobi": "~1.0.0", - "kphoen/rulerz-bundle": "~0.10" + "kphoen/rulerz-bundle": "~0.10", + "guzzlehttp/guzzle": "^5.2.0" }, "require-dev": { "doctrine/doctrine-fixtures-bundle": "~2.2.0", diff --git a/composer.lock b/composer.lock index aee96198..076dfcac 100644 --- a/composer.lock +++ b/composer.lock @@ -117,16 +117,16 @@ }, { "name": "doctrine/cache", - "version": "v1.5.4", + "version": "v1.5.2", "source": { "type": "git", "url": "https://github.com/doctrine/cache.git", - "reference": "47cdc76ceb95cc591d9c79a36dc3794975b5d136" + "reference": "47c7128262da274f590ae6f86eb137a7a64e82af" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/cache/zipball/47cdc76ceb95cc591d9c79a36dc3794975b5d136", - "reference": "47cdc76ceb95cc591d9c79a36dc3794975b5d136", + "url": "https://api.github.com/repos/doctrine/cache/zipball/47c7128262da274f590ae6f86eb137a7a64e82af", + "reference": "47c7128262da274f590ae6f86eb137a7a64e82af", "shasum": "" }, "require": { @@ -183,7 +183,7 @@ "cache", "caching" ], - "time": "2015-12-19 05:03:47" + "time": "2015-12-03 10:50:37" }, { "name": "doctrine/collections", @@ -981,17 +981,17 @@ }, { "name": "friendsofsymfony/rest-bundle", - "version": "1.7.6", + "version": "1.7.4", "target-dir": "FOS/RestBundle", "source": { "type": "git", "url": "https://github.com/FriendsOfSymfony/FOSRestBundle.git", - "reference": "f95b2f141748e9a5e2ddae833f60c38417aee8c3" + "reference": "64ba918b1eb47acb5aa7fef1ce95623235b53775" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/FriendsOfSymfony/FOSRestBundle/zipball/f95b2f141748e9a5e2ddae833f60c38417aee8c3", - "reference": "f95b2f141748e9a5e2ddae833f60c38417aee8c3", + "url": "https://api.github.com/repos/FriendsOfSymfony/FOSRestBundle/zipball/64ba918b1eb47acb5aa7fef1ce95623235b53775", + "reference": "64ba918b1eb47acb5aa7fef1ce95623235b53775", "shasum": "" }, "require": { @@ -1063,7 +1063,7 @@ "keywords": [ "rest" ], - "time": "2015-12-20 13:45:30" + "time": "2015-12-05 14:55:07" }, { "name": "friendsofsymfony/user-bundle", @@ -2313,16 +2313,16 @@ }, { "name": "j0k3r/graby", - "version": "1.0.8", + "version": "1.0.6", "source": { "type": "git", "url": "https://github.com/j0k3r/graby.git", - "reference": "bf152ccc6629bdd63b1e5e8b297c2912516b5f1e" + "reference": "c9f5543fad60dc4efd12195733f96bb4fdb0e6e0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/j0k3r/graby/zipball/bf152ccc6629bdd63b1e5e8b297c2912516b5f1e", - "reference": "bf152ccc6629bdd63b1e5e8b297c2912516b5f1e", + "url": "https://api.github.com/repos/j0k3r/graby/zipball/c9f5543fad60dc4efd12195733f96bb4fdb0e6e0", + "reference": "c9f5543fad60dc4efd12195733f96bb4fdb0e6e0", "shasum": "" }, "require": { @@ -2365,20 +2365,20 @@ } ], "description": "Graby helps you extract article content from web pages", - "time": "2015-12-24 08:28:38" + "time": "2015-12-02 13:22:19" }, { "name": "j0k3r/graby-site-config", - "version": "1.0.11", + "version": "1.0.9", "source": { "type": "git", "url": "https://github.com/j0k3r/graby-site-config.git", - "reference": "ac198f308beabccc97bbd35ed0daeaac63fbf1e3" + "reference": "7666fed2a2cd211ef366f6fed9ccddd8e0b9e623" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/j0k3r/graby-site-config/zipball/ac198f308beabccc97bbd35ed0daeaac63fbf1e3", - "reference": "ac198f308beabccc97bbd35ed0daeaac63fbf1e3", + "url": "https://api.github.com/repos/j0k3r/graby-site-config/zipball/7666fed2a2cd211ef366f6fed9ccddd8e0b9e623", + "reference": "7666fed2a2cd211ef366f6fed9ccddd8e0b9e623", "shasum": "" }, "require": { @@ -2401,7 +2401,7 @@ } ], "description": "Graby site config files", - "time": "2015-12-23 22:52:15" + "time": "2015-12-03 19:49:20" }, { "name": "j0k3r/php-readability", @@ -3138,7 +3138,9 @@ "authors": [ { "name": "S.C. Chen", - "email": "me578022@gmail.com" + "email": "me578022@gmail.com", + "homepage": "http://simplehtmldom.sourceforge.net/", + "role": "Lead Developer" } ], "description": "Composer package that gives you access to and (unlike all the others at this time) autoloads S.C. Chen's PHP Simple HTML DOM Parser Library", @@ -3765,16 +3767,16 @@ }, { "name": "scheb/two-factor-bundle", - "version": "v1.4.7", + "version": "v1.5.0", "source": { "type": "git", "url": "https://github.com/scheb/two-factor-bundle.git", - "reference": "ef6830dbbf62b22efd335db8f64bf0f51d4284a2" + "reference": "b0da3a85b181237c3bebde88c99b18745313360b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/scheb/two-factor-bundle/zipball/ef6830dbbf62b22efd335db8f64bf0f51d4284a2", - "reference": "ef6830dbbf62b22efd335db8f64bf0f51d4284a2", + "url": "https://api.github.com/repos/scheb/two-factor-bundle/zipball/b0da3a85b181237c3bebde88c99b18745313360b", + "reference": "b0da3a85b181237c3bebde88c99b18745313360b", "shasum": "" }, "require": { @@ -3810,7 +3812,7 @@ "two-factor", "two-step" ], - "time": "2015-08-25 19:58:00" + "time": "2015-11-15 13:31:23" }, { "name": "sensio/distribution-bundle", @@ -5437,16 +5439,16 @@ }, { "name": "phpunit/phpunit", - "version": "4.8.21", + "version": "4.8.20", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "ea76b17bced0500a28098626b84eda12dbcf119c" + "reference": "7438c43bc2bbb2febe1723eb595b1c49283a26ad" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/ea76b17bced0500a28098626b84eda12dbcf119c", - "reference": "ea76b17bced0500a28098626b84eda12dbcf119c", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/7438c43bc2bbb2febe1723eb595b1c49283a26ad", + "reference": "7438c43bc2bbb2febe1723eb595b1c49283a26ad", "shasum": "" }, "require": { @@ -5455,7 +5457,7 @@ "ext-pcre": "*", "ext-reflection": "*", "ext-spl": "*", - "php": ">=5.3.3", + "php": "~5.3.3|~5.4|~5.5|~5.6", "phpspec/prophecy": "^1.3.1", "phpunit/php-code-coverage": "~2.1", "phpunit/php-file-iterator": "~1.4", @@ -5505,7 +5507,7 @@ "testing", "xunit" ], - "time": "2015-12-12 07:45:58" + "time": "2015-12-10 07:48:52" }, { "name": "phpunit/phpunit-mock-objects", diff --git a/src/Wallabag/CoreBundle/Tools/Utils.php b/src/Wallabag/CoreBundle/Tools/Utils.php index a16baca9..b146d98b 100644 --- a/src/Wallabag/CoreBundle/Tools/Utils.php +++ b/src/Wallabag/CoreBundle/Tools/Utils.php @@ -26,6 +26,15 @@ class Utils return str_replace(array('+', '/'), '', $token); } + /** + * @param $words + * @return float + */ + public static function convertWordsToMinutes($words) + { + return floor($words / 200); + } + /** * For a given text, we calculate reading time for an article * based on 200 words per minute. @@ -36,6 +45,6 @@ class Utils */ public static function getReadingTime($text) { - return floor(str_word_count(strip_tags($text)) / 200); + return self::convertWordsToMinutes(str_word_count(strip_tags($text))); } } diff --git a/src/Wallabag/ImportBundle/Controller/PocketController.php b/src/Wallabag/ImportBundle/Controller/PocketController.php new file mode 100644 index 00000000..ffd0c9ab --- /dev/null +++ b/src/Wallabag/ImportBundle/Controller/PocketController.php @@ -0,0 +1,139 @@ +render('WallabagImportBundle:Pocket:index.html.twig', array()); + } + + /** + * Create a new Client. + * + * @return Client + */ + private function createClient() + { + return new Client([ + 'defaults' => [ + 'headers' => [ + 'content-type' => 'application/json', + 'X-Accept' => 'application/json', + ], + ], + ]); + } + + /** + * @Route("/auth-pocket", name="authpocket") + */ + public function authAction() + { + $client = $this->createClient(); + $request = $client->createRequest('POST', 'https://getpocket.com/v3/oauth/request', + [ + 'body' => json_encode([ + 'consumer_key' => $this->container->getParameter('pocket_consumer_key'), + 'redirect_uri' => $this->generateUrl('import', array(), true), + ]), + ] + ); + + $response = $client->send($request); + $values = $response->json(); + $code = $values['code']; + + // store code in session for callback method + $session = $this->get('session'); + $session->set('pocketCode', $code); + + $url = 'https://getpocket.com/auth/authorize?request_token='.$code.'&redirect_uri='.$this->generateUrl('callbackpocket', array(), true); + + return $this->redirect($url, 301); + } + + /** + * @Route("/callback-pocket", name="callbackpocket") + */ + public function callbackAction() + { + $client = $this->createClient(); + + $request = $client->createRequest('POST', 'https://getpocket.com/v3/oauth/authorize', + [ + 'body' => json_encode([ + 'consumer_key' => $this->container->getParameter('pocket_consumer_key'), + 'code' => $this->get('session')->get('pocketCode'), + ]), + ] + ); + + $response = $client->send($request); + $values = $response->json(); + $accessToken = $values['access_token']; + + $request = $client->createRequest('POST', 'https://getpocket.com/v3/get', + [ + 'body' => json_encode([ + 'consumer_key' => $this->container->getParameter('pocket_consumer_key'), + 'access_token' => $accessToken, + 'detailType' => 'complete', + ]), + ] + ); + + $response = $client->send($request); + $entries = $response->json(); + + $this->parsePocketEntries($entries['list']); + + $this->get('session')->getFlashBag()->add( + 'notice', + count($entries['list']).' entries imported' + ); + + return $this->redirect($this->generateUrl('homepage')); + } + + /** + * @param $entries + */ + private function parsePocketEntries($entries) + { + $em = $this->getDoctrine()->getManager(); + + foreach ($entries as $entry) { + $newEntry = new Entry($this->getUser()); + $newEntry->setUrl($entry['given_url']); + $newEntry->setTitle(isset($entry['resolved_title']) ? $entry['resolved_title'] : (isset($entry['given_title']) ? $entry['given_title'] : 'Untitled')); + + if (isset($entry['excerpt'])) { + $newEntry->setContent($entry['excerpt']); + } + + if (isset($entry['has_image']) && $entry['has_image'] > 0) { + $newEntry->setPreviewPicture($entry['image']['src']); + } + + if (isset($entry['word_count'])) { + $newEntry->setReadingTime(Utils::convertWordsToMinutes($entry['word_count'])); + } + + $em->persist($newEntry); + } + + $em->flush(); + } +} diff --git a/src/Wallabag/ImportBundle/Resources/views/Pocket/index.html.twig b/src/Wallabag/ImportBundle/Resources/views/Pocket/index.html.twig new file mode 100644 index 00000000..d47dd8d5 --- /dev/null +++ b/src/Wallabag/ImportBundle/Resources/views/Pocket/index.html.twig @@ -0,0 +1,16 @@ +{% extends "WallabagCoreBundle::layout.html.twig" %} +{% block title %}{% trans %}import{% endtrans %}{% endblock %} + +{% block content %} + +
+
+
+ {% trans %}You can import your data from your Pocket account. You just have to click on the below button and authorize the application to connect to getpocket.com.{% endtrans %} +
+ +
+
+
+
+{% endblock %} diff --git a/src/Wallabag/ImportBundle/WallabagImportBundle.php b/src/Wallabag/ImportBundle/WallabagImportBundle.php new file mode 100644 index 00000000..d00f2fe9 --- /dev/null +++ b/src/Wallabag/ImportBundle/WallabagImportBundle.php @@ -0,0 +1,9 @@ +