diff --git a/README.md b/README.md index 96438c5..85b4f9d 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,11 @@ return $feed->getItems(12); ## Combine feeds -*mixedfeed* can combine multiple social feeds so you can loop over them and use some common data fields such as `feedItemPlatform`, `normalizedDate` and `canonicalMessage`. +*mixedfeed* can combine multiple social feeds so you can loop over them and use some common data fields such as `feedItemPlatform`, `normalizedDate` and `canonicalMessage`. *mixedfeed* will sort all your feed items by *descending* `normalizedDate`, but you can configure it to sort *ascending*: + +```php +new MixedFeed([…], MixedFeed::ASC); +``` Each feed provider must inject these three parameters in feed items: @@ -115,8 +119,9 @@ No problem, you can easily create your own feed provider to use in *mixedfeed*. will inherit from `RZ\MixedFeed\AbstractFeedProvider`. Then you will have to implement each method from `FeedProviderInterface`: * `getDateTime` method to look for the critical datetime field in your feed. -* `getFeed` method to consume your API endpoint with a count limit and take care of caching your responses. -* `getCanonicalMessage` method to look for the important text content in your feed. +* `getFeed` method to consume your API endpoint with a count limit and take care of caching your responses. +This method **must convert your own feed items into `\stdClass` objects.** +* `getCanonicalMessage` method to look for the important text content in your feed items. * `getFeedPlatform` method to get a global text identifier for your feed items. * `isValid` method to check if API call has succeeded regarding feed content. * `getErrors` method to errors from API feed that did not succeed. @@ -125,3 +130,62 @@ will inherit from `RZ\MixedFeed\AbstractFeedProvider`. Then you will have to imp Feel free to check our existing Feed providers to see how they work. And we strongly advise you to implement a caching system not to call your API endpoints at each request. By default, we use *Doctrine*’s caching system which has many storage options. + +### Create a feed provider from a *Doctrine* repository + +If you need to merge social network feeds with your own website articles, you can create a custom FeedProvider which wraps your Doctrine objects into `\stdClass` items. You’ll need to implement your `getFeed` method using an EntityManager: + +```php +protected $entityManager; + +public function __construct(\Doctrine\ORM\EntityManagerInterface $entityManager) +{ + $this->entityManager = $entityManager; + $this->tags = $tags; + $this->timespan = $timespan; +} + +protected function getFeed($count = 5) +{ + return array_map( + function (Article $article) { + $object = new \stdClass(); + $object->native = $article; + return $object; + }, + $this->entityManager->getRepository(Article::class)->findBy( + [], + ['datetime' => 'DESC'], + $count + ) + ); +} +``` + +Then you can define your *date-time* and *canonical message* methods to look into this object: + +```php +/** + * @inheritDoc + */ +public function getDateTime($item) +{ + if ($item->native instanceof Article) { + return $item->native->getDatetime(); + } + + return null; +} + +/** + * @inheritDoc + */ +public function getCanonicalMessage($item) +{ + if ($item->native instanceof Article) { + return $item->native->getExcerpt(); + } + + return null; +} +``` diff --git a/composer.json b/composer.json index 4f52803..139a3bf 100644 --- a/composer.json +++ b/composer.json @@ -7,7 +7,7 @@ { "name": "Ambroise Maupate", "email": "ambroise@rezo-zero.com", - "homepage": "http://www.rezo-zero.com", + "homepage": "https://www.rezo-zero.com", "role": "Lead developer" } ], @@ -25,5 +25,8 @@ }, "autoload": { "psr-4": {"RZ\\MixedFeed\\": "src/"} + }, + "require-dev": { + "squizlabs/php_codesniffer": "^3.3" } } diff --git a/src/AbstractFeedProvider.php b/src/AbstractFeedProvider.php index abaf51f..17bca71 100644 --- a/src/AbstractFeedProvider.php +++ b/src/AbstractFeedProvider.php @@ -39,7 +39,7 @@ abstract class AbstractFeedProvider implements FeedProviderInterface * @param int $count * @return array */ - protected abstract function getFeed($count = 5); + abstract protected function getFeed($count = 5); /** * {@inheritdoc} diff --git a/src/FeedProviderInterface.php b/src/FeedProviderInterface.php index 953e1cf..7722929 100644 --- a/src/FeedProviderInterface.php +++ b/src/FeedProviderInterface.php @@ -25,6 +25,8 @@ */ namespace RZ\MixedFeed; +use RZ\MixedFeed\Exception\FeedProviderErrorException; + interface FeedProviderInterface { /** @@ -43,13 +45,14 @@ public function getFeedPlatform(); * * @param integer $count * @return array + * @throws FeedProviderErrorException */ public function getItems($count = 5); /** * Get a \DateTime object from a social feed item. * - * @param stdClass $item + * @param \stdClass $item * @return \DateTime */ public function getDateTime($item); diff --git a/src/MixedFeed.php b/src/MixedFeed.php index cfdca0a..0abeddf 100644 --- a/src/MixedFeed.php +++ b/src/MixedFeed.php @@ -33,15 +33,23 @@ */ class MixedFeed extends AbstractFeedProvider { + const ASC = 'ASC'; + const DESC = 'DESC'; + protected $providers; + /** + * @var string + */ + protected $sortDirection; /** * Create a mixed feed composed of heterogeneous feed * providers. * - * @param array $providers + * @param array $providers + * @param string $sortDirection */ - public function __construct(array $providers = []) + public function __construct(array $providers = [], $sortDirection = MixedFeed::DESC) { foreach ($providers as $provider) { if (!($provider instanceof FeedProviderInterface)) { @@ -50,6 +58,7 @@ public function __construct(array $providers = []) } $this->providers = $providers; + $this->sortDirection = $sortDirection; } /** @@ -79,6 +88,10 @@ public function getItems($count = 5) if ($aDT == $bDT) { return 0; } + // ASC sorting + if ($this->sortDirection === static::ASC) { + return ($aDT > $bDT) ? 1 : -1; + } // DESC sorting return ($aDT > $bDT) ? -1 : 1; });