diff --git a/LICENSE b/LICENSE index c384885..16d585d 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2015 REZO ZERO +Copyright (c) 2019 REZO ZERO Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 85b4f9d..b232da1 100644 --- a/README.md +++ b/README.md @@ -3,10 +3,20 @@ > 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) +![License](http://img.shields.io/:license-mit-blue.svg?style=flat) ![Packagist](https://img.shields.io/packagist/v/rezozero/mixedfeed.svg?style=flat) + +- [Install](#install) +- [Combine feeds](#combine-feeds) +- [Use *FeedItem* instead of raw feed](#use--feeditem--instead-of-raw-feed) +- [Feed providers](#feed-providers) +- [Modify cache TTL](#modify-cache-ttl) +- [Create your own feed provider](#create-your-own-feed-provider) + * [Create a feed provider from a *Doctrine* repository](#create-a-feed-provider-from-a--doctrine--repository) ## Install +*mixedfeed* v2+ needs at least PHP 7.1, check your server configuration. + ```shell composer require rezozero/mixedfeed ``` @@ -70,6 +80,10 @@ $feed = new MixedFeed([ ]); return $feed->getItems(12); +// Or use canonical \RZ\MixedFeed\Canonical\FeedItem objects +// for a better compatibility and easier templating with multiple +// social platforms. +return $feed->getCanonicalItems(12); ``` ## Combine feeds @@ -95,10 +109,24 @@ For example, if you are using *Twig*, you will be able to include a sub-template * `normalizedDate`: This is a crucial parameter as it allows *mixedfeed* library to sort *antechronologically* multiple feeds with heterogeneous structures. * `canonicalMessage`: This is a useful field which contains the **text content** for each item over **all** platforms. You can use this to display items texts within a simple loop. +## Use *FeedItem* instead of raw feed + +If you need to serialize your MixedFeed to JSON or XML again, you should not want all the raw data contained in each +social feed item. So you can use the `$feed->getCanonicalItems(12);` method instead of `getItems` to get a more concise +object with essential data: `RZ\MixedFeed\Canonical\FeedItem`. + +When FeedItem has images, `FeedItem::$images` will hold an array of `RZ\MixedFeed\Canonical\Image` objects to +have better access to its `url`, `width` and `height` if they're available. + +Each feed provider must implement how to *hydrate* a `FeedItem` from the raw feed overriding `createFeedItemFromObject()` +method. + ## Feed providers | Feed provider class | Description | `feedItemPlatform` | | -------------- | ---------------- | ------------------ | +| Medium | Call over `https://medium.com/@username/latest` endpoint. It only needs a `$username` | `medium` | +| InstagramOEmbedFeed | Call over `https://api.instagram.com/oembed/` endpoint. It only needs a `$embedUrls` array | `instagram_oembed` | | InstagramFeed | Call over `/v1/users/$userId/media/recent/` endpoint. It needs a `$userId` and an `$accessToken` | `instagram` | | TwitterFeed | Call over `statuses/user_timeline` endpoint. It requires a `$userId`, a `$consumerKey`, a `$consumerSecret`, an `$accessToken` and an `$accessTokenSecret`. Be careful, this [endpoint](https://dev.twitter.com/rest/reference/get/statuses/user_timeline) can **only return up to 3,200 of a user’s most recent Tweets**, your item count could be lesser than expected. In the same way, Twitter removes retweets after retrieving the items count. | `twitter` | | TwitterSearchFeed | Call over `search/tweets` endpoint. It requires a `$queryParams` array, a `$consumerKey`, a `$consumerSecret`, an `$accessToken` and an `$accessTokenSecret`. Be careful, Twitter API **won’t retrieve tweets older than 7 days**, your item count could be lesser than expected. `$queryParams` must be a *key-valued* array with *query operators* according to [Twitter API documentation](https://dev.twitter.com/rest/public/search). | `twitter` | @@ -118,6 +146,7 @@ There are plenty of APIs on the internet, and this tool won’t be able to handl No problem, you can easily create your own feed provider to use in *mixedfeed*. You just have to create a new *class* that will inherit from `RZ\MixedFeed\AbstractFeedProvider`. Then you will have to implement each method from `FeedProviderInterface`: +* `createFeedItemFromObject($item)` method which transform a raw feed object into a canonical `RZ\MixedFeed\Canonical\FeedItem` and `RZ\MixedFeed\Canonical\Image` * `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. This method **must convert your own feed items into `\stdClass` objects.** @@ -141,8 +170,6 @@ protected $entityManager; public function __construct(\Doctrine\ORM\EntityManagerInterface $entityManager) { $this->entityManager = $entityManager; - $this->tags = $tags; - $this->timespan = $timespan; } protected function getFeed($count = 5) @@ -160,6 +187,22 @@ protected function getFeed($count = 5) ) ); } + +protected function createFeedItemFromObject($item) +{ + $feedItem = new RZ\MixedFeed\Canonical\FeedItem(); + $feedItem->setDateTime($this->getDateTime($item)); + $feedItem->setMessage($this->getCanonicalMessage($item)); + $feedItem->setPlatform($this->getFeedPlatform()); + + for ($item->images as $image) { + $feedItemImage = new RZ\MixedFeed\Canonical\Image(); + $feedItemImage->setUrl($image->url); + $feedItem->addImage($feedItemImage); + } + + return $feedItem; +} ``` Then you can define your *date-time* and *canonical message* methods to look into this object: diff --git a/composer.json b/composer.json index 139a3bf..39c09e1 100644 --- a/composer.json +++ b/composer.json @@ -19,9 +19,12 @@ "rezo zero" ], "require": { + "php": ">=7.1", "abraham/twitteroauth": "^0.7.4", "doctrine/cache": "^1.6.2", - "guzzlehttp/guzzle": "~5.0 || ~6.0" + "guzzlehttp/guzzle": "~6.0", + "ext-json": "*", + "jms/serializer": "^2.1" }, "autoload": { "psr-4": {"RZ\\MixedFeed\\": "src/"} diff --git a/src/AbstractFeedProvider.php b/src/AbstractFeedProvider.php index 17bca71..d24eb99 100644 --- a/src/AbstractFeedProvider.php +++ b/src/AbstractFeedProvider.php @@ -25,6 +25,7 @@ */ namespace RZ\MixedFeed; +use RZ\MixedFeed\Canonical\FeedItem; use RZ\MixedFeed\Exception\FeedProviderErrorException; /** @@ -63,9 +64,27 @@ public function getItems($count = 5) } } return $list; - } else { - throw new FeedProviderErrorException($this->getFeedPlatform(), $this->getErrors($list)); } + throw new FeedProviderErrorException($this->getFeedPlatform(), $this->getErrors($list)); + } + + /** + * {@inheritdoc} + */ + public function getCanonicalItems($count = 5) + { + $list = $this->getFeed($count); + + if ($this->isValid($list)) { + $items = []; + foreach ($list as $index => $item) { + if (is_object($item)) { + $items[] = $this->createFeedItemFromObject($item); + } + } + return $items; + } + throw new FeedProviderErrorException($this->getFeedPlatform(), $this->getErrors($list)); } /** @@ -91,4 +110,18 @@ public function setTtl($ttl) return $this; } + + /** + * @param \stdClass $item + * + * @return FeedItem + */ + protected function createFeedItemFromObject($item) + { + $feedItem = new FeedItem(); + $feedItem->setDateTime($this->getDateTime($item)); + $feedItem->setMessage($this->getCanonicalMessage($item)); + $feedItem->setPlatform($this->getFeedPlatform()); + return $feedItem; + } } diff --git a/src/AbstractFeedProvider/AbstractTwitterFeed.php b/src/AbstractFeedProvider/AbstractTwitterFeed.php index 92ef72f..720fef2 100644 --- a/src/AbstractFeedProvider/AbstractTwitterFeed.php +++ b/src/AbstractFeedProvider/AbstractTwitterFeed.php @@ -28,6 +28,7 @@ use Abraham\TwitterOAuth\TwitterOAuth; use Doctrine\Common\Cache\CacheProvider; use RZ\MixedFeed\AbstractFeedProvider as BaseFeedProvider; +use RZ\MixedFeed\Canonical\Image; use RZ\MixedFeed\Exception\CredentialsException; /** @@ -143,4 +144,29 @@ public function getErrors($feed) return $errors; } + + /** + * @inheritDoc + */ + protected function createFeedItemFromObject($item) + { + $feedItem = parent::createFeedItemFromObject($item); + $feedItem->setId($item->id_str); + $feedItem->setAuthor($item->user->name); + if (isset($item->entities->urls[0])) { + $feedItem->setLink($item->entities->urls[0]->expanded_url); + } + + if (isset($item->entities->media)) { + foreach ($item->entities->media as $media) { + $feedItemImage = new Image(); + $feedItemImage->setUrl($media->media_url_https); + $feedItemImage->setWidth($media->sizes->large->w); + $feedItemImage->setHeight($media->sizes->large->h); + $feedItem->addImage($feedItemImage); + } + } + + return $feedItem; + } } diff --git a/src/Canonical/FeedItem.php b/src/Canonical/FeedItem.php new file mode 100644 index 0000000..2da0535 --- /dev/null +++ b/src/Canonical/FeedItem.php @@ -0,0 +1,216 @@ +id; + } + + /** + * @param string $id + * + * @return FeedItem + */ + public function setId($id) + { + $this->id = $id; + + return $this; + } + + /** + * @return string + */ + public function getPlatform() + { + return $this->platform; + } + + /** + * @param string $platform + * + * @return FeedItem + */ + public function setPlatform($platform) + { + $this->platform = $platform; + + return $this; + } + + /** + * @return string + */ + public function getAuthor() + { + return $this->author; + } + + /** + * @param string $author + * + * @return FeedItem + */ + public function setAuthor($author) + { + $this->author = $author; + + return $this; + } + + /** + * @return string + */ + public function getTitle() + { + return $this->title; + } + + /** + * @param string $title + * + * @return FeedItem + */ + public function setTitle($title) + { + $this->title = $title; + + return $this; + } + + /** + * @return Image[] + */ + public function getImages() + { + return $this->images; + } + + /** + * @param Image[] $images + * + * @return FeedItem + */ + public function setImages($images) + { + $this->images = $images; + + return $this; + } + + /** + * @param Image $image + * + * @return FeedItem + */ + public function addImage(Image $image) + { + $this->images[] = $image; + return $this; + } + + /** + * @return string + */ + public function getMessage() + { + return $this->message; + } + + /** + * @param string $message + * + * @return FeedItem + */ + public function setMessage($message) + { + $this->message = $message; + + return $this; + } + + /** + * @return \DateTime + */ + public function getDateTime() + { + return $this->dateTime; + } + + /** + * @param \DateTime $dateTime + * + * @return FeedItem + */ + public function setDateTime($dateTime) + { + $this->dateTime = $dateTime; + + return $this; + } + + /** + * @return string + */ + public function getLink() + { + return $this->link; + } + + /** + * @param string $link + * + * @return FeedItem + */ + public function setLink($link) + { + $this->link = $link; + + return $this; + } +} diff --git a/src/Canonical/Image.php b/src/Canonical/Image.php new file mode 100644 index 0000000..1fc22d9 --- /dev/null +++ b/src/Canonical/Image.php @@ -0,0 +1,85 @@ +url; + } + + /** + * @param string $url + * + * @return Image + */ + public function setUrl($url) + { + $this->url = $url; + + return $this; + } + + /** + * @return int + */ + public function getWidth() + { + return $this->width; + } + + /** + * @param int $width + * + * @return Image + */ + public function setWidth($width) + { + $this->width = $width; + + return $this; + } + + /** + * @return int + */ + public function getHeight() + { + return $this->height; + } + + /** + * @param int $height + * + * @return Image + */ + public function setHeight($height) + { + $this->height = $height; + + return $this; + } +} diff --git a/src/FacebookPageFeed.php b/src/FacebookPageFeed.php index 38860cc..f896323 100644 --- a/src/FacebookPageFeed.php +++ b/src/FacebookPageFeed.php @@ -28,6 +28,7 @@ use Doctrine\Common\Cache\CacheProvider; use GuzzleHttp\Client; use GuzzleHttp\Exception\ClientException; +use RZ\MixedFeed\Canonical\Image; use RZ\MixedFeed\Exception\CredentialsException; /** @@ -72,7 +73,7 @@ public function __construct( $this->cacheProvider = $cacheProvider; $this->cacheKey = $this->getFeedPlatform() . $this->pageId; - $this->fields = ['link', 'picture', 'full_picture', 'message', 'story', 'type', 'created_time', 'source', 'status_type']; + $this->fields = ['from', 'link', 'picture', 'full_picture', 'message', 'story', 'type', 'created_time', 'source', 'status_type']; $this->fields = array_unique(array_merge($this->fields, $fields)); if (null === $this->accessToken || @@ -220,4 +221,27 @@ public function setUntil(\Datetime $until) return $this; } + + /** + * @inheritDoc + */ + protected function createFeedItemFromObject($item) + { + $feedItem = parent::createFeedItemFromObject($item); + $feedItem->setId($item->id); + if (isset($item->from)) { + $feedItem->setAuthor($item->from->name); + } + if (isset($item->link)) { + $feedItem->setLink($item->link); + } + + if (isset($item->full_picture)) { + $feedItemImage = new Image(); + $feedItemImage->setUrl($item->full_picture); + $feedItem->addImage($feedItemImage); + } + + return $feedItem; + } } diff --git a/src/FeedProviderInterface.php b/src/FeedProviderInterface.php index 7722929..a0f8d80 100644 --- a/src/FeedProviderInterface.php +++ b/src/FeedProviderInterface.php @@ -49,6 +49,15 @@ public function getFeedPlatform(); */ public function getItems($count = 5); + /** + * Get item method must return a normalized array of FeedItem. + * + * @param int $count + * + * @return mixed + */ + public function getCanonicalItems($count = 5); + /** * Get a \DateTime object from a social feed item. * @@ -61,6 +70,8 @@ public function getDateTime($item); * Check if the feed provider has succeded to * contact API. * + * @param $feed + * * @return boolean */ public function isValid($feed); @@ -68,6 +79,8 @@ public function isValid($feed); /** * Get errors details. * + * @param $feed + * * @return string */ public function getErrors($feed); @@ -75,7 +88,7 @@ public function getErrors($feed); /** * Get a canonical message from current feed item. * - * @param stdClass $item + * @param \stdClass $item * @return string */ public function getCanonicalMessage($item); diff --git a/src/GithubCommitsFeed.php b/src/GithubCommitsFeed.php index d824ba9..5c6e0a5 100644 --- a/src/GithubCommitsFeed.php +++ b/src/GithubCommitsFeed.php @@ -162,4 +162,16 @@ public function getErrors($feed) return $errors; } + + /** + * @inheritDoc + */ + protected function createFeedItemFromObject($item) + { + $feedItem = parent::createFeedItemFromObject($item); + $feedItem->setId($item->sha); + $feedItem->setAuthor($item->commit->author->name); + $feedItem->setLink($item->html_url); + return $feedItem; + } } diff --git a/src/GithubReleasesFeed.php b/src/GithubReleasesFeed.php index 8d37438..8043629 100644 --- a/src/GithubReleasesFeed.php +++ b/src/GithubReleasesFeed.php @@ -1,33 +1,9 @@ setId($item->id); + $feedItem->setAuthor($item->author->login); + $feedItem->setLink($item->html_url); + $feedItem->setTitle($item->name); + $feedItem->setMessage($item->body); + return $feedItem; + } } diff --git a/src/InstagramFeed.php b/src/InstagramFeed.php index a1ef290..2716251 100644 --- a/src/InstagramFeed.php +++ b/src/InstagramFeed.php @@ -27,6 +27,7 @@ use Doctrine\Common\Cache\CacheProvider; use GuzzleHttp\Exception\ClientException; +use RZ\MixedFeed\Canonical\Image; use RZ\MixedFeed\Exception\CredentialsException; /** @@ -134,4 +135,21 @@ public function getErrors($feed) { return $feed['error']; } + + /** + * @inheritDoc + */ + protected function createFeedItemFromObject($item) + { + $feedItem = parent::createFeedItemFromObject($item); + $feedItem->setId($item->id); + $feedItem->setAuthor($item->user->full_name); + $feedItem->setLink($item->link); + $feedItemImage = new Image(); + $feedItemImage->setUrl($item->images->standard_resolution->url); + $feedItemImage->setWidth($item->images->standard_resolution->width); + $feedItemImage->setHeight($item->images->standard_resolution->height); + $feedItem->addImage($feedItemImage); + return $feedItem; + } } diff --git a/src/InstagramOEmbedFeed.php b/src/InstagramOEmbedFeed.php new file mode 100644 index 0000000..b8fb5d0 --- /dev/null +++ b/src/InstagramOEmbedFeed.php @@ -0,0 +1,135 @@ +cacheProvider = $cacheProvider; + $this->cacheKey = $this->getFeedPlatform() . serialize($embedUrls); + $this->embedUrls = $embedUrls; + } + + protected function getFeed($count = 5) + { + try { + $countKey = $this->cacheKey . $count; + if (null !== $this->cacheProvider && + $this->cacheProvider->contains($countKey)) { + return $this->cacheProvider->fetch($countKey); + } + $body = []; + + foreach ($this->embedUrls as $embedUrl) { + $client = new \GuzzleHttp\Client(); + $response = $client->get('https://api.instagram.com/oembed', [ + 'query' => [ + 'url' => $embedUrl, + ], + ]); + array_push($body, json_decode($response->getBody())); + } + if (null !== $this->cacheProvider) { + $this->cacheProvider->save( + $countKey, + $body, + $this->ttl + ); + } + + return $body; + } catch (ClientException $e) { + return [ + 'error' => $e->getMessage(), + ]; + } + } + + /** + * {@inheritdoc} + */ + public function getFeedPlatform() + { + return 'instagram_oembed'; + } + + /** + * {@inheritdoc} + */ + public function getDateTime($item) + { + if (false !== preg_match("#datetime=\\\"([^\"]+)\\\"#", $item->html, $matches)) { + return new \DateTime($matches[1]); + } + return null; + } + + /** + * {@inheritdoc} + */ + public function getCanonicalMessage($item) + { + if (isset($item->title)) { + return $item->title; + } + + return ""; + } + + /** + * {@inheritdoc} + */ + public function isValid($feed) + { + return null !== $feed && is_array($feed) && !isset($feed['error']); + } + + /** + * {@inheritdoc} + */ + public function getErrors($feed) + { + return $feed['error']; + } + + /** + * @inheritDoc + */ + protected function createFeedItemFromObject($item) + { + $feedItem = parent::createFeedItemFromObject($item); + $feedItem->setId($item->media_id); + $feedItem->setAuthor($item->author_name); + $feedItem->setLink($item->author_url); + $feedItemImage = new Image(); + $feedItemImage->setUrl($item->thumbnail_url); + $feedItemImage->setWidth($item->thumbnail_width); + $feedItemImage->setHeight($item->thumbnail_height); + $feedItem->addImage($feedItemImage); + return $feedItem; + } +} diff --git a/src/MediumFeed.php b/src/MediumFeed.php new file mode 100644 index 0000000..b3c8b4a --- /dev/null +++ b/src/MediumFeed.php @@ -0,0 +1,192 @@ +username = $username; + if (substr($username, 0, 1) !== '@') { + $this->username = '@'.$username; + } + $this->cacheProvider = $cacheProvider; + } + + + protected function getFeed($count = 5) + { + try { + $countKey = $this->cacheKey . $count; + if (null !== $this->cacheProvider && + $this->cacheProvider->contains($countKey)) { + return $this->getTypedFeed($this->cacheProvider->fetch($countKey)); + } + + $client = new \GuzzleHttp\Client(); + $response = $client->get('https://medium.com/' . $this->username . '/latest', [ + 'query' => [ + 'format' => 'json', + 'limit' => $count, + 'collectionId' => null, + 'source' => 'latest', + ], + ]); + $raw = $response->getBody(); + $raw = str_replace('])}while(1);', '', $raw); + $body = json_decode($raw); + + if (null !== $this->cacheProvider) { + $this->cacheProvider->save( + $countKey, + $body, + $this->ttl + ); + } + + return $this->getTypedFeed($body); + } catch (ClientException $e) { + return [ + 'error' => $e->getMessage(), + ]; + } + } + + /** + * @param $body + * + * @return array + */ + protected function getTypedFeed($body) + { + $feed = []; + if (isset($body->payload->user)) { + $this->name = $body->payload->user->name; + } + foreach ($body->payload->streamItems as $item) { + if ($item->itemType === 'postPreview') { + $id = $item->postPreview->postId; + $createdAt = new \DateTime(); + $createdAt->setTimestamp($item->createdAt); + + if (isset($body->payload->references->Post->$id)) { + $feed[] = $body->payload->references->Post->$id; + } + } + } + + return $feed; + } + + /** + * {@inheritdoc} + */ + public function getFeedPlatform() + { + return 'medium'; + } + + /** + * {@inheritdoc} + */ + public function getDateTime($item) + { + $createdAt = new \DateTime(); + $createdAt->setTimestamp($item->latestPublishedAt/1000); + return $createdAt; + } + + /** + * {@inheritdoc} + */ + public function getCanonicalMessage($item) + { + if (isset($item->title)) { + return $item->title; + } + + return ""; + } + + /** + * {@inheritdoc} + */ + public function isValid($feed) + { + return null !== $feed && is_array($feed) && !isset($feed['error']); + } + + /** + * {@inheritdoc} + */ + public function getErrors($feed) + { + return $feed['error']; + } + + /** + * @inheritDoc + */ + protected function createFeedItemFromObject($item) + { + $feedItem = parent::createFeedItemFromObject($item); + $feedItem->setId($item->uniqueSlug); + $feedItem->setAuthor($this->name); + $feedItem->setLink('https://medium.com/'.$this->username.'/'.$item->uniqueSlug); + $feedItem->setTitle($item->title); + if (isset($item->content) && isset($item->content->subtitle)) { + $feedItem->setMessage($item->content->subtitle); + } + + if (isset($item->previewContent->bodyModel->paragraphs)) { + foreach ($item->previewContent->bodyModel->paragraphs as $paragraph) { + /* + * 4 seems to be an image type + */ + if ($paragraph->type === 4 && isset($paragraph->metadata)) { + $feedItemImage = new Image(); + $feedItemImage->setUrl('https://miro.medium.com/' . $paragraph->metadata->id); + $feedItemImage->setWidth($paragraph->metadata->originalWidth); + $feedItemImage->setHeight($paragraph->metadata->originalHeight); + $feedItem->addImage($feedItemImage); + } + } + } + return $feedItem; + } + + /** + * @return string + */ + public function getName() + { + return $this->name; + } +} diff --git a/src/MixedFeed.php b/src/MixedFeed.php index 5ff2e2a..94ffa69 100644 --- a/src/MixedFeed.php +++ b/src/MixedFeed.php @@ -25,6 +25,7 @@ */ namespace RZ\MixedFeed; +use RZ\MixedFeed\Canonical\FeedItem; use RZ\MixedFeed\Exception\FeedProviderErrorException; use RZ\MixedFeed\MockObject\ErroredFeedItem; @@ -103,6 +104,49 @@ public function getItems($count = 5) return $list; } + /** + * @inheritDoc + */ + public function getCanonicalItems($count = 5) + { + $list = []; + 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->getCanonicalItems($perProviderCount)); + } catch (FeedProviderErrorException $e) { + $errorItem = new FeedItem(); + $errorItem->setMessage($e->getMessage()); + $errorItem->setPlatform($provider->getFeedPlatform() . ' [errored]'); + $errorItem->setDateTime(new \DateTime()); + $list = array_merge($list, [ + $errorItem + ]); + } + } + + usort($list, function (FeedItem $a, FeedItem $b) { + $aDT = $a->getDateTime(); + $bDT = $b->getDateTime(); + + if ($aDT == $bDT) { + return 0; + } + // ASC sorting + if ($this->sortDirection === static::ASC) { + return ($aDT > $bDT) ? 1 : -1; + } + // DESC sorting + return ($aDT > $bDT) ? -1 : 1; + }); + } + + return $list; + } + /** * {@inheritdoc} */ diff --git a/src/PinterestBoardFeed.php b/src/PinterestBoardFeed.php index 8cf96cd..4a0ff1a 100644 --- a/src/PinterestBoardFeed.php +++ b/src/PinterestBoardFeed.php @@ -28,6 +28,7 @@ use Doctrine\Common\Cache\CacheProvider; use GuzzleHttp\Client; use GuzzleHttp\Exception\ClientException; +use RZ\MixedFeed\Canonical\Image; use RZ\MixedFeed\Exception\CredentialsException; /** @@ -127,7 +128,7 @@ public function getCanonicalMessage($item) */ public function getFeedPlatform() { - return 'pinterest_board'; + return 'pinterest_pin'; } /** @@ -145,4 +146,24 @@ public function getErrors($feed) { return $feed['error']; } + + /** + * @inheritDoc + */ + protected function createFeedItemFromObject($item) + { + $feedItem = parent::createFeedItemFromObject($item); + $feedItem->setId($item->id); + $feedItem->setAuthor($item->creator->first_name . ' ' . $item->creator->last_name); + $feedItem->setLink($item->url); + + if (isset($item->image)) { + $feedItemImage = new Image(); + $feedItemImage->setUrl($item->image->original->url); + $feedItemImage->setWidth($item->image->original->width); + $feedItemImage->setHeight($item->image->original->height); + $feedItem->addImage($feedItemImage); + } + return $feedItem; + } }