Skip to content

Commit

Permalink
Added file upload support for normal and batch requests
Browse files Browse the repository at this point in the history
  • Loading branch information
SammyK committed Nov 20, 2014
1 parent 8a1c4f2 commit dc52291
Show file tree
Hide file tree
Showing 43 changed files with 3,593 additions and 949 deletions.
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"require-dev": {
"phpunit/phpunit": "~4.0",
"mockery/mockery": "~0.8",
"guzzlehttp/guzzle": "~4.0"
"guzzlehttp/guzzle": "~5.0"
},
"suggest": {
"guzzlehttp/guzzle": "Allows for implementation of the Guzzle HTTP client"
Expand Down
53 changes: 53 additions & 0 deletions docs/Facebook.fbmd
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,14 @@ public FacebookClient getClient()
Returns the instance of `Facebook\FacebookClient` for the instantiated service.
</card>

<card>
### getLastResponse() {#get-last-response}
~~~~
public Facebook\Entities\FacebookResponse|Facebook\Entities\FacebookBatchResponse|null getLastResponse()
~~~~
Returns the last response received from the Graph API in the form of a `Facebook\Entities\FacebookResponse` or `Facebook\Entities\FacebookBatchResponse`.
</card>

<card>
### getDefaultAccessToken() {#get-default-access-token}
~~~~
Expand Down Expand Up @@ -306,3 +314,48 @@ Returns a [`Facebook\Helpers\FacebookRedirectLoginHelper`](/docs/php/FacebookRed
$helper = $fb->getRedirectLoginHelper();
~~~~
</card>

<card>
### next() {#next}
~~~~
public Facebook\GraphNodes\GraphList|null next(Facebook\GraphNodes\GraphList $graphList)
~~~~

Requests and returns the next page of results in a [`Facebook\GraphNodes\GraphList`](/docs/php/GraphList) object. If the next page returns no results, `null` will be returned.

~~~~
// Iterate over 5 pages max
$maxPages = 5;

// Get a list of photo objects
$response = $fb->get('/me/photos?fields=id,source,likes&limit=5');

$photosList = $response->getGraphList();

if (count($photosList) > 0) {
$pageCount = 0;
do {
foreach ($photosList as $photo) {
var_dump($photo->asArray());

// Deep pagination is supported on child GraphList's
$likes = $photo['likes'];
do {
echo '<p>Likes:</p>' . "\n\n";
var_dump($likes->asArray());
} while ($likes = $fqb->next($likes));
}
$pageCount++;
} while ($pageCount < $maxPages && $photosList = $fb->next($photosList));
}
~~~~
</card>

<card>
### previous() {#previous}
~~~~
public Facebook\GraphNodes\GraphList|null previous(Facebook\GraphNodes\GraphList $graphList)
~~~~

Requests and returns the previous page of results in a `Facebook\GraphNodes\GraphList` object. Functions just like `next()` above, but in the opposite direction of pagination.
</card>
16 changes: 8 additions & 8 deletions docs/sdk_reference.fbmd
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,14 @@ Graph nodes are collections that represent nodes returned by Graph.
FB(devsite:markdown-wiki:table {
columns: ['Class name','Description',],
rows: [
[
'`[Facebook\GraphNodes\GraphObject](/docs/php/GraphObject)`',
'The base collection object that represents a generic node.',
],
[
'`[Facebook\GraphNodes\GraphList](/docs/php/GraphList)`',
'A list of GraphObject's with special methods to help paginate over the list.',
],
[
'`[Facebook\GraphNodes\GraphAlbum](/docs/php/GraphAlbum)`',
'A collection that represents an album node.',
Expand All @@ -124,10 +132,6 @@ FB(devsite:markdown-wiki:table {
'`[Facebook\GraphNodes\GraphLocation](/docs/php/GraphLocation)`',
'A collection that represents a location node.',
],
[
'`[Facebook\GraphNodes\GraphObject](/docs/php/GraphObject)`',
'The base collection object that represents a generic node.',
],
[
'`[Facebook\GraphNodes\GraphPage](/docs/php/GraphPage)`',
'A collection that represents a page node.',
Expand All @@ -140,10 +144,6 @@ FB(devsite:markdown-wiki:table {
'`[Facebook\GraphNodes\GraphUser](/docs/php/GraphUser)`',
'A collection that represents a user node.',
],
[
'`[Facebook\GraphNodes\GraphUserPage](/docs/php/GraphUserPage)`',
'*(Deprecated)* A collection that represents a user page node.',
],
],
})
</card>
Expand Down
7 changes: 5 additions & 2 deletions src/Facebook/Entities/AccessToken.php
Original file line number Diff line number Diff line change
Expand Up @@ -343,9 +343,12 @@ protected static function request($endpoint, array $params, FacebookApp $app, Fa
$app,
$app->getAccessToken(),
'GET',
$endpoint,
$params
$endpoint
);
// We know what we're doing here.
// We want to send the access token as a param.
$request->dangerouslySetParams($params);

return $client->sendRequest($request);
}

Expand Down
120 changes: 108 additions & 12 deletions src/Facebook/Entities/FacebookBatchRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,32 +23,40 @@
*/
namespace Facebook\Entities;

use ArrayIterator;
use IteratorAggregate;
use ArrayAccess;
use Facebook\Exceptions\FacebookSDKException;

/**
* Class BatchRequest
* @package Facebook
*/
class FacebookBatchRequest extends FacebookRequest
class FacebookBatchRequest extends FacebookRequest implements IteratorAggregate, ArrayAccess
{

/**
* @var array An array of FacebookRequest entities to send.
*/
protected $requests;

/**
* @var array An array of files to upload.
*/
protected $attachedFiles;

/**
* Creates a new Request entity.
*
* @param FacebookApp|null $app
* @param AccessToken|string|null $accessToken
* @param array $requests
* @param AccessToken|string|null $accessToken
* @param string|null $graphVersion
*/
public function __construct(
FacebookApp $app = null,
$accessToken = null,
array $requests = [],
$accessToken = null,
$graphVersion = null
)
{
Expand All @@ -65,7 +73,7 @@ public function __construct(
*
* @return FacebookBatchRequest
*
* @throws FacebookSDKException
* @throws \InvalidArgumentException
*/
public function add($request, $name = null)
{
Expand All @@ -76,13 +84,21 @@ public function add($request, $name = null)
return $this;
} elseif ($request instanceof FacebookRequest) {
$this->addFallbackDefaults($request);
$this->requests[] = [
$requestToAdd = [
'name' => $name,
'request' => $request,
];

// File uploads
$attachedFiles = $this->extractFileAttachments($request);
if ($attachedFiles) {
$requestToAdd['attached_files'] = $attachedFiles;
}
$this->requests[] = $requestToAdd;

return $this;
}
throw new FacebookSDKException(
throw new \InvalidArgumentException(
'Argument for add() must be of type array or FacebookRequest.'
);
}
Expand Down Expand Up @@ -116,6 +132,34 @@ public function addFallbackDefaults(FacebookRequest $request)
}
}

/**
* Extracts the files from a request.
*
* @param FacebookRequest $request
*
* @return string|null
*
* @throws FacebookSDKException
*/
public function extractFileAttachments(FacebookRequest $request)
{
if ( ! $request->containsFileUploads()) {
return null;
}
$files = $request->getFiles();
$fileNames = [];
foreach ($files as $file) {
$fileName = uniqid();
$this->addFile($fileName, $file);
$fileNames[] = $fileName;
}

$request->resetFiles();

// @TODO Does Graph support multiple uploads on one endpoint?
return implode(',', $fileNames);
}

/**
* Return the FacebookRequest entities.
*
Expand Down Expand Up @@ -151,7 +195,8 @@ public function convertRequestsToJson()
{
$requests = [];
foreach ($this->requests as $request) {
$requests[] = static::requestEntityToBatchArray($request['request'], $request['name']);
$attachedFiles = isset($request['attached_files']) ? $request['attached_files'] : null;
$requests[] = $this->requestEntityToBatchArray($request['request'], $request['name'], $attachedFiles);
}

return json_encode($requests);
Expand Down Expand Up @@ -182,10 +227,14 @@ public function validateBatchRequestCount()
*
* @param FacebookRequest $request The request entity to convert.
* @param string|null $requestName The name of the request.
* @param string|null $attachedFiles Names of files associated with the request.
*
* @return array
*/
public static function requestEntityToBatchArray(FacebookRequest $request, $requestName = null)
public function requestEntityToBatchArray(
FacebookRequest $request,
$requestName = null,
$attachedFiles = null)
{
$compiledHeaders = [];
$headers = $request->getHeaders();
Expand All @@ -199,21 +248,68 @@ public static function requestEntityToBatchArray(FacebookRequest $request, $requ
'relative_url' => $request->getUrl(),
];

$params = $request->getPostParams();
if ($params) {
$batch['body'] = http_build_query($params, null, '&');
// Since file uploads are moved to the root request of a batch request,
// the child requests will always be URL-encoded.
$body = $request->getUrlEncodedBody()->getBody();
if ($body) {
$batch['body'] = $body;
}

if (isset($requestName)) {
$batch['name'] = $requestName;
}

if (isset($attachedFiles)) {
$batch['attached_files'] = $attachedFiles;
}

// @TODO Add support for "omit_response_on_success"
// @TODO Add support for "depends_on"
// @TODO Add support for "attached_files"
// @TODO Add support for JSONP with "callback"

return $batch;
}

/**
* Get an iterator for the items.
*
* @return ArrayIterator
*/
public function getIterator()
{
return new ArrayIterator($this->requests);
}

/**
* @return @inheritdoc
*/
public function offsetSet($offset, $value)
{
$this->add($value, $offset);
}

/**
* @return @inheritdoc
*/
public function offsetExists($offset)
{
return isset($this->requests[$offset]);
}

/**
* @return @inheritdoc
*/
public function offsetUnset($offset)
{
unset($this->requests[$offset]);
}

/**
* @return @inheritdoc
*/
public function offsetGet($offset)
{
return isset($this->requests[$offset]['request']) ? $this->requests[$offset]['request'] : null;
}

}
Loading

0 comments on commit dc52291

Please sign in to comment.