diff --git a/.gitignore b/.gitignore index e103e7e..b10ea56 100644 --- a/.gitignore +++ b/.gitignore @@ -43,3 +43,10 @@ sftp-config.json test.php /cache + + +### PhpStorm+all Patch ### +# Ignores the whole idea folder +# See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360 + +.idea/ \ No newline at end of file diff --git a/README.md b/README.md index 187e154..d1c90a6 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,11 @@ # mixedfeed -A PHP library to get social networks feeds and merge them + +> A PHP library to rule them all, to entangle them with magic, a PHP library to gather them and bind them in darkness [![SensioLabsInsight](https://insight.sensiolabs.com/projects/ed3544de-7d64-4ef9-a551-c61a66fb668d/mini.png)](https://insight.sensiolabs.com/projects/ed3544de-7d64-4ef9-a551-c61a66fb668d) ![License](http://img.shields.io/:license-mit-blue.svg) -## Install +## Install ```shell composer require rezozero/mixedfeed @@ -32,6 +33,9 @@ $feed = new MixedFeed([ 'twitter_access_token', 'twitter_access_token_secret', // you can add a doctrine cache provider + // exclude replies true/false + // include retweets true/false + // extended mode true/false ), new TwitterSearchFeed( [ diff --git a/composer.json b/composer.json index e991bbf..70721fb 100644 --- a/composer.json +++ b/composer.json @@ -18,9 +18,9 @@ "rezo zero" ], "require": { - "abraham/twitteroauth": "^0.6.1", - "doctrine/cache": "^1.4", - "guzzlehttp/guzzle": "~5.0" + "abraham/twitteroauth": "^0.7.4", + "doctrine/cache": "^1.6.2", + "guzzlehttp/guzzle": "~5.0 || ~6.0" }, "autoload": { "psr-4": {"RZ\\MixedFeed\\": "src/"} diff --git a/src/AbstractFeedProvider.php b/src/AbstractFeedProvider.php index 9beaa7b..abaf51f 100644 --- a/src/AbstractFeedProvider.php +++ b/src/AbstractFeedProvider.php @@ -26,7 +26,6 @@ namespace RZ\MixedFeed; use RZ\MixedFeed\Exception\FeedProviderErrorException; -use RZ\MixedFeed\FeedProviderInterface; /** * Implements a basic feed provider with @@ -36,6 +35,12 @@ abstract class AbstractFeedProvider implements FeedProviderInterface { protected $ttl = 7200; + /** + * @param int $count + * @return array + */ + protected abstract function getFeed($count = 5); + /** * {@inheritdoc} */ diff --git a/src/AbstractFeedProvider/AbstractTwitterFeed.php b/src/AbstractFeedProvider/AbstractTwitterFeed.php index e1f26e9..92ef72f 100644 --- a/src/AbstractFeedProvider/AbstractTwitterFeed.php +++ b/src/AbstractFeedProvider/AbstractTwitterFeed.php @@ -27,14 +27,13 @@ use Abraham\TwitterOAuth\TwitterOAuth; use Doctrine\Common\Cache\CacheProvider; -use RZ\MixedFeed\AbstractFeedProvider; -use RZ\MixedFeed\Exception\CredentialsException; use RZ\MixedFeed\AbstractFeedProvider as BaseFeedProvider; +use RZ\MixedFeed\Exception\CredentialsException; /** * Get a Twitter tweets abstract feed. */ -class AbstractTwitterFeed extends BaseFeedProvider +abstract class AbstractTwitterFeed extends BaseFeedProvider { protected $accessToken; protected $cacheProvider; @@ -44,12 +43,12 @@ class AbstractTwitterFeed extends BaseFeedProvider /** * - * @param array $queryParams - * @param string $consumerKey - * @param string $consumerSecret - * @param string $accessToken - * @param string $accessTokenSecret + * @param string $consumerKey + * @param string $consumerSecret + * @param string $accessToken + * @param string $accessTokenSecret * @param CacheProvider|null $cacheProvider + * @throws CredentialsException */ public function __construct( $consumerKey, @@ -105,7 +104,11 @@ public function getDateTime($item) */ public function getCanonicalMessage($item) { - return $item->text; + if (isset($item->text)) { + return $item->text; + } + + return $item->full_text; } /** diff --git a/src/Exception/CredentialsException.php b/src/Exception/CredentialsException.php index 03286b4..1474a31 100644 --- a/src/Exception/CredentialsException.php +++ b/src/Exception/CredentialsException.php @@ -25,10 +25,12 @@ */ namespace RZ\MixedFeed\Exception; +use Throwable; + class CredentialsException extends \Exception { - public function __construct($message = "Unsufficient authentification data found.") + public function __construct($message = "Unsufficient authentification data found.", $code = 0, Throwable $previous = null) { - parent::__construct($message, 1); + parent::__construct($message, $code, $previous); } } diff --git a/src/FacebookPageFeed.php b/src/FacebookPageFeed.php index 9dc343d..38860cc 100644 --- a/src/FacebookPageFeed.php +++ b/src/FacebookPageFeed.php @@ -26,8 +26,8 @@ namespace RZ\MixedFeed; use Doctrine\Common\Cache\CacheProvider; +use GuzzleHttp\Client; use GuzzleHttp\Exception\ClientException; -use RZ\MixedFeed\AbstractFeedProvider; use RZ\MixedFeed\Exception\CredentialsException; /** @@ -42,17 +42,24 @@ class FacebookPageFeed extends AbstractFeedProvider protected $cacheProvider; protected $cacheKey; protected $fields; + /** + * @var \DateTime|null + */ protected $since = null; + /** + * @var \DateTime|null + */ protected $until = null; protected static $timeKey = 'created_time'; /** * - * @param string $pageId - * @param string $accessToken Your App Token + * @param string $pageId + * @param string $accessToken Your App Token * @param CacheProvider|null $cacheProvider - * @param array $fields + * @param array $fields + * @throws CredentialsException */ public function __construct( $pageId, @@ -85,7 +92,7 @@ protected function getFeed($count = 5) return $this->cacheProvider->fetch($countKey); } - $client = new \GuzzleHttp\Client(); + $client = new Client(); $params = [ 'query' => [ 'access_token' => $this->accessToken, diff --git a/src/GithubCommitsFeed.php b/src/GithubCommitsFeed.php index 849b112..d824ba9 100644 --- a/src/GithubCommitsFeed.php +++ b/src/GithubCommitsFeed.php @@ -27,7 +27,6 @@ use Doctrine\Common\Cache\CacheProvider; use GuzzleHttp\Exception\ClientException; -use RZ\MixedFeed\AbstractFeedProvider; use RZ\MixedFeed\Exception\CredentialsException; /** @@ -45,9 +44,11 @@ class GithubCommitsFeed extends AbstractFeedProvider /** * - * @param string $repository - * @param string $accessToken + * @param string $repository + * @param string $accessToken * @param CacheProvider|null $cacheProvider + * @param int $page + * @throws CredentialsException */ public function __construct( $repository, diff --git a/src/InstagramFeed.php b/src/InstagramFeed.php index ac4fd36..a1ef290 100644 --- a/src/InstagramFeed.php +++ b/src/InstagramFeed.php @@ -27,7 +27,6 @@ use Doctrine\Common\Cache\CacheProvider; use GuzzleHttp\Exception\ClientException; -use RZ\MixedFeed\AbstractFeedProvider; use RZ\MixedFeed\Exception\CredentialsException; /** diff --git a/src/MixedFeed.php b/src/MixedFeed.php index 101d719..cfdca0a 100644 --- a/src/MixedFeed.php +++ b/src/MixedFeed.php @@ -25,19 +25,18 @@ */ namespace RZ\MixedFeed; -use RZ\MixedFeed\AbstractFeedProvider; use RZ\MixedFeed\Exception\FeedProviderErrorException; use RZ\MixedFeed\MockObject\ErroredFeedItem; /** - * Combine feed providers and sort them antechronological. + * Combine feed providers and sort them ante-chronological. */ class MixedFeed extends AbstractFeedProvider { protected $providers; /** - * Create a mixed feed composed of hetergeneous feed + * Create a mixed feed composed of heterogeneous feed * providers. * * @param array $providers @@ -62,6 +61,7 @@ public function getItems($count = 5) if (count($this->providers) > 0) { $perProviderCount = floor($count / count($this->providers)); + /** @var FeedProviderInterface $provider */ foreach ($this->providers as $provider) { try { $list = array_merge($list, $provider->getItems($perProviderCount)); @@ -126,4 +126,12 @@ public function getErrors($feed) { return ''; } + + /** + * @inheritDoc + */ + protected function getFeed($count = 5) + { + trigger_error('getFeed method must not be called in MixedFeed.', E_USER_ERROR); + } } diff --git a/src/PinterestBoardFeed.php b/src/PinterestBoardFeed.php index 8b764fa..8cf96cd 100644 --- a/src/PinterestBoardFeed.php +++ b/src/PinterestBoardFeed.php @@ -26,8 +26,8 @@ namespace RZ\MixedFeed; use Doctrine\Common\Cache\CacheProvider; +use GuzzleHttp\Client; use GuzzleHttp\Exception\ClientException; -use RZ\MixedFeed\AbstractFeedProvider; use RZ\MixedFeed\Exception\CredentialsException; /** @@ -46,9 +46,10 @@ class PinterestBoardFeed extends AbstractFeedProvider /** * - * @param string $boardId - * @param string $accessToken Your App Token + * @param string $boardId + * @param string $accessToken Your App Token * @param CacheProvider|null $cacheProvider + * @throws CredentialsException */ public function __construct( $boardId, @@ -77,7 +78,7 @@ protected function getFeed($count = 5) return $this->cacheProvider->fetch($countKey); } - $client = new \GuzzleHttp\Client(); + $client = new Client(); $response = $client->get('https://api.pinterest.com/v1/boards/' . $this->boardId . '/pins/', [ 'query' => [ 'access_token' => $this->accessToken, diff --git a/src/TwitterFeed.php b/src/TwitterFeed.php index 98b5f67..4ffa066 100644 --- a/src/TwitterFeed.php +++ b/src/TwitterFeed.php @@ -43,17 +43,23 @@ class TwitterFeed extends AbstractTwitterFeed protected $includeRts; protected static $timeKey = 'created_at'; + /** + * @var bool + */ + protected $extended; /** * - * @param string $userId - * @param string $consumerKey - * @param string $consumerSecret - * @param string $accessToken - * @param string $accessTokenSecret + * @param string $userId + * @param string $consumerKey + * @param string $consumerSecret + * @param string $accessToken + * @param string $accessTokenSecret * @param CacheProvider|null $cacheProvider - * @param boolean $excludeReplies - * @param boolean $includeRts + * @param boolean $excludeReplies + * @param boolean $includeRts + * @param bool $extended + * @throws Exception\CredentialsException */ public function __construct( $userId, @@ -63,7 +69,8 @@ public function __construct( $accessTokenSecret, CacheProvider $cacheProvider = null, $excludeReplies = true, - $includeRts = false + $includeRts = false, + $extended = false ) { parent::__construct( @@ -77,6 +84,7 @@ public function __construct( $this->userId = $userId; $this->excludeReplies = $excludeReplies; $this->includeRts = $includeRts; + $this->extended = $extended; $this->cacheKey = $this->getFeedPlatform() . $this->userId; } @@ -94,6 +102,7 @@ protected function getFeed($count = 5) "count" => $count, "exclude_replies" => $this->excludeReplies, 'include_rts' => $this->includeRts, + 'tweet_mode' => ($this->extended ? 'extended' : '') ]); if (null !== $this->cacheProvider) { $this->cacheProvider->save( diff --git a/src/TwitterSearchFeed.php b/src/TwitterSearchFeed.php index 0882e1f..751679e 100644 --- a/src/TwitterSearchFeed.php +++ b/src/TwitterSearchFeed.php @@ -37,16 +37,30 @@ class TwitterSearchFeed extends AbstractTwitterFeed protected $cacheKey; protected $queryParams; + /** + * @var bool + */ + protected $includeRetweets = true; + + /** + * @var string + */ + protected $resultType = 'mixed'; + + /** + * @var string + */ protected static $timeKey = 'created_at'; /** * - * @param array $queryParams - * @param string $consumerKey - * @param string $consumerSecret - * @param string $accessToken - * @param string $accessTokenSecret + * @param array $queryParams + * @param string $consumerKey + * @param string $consumerSecret + * @param string $accessToken + * @param string $accessTokenSecret * @param CacheProvider|null $cacheProvider + * @throws Exception\CredentialsException */ public function __construct( array $queryParams, @@ -95,10 +109,17 @@ protected function getFeed($count = 5) return $this->cacheProvider->fetch($countKey); } - $body = $this->twitterConnection->get("search/tweets", [ + if ($this->includeRetweets === false) { + $this->queryParams['-filter'] = 'retweets'; + } + + $params = [ "q" => $this->formatQueryParams(), "count" => $count, - ]); + "result_type" => $this->resultType, + ]; + + $body = $this->twitterConnection->get("search/tweets", $params); if (null !== $this->cacheProvider) { $this->cacheProvider->save( @@ -115,4 +136,45 @@ protected function getFeed($count = 5) ]; } } + + /** + * @return bool + */ + public function isIncludeRetweets() + { + return $this->includeRetweets; + } + + /** + * @param bool $includeRetweets + * @return TwitterSearchFeed + */ + public function setIncludeRetweets($includeRetweets) + { + $this->includeRetweets = $includeRetweets; + return $this; + } + + /** + * @return string + */ + public function getResultType() + { + return $this->resultType; + } + + /** + * Optional. Specifies what type of search results you would prefer to receive. The current default is “mixed.” Valid values include: + * mixed : Include both popular and real time results in the response. + * recent : return only the most recent results in the response + * popular : return only the most popular results in the response. + * + * @param string $resultType + * @return TwitterSearchFeed + */ + public function setResultType($resultType) + { + $this->resultType = $resultType; + return $this; + } }