2015-10-23 12:01:27 +00:00
< ? php
namespace Wallabag\ImportBundle\Import ;
2015-12-30 11:23:51 +00:00
use Psr\Log\LoggerInterface ;
use Psr\Log\NullLogger ;
2015-10-23 12:01:27 +00:00
use Doctrine\ORM\EntityManager ;
use GuzzleHttp\Client ;
2015-12-30 11:23:51 +00:00
use GuzzleHttp\Exception\RequestException ;
2015-12-24 14:22:56 +00:00
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface ;
2015-10-23 12:01:27 +00:00
use Wallabag\CoreBundle\Entity\Entry ;
2015-10-26 09:55:35 +00:00
use Wallabag\CoreBundle\Entity\Tag ;
2015-12-30 11:23:51 +00:00
use Wallabag\CoreBundle\Helper\ContentProxy ;
2016-01-05 21:38:09 +00:00
use Symfony\Component\Translation\TranslatorInterface ;
2015-10-23 12:01:27 +00:00
class PocketImport implements ImportInterface
{
private $user ;
private $em ;
2015-12-30 11:23:51 +00:00
private $contentProxy ;
private $logger ;
2016-01-03 09:59:55 +00:00
private $client ;
2015-10-23 12:01:27 +00:00
private $consumerKey ;
2015-10-26 14:49:44 +00:00
private $skippedEntries = 0 ;
private $importedEntries = 0 ;
2015-12-30 11:23:51 +00:00
protected $accessToken ;
2016-01-05 21:38:09 +00:00
private $translator ;
2015-10-23 12:01:27 +00:00
2016-01-05 21:38:09 +00:00
public function __construct ( TokenStorageInterface $tokenStorage , EntityManager $em , ContentProxy $contentProxy , $consumerKey , TranslatorInterface $translator )
2015-10-23 12:01:27 +00:00
{
$this -> user = $tokenStorage -> getToken () -> getUser ();
$this -> em = $em ;
2015-12-30 11:23:51 +00:00
$this -> contentProxy = $contentProxy ;
2015-10-23 12:01:27 +00:00
$this -> consumerKey = $consumerKey ;
2015-12-30 11:23:51 +00:00
$this -> logger = new NullLogger ();
2016-01-05 21:38:09 +00:00
$this -> translator = $translator ;
2015-12-30 11:23:51 +00:00
}
public function setLogger ( LoggerInterface $logger )
{
$this -> logger = $logger ;
2015-10-23 12:01:27 +00:00
}
2015-12-24 14:22:56 +00:00
/**
* { @ inheritdoc }
*/
2015-10-23 12:45:50 +00:00
public function getName ()
{
return 'Pocket' ;
}
2015-12-31 10:24:46 +00:00
/**
* { @ inheritdoc }
*/
public function getUrl ()
{
return 'import_pocket' ;
}
2015-12-24 14:22:56 +00:00
/**
* { @ inheritdoc }
*/
2015-10-23 12:45:50 +00:00
public function getDescription ()
{
2016-01-05 21:38:09 +00:00
return $this -> translator -> trans ( " This importer will import all your <a href= \" https://getpocket.com \" >Pocket</a> data. Pocket doesn't allow us to retrieve content from their service, so the readable content of each article will be re-fetched by wallabag. " );
2015-10-23 12:45:50 +00:00
}
2015-10-23 12:01:27 +00:00
/**
2015-12-30 11:23:51 +00:00
* Return the oauth url to authenticate the client .
*
* @ param string $redirectUri Redirect url in case of error
*
* @ return string request_token for callback method
2015-12-24 14:24:18 +00:00
*/
2015-12-30 11:23:51 +00:00
public function getRequestToken ( $redirectUri )
2015-12-24 14:24:18 +00:00
{
$request = $this -> client -> createRequest ( 'POST' , 'https://getpocket.com/v3/oauth/request' ,
[
'body' => json_encode ([
'consumer_key' => $this -> consumerKey ,
'redirect_uri' => $redirectUri ,
]),
]
);
2015-12-30 11:23:51 +00:00
try {
$response = $this -> client -> send ( $request );
} catch ( RequestException $e ) {
$this -> logger -> error ( sprintf ( 'PocketImport: Failed to request token: %s' , $e -> getMessage ()), [ 'exception' => $e ]);
2015-12-24 14:24:18 +00:00
2015-12-30 11:23:51 +00:00
return false ;
}
2015-12-24 14:24:18 +00:00
2015-12-30 11:23:51 +00:00
return $response -> json ()[ 'code' ];
2015-12-24 14:24:18 +00:00
}
/**
2015-12-30 11:23:51 +00:00
* Usually called by the previous callback to authorize the client .
* Then it return a token that can be used for next requests .
*
* @ param string $code request_token from getRequestToken
*
* @ return bool
2015-12-24 14:24:18 +00:00
*/
2015-12-30 11:23:51 +00:00
public function authorize ( $code )
2015-12-24 14:24:18 +00:00
{
$request = $this -> client -> createRequest ( 'POST' , 'https://getpocket.com/v3/oauth/authorize' ,
[
'body' => json_encode ([
'consumer_key' => $this -> consumerKey ,
2015-12-30 11:23:51 +00:00
'code' => $code ,
2015-12-24 14:24:18 +00:00
]),
]
);
2015-12-30 11:23:51 +00:00
try {
$response = $this -> client -> send ( $request );
} catch ( RequestException $e ) {
$this -> logger -> error ( sprintf ( 'PocketImport: Failed to authorize client: %s' , $e -> getMessage ()), [ 'exception' => $e ]);
2015-12-24 14:24:18 +00:00
2015-12-30 11:23:51 +00:00
return false ;
}
$this -> accessToken = $response -> json ()[ 'access_token' ];
return true ;
2015-12-24 14:24:18 +00:00
}
/**
* { @ inheritdoc }
*/
2015-12-30 11:23:51 +00:00
public function import ()
2015-12-24 14:24:18 +00:00
{
$request = $this -> client -> createRequest ( 'POST' , 'https://getpocket.com/v3/get' ,
[
'body' => json_encode ([
'consumer_key' => $this -> consumerKey ,
2015-12-30 11:23:51 +00:00
'access_token' => $this -> accessToken ,
2015-12-24 14:24:18 +00:00
'detailType' => 'complete' ,
'state' => 'all' ,
'sort' => 'oldest' ,
]),
]
);
2015-12-30 11:23:51 +00:00
try {
$response = $this -> client -> send ( $request );
} catch ( RequestException $e ) {
$this -> logger -> error ( sprintf ( 'PocketImport: Failed to import: %s' , $e -> getMessage ()), [ 'exception' => $e ]);
return false ;
}
2015-12-24 14:24:18 +00:00
$entries = $response -> json ();
2015-12-30 12:26:30 +00:00
$this -> parseEntries ( $entries [ 'list' ]);
2015-12-24 14:24:18 +00:00
2015-12-30 11:23:51 +00:00
return true ;
2015-12-24 14:24:18 +00:00
}
/**
2015-12-30 11:23:51 +00:00
* { @ inheritdoc }
2015-10-23 12:01:27 +00:00
*/
2015-12-30 11:23:51 +00:00
public function getSummary ()
2015-10-23 12:01:27 +00:00
{
2015-12-30 11:23:51 +00:00
return [
'skipped' => $this -> skippedEntries ,
'imported' => $this -> importedEntries ,
];
2015-10-23 12:01:27 +00:00
}
2015-10-26 09:55:35 +00:00
/**
2015-12-30 11:23:51 +00:00
* Set the Guzzle client .
2015-10-26 09:55:35 +00:00
*
2015-12-30 11:23:51 +00:00
* @ param Client $client
2015-10-26 09:55:35 +00:00
*/
2015-12-30 11:23:51 +00:00
public function setClient ( Client $client )
2015-10-26 09:55:35 +00:00
{
2015-12-30 11:23:51 +00:00
$this -> client = $client ;
2015-10-26 13:38:24 +00:00
}
/**
2015-12-30 11:23:51 +00:00
* @ todo move that in a more global place
2015-10-26 13:38:24 +00:00
*/
2015-10-26 09:55:35 +00:00
private function assignTagsToEntry ( Entry $entry , $tags )
{
foreach ( $tags as $tag ) {
$label = trim ( $tag [ 'tag' ]);
$tagEntity = $this -> em
-> getRepository ( 'WallabagCoreBundle:Tag' )
2016-01-03 09:32:56 +00:00
-> findOneByLabel ( $label );
2015-10-26 09:55:35 +00:00
if ( is_object ( $tagEntity )) {
$entry -> addTag ( $tagEntity );
} else {
2016-01-03 09:32:56 +00:00
$newTag = new Tag ();
2015-10-26 09:55:35 +00:00
$newTag -> setLabel ( $label );
2016-01-03 09:32:56 +00:00
2015-10-26 09:55:35 +00:00
$entry -> addTag ( $newTag );
}
$this -> em -> flush ();
}
}
2015-10-23 12:01:27 +00:00
/**
2015-12-30 11:23:51 +00:00
* @ see https :// getpocket . com / developer / docs / v3 / retrieve
*
2015-10-23 12:01:27 +00:00
* @ param $entries
*/
2015-12-30 12:26:30 +00:00
private function parseEntries ( $entries )
2015-10-23 12:01:27 +00:00
{
2015-12-31 10:24:46 +00:00
$i = 1 ;
2015-10-26 09:55:35 +00:00
foreach ( $entries as $pocketEntry ) {
2015-12-30 11:23:51 +00:00
$url = isset ( $pocketEntry [ 'resolved_url' ]) && $pocketEntry [ 'resolved_url' ] != '' ? $pocketEntry [ 'resolved_url' ] : $pocketEntry [ 'given_url' ];
2015-10-26 13:38:24 +00:00
$existingEntry = $this -> em
-> getRepository ( 'WallabagCoreBundle:Entry' )
2015-12-24 14:19:50 +00:00
-> existByUrlAndUserId ( $url , $this -> user -> getId ());
2015-10-26 13:38:24 +00:00
2015-12-24 14:19:50 +00:00
if ( false !== $existingEntry ) {
2015-10-26 13:38:24 +00:00
++ $this -> skippedEntries ;
continue ;
}
2015-12-30 12:26:30 +00:00
$entry = new Entry ( $this -> user );
2015-12-30 11:23:51 +00:00
$entry = $this -> contentProxy -> updateEntry ( $entry , $url );
2015-10-26 13:38:24 +00:00
2015-12-30 11:23:51 +00:00
// 0, 1, 2 - 1 if the item is archived - 2 if the item should be deleted
2015-10-26 09:55:35 +00:00
if ( $pocketEntry [ 'status' ] == 1 ) {
$entry -> setArchived ( true );
}
2015-12-30 11:23:51 +00:00
// 0 or 1 - 1 If the item is favorited
2015-10-26 09:55:35 +00:00
if ( $pocketEntry [ 'favorite' ] == 1 ) {
$entry -> setStarred ( true );
}
2015-12-30 11:23:51 +00:00
$title = 'Untitled' ;
if ( isset ( $pocketEntry [ 'resolved_title' ]) && $pocketEntry [ 'resolved_title' ] != '' ) {
$title = $pocketEntry [ 'resolved_title' ];
} elseif ( isset ( $pocketEntry [ 'given_title' ]) && $pocketEntry [ 'given_title' ] != '' ) {
$title = $pocketEntry [ 'given_title' ];
2015-10-26 09:55:35 +00:00
}
2015-10-23 12:01:27 +00:00
2015-12-30 11:23:51 +00:00
$entry -> setTitle ( $title );
2015-10-23 12:01:27 +00:00
2015-12-30 11:23:51 +00:00
// 0, 1, or 2 - 1 if the item has images in it - 2 if the item is an image
if ( isset ( $pocketEntry [ 'has_image' ]) && $pocketEntry [ 'has_image' ] > 0 && isset ( $pocketEntry [ 'images' ][ 1 ])) {
$entry -> setPreviewPicture ( $pocketEntry [ 'images' ][ 1 ][ 'src' ]);
2015-10-23 12:01:27 +00:00
}
2015-12-30 11:23:51 +00:00
if ( isset ( $pocketEntry [ 'tags' ]) && ! empty ( $pocketEntry [ 'tags' ])) {
2015-10-26 14:49:44 +00:00
$this -> assignTagsToEntry ( $entry , $pocketEntry [ 'tags' ]);
2015-10-23 12:01:27 +00:00
}
2015-10-26 09:55:35 +00:00
$this -> em -> persist ( $entry );
2015-10-26 13:38:24 +00:00
++ $this -> importedEntries ;
2015-12-31 10:24:46 +00:00
// flush every 20 entries
if (( $i % 20 ) === 0 ) {
2016-01-03 09:59:55 +00:00
$this -> em -> flush ();
2015-12-31 10:24:46 +00:00
}
++ $i ;
2015-10-23 12:01:27 +00:00
}
$this -> em -> flush ();
}
}