Skip to content
This repository has been archived by the owner on Nov 9, 2017. It is now read-only.

Abstracting Facebook API functions #78

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
122 changes: 122 additions & 0 deletions Model/StreamPost.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
<?php

/*
* This file is part of the FOSFacebookBundle package.
*
* (c) FriendsOfSymfony <http://friendsofsymfony.github.com/>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace FOS\FacebookBundle\Model;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please add a blank line before and after the license header


use \InvalidArgumentException;

/**
*
* This class functions as a model for messages to be sent by the facebookPush-service to the Facebook api.
* @author Teemu Reisbacka <[email protected]>
*
*/
class StreamPost
{
protected $accessToken;
protected $message;
protected $attachment;
protected $linkout;

/**
* Sets the access token used in message body. This is set automatically inside facebookPush-service.
*
* @param string $accessToken
*/
public function setAccessToken($accessToken)
{
$this->accessToken = $accessToken;
}

/**
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please add an empty line between the methods (same for all other places where needed)

* Sets the actual text content of the message
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the empty phpdoc line should be after the short description, not before

*
* @param string $message
*/
public function setMessage($message)
{
$this->message = $message;
}

/**
* Adds an attachment-picture to your Facebook message. If you specify a link, the image will function as a link.
* If you set an attachment, you cannot set any additional links with setLink(...).
*
* @param string $name This is the title of the attachment (top-most descriptive text)
* @param string $caption This is the image caption (text under the title)
* @param string $uriAttachment Full uri to the image you wish to attach. This location must be visible to Facebook, they will cache the picture.
* @param string $uriLinkOut Full uri to where you sish the image to link to
* @param string $description Description field in the message. If you do not specify this, Facebook may crawl the website specified in the link/image and attach a meta-description foiund from there to the message.
*/
public function setAttachment($name, $caption, $uriAttachment, $uriLinkOut = null, $description = null)
{
$attachment = array(
'name' => $name,
'caption' => $caption,
'picture' => $uriAttachment,
);

if (!empty($description)) {
$attachment['description'] = $description;
}
if (!empty($uriLinkOut)) {
$attachment['link'] = $uriLinkOut;
}
$this->attachment = $attachment;
}

/**
* Shortcut for adding a link to you Facebook-message without an image. If you
* specify an attachment with setAttachment(...), that will be used instead of this link.
*
* @param string $name This is the title of the link (top-most descriptive text)
* @param string $linkOut Full uri to where you wish to link to
* @param string $caption Optional description of the link
*/
public function setLink($name, $linkOut, $caption = null)
{
$this->linkout = array(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this property is not defined in the class.

'name' => $name,
'link' => $linkOut
);
if (!empty($caption)) {
$this->linkout['caption'] = $caption;
}
}

/**
* Formats this object into on array that can be fed to the php-api class. This function will be called automatically.
*
* @throws \InvalidArgumentException;
* @return array
*/
public function formatData()
{
if (empty($this->accessToken)) {
throw new \InvalidArgumentException('cannot format Facebook message: Facebook access token is empty');
}
if (empty($this->message)) {
throw new \InvalidArgumentException('cannot format Facebook message: Message is empty, nothing to send');
}
$streamPost = array(
'access_token' => $this->accessToken,
'message' => $this->message
);
if (!empty($this->linkout)) {
$streamPost = array_merge($streamPost, $this->linkout);
}
if (!empty($this->attachment)) {
$streamPost = array_merge($streamPost, $this->attachment);
}

return $streamPost;
}
}
4 changes: 4 additions & 0 deletions Resources/config/facebook.xml
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,9 @@
<tag name="twig.extension" />
</service>

<service id="fos_facebook.facebook_push" class="FOS\FacebookBundle\Services\FacebookPush">
<argument type="service" id="fos_facebook.api" />
</service>

</services>
</container>
171 changes: 171 additions & 0 deletions Services/FacebookPush.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
<?php

/*
* This file is part of the FOSFacebookBundle package.
*
* (c) FriendsOfSymfony <http://friendsofsymfony.github.com/>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace FOS\FacebookBundle\Services;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here than fpr the other file

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Services is a bad naming IMO.

In Symfony2, a service is an instance managed by the DIC. Note that I said instance, not class. The class does not know at all it is managed by the DIC and is totally independent from it. I could use it without the DIC my doing the injection of the dependencies myself:

<?php

$facebook = // some way to get the facebook api

$facebookPush = new FacebookPush($facebook);

// do something with it


use Symfony\Bundle\FrameworkBundle\Controller\Controller;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why this ?

use FOS\FacebookBundle\Model\StreamPost as BaseMessage;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why aliasing it to BaseMessage ? it is absolutely not needed here so keeping the original name would make it easier to read

use \BaseFacebook;
use \FacebookApiException;
use \InvalidArgumentException;
use \UnexpectedValueException;

/**
*
* This class provides a service that abstracts Facebook API functionality such as retrieving user information and
* posting data to Facebook API.
* @author Teemu Reisbacka <[email protected]>
*
*/
class FacebookPush
{
protected $facebook;
protected $errorMessage;

public function __construct(BaseFacebook $facebook)
{
$this->facebook = $facebook;
}

/**
* Returns error message if an executed function returned a failure (false value).
*
* @return string
*/
public function getErrorMessage()
{

return empty($this->errorMessage) ? '' : $this->errorMessage;
}

/**
* Retrieves available user information from Facebook for the logged in user. Available information
* depends on what access privileges the user has granted to your app.
*
* @return array|null
*/
public function getUserInfromation()
{
$accessToken = $this->facebook->getAccessToken();
/* Adding the locale parameter is important, because otherwise Facebook api might localize some
* variable values, such as gender.
*/
$me = json_decode(file_get_contents("https://graph.facebook.com/me?access_token={$accessToken}&locale=en_US"), true);

return $me;
}

/**
* Retrieves the profile picture of the logged in user in binary format, so that you can
* save it locally.
*
* @return string|boolean
*/
public function getProfilePicture()
{
$facebookUID = $this->facebook->getUser();
if (empty($facebookUID)) {
return null;
}

$binaryImage = file_get_contents("http://graph.facebook.com/{$facebookUID}/picture?type=large");

return $binaryImage;
}

/**
* Publishes a message to user's Facebook stream as the user. You application name will be displayed at the bottom
* of the message.
* REQUIRES Facebook access permission "publish_stream"
*
* @param Rohea\FacebookBundle\Models\streamPost $streamPost Stream post object
* @param string $accessToken Optional Facebook Access token, if not given, logged in user is used
* @return boolean
*/
public function publishStream(BaseMessage $streamPost, $accessToken = null)
{
if (empty($accessToken)) {
$accessToken = $this->facebook->getAccessToken();
}
if (empty($accessToken)) {
throw new InvalidArgumentException('No facebook access token, cannot post to stream');
}

$streamPost->setAccessToken($accessToken);
$message = $streamPost->formatData();
try {
$result = $this->facebook->api( '/me/feed/', 'post', $message );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you should remove spaces after the opening brace and before the closing one

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you should remove the extra spaces inside the braces


/* Confirm that the post went through -> Facebook api return message id
*/
if (!is_array($result) || empty($result["id"])) {
$this->errorMessage = "Did not receive message id back from the api, post failed.";
return false;
}
} catch (FacebookApiException $e) {
$this->errorMessage = $e->getMessage();

return false;
}

return true;
}

/**
* Publishes a message to user's Facebook page as the page.
* REQUIRES Facebook access permission "manage_pages"
*
* @param Rohea\FacebookBundle\Models\streamPost $streamPost Stream post object
* @param string $pageID Your page facebook id. You can see this for examnple in your browser uri-bar when browsing the page.
* @return boolean
*/
public function publishPage(BaseMessage $streamPost, $pageID)
{
try {
$accessToken = $this->getPageAccessToken($pageID);
$streamPost->setAccessToken($accessToken);
$message = $streamPost->formatData();
$result = $this->facebook->api( "/{$pageID}/feed/", 'post', $message );

/* Confirm that the post went through -> Facebook api return message id
*/
if (!is_array($result) || empty($result["id"])) {
$this->errorMessage = "Did not receive message id back from the api, post failed.";
return false;
}
} catch (FacebookApiException $e) {
$this->errorMessage = $e->getMessage();

return false;
}

return true;
}

/**
* Attempts to query access token for give Facebook page
* REQUIRES Facebook access permission "manage_pages"
*
* @param string $pageID Facebook page id
* @throws \UnexpectedValueException
* @return string
*/
public function getPageAccessToken($pageID)
{
$pageInfo = $this->facebook->api("/$pageID?fields=access_token");

if (empty($pageInfo['access_token'])) {
throw new UnexpectedValueException("Could not retrieve access token for the page $pageID");
}

return $pageInfo['access_token'];
}
}