Skip to content

Commit

Permalink
Make Facebook spout work again
Browse files Browse the repository at this point in the history
In 2015, Facebook removed its feed support. Unfortunately,
it is no longer possible to access the site content
programmatically without registering an app.

This patch switches to the new API and adds fields for entering
the app credentials.

Closes: #687
  • Loading branch information
jtojnar committed Jun 15, 2017
1 parent 308b87c commit 2ecf6dc
Showing 1 changed file with 179 additions and 22 deletions.
201 changes: 179 additions & 22 deletions spouts/facebook/page.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,20 @@

namespace spouts\facebook;

use GuzzleHttp\Url;
use helpers\WebClient;

/**
* Spout for fetching a facebook page feed
*
* @copyright Copyright (c) Tobias Zeising (http://www.aditu.de)
* @license GPLv3 (https://www.gnu.org/licenses/gpl-3.0.html)
* @author Tobias Zeising <tobias.zeising@aditu.de>
* @author Thomas Muguet <t.muguet@thomasmuguet.info>
* https://developers.facebook.com/docs/graph-api/reference/v2.9/page/feed
*
* @copyright Copyright (c) Tobias Zeising (http://www.aditu.de)
* @license GPLv3 (https://www.gnu.org/licenses/gpl-3.0.html)
* @author Tobias Zeising <tobias.zeising@aditu.de>
* @author Jan Tojnar <jtojnar@gmail.com>
*/
class page extends \spouts\rss\feed {
class page extends \spouts\spout {
/** @var string name of source */
public $name = 'Facebook page feed';

Expand Down Expand Up @@ -45,41 +50,193 @@ class page extends \spouts\rss\feed {
'default' => '',
'required' => true,
'validation' => ['notempty']
]
],
'app_id' => [
'title' => 'App ID',
'type' => 'text',
'default' => '',
'required' => true,
'validation' => ['notempty']
],
'app_secret' => [
'title' => 'App Secret',
'type' => 'text',
'default' => '',
'required' => true,
'validation' => ['notempty']
],
];

//
// Source Methods
//
/** @var ?string page picture */
private $pageLink;

/** @var ?string page picture */
private $pagePicture;

/**
* loads content for given source
* I supress all Warnings of SimplePie for ensuring
* working plugin in PHP Strict mode
*
* @param mixed $params the params of this source
*
* @return void
*/
public function load($params) {
parent::load(['url' => $this->getXmlUrl($params)]);
$http = WebClient::getHttpClient();
$url = Url::fromString('https://graph.facebook.com/' . urlencode($params['user']));
$qs = $url->getQuery();
$qs['access_token'] = $params['app_id'] . '|' . $params['app_secret'];
$qs['fields'] = 'name,picture{url},link,feed{id,message,created_time,attachments,permalink_url}';
$data = $http->get($url)->json();

$this->spoutTitle = $data['name'];
$this->pagePicture = $data['picture']['data']['url'];
$this->pageLink = $data['picture']['link'];
$this->items = $data['feed']['data'];
}

public function getHtmlUrl() {
return $this->pageLink;
}

public function getId() {
if ($this->items !== false) {
$item = current($this->items);

return $item['id'];
}

return false;
}

public function getTitle() {
if ($this->items !== false) {
$item = current($this->items);

if (mb_strlen($item['message']) > 80) {
return mb_substr($item['message'], 0, 100) . '';
} else {
return $item['message'];
}
}

return false;
}

public function getContent() {
if ($this->items !== false) {
$item = current($this->items);
$message = $item['message'];

if (isset($item['attachments']) && count($item['attachments']['data']) > 0) {
foreach ($item['attachments']['data'] as $media) {
if ($media['type'] === 'photo') {
$message .= '<figure>' . PHP_EOL;
$message .= '<a href="' . $media['target']['url'] . '"><img src="' . $media['media']['image']['src'] . '" alt=""></a>' . PHP_EOL;

// Some photos will have the same description, no need to display it twice
if ($media['description'] !== $item['message']) {
$message .= '<figcaption>' . $media['description'] . '</figcaption>' . PHP_EOL;
}

$message .= '</figure>' . PHP_EOL;
}
}
}

return $message;
}

return false;
}

public function getIcon() {
return $this->pagePicture;
}

public function getLink() {
if ($this->items !== false) {
$item = current($this->items);

return $item['permalink_url'];
}

return false;
}

public function getDate() {
if ($this->items !== false) {
$item = current($this->items);

return $item['created_time'];
}

return false;
}

//
// Iterator Interface
//

/**
* reset iterator
*
* @return void
*/
public function rewind() {
if ($this->items !== false) {
reset($this->items);
}
}

/**
* receive current item
*
* @return page current item
*/
public function current() {
if ($this->items !== false) {
return $this;
}

return false;
}

/**
* returns the xml feed url for the source
* receive key of current item
*
* @param mixed $params params for the source
* @return mixed key of current item
*/
public function key() {
if ($this->items !== false) {
return key($this->items);
}

return false;
}

/**
* select next item
*
* @return page next item
*/
public function next() {
if ($this->items !== false) {
next($this->items);
}

return $this;
}

/**
* end reached
*
* @return string url as xml
* @return bool false if end reached
*/
public function getXmlUrl($params) {
$protocol = 'http://';
if (version_compare(PHP_VERSION, '5.3.0') >= 0 && defined('OPENSSL_VERSION_NUMBER')) {
$protocol = 'https://';
public function valid() {
if ($this->items !== false) {
return current($this->items) !== false;
}
$content = @file_get_contents($protocol . 'graph.facebook.com/' . urlencode($params['user']));
$data = json_decode($content, true);

return $protocol . 'www.facebook.com/feeds/page.php?format=atom10&id=' . $data['id'];
return false;
}
}

0 comments on commit 2ecf6dc

Please sign in to comment.