From 4b8a9a5189a625bf99fedec7fd31f6e146410a14 Mon Sep 17 00:00:00 2001 From: emkael Date: Thu, 26 Apr 2018 01:00:12 +0200 Subject: Update FB API library --- lib/facebook-graph-sdk/.scrutinizer.yml | 1 + lib/facebook-graph-sdk/.travis.yml | 20 +- lib/facebook-graph-sdk/CHANGELOG.md | 53 +++++- lib/facebook-graph-sdk/CODE_OF_CONDUCT.md | 3 + lib/facebook-graph-sdk/CONTRIBUTING.md | 14 +- lib/facebook-graph-sdk/LICENSE | 2 +- lib/facebook-graph-sdk/README.md | 50 ++--- lib/facebook-graph-sdk/composer.json | 13 +- lib/facebook-graph-sdk/phpcs.xml.dist | 7 + .../src/Facebook/Authentication/AccessToken.php | 2 +- .../Authentication/AccessTokenMetadata.php | 4 +- .../src/Facebook/Authentication/OAuth2Client.php | 10 +- .../Exceptions/FacebookAuthenticationException.php | 2 +- .../Exceptions/FacebookAuthorizationException.php | 2 +- .../Exceptions/FacebookClientException.php | 2 +- .../Facebook/Exceptions/FacebookOtherException.php | 2 +- .../Exceptions/FacebookResponseException.php | 14 +- .../FacebookResumableUploadException.php | 33 ++++ .../Facebook/Exceptions/FacebookSDKException.php | 2 +- .../Exceptions/FacebookServerException.php | 2 +- .../Exceptions/FacebookThrottleException.php | 2 +- lib/facebook-graph-sdk/src/Facebook/Facebook.php | 206 +++++++++++++-------- .../src/Facebook/FacebookApp.php | 17 +- .../src/Facebook/FacebookBatchRequest.php | 69 ++++--- .../src/Facebook/FacebookBatchResponse.php | 24 ++- .../src/Facebook/FacebookClient.php | 6 +- .../src/Facebook/FacebookRequest.php | 10 +- .../src/Facebook/FacebookResponse.php | 14 +- .../src/Facebook/FileUpload/FacebookFile.php | 40 +++- .../FileUpload/FacebookResumableUploader.php | 167 +++++++++++++++++ .../Facebook/FileUpload/FacebookTransferChunk.php | 133 +++++++++++++ .../src/Facebook/FileUpload/FacebookVideo.php | 2 +- .../src/Facebook/FileUpload/Mimetypes.php | 3 +- .../src/Facebook/GraphNodes/Birthday.php | 85 +++++++++ .../src/Facebook/GraphNodes/Collection.php | 4 +- .../src/Facebook/GraphNodes/GraphAchievement.php | 5 +- .../src/Facebook/GraphNodes/GraphAlbum.php | 2 +- .../src/Facebook/GraphNodes/GraphApplication.php | 2 +- .../src/Facebook/GraphNodes/GraphCoverPhoto.php | 2 +- .../src/Facebook/GraphNodes/GraphEdge.php | 44 ++--- .../src/Facebook/GraphNodes/GraphEvent.php | 2 +- .../src/Facebook/GraphNodes/GraphGroup.php | 3 +- .../src/Facebook/GraphNodes/GraphList.php | 2 +- .../src/Facebook/GraphNodes/GraphLocation.php | 2 +- .../src/Facebook/GraphNodes/GraphNode.php | 18 +- .../src/Facebook/GraphNodes/GraphNodeFactory.php | 4 +- .../src/Facebook/GraphNodes/GraphObject.php | 2 +- .../src/Facebook/GraphNodes/GraphObjectFactory.php | 8 +- .../src/Facebook/GraphNodes/GraphPage.php | 24 ++- .../src/Facebook/GraphNodes/GraphPicture.php | 2 +- .../src/Facebook/GraphNodes/GraphSessionInfo.php | 2 +- .../src/Facebook/GraphNodes/GraphUser.php | 14 +- .../src/Facebook/Helpers/FacebookCanvasHelper.php | 2 +- .../Facebook/Helpers/FacebookJavaScriptHelper.php | 2 +- .../src/Facebook/Helpers/FacebookPageTabHelper.php | 2 +- .../Helpers/FacebookRedirectLoginHelper.php | 81 +++----- .../FacebookSignedRequestFromInputHelper.php | 2 +- .../src/Facebook/Http/GraphRawResponse.php | 4 +- .../src/Facebook/Http/RequestBodyInterface.php | 2 +- .../src/Facebook/Http/RequestBodyMultipart.php | 2 +- .../src/Facebook/Http/RequestBodyUrlEncoded.php | 2 +- .../src/Facebook/HttpClients/FacebookCurl.php | 2 +- .../HttpClients/FacebookCurlHttpClient.php | 57 +----- .../HttpClients/FacebookGuzzleHttpClient.php | 2 +- .../HttpClients/FacebookHttpClientInterface.php | 2 +- .../src/Facebook/HttpClients/FacebookStream.php | 8 +- .../HttpClients/FacebookStreamHttpClient.php | 4 +- .../Facebook/HttpClients/HttpClientsFactory.php | 99 ++++++++++ .../FacebookMemoryPersistentDataHandler.php | 2 +- .../FacebookSessionPersistentDataHandler.php | 2 +- .../PersistentData/PersistentDataFactory.php | 65 +++++++ .../PersistentData/PersistentDataInterface.php | 2 +- .../McryptPseudoRandomStringGenerator.php | 2 +- .../OpenSslPseudoRandomStringGenerator.php | 2 +- .../PseudoRandomStringGeneratorFactory.php | 101 ++++++++++ .../PseudoRandomStringGeneratorInterface.php | 2 +- .../PseudoRandomStringGeneratorTrait.php | 4 +- .../RandomBytesPseudoRandomStringGenerator.php | 59 ++++++ .../UrandomPseudoRandomStringGenerator.php | 2 +- .../src/Facebook/SignedRequest.php | 18 +- .../Facebook/Url/FacebookUrlDetectionHandler.php | 25 ++- .../src/Facebook/Url/FacebookUrlManipulator.php | 4 +- .../src/Facebook/Url/UrlDetectionInterface.php | 2 +- lib/facebook-graph-sdk/src/Facebook/autoload.php | 4 +- lib/facebook-graph-sdk/src/Facebook/polyfills.php | 49 +++++ .../Authentication/AccessTokenMetadataTest.php | 138 ++++++++++++++ .../tests/Authentication/AccessTokenTest.php | 2 +- .../FooFacebookClientForOAuth2Test.php | 2 +- .../tests/Authentication/OAuth2ClientTest.php | 5 +- .../Exceptions/FacebookResponseExceptionTest.php | 4 +- lib/facebook-graph-sdk/tests/FacebookAppTest.php | 19 +- .../tests/FacebookBatchRequestTest.php | 57 +++++- .../tests/FacebookBatchResponseTest.php | 30 ++- .../tests/FacebookClientTest.php | 40 ++-- .../tests/FacebookRequestTest.php | 2 +- .../tests/FacebookResponseTest.php | 4 +- lib/facebook-graph-sdk/tests/FacebookTest.php | 154 +++++++++------ .../tests/FacebookTestCredentials.php.dist | 2 +- .../tests/FileUpload/FacebookFileTest.php | 13 +- .../FileUpload/FacebookResumableUploaderTest.php | 101 ++++++++++ .../tests/FileUpload/MimetypesTest.php | 2 +- .../Fixtures/FakeGraphApiForResumableUpload.php | 111 +++++++++++ .../Fixtures/FooBarPseudoRandomStringGenerator.php | 34 ++++ .../tests/Fixtures/FooClientInterface.php | 38 ++++ .../tests/Fixtures/FooPersistentDataInterface.php | 38 ++++ .../Fixtures/FooPseudoRandomStringGenerator.php | 34 ++++ .../Fixtures/FooRedirectLoginOAuth2Client.php | 35 ++++ .../tests/Fixtures/FooSignedRequestHelper.php | 34 ++++ .../FooSignedRequestHelperFacebookClient.php | 41 ++++ .../tests/Fixtures/FooUrlDetectionInterface.php | 34 ++++ .../MyFooBarPseudoRandomStringGenerator.php | 31 ++++ .../tests/Fixtures/MyFooBatchClientHandler.php | 38 ++++ .../tests/Fixtures/MyFooClientHandler.php | 38 ++++ .../tests/Fixtures/MyFooGraphNode.php | 33 ++++ .../tests/Fixtures/MyFooSubClassGraphNode.php | 30 +++ .../tests/GraphNodes/AbstractGraphNode.php | 4 +- .../tests/GraphNodes/CollectionTest.php | 16 +- .../tests/GraphNodes/GraphAchievementTest.php | 2 +- .../tests/GraphNodes/GraphAlbumTest.php | 4 +- .../tests/GraphNodes/GraphEdgeTest.php | 64 ++++--- .../tests/GraphNodes/GraphEventTest.php | 4 +- .../tests/GraphNodes/GraphGroupTest.php | 4 +- .../tests/GraphNodes/GraphNodeFactoryTest.php | 34 ++-- .../tests/GraphNodes/GraphNodeTest.php | 2 +- .../tests/GraphNodes/GraphObjectFactoryTest.php | 4 +- .../tests/GraphNodes/GraphPageTest.php | 4 +- .../tests/GraphNodes/GraphSessionInfoTest.php | 4 +- .../tests/GraphNodes/GraphUserTest.php | 70 ++++++- .../tests/Helpers/FacebookCanvasHelperTest.php | 4 +- .../tests/Helpers/FacebookJavaScriptHelperTest.php | 2 +- .../tests/Helpers/FacebookPageTabHelperTest.php | 2 +- .../Helpers/FacebookRedirectLoginHelperTest.php | 41 ++-- .../FacebookSignedRequestFromInputHelperTest.php | 31 +--- .../tests/Http/GraphRawResponseTest.php | 13 +- .../tests/Http/RequestBodyMultipartTest.php | 2 +- .../tests/Http/RequestUrlEncodedTest.php | 2 +- .../tests/HttpClients/AbstractTestHttpClient.php | 2 +- .../HttpClients/FacebookCurlHttpClientTest.php | 61 +----- .../HttpClients/FacebookGuzzleHttpClientTest.php | 4 +- .../HttpClients/FacebookStreamHttpClientTest.php | 4 +- .../tests/HttpClients/HttpClientsFactoryTest.php | 72 +++++++ .../FacebookMemoryPersistentDataHandlerTest.php | 2 +- .../FacebookSessionPersistentDataHandlerTest.php | 4 +- .../PersistentData/PersistentDataFactoryTest.php | 68 +++++++ .../McryptPseudoRandomStringGeneratorTest.php | 6 +- .../OpenSslPseudoRandomStringGeneratorTest.php | 2 +- .../PseudoRandomStringFactoryTest.php | 71 +++++++ .../PseudoRandomStringGeneratorTraitTest.php | 9 +- .../RandomBytesPseudoRandomStringGeneratorTest.php | 44 +++++ .../UrandomPseudoRandomStringGeneratorTest.php | 2 +- lib/facebook-graph-sdk/tests/SignedRequestTest.php | 4 +- .../tests/Url/FacebookUrlDetectionHandlerTest.php | 2 +- .../tests/Url/FacebookUrlManipulatorTest.php | 2 +- lib/facebook-graph-sdk/tests/bootstrap.php | 4 +- 154 files changed, 2876 insertions(+), 720 deletions(-) create mode 100644 lib/facebook-graph-sdk/CODE_OF_CONDUCT.md create mode 100644 lib/facebook-graph-sdk/phpcs.xml.dist create mode 100644 lib/facebook-graph-sdk/src/Facebook/Exceptions/FacebookResumableUploadException.php create mode 100644 lib/facebook-graph-sdk/src/Facebook/FileUpload/FacebookResumableUploader.php create mode 100644 lib/facebook-graph-sdk/src/Facebook/FileUpload/FacebookTransferChunk.php create mode 100644 lib/facebook-graph-sdk/src/Facebook/GraphNodes/Birthday.php create mode 100644 lib/facebook-graph-sdk/src/Facebook/HttpClients/HttpClientsFactory.php create mode 100644 lib/facebook-graph-sdk/src/Facebook/PersistentData/PersistentDataFactory.php create mode 100644 lib/facebook-graph-sdk/src/Facebook/PseudoRandomString/PseudoRandomStringGeneratorFactory.php create mode 100644 lib/facebook-graph-sdk/src/Facebook/PseudoRandomString/RandomBytesPseudoRandomStringGenerator.php create mode 100644 lib/facebook-graph-sdk/src/Facebook/polyfills.php create mode 100644 lib/facebook-graph-sdk/tests/Authentication/AccessTokenMetadataTest.php create mode 100644 lib/facebook-graph-sdk/tests/FileUpload/FacebookResumableUploaderTest.php create mode 100644 lib/facebook-graph-sdk/tests/Fixtures/FakeGraphApiForResumableUpload.php create mode 100644 lib/facebook-graph-sdk/tests/Fixtures/FooBarPseudoRandomStringGenerator.php create mode 100644 lib/facebook-graph-sdk/tests/Fixtures/FooClientInterface.php create mode 100644 lib/facebook-graph-sdk/tests/Fixtures/FooPersistentDataInterface.php create mode 100644 lib/facebook-graph-sdk/tests/Fixtures/FooPseudoRandomStringGenerator.php create mode 100644 lib/facebook-graph-sdk/tests/Fixtures/FooRedirectLoginOAuth2Client.php create mode 100644 lib/facebook-graph-sdk/tests/Fixtures/FooSignedRequestHelper.php create mode 100644 lib/facebook-graph-sdk/tests/Fixtures/FooSignedRequestHelperFacebookClient.php create mode 100644 lib/facebook-graph-sdk/tests/Fixtures/FooUrlDetectionInterface.php create mode 100644 lib/facebook-graph-sdk/tests/Fixtures/MyFooBarPseudoRandomStringGenerator.php create mode 100644 lib/facebook-graph-sdk/tests/Fixtures/MyFooBatchClientHandler.php create mode 100644 lib/facebook-graph-sdk/tests/Fixtures/MyFooClientHandler.php create mode 100644 lib/facebook-graph-sdk/tests/Fixtures/MyFooGraphNode.php create mode 100644 lib/facebook-graph-sdk/tests/Fixtures/MyFooSubClassGraphNode.php create mode 100644 lib/facebook-graph-sdk/tests/HttpClients/HttpClientsFactoryTest.php create mode 100644 lib/facebook-graph-sdk/tests/PersistentData/PersistentDataFactoryTest.php create mode 100644 lib/facebook-graph-sdk/tests/PseudoRandomString/PseudoRandomStringFactoryTest.php create mode 100644 lib/facebook-graph-sdk/tests/PseudoRandomString/RandomBytesPseudoRandomStringGeneratorTest.php (limited to 'lib/facebook-graph-sdk') diff --git a/lib/facebook-graph-sdk/.scrutinizer.yml b/lib/facebook-graph-sdk/.scrutinizer.yml index 6632013..05bdf77 100644 --- a/lib/facebook-graph-sdk/.scrutinizer.yml +++ b/lib/facebook-graph-sdk/.scrutinizer.yml @@ -1,6 +1,7 @@ filter: paths: - 'src/*' + - 'tests/*' tools: php_code_sniffer: diff --git a/lib/facebook-graph-sdk/.travis.yml b/lib/facebook-graph-sdk/.travis.yml index c3082df..a7877ae 100644 --- a/lib/facebook-graph-sdk/.travis.yml +++ b/lib/facebook-graph-sdk/.travis.yml @@ -5,20 +5,26 @@ php: - 5.5 - 5.6 - 7.0 - - hhvm + - 7.1 sudo: false +cache: + directories: + - $HOME/.composer/cache + +matrix: + include: + - php: hhvm + dist: trusty + before_install: - travis_retry composer self-update install: - - travis_retry composer install --prefer-source --no-interaction + - travis_retry composer require --dev --no-update squizlabs/php_codesniffer + - travis_retry composer install --prefer-dist --no-interaction script: + - vendor/bin/phpcs - vendor/bin/phpunit --coverage-text --exclude-group integration - -matrix: - allow_failures: - - php: 7.0 - fast_finish: true diff --git a/lib/facebook-graph-sdk/CHANGELOG.md b/lib/facebook-graph-sdk/CHANGELOG.md index aeb629e..66d6fe8 100644 --- a/lib/facebook-graph-sdk/CHANGELOG.md +++ b/lib/facebook-graph-sdk/CHANGELOG.md @@ -2,12 +2,52 @@ Starting with version 5, the Facebook PHP SDK follows [SemVer](http://semver.org/). - -## 5.0.x +## 5.x Version 5 of the Facebook PHP SDK is a complete refactor of version 4. It comes loaded with lots of new features and a friendlier API. -- 5.0 (2015-??-??) +- 5.6.2 (2018-02-15) + - Strip 'code' param (#913) +- 5.6.1 (2017-08-16) + - Fixed doc block syntax that interfered with Doctrine (#844) +- 5.6.0 (2017-07-23) + - Bump Graph API version to v2.10 (#829) +- 5.5.0 (2017-04-20) + - Added support for batch options (#713) + - Bump Graph API version to v2.9. +- 5.4.4 (2017-01-19) + - Added the `application/octet-stream` MIME type for SRT files (#734) +- 5.4.3 (2016-12-30) + - Fixed a bug that would throw a type error in `GraphEdge` in some cases (#715) +- 5.4.2 (2016-11-15) + - Added check for [PHP 7 CSPRNG](http://php.net/manual/en/function.random-bytes.php) first to keep mcrypt deprecation messages from appearing in PHP 7.1 (#692) +- 5.4.1 (2016-10-18) + - Fixed a bug that was not properly parsing response headers when they contained the colon `:` character. (#679) +- 5.4.0 (2016-10-12) + - Bump Graph API version to v2.8. + - Auto-cast `cover` field to `GraphCoverPhoto` and `picture` field to `GraphPicture` in `GraphPage`. (#655) + - Added `getCover()` and `getPicture()` to `GraphPage`. (#655) +- 5.3.1 + - Fixed a bug where the `polyfills.php` file wasn't being included properly when using the built-in auto loader (#633) +- 5.3.0 + - Bump Graph API version to v2.7. +- 5.2.1 + - Fix notice that is raised in `FacebookUrlDetectionHandler` (#626) + - Fix bug in `FacebookRedirectLoginHelper::getLoginUrl()` where the CSRF token gets overwritten in certain scenarios (#613) + - Fix bug with polyfills not getting loaded when installing the Facebook PHP SDK manually (#599) +- 5.2.0 + - Added new Birthday class to handle Graph API response variations + - Bumped Graph version to v2.6 + - Added better error checking for app IDs that are cast as int when they are greater than PHP_INT_MAX +- 5.1.5 + - Removed mbstring extension dependency + - Updated required PHP version syntax in composer.json +- 5.1.4 + - Breaking changes + - Changes the serialization method of FacebookApp + - FacebookApps serialized by versions prior 5.1.4 cannot be unserialized by this version + - Fixed redirect_uri injection vulnerability +- 5.0 (2015-07-09) - New features - Added the `Facebook\Facebook` super service for an easier API - Improved "reauthentication" and "rerequest" support @@ -22,8 +62,8 @@ Version 5 of the Facebook PHP SDK is a complete refactor of version 4. It comes - Many improvements to the Graph node subtypes - New injectable interfaces - Added a `PersistentDataInterface` for custom persistent data handling - - Added a `PseudoRandomStringGeneratorInterface` for customizable CSPRNG's - - Added a `UrlDetectionInterface` for custom URL-detection logic + - Added a `PseudoRandomStringGeneratorInterface` for customizable CSPRNG's + - Added a `UrlDetectionInterface` for custom URL-detection logic - Codebase changes - Moved exception classes to `Exception\*` directory - Moved response collection objects to `GraphNodes\*` directory @@ -34,6 +74,7 @@ Version 5 of the Facebook PHP SDK is a complete refactor of version 4. It comes - Renamed `FacebookHttpable` to `FacebookHttpClientInterface` - Added `FacebookApp` entity that contains info about the Facebook app - Updated the API for the helpers + - Added `HttpClients`, `PersistentData` and `PseudoRandomString` factories to reduce main class' complexity - Tests - Added namespaces to the tests - Grouped functional tests under `functional` group @@ -45,12 +86,10 @@ Version 5 of the Facebook PHP SDK is a complete refactor of version 4. It comes - Added `ext-mbstring` to composer require - Added this CHANGELOG. Hi! :) - ## 4.1-dev Since the Facebook PHP SDK didn't follow SemVer in version 4.x, the master branch was going to be released as 4.1. However, the SDK switched to SemVer in v5.0. So any references on the internet to version 4.1 can be assumed to be an alias to version `5.0.0` - ## 4.0.x Version 4.0 of the Facebook PHP SDK did not follow [SemVer](http://semver.org/). The versioning format used was as follows: `4.MAJOR.(MINOR|PATCH)`. The `MINOR` and `PATCH` versions were squashed together. diff --git a/lib/facebook-graph-sdk/CODE_OF_CONDUCT.md b/lib/facebook-graph-sdk/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..0a45f9b --- /dev/null +++ b/lib/facebook-graph-sdk/CODE_OF_CONDUCT.md @@ -0,0 +1,3 @@ +# Code of Conduct + +Facebook has adopted a Code of Conduct that we expect project participants to adhere to. Please [read the full text](https://code.facebook.com/codeofconduct) so that you can understand what actions will and will not be tolerated. diff --git a/lib/facebook-graph-sdk/CONTRIBUTING.md b/lib/facebook-graph-sdk/CONTRIBUTING.md index e3c16c4..3081751 100644 --- a/lib/facebook-graph-sdk/CONTRIBUTING.md +++ b/lib/facebook-graph-sdk/CONTRIBUTING.md @@ -3,8 +3,16 @@ Contributing Contributions are **welcome** and will be fully **credited**. -We accept contributions via Pull Requests on [Github](https://github.com/facebook/facebook-php-sdk-v4). +We accept contributions via Pull Requests on [Github](https://github.com/facebook/php-graph-sdk/pull/new). +The current stable major version is v5. The v6 is under active development. + +This means any new feature MUST target v6 (`master` branch). + +The v5 (`5.x` branch) is maintained only for bug fixes, node/edge updates or documentation improvements. + +## Code of Conduct +The code of conduct is described in [`CODE_OF_CONDUCT.md`](CODE_OF_CONDUCT.md) ## Pull Requests @@ -29,14 +37,12 @@ We accept contributions via Pull Requests on [Github](https://github.com/faceboo - **Ensure no coding standards violations** - Please [run PHP Code Sniffer](#running-php-code-sniffer) using the PSR-2 standard before submitting your pull request. A violation will cause the build to fail, so please make sure there are no violations. We can't accept a patch if the build fails. - ## Running Tests ``` bash $ ./vendor/bin/phpunit ``` - ## Running PHP Code Sniffer You can install [PHP Code Sniffer](https://github.com/squizlabs/PHP_CodeSniffer) globally with composer. @@ -48,7 +54,7 @@ $ composer global require squizlabs/php_codesniffer Then you can `cd` into the Facebook PHP SDK folder and run Code Sniffer against the `src/` directory. ``` bash -$ ~/.composer/vendor/bin/phpcs src --standard=psr2 -sp +$ ~/.composer/vendor/bin/phpcs ``` **Happy coding**! diff --git a/lib/facebook-graph-sdk/LICENSE b/lib/facebook-graph-sdk/LICENSE index be3927b..8b93109 100644 --- a/lib/facebook-graph-sdk/LICENSE +++ b/lib/facebook-graph-sdk/LICENSE @@ -1,4 +1,4 @@ -Copyright 2014 Facebook, Inc. +Copyright 2017 Facebook, Inc. You are hereby granted a non-exclusive, worldwide, royalty-free license to use, copy, modify, and distribute this software in source code or binary diff --git a/lib/facebook-graph-sdk/README.md b/lib/facebook-graph-sdk/README.md index 7d60e6e..05506d8 100644 --- a/lib/facebook-graph-sdk/README.md +++ b/lib/facebook-graph-sdk/README.md @@ -1,25 +1,24 @@ -# Facebook SDK for PHP - -[![Build Status](https://img.shields.io/travis/facebook/facebook-php-sdk-v4/master.svg)](https://travis-ci.org/facebook/facebook-php-sdk-v4) -[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/facebook/facebook-php-sdk-v4/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/facebook/facebook-php-sdk-v4/?branch=master) -[![Latest Stable Version](http://img.shields.io/badge/Latest%20Stable-5.0.0-blue.svg)](https://packagist.org/packages/facebook/php-sdk-v4) +# Facebook SDK for PHP (v5) +[![Build Status](https://img.shields.io/travis/facebook/php-graph-sdk/5.x.svg)](https://travis-ci.org/facebook/php-graph-sdk) +[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/facebook/facebook-php-sdk-v4/badges/quality-score.png?b=5.x)](https://scrutinizer-ci.com/g/facebook/facebook-php-sdk-v4/?branch=5.x) +[![Latest Stable Version](http://img.shields.io/badge/Latest%20Stable-5.6.2-blue.svg)](https://packagist.org/packages/facebook/graph-sdk) This repository contains the open source PHP SDK that allows you to access the Facebook Platform from your PHP app. - ## Installation -The Facebook PHP SDK can be installed with [Composer](https://getcomposer.org/). Add the Facebook PHP SDK package to your `composer.json` file. +The Facebook PHP SDK can be installed with [Composer](https://getcomposer.org/). Run this command: -```json -{ - "require": { - "facebook/php-sdk-v4": "~5.0" - } -} +```sh +composer require facebook/graph-sdk ``` +Please be aware, that there are issues when using the Facebook SDK together with [Guzzle](https://github.com/guzzle/guzzle) 6.x. php-graph-sdk v5.x only works with Guzzle 5.x out of the box. However, [there is a workaround to make it work with Guzzle 6.x](https://www.sammyk.me/how-to-inject-your-own-http-client-in-the-facebook-php-sdk-v5#writing-a-guzzle-6-http-client-implementation-from-scratch). + +## Upgrading to v5.x + +Upgrading from v4.x? Facebook PHP SDK v5.x introduced breaking changes. Please [read the upgrade guide](https://www.sammyk.me/upgrading-the-facebook-php-sdk-from-v4-to-v5) before upgrading. ## Usage @@ -28,10 +27,12 @@ The Facebook PHP SDK can be installed with [Composer](https://getcomposer.org/). Simple GET example of a user's profile. ```php -$fb = new Facebook\Facebook([ +require_once __DIR__ . '/vendor/autoload.php'; // change path as needed + +$fb = new \Facebook\Facebook([ 'app_id' => '{app-id}', 'app_secret' => '{app-secret}', - 'default_graph_version' => 'v2.4', + 'default_graph_version' => 'v2.10', //'default_access_token' => '{access-token}', // optional ]); @@ -42,14 +43,14 @@ $fb = new Facebook\Facebook([ // $helper = $fb->getPageTabHelper(); try { - // Get the Facebook\GraphNodes\GraphUser object for the current user. + // Get the \Facebook\GraphNodes\GraphUser object for the current user. // If you provided a 'default_access_token', the '{access-token}' is optional. $response = $fb->get('/me', '{access-token}'); -} catch(Facebook\Exceptions\FacebookResponseException $e) { +} catch(\Facebook\Exceptions\FacebookResponseException $e) { // When Graph returns an error echo 'Graph returned an error: ' . $e->getMessage(); exit; -} catch(Facebook\Exceptions\FacebookSDKException $e) { +} catch(\Facebook\Exceptions\FacebookSDKException $e) { // When validation fails or other local issues echo 'Facebook SDK returned an error: ' . $e->getMessage(); exit; @@ -59,8 +60,7 @@ $me = $response->getGraphUser(); echo 'Logged in as ' . $me->getName(); ``` -Complete documentation, installation instructions, and examples are available at: [https://developers.facebook.com/docs/php](https://developers.facebook.com/docs/php) - +Complete documentation, installation instructions, and examples are available [here](docs/). ## Tests @@ -78,12 +78,14 @@ By default the tests will send live HTTP requests to the Graph API. If you are w $ ./vendor/bin/phpunit --exclude-group integration ``` - ## Contributing -For us to accept contributions you will have to first have signed the [Contributor License Agreement](https://developers.facebook.com/opensource/cla). Please see [CONTRIBUTING](https://github.com/facebook/facebook-php-sdk-v4/blob/master/CONTRIBUTING.md) for details. - +For us to accept contributions you will have to first have signed the [Contributor License Agreement](https://developers.facebook.com/opensource/cla). Please see [CONTRIBUTING](https://github.com/facebook/php-graph-sdk/blob/master/CONTRIBUTING.md) for details. ## License -Please see the [license file](https://github.com/facebook/facebook-php-sdk-v4/blob/master/LICENSE) for more information. +Please see the [license file](https://github.com/facebook/php-graph-sdk/blob/master/LICENSE) for more information. + +## Security Vulnerabilities + +If you have found a security issue, please contact the maintainers directly at [me@sammyk.me](mailto:me@sammyk.me). diff --git a/lib/facebook-graph-sdk/composer.json b/lib/facebook-graph-sdk/composer.json index 31e70cd..9d54abc 100644 --- a/lib/facebook-graph-sdk/composer.json +++ b/lib/facebook-graph-sdk/composer.json @@ -1,19 +1,18 @@ { - "name": "facebook/php-sdk-v4", + "name": "facebook/graph-sdk", "description": "Facebook SDK for PHP", "keywords": ["facebook", "sdk"], "type": "library", - "homepage": "https://github.com/facebook/facebook-php-sdk-v4", + "homepage": "https://github.com/facebook/php-graph-sdk", "license": "Facebook Platform", "authors": [ { "name": "Facebook", - "homepage": "https://github.com/facebook/facebook-php-sdk-v4/contributors" + "homepage": "https://github.com/facebook/php-graph-sdk/contributors" } ], "require": { - "php": ">=5.4.0", - "ext-mbstring": "*" + "php": "^5.4|^7.0" }, "require-dev": { "phpunit/phpunit": "~4.0", @@ -21,12 +20,14 @@ "guzzlehttp/guzzle": "~5.0" }, "suggest": { + "paragonie/random_compat": "Provides a better CSPRNG option in PHP 5", "guzzlehttp/guzzle": "Allows for implementation of the Guzzle HTTP client" }, "autoload": { "psr-4": { "Facebook\\": "src/Facebook/" - } + }, + "files": ["src/Facebook/polyfills.php"] }, "autoload-dev": { "psr-4": { diff --git a/lib/facebook-graph-sdk/phpcs.xml.dist b/lib/facebook-graph-sdk/phpcs.xml.dist new file mode 100644 index 0000000..96c56f8 --- /dev/null +++ b/lib/facebook-graph-sdk/phpcs.xml.dist @@ -0,0 +1,7 @@ + + + src/ + tests/ + + + diff --git a/lib/facebook-graph-sdk/src/Facebook/Authentication/AccessToken.php b/lib/facebook-graph-sdk/src/Facebook/Authentication/AccessToken.php index 582ea61..5d70073 100644 --- a/lib/facebook-graph-sdk/src/Facebook/Authentication/AccessToken.php +++ b/lib/facebook-graph-sdk/src/Facebook/Authentication/AccessToken.php @@ -1,6 +1,6 @@ metadata[$key])) { + if (isset($this->metadata[$key]) && $this->metadata[$key] !== 0) { $this->metadata[$key] = $this->convertTimestampToDateTime($this->metadata[$key]); } } diff --git a/lib/facebook-graph-sdk/src/Facebook/Authentication/OAuth2Client.php b/lib/facebook-graph-sdk/src/Facebook/Authentication/OAuth2Client.php index 8e364ec..94df9b7 100644 --- a/lib/facebook-graph-sdk/src/Facebook/Authentication/OAuth2Client.php +++ b/lib/facebook-graph-sdk/src/Facebook/Authentication/OAuth2Client.php @@ -1,6 +1,6 @@ getenv(static::APP_ID_ENV_NAME), + 'app_secret' => getenv(static::APP_SECRET_ENV_NAME), + 'default_graph_version' => static::DEFAULT_GRAPH_VERSION, + 'enable_beta_mode' => false, + 'http_client_handler' => null, + 'persistent_data_handler' => null, + 'pseudo_random_string_generator' => null, + 'url_detection_handler' => null, + ], $config); + + if (!$config['app_id']) { throw new FacebookSDKException('Required "app_id" key not supplied in config and could not find fallback environment variable "' . static::APP_ID_ENV_NAME . '"'); } - - $appSecret = isset($config['app_secret']) ? $config['app_secret'] : getenv(static::APP_SECRET_ENV_NAME); - if (!$appSecret) { + if (!$config['app_secret']) { throw new FacebookSDKException('Required "app_secret" key not supplied in config and could not find fallback environment variable "' . static::APP_SECRET_ENV_NAME . '"'); } - $this->app = new FacebookApp($appId, $appSecret); - - $httpClientHandler = null; - if (isset($config['http_client_handler'])) { - if ($config['http_client_handler'] instanceof FacebookHttpClientInterface) { - $httpClientHandler = $config['http_client_handler']; - } elseif ($config['http_client_handler'] === 'curl') { - $httpClientHandler = new FacebookCurlHttpClient(); - } elseif ($config['http_client_handler'] === 'stream') { - $httpClientHandler = new FacebookStreamHttpClient(); - } elseif ($config['http_client_handler'] === 'guzzle') { - $httpClientHandler = new FacebookGuzzleHttpClient(); - } else { - throw new \InvalidArgumentException('The http_client_handler must be set to "curl", "stream", "guzzle", or be an instance of Facebook\HttpClients\FacebookHttpClientInterface'); - } - } - - $enableBeta = isset($config['enable_beta_mode']) && $config['enable_beta_mode'] === true; - $this->client = new FacebookClient($httpClientHandler, $enableBeta); - - if (isset($config['url_detection_handler'])) { - if ($config['url_detection_handler'] instanceof UrlDetectionInterface) { - $this->urlDetectionHandler = $config['url_detection_handler']; - } else { - throw new \InvalidArgumentException('The url_detection_handler must be an instance of Facebook\Url\UrlDetectionInterface'); - } - } - - if (isset($config['pseudo_random_string_generator'])) { - if ($config['pseudo_random_string_generator'] instanceof PseudoRandomStringGeneratorInterface) { - $this->pseudoRandomStringGenerator = $config['pseudo_random_string_generator']; - } elseif ($config['pseudo_random_string_generator'] === 'mcrypt') { - $this->pseudoRandomStringGenerator = new McryptPseudoRandomStringGenerator(); - } elseif ($config['pseudo_random_string_generator'] === 'openssl') { - $this->pseudoRandomStringGenerator = new OpenSslPseudoRandomStringGenerator(); - } elseif ($config['pseudo_random_string_generator'] === 'urandom') { - $this->pseudoRandomStringGenerator = new UrandomPseudoRandomStringGenerator(); - } else { - throw new \InvalidArgumentException('The pseudo_random_string_generator must be set to "mcrypt", "openssl", or "urandom", or be an instance of Facebook\PseudoRandomString\PseudoRandomStringGeneratorInterface'); - } - } - - if (isset($config['persistent_data_handler'])) { - if ($config['persistent_data_handler'] instanceof PersistentDataInterface) { - $this->persistentDataHandler = $config['persistent_data_handler']; - } elseif ($config['persistent_data_handler'] === 'session') { - $this->persistentDataHandler = new FacebookSessionPersistentDataHandler(); - } elseif ($config['persistent_data_handler'] === 'memory') { - $this->persistentDataHandler = new FacebookMemoryPersistentDataHandler(); - } else { - throw new \InvalidArgumentException('The persistent_data_handler must be set to "session", "memory", or be an instance of Facebook\PersistentData\PersistentDataInterface'); - } - } + $this->app = new FacebookApp($config['app_id'], $config['app_secret']); + $this->client = new FacebookClient( + HttpClientsFactory::createHttpClient($config['http_client_handler']), + $config['enable_beta_mode'] + ); + $this->pseudoRandomStringGenerator = PseudoRandomStringGeneratorFactory::createPseudoRandomStringGenerator( + $config['pseudo_random_string_generator'] + ); + $this->setUrlDetectionHandler($config['url_detection_handler'] ?: new FacebookUrlDetectionHandler()); + $this->persistentDataHandler = PersistentDataFactory::createPersistentDataHandler( + $config['persistent_data_handler'] + ); if (isset($config['default_access_token'])) { $this->setDefaultAccessToken($config['default_access_token']); } - if (isset($config['default_graph_version'])) { - $this->defaultGraphVersion = $config['default_graph_version']; - } else { - // @todo v6: Throw an InvalidArgumentException if "default_graph_version" is not set - $this->defaultGraphVersion = static::DEFAULT_GRAPH_VERSION; - } + // @todo v6: Throw an InvalidArgumentException if "default_graph_version" is not set + $this->defaultGraphVersion = $config['default_graph_version']; } /** @@ -257,13 +216,19 @@ class Facebook */ public function getUrlDetectionHandler() { - if (!$this->urlDetectionHandler instanceof UrlDetectionInterface) { - $this->urlDetectionHandler = new FacebookUrlDetectionHandler(); - } - return $this->urlDetectionHandler; } + /** + * Changes the URL detection handler. + * + * @param UrlDetectionInterface $urlDetectionHandler + */ + private function setUrlDetectionHandler(UrlDetectionInterface $urlDetectionHandler) + { + $this->urlDetectionHandler = $urlDetectionHandler; + } + /** * Returns the default AccessToken entity. * @@ -529,6 +494,27 @@ class Facebook return $this->lastResponse = $this->client->sendBatchRequest($batchRequest); } + /** + * Instantiates an empty FacebookBatchRequest entity. + * + * @param AccessToken|string|null $accessToken The top-level access token. Requests with no access token + * will fallback to this. + * @param string|null $graphVersion The Graph API version to use. + * @return FacebookBatchRequest + */ + public function newBatchRequest($accessToken = null, $graphVersion = null) + { + $accessToken = $accessToken ?: $this->defaultAccessToken; + $graphVersion = $graphVersion ?: $this->defaultGraphVersion; + + return new FacebookBatchRequest( + $this->app, + [], + $accessToken, + $graphVersion + ); + } + /** * Instantiates a new FacebookRequest entity. * @@ -586,4 +572,64 @@ class Facebook { return new FacebookVideo($pathToFile); } + + /** + * Upload a video in chunks. + * + * @param int $target The id of the target node before the /videos edge. + * @param string $pathToFile The full path to the file. + * @param array $metadata The metadata associated with the video file. + * @param string|null $accessToken The access token. + * @param int $maxTransferTries The max times to retry a failed upload chunk. + * @param string|null $graphVersion The Graph API version to use. + * + * @return array + * + * @throws FacebookSDKException + */ + public function uploadVideo($target, $pathToFile, $metadata = [], $accessToken = null, $maxTransferTries = 5, $graphVersion = null) + { + $accessToken = $accessToken ?: $this->defaultAccessToken; + $graphVersion = $graphVersion ?: $this->defaultGraphVersion; + + $uploader = new FacebookResumableUploader($this->app, $this->client, $accessToken, $graphVersion); + $endpoint = '/'.$target.'/videos'; + $file = $this->videoToUpload($pathToFile); + $chunk = $uploader->start($endpoint, $file); + + do { + $chunk = $this->maxTriesTransfer($uploader, $endpoint, $chunk, $maxTransferTries); + } while (!$chunk->isLastChunk()); + + return [ + 'video_id' => $chunk->getVideoId(), + 'success' => $uploader->finish($endpoint, $chunk->getUploadSessionId(), $metadata), + ]; + } + + /** + * Attempts to upload a chunk of a file in $retryCountdown tries. + * + * @param FacebookResumableUploader $uploader + * @param string $endpoint + * @param FacebookTransferChunk $chunk + * @param int $retryCountdown + * + * @return FacebookTransferChunk + * + * @throws FacebookSDKException + */ + private function maxTriesTransfer(FacebookResumableUploader $uploader, $endpoint, FacebookTransferChunk $chunk, $retryCountdown) + { + $newChunk = $uploader->transfer($endpoint, $chunk, $retryCountdown < 1); + + if ($newChunk !== $chunk) { + return $newChunk; + } + + $retryCountdown--; + + // If transfer() returned the same chunk entity, the transfer failed but is resumable. + return $this->maxTriesTransfer($uploader, $endpoint, $chunk, $retryCountdown); + } } diff --git a/lib/facebook-graph-sdk/src/Facebook/FacebookApp.php b/lib/facebook-graph-sdk/src/Facebook/FacebookApp.php index 84956ce..804c9bb 100644 --- a/lib/facebook-graph-sdk/src/Facebook/FacebookApp.php +++ b/lib/facebook-graph-sdk/src/Facebook/FacebookApp.php @@ -1,6 +1,6 @@ id = $id; + if (!is_string($id) + // Keeping this for BC. Integers greater than PHP_INT_MAX will make is_int() return false + && !is_int($id)) { + throw new FacebookSDKException('The "app_id" must be formatted as a string since many app ID\'s are greater than PHP_INT_MAX on some systems.'); + } + // We cast as a string in case a valid int was set on a 64-bit system and this is unserialised on a 32-bit system + $this->id = (string) $id; $this->secret = $secret; } @@ -84,7 +93,7 @@ class FacebookApp implements \Serializable */ public function serialize() { - return serialize([$this->id, $this->secret]); + return implode('|', [$this->id, $this->secret]); } /** @@ -94,7 +103,7 @@ class FacebookApp implements \Serializable */ public function unserialize($serialized) { - list($id, $secret) = unserialize($serialized); + list($id, $secret) = explode('|', $serialized); $this->__construct($id, $secret); } diff --git a/lib/facebook-graph-sdk/src/Facebook/FacebookBatchRequest.php b/lib/facebook-graph-sdk/src/Facebook/FacebookBatchRequest.php index 33c489c..3d5d5d5 100644 --- a/lib/facebook-graph-sdk/src/Facebook/FacebookBatchRequest.php +++ b/lib/facebook-graph-sdk/src/Facebook/FacebookBatchRequest.php @@ -1,6 +1,6 @@ $req) { @@ -85,17 +86,28 @@ class FacebookBatchRequest extends FacebookRequest implements IteratorAggregate, throw new \InvalidArgumentException('Argument for add() must be of type array or FacebookRequest.'); } + if (null === $options) { + $options = []; + } elseif (!is_array($options)) { + $options = ['name' => $options]; + } + $this->addFallbackDefaults($request); + + // File uploads + $attachedFiles = $this->extractFileAttachments($request); + + $name = isset($options['name']) ? $options['name'] : null; + + unset($options['name']); + $requestToAdd = [ 'name' => $name, 'request' => $request, + 'options' => $options, + 'attached_files' => $attachedFiles, ]; - // File uploads - $attachedFiles = $this->extractFileAttachments($request); - if ($attachedFiles) { - $requestToAdd['attached_files'] = $attachedFiles; - } $this->requests[] = $requestToAdd; return $this; @@ -168,8 +180,6 @@ class FacebookBatchRequest extends FacebookRequest implements IteratorAggregate, /** * Prepares the requests to be sent as a batch request. - * - * @return string */ public function prepareRequestsForBatch() { @@ -191,8 +201,15 @@ class FacebookBatchRequest extends FacebookRequest implements IteratorAggregate, { $requests = []; foreach ($this->requests as $request) { - $attachedFiles = isset($request['attached_files']) ? $request['attached_files'] : null; - $requests[] = $this->requestEntityToBatchArray($request['request'], $request['name'], $attachedFiles); + $options = []; + + if (null !== $request['name']) { + $options['name'] = $request['name']; + } + + $options += $request['options']; + + $requests[] = $this->requestEntityToBatchArray($request['request'], $options, $request['attached_files']); } return json_encode($requests); @@ -217,14 +234,22 @@ class FacebookBatchRequest extends FacebookRequest implements IteratorAggregate, /** * Converts a Request entity into an array that is batch-friendly. * - * @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. + * @param FacebookRequest $request The request entity to convert. + * @param string|null|array $options Array of batch request options e.g. 'name', 'omit_response_on_success'. + * If a string is given, it is the value of the 'name' option. + * @param string|null $attachedFiles Names of files associated with the request. * * @return array */ - public function requestEntityToBatchArray(FacebookRequest $request, $requestName = null, $attachedFiles = null) + public function requestEntityToBatchArray(FacebookRequest $request, $options = null, $attachedFiles = null) { + + if (null === $options) { + $options = []; + } elseif (!is_array($options)) { + $options = ['name' => $options]; + } + $compiledHeaders = []; $headers = $request->getHeaders(); foreach ($headers as $name => $value) { @@ -244,18 +269,12 @@ class FacebookBatchRequest extends FacebookRequest implements IteratorAggregate, $batch['body'] = $body; } - if (isset($requestName)) { - $batch['name'] = $requestName; - } + $batch += $options; - if (isset($attachedFiles)) { + if (null !== $attachedFiles) { $batch['attached_files'] = $attachedFiles; } - // @TODO Add support for "omit_response_on_success" - // @TODO Add support for "depends_on" - // @TODO Add support for JSONP with "callback" - return $batch; } diff --git a/lib/facebook-graph-sdk/src/Facebook/FacebookBatchResponse.php b/lib/facebook-graph-sdk/src/Facebook/FacebookBatchResponse.php index 5ea765e..8e1464c 100644 --- a/lib/facebook-graph-sdk/src/Facebook/FacebookBatchResponse.php +++ b/lib/facebook-graph-sdk/src/Facebook/FacebookBatchResponse.php @@ -1,6 +1,6 @@ normalizeBatchHeaders($response['headers']) : []; $this->responses[$originalRequestName] = new FacebookResponse( $originalRequest, @@ -151,4 +152,23 @@ class FacebookBatchResponse extends FacebookResponse implements IteratorAggregat { return isset($this->responses[$offset]) ? $this->responses[$offset] : null; } + + /** + * Converts the batch header array into a standard format. + * @TODO replace with array_column() when PHP 5.5 is supported. + * + * @param array $batchHeaders + * + * @return array + */ + private function normalizeBatchHeaders(array $batchHeaders) + { + $headers = []; + + foreach ($batchHeaders as $header) { + $headers[$header['name']] = $header['value']; + } + + return $headers; + } } diff --git a/lib/facebook-graph-sdk/src/Facebook/FacebookClient.php b/lib/facebook-graph-sdk/src/Facebook/FacebookClient.php index b10762f..dbf7592 100644 --- a/lib/facebook-graph-sdk/src/Facebook/FacebookClient.php +++ b/lib/facebook-graph-sdk/src/Facebook/FacebookClient.php @@ -1,6 +1,6 @@ validateAccessToken(); } diff --git a/lib/facebook-graph-sdk/src/Facebook/FacebookRequest.php b/lib/facebook-graph-sdk/src/Facebook/FacebookRequest.php index 5e4083f..2b10089 100644 --- a/lib/facebook-graph-sdk/src/Facebook/FacebookRequest.php +++ b/lib/facebook-graph-sdk/src/Facebook/FacebookRequest.php @@ -1,6 +1,6 @@ path = $filePath; + $this->maxLength = $maxLength; + $this->offset = $offset; $this->open(); } @@ -98,7 +112,7 @@ class FacebookFile */ public function getContents() { - return stream_get_contents($this->stream); + return stream_get_contents($this->stream, $this->maxLength, $this->offset); } /** @@ -111,6 +125,26 @@ class FacebookFile return basename($this->path); } + /** + * Return the path of the file. + * + * @return string + */ + public function getFilePath() + { + return $this->path; + } + + /** + * Return the size of the file. + * + * @return int + */ + public function getSize() + { + return filesize($this->path); + } + /** * Return the mimetype of the file. * diff --git a/lib/facebook-graph-sdk/src/Facebook/FileUpload/FacebookResumableUploader.php b/lib/facebook-graph-sdk/src/Facebook/FileUpload/FacebookResumableUploader.php new file mode 100644 index 0000000..92a22f1 --- /dev/null +++ b/lib/facebook-graph-sdk/src/Facebook/FileUpload/FacebookResumableUploader.php @@ -0,0 +1,167 @@ +app = $app; + $this->client = $client; + $this->accessToken = $accessToken; + $this->graphVersion = $graphVersion; + } + + /** + * Upload by chunks - start phase + * + * @param string $endpoint + * @param FacebookFile $file + * + * @return FacebookTransferChunk + * + * @throws FacebookSDKException + */ + public function start($endpoint, FacebookFile $file) + { + $params = [ + 'upload_phase' => 'start', + 'file_size' => $file->getSize(), + ]; + $response = $this->sendUploadRequest($endpoint, $params); + + return new FacebookTransferChunk($file, $response['upload_session_id'], $response['video_id'], $response['start_offset'], $response['end_offset']); + } + + /** + * Upload by chunks - transfer phase + * + * @param string $endpoint + * @param FacebookTransferChunk $chunk + * @param boolean $allowToThrow + * + * @return FacebookTransferChunk + * + * @throws FacebookResponseException + */ + public function transfer($endpoint, FacebookTransferChunk $chunk, $allowToThrow = false) + { + $params = [ + 'upload_phase' => 'transfer', + 'upload_session_id' => $chunk->getUploadSessionId(), + 'start_offset' => $chunk->getStartOffset(), + 'video_file_chunk' => $chunk->getPartialFile(), + ]; + + try { + $response = $this->sendUploadRequest($endpoint, $params); + } catch (FacebookResponseException $e) { + $preException = $e->getPrevious(); + if ($allowToThrow || !$preException instanceof FacebookResumableUploadException) { + throw $e; + } + + // Return the same chunk entity so it can be retried. + return $chunk; + } + + return new FacebookTransferChunk($chunk->getFile(), $chunk->getUploadSessionId(), $chunk->getVideoId(), $response['start_offset'], $response['end_offset']); + } + + /** + * Upload by chunks - finish phase + * + * @param string $endpoint + * @param string $uploadSessionId + * @param array $metadata The metadata associated with the file. + * + * @return boolean + * + * @throws FacebookSDKException + */ + public function finish($endpoint, $uploadSessionId, $metadata = []) + { + $params = array_merge($metadata, [ + 'upload_phase' => 'finish', + 'upload_session_id' => $uploadSessionId, + ]); + $response = $this->sendUploadRequest($endpoint, $params); + + return $response['success']; + } + + /** + * Helper to make a FacebookRequest and send it. + * + * @param string $endpoint The endpoint to POST to. + * @param array $params The params to send with the request. + * + * @return array + */ + private function sendUploadRequest($endpoint, $params = []) + { + $request = new FacebookRequest($this->app, $this->accessToken, 'POST', $endpoint, $params, null, $this->graphVersion); + + return $this->client->sendRequest($request)->getDecodedBody(); + } +} diff --git a/lib/facebook-graph-sdk/src/Facebook/FileUpload/FacebookTransferChunk.php b/lib/facebook-graph-sdk/src/Facebook/FileUpload/FacebookTransferChunk.php new file mode 100644 index 0000000..a909e87 --- /dev/null +++ b/lib/facebook-graph-sdk/src/Facebook/FileUpload/FacebookTransferChunk.php @@ -0,0 +1,133 @@ +file = $file; + $this->uploadSessionId = $uploadSessionId; + $this->videoId = $videoId; + $this->startOffset = $startOffset; + $this->endOffset = $endOffset; + } + + /** + * Return the file entity. + * + * @return FacebookFile + */ + public function getFile() + { + return $this->file; + } + + /** + * Return a FacebookFile entity with partial content. + * + * @return FacebookFile + */ + public function getPartialFile() + { + $maxLength = $this->endOffset - $this->startOffset; + + return new FacebookFile($this->file->getFilePath(), $maxLength, $this->startOffset); + } + + /** + * Return upload session Id + * + * @return int + */ + public function getUploadSessionId() + { + return $this->uploadSessionId; + } + + /** + * Check whether is the last chunk + * + * @return bool + */ + public function isLastChunk() + { + return $this->startOffset === $this->endOffset; + } + + /** + * @return int + */ + public function getStartOffset() + { + return $this->startOffset; + } + + /** + * Get uploaded video Id + * + * @return int + */ + public function getVideoId() + { + return $this->videoId; + } +} diff --git a/lib/facebook-graph-sdk/src/Facebook/FileUpload/FacebookVideo.php b/lib/facebook-graph-sdk/src/Facebook/FileUpload/FacebookVideo.php index 1e8c55a..ee6dd53 100644 --- a/lib/facebook-graph-sdk/src/Facebook/FileUpload/FacebookVideo.php +++ b/lib/facebook-graph-sdk/src/Facebook/FileUpload/FacebookVideo.php @@ -1,6 +1,6 @@ 'application/scvp-vp-request', 'spx' => 'audio/ogg', 'src' => 'application/x-wais-source', + 'srt' => 'application/octet-stream', 'sru' => 'application/sru+xml', 'srx' => 'application/sparql-results+xml', 'sse' => 'application/vnd.kodak-descriptor', diff --git a/lib/facebook-graph-sdk/src/Facebook/GraphNodes/Birthday.php b/lib/facebook-graph-sdk/src/Facebook/GraphNodes/Birthday.php new file mode 100644 index 0000000..4338b65 --- /dev/null +++ b/lib/facebook-graph-sdk/src/Facebook/GraphNodes/Birthday.php @@ -0,0 +1,85 @@ +hasYear = count($parts) === 3 || count($parts) === 1; + $this->hasDate = count($parts) === 3 || count($parts) === 2; + + parent::__construct($date); + } + + /** + * Returns whether date object contains birth day and month + * + * @return bool + */ + public function hasDate() + { + return $this->hasDate; + } + + /** + * Returns whether date object contains birth year + * + * @return bool + */ + public function hasYear() + { + return $this->hasYear; + } +} diff --git a/lib/facebook-graph-sdk/src/Facebook/GraphNodes/Collection.php b/lib/facebook-graph-sdk/src/Facebook/GraphNodes/Collection.php index cac010b..424b7cf 100644 --- a/lib/facebook-graph-sdk/src/Facebook/GraphNodes/Collection.php +++ b/lib/facebook-graph-sdk/src/Facebook/GraphNodes/Collection.php @@ -1,6 +1,6 @@ items[$name]; } - return $default ?: null; + return $default; } /** diff --git a/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphAchievement.php b/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphAchievement.php index 3fba815..31508ee 100644 --- a/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphAchievement.php +++ b/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphAchievement.php @@ -1,6 +1,6 @@ validateForPagination(); // Do we have a paging URL? - if (isset($this->metaData['paging'][$direction])) { - // Graph returns the full URL with all the original params. - // We just want the endpoint though. - $pageUrl = $this->metaData['paging'][$direction]; - - return FacebookUrlManipulator::baseGraphUrlEndpoint($pageUrl); - } - - // Do we have a cursor to work with? - $cursorDirection = $direction === 'next' ? 'after' : 'before'; - $cursor = $this->getCursor($cursorDirection); - if (!$cursor) { - return null; - } - - // If we don't know the ID of the parent node, this ain't gonna work. - if (!$this->parentEdgeEndpoint) { + if (!isset($this->metaData['paging'][$direction])) { return null; } - // We have the parent node ID, paging cursor & original request. - // These were the ingredients chosen to create the perfect little URL. - $pageUrl = $this->parentEdgeEndpoint . '?' . $cursorDirection . '=' . urlencode($cursor); + $pageUrl = $this->metaData['paging'][$direction]; - // Pull in the original params - $originalUrl = $this->request->getUrl(); - $pageUrl = FacebookUrlManipulator::mergeUrlParams($originalUrl, $pageUrl); - - return FacebookUrlManipulator::forceSlashPrefix($pageUrl); + return FacebookUrlManipulator::baseGraphUrlEndpoint($pageUrl); } /** @@ -257,4 +235,18 @@ class GraphEdge extends Collection return null; } + + /** + * @inheritDoc + */ + public function map(\Closure $callback) + { + return new static( + $this->request, + array_map($callback, $this->items, array_keys($this->items)), + $this->metaData, + $this->parentEdgeEndpoint, + $this->subclassName + ); + } } diff --git a/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphEvent.php b/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphEvent.php index 19ff2fb..a470d89 100644 --- a/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphEvent.php +++ b/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphEvent.php @@ -1,6 +1,6 @@ getField('venue'); } - } diff --git a/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphList.php b/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphList.php index a60a07a..3dfbd49 100644 --- a/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphList.php +++ b/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphList.php @@ -1,6 +1,6 @@ $v) { if ($this->shouldCastAsDateTime($k) && (is_numeric($v) - || $k === 'birthday' || $this->isIso8601DateString($v)) ) { $items[$k] = $this->castToDateTime($v); + } elseif ($k === 'birthday') { + $items[$k] = $this->castToBirthday($v); } else { $items[$k] = $v; } @@ -149,7 +150,6 @@ class GraphNode extends Collection 'backdated_time', 'issued_at', 'expires_at', - 'birthday', 'publish_time' ], true); } @@ -173,6 +173,18 @@ class GraphNode extends Collection return $dt; } + /** + * Casts a birthday value from Graph to Birthday + * + * @param string $value + * + * @return Birthday + */ + public function castToBirthday($value) + { + return new Birthday($value); + } + /** * Getter for $graphObjectMap. * diff --git a/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphNodeFactory.php b/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphNodeFactory.php index e1bedd9..6a37091 100644 --- a/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphNodeFactory.php +++ b/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphNodeFactory.php @@ -1,6 +1,6 @@ safelyMakeGraphNode($graphNode, $subclassName, $parentKey, $parentNodeId); + $dataList[] = $this->safelyMakeGraphNode($graphNode, $subclassName); } $metaData = $this->getMetaData($data); diff --git a/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphObject.php b/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphObject.php index bb8f8e4..0633c40 100644 --- a/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphObject.php +++ b/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphObject.php @@ -1,6 +1,6 @@ makeGraphNode($subclassName); } - + /** * Convenience method for creating a GraphEvent collection. * @@ -66,7 +68,7 @@ class GraphObjectFactory extends GraphNodeFactory */ public function makeGraphEvent() { - return $this->makeGraphObject(static::BASE_GRAPH_OBJECT_PREFIX . 'GraphEvent'); + return $this->makeGraphNode(static::BASE_GRAPH_OBJECT_PREFIX . 'GraphEvent'); } /** diff --git a/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphPage.php b/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphPage.php index ab8e31a..3dfb0e0 100644 --- a/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphPage.php +++ b/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphPage.php @@ -1,6 +1,6 @@ '\Facebook\GraphNodes\GraphPage', 'global_brand_parent_page' => '\Facebook\GraphNodes\GraphPage', 'location' => '\Facebook\GraphNodes\GraphLocation', + 'cover' => '\Facebook\GraphNodes\GraphCoverPhoto', + 'picture' => '\Facebook\GraphNodes\GraphPicture', ]; /** @@ -99,6 +101,26 @@ class GraphPage extends GraphNode return $this->getField('location'); } + /** + * Returns CoverPhoto of the Page. + * + * @return GraphCoverPhoto|null + */ + public function getCover() + { + return $this->getField('cover'); + } + + /** + * Returns Picture of the Page. + * + * @return GraphPicture|null + */ + public function getPicture() + { + return $this->getField('picture'); + } + /** * Returns the page access token for the admin user. * diff --git a/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphPicture.php b/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphPicture.php index bfd37fa..10274ec 100644 --- a/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphPicture.php +++ b/lib/facebook-graph-sdk/src/Facebook/GraphNodes/GraphPicture.php @@ -1,6 +1,6 @@ getField('last_name'); } + /** + * Returns the email for the user as a string if present. + * + * @return string|null + */ + public function getEmail() + { + return $this->getField('email'); + } + /** * Returns the gender for the user as a string if present. * @@ -113,7 +123,7 @@ class GraphUser extends GraphNode /** * Returns the users birthday, if available. * - * @return \DateTime|null + * @return Birthday|null */ public function getBirthday() { diff --git a/lib/facebook-graph-sdk/src/Facebook/Helpers/FacebookCanvasHelper.php b/lib/facebook-graph-sdk/src/Facebook/Helpers/FacebookCanvasHelper.php index 8068526..7f3466f 100644 --- a/lib/facebook-graph-sdk/src/Facebook/Helpers/FacebookCanvasHelper.php +++ b/lib/facebook-graph-sdk/src/Facebook/Helpers/FacebookCanvasHelper.php @@ -1,6 +1,6 @@ oAuth2Client = $oAuth2Client; $this->persistentDataHandler = $persistentDataHandler ?: new FacebookSessionPersistentDataHandler(); $this->urlDetectionHandler = $urlHandler ?: new FacebookUrlDetectionHandler(); - $this->pseudoRandomStringGenerator = $prsg ?: $this->detectPseudoRandomStringGenerator(); + $this->pseudoRandomStringGenerator = PseudoRandomStringGeneratorFactory::createPseudoRandomStringGenerator($prsg); } /** @@ -112,32 +110,6 @@ class FacebookRedirectLoginHelper return $this->pseudoRandomStringGenerator; } - /** - * Detects which pseudo-random string generator to use. - * - * @return PseudoRandomStringGeneratorInterface - * - * @throws FacebookSDKException - */ - public function detectPseudoRandomStringGenerator() - { - // Since openssl_random_pseudo_bytes() can sometimes return non-cryptographically - // secure pseudo-random strings (in rare cases), we check for mcrypt_create_iv() first. - if (function_exists('mcrypt_create_iv')) { - return new McryptPseudoRandomStringGenerator(); - } - - if (function_exists('openssl_random_pseudo_bytes')) { - return new OpenSslPseudoRandomStringGenerator(); - } - - if (!ini_get('open_basedir') && is_readable('/dev/urandom')) { - return new UrandomPseudoRandomStringGenerator(); - } - - throw new FacebookSDKException('Unable to detect a cryptographically secure pseudo-random string generator.'); - } - /** * Stores CSRF state and returns a URL to which the user should be sent to in order to continue the login process with Facebook. * @@ -150,7 +122,7 @@ class FacebookRedirectLoginHelper */ private function makeUrl($redirectUrl, array $scope, array $params = [], $separator = '&') { - $state = $this->pseudoRandomStringGenerator->getPseudoRandomString(static::CSRF_LENGTH); + $state = $this->persistentDataHandler->get('state') ?: $this->pseudoRandomStringGenerator->getPseudoRandomString(static::CSRF_LENGTH); $this->persistentDataHandler->set('state', $state); return $this->oAuth2Client->getAuthorizationUrl($redirectUrl, $state, $scope, $params, $separator); @@ -247,10 +219,11 @@ class FacebookRedirectLoginHelper } $this->validateCsrf(); + $this->resetCsrf(); $redirectUrl = $redirectUrl ?: $this->urlDetectionHandler->getCurrentUrl(); - // At minimum we need to remove the state param - $redirectUrl = FacebookUrlManipulator::removeParamsFromUrl($redirectUrl, ['state']); + // At minimum we need to remove the 'state' and 'code' params + $redirectUrl = FacebookUrlManipulator::removeParamsFromUrl($redirectUrl, ['code', 'state']); return $this->oAuth2Client->getAccessTokenFromCode($code, $redirectUrl); } @@ -263,27 +236,27 @@ class FacebookRedirectLoginHelper protected function validateCsrf() { $state = $this->getState(); + if (!$state) { + throw new FacebookSDKException('Cross-site request forgery validation failed. Required GET param "state" missing.'); + } $savedState = $this->persistentDataHandler->get('state'); - - if (!$state || !$savedState) { - throw new FacebookSDKException('Cross-site request forgery validation failed. Required param "state" missing.'); + if (!$savedState) { + throw new FacebookSDKException('Cross-site request forgery validation failed. Required param "state" missing from persistent data.'); } - $savedLen = strlen($savedState); - $givenLen = strlen($state); - - if ($savedLen !== $givenLen) { - throw new FacebookSDKException('Cross-site request forgery validation failed. The "state" param from the URL and session do not match.'); + if (\hash_equals($savedState, $state)) { + return; } - $result = 0; - for ($i = 0; $i < $savedLen; $i++) { - $result |= ord($state[$i]) ^ ord($savedState[$i]); - } + throw new FacebookSDKException('Cross-site request forgery validation failed. The "state" param from the URL and session do not match.'); + } - if ($result !== 0) { - throw new FacebookSDKException('Cross-site request forgery validation failed. The "state" param from the URL and session do not match.'); - } + /** + * Resets the CSRF so that it doesn't get reused. + */ + private function resetCsrf() + { + $this->persistentDataHandler->set('state', null); } /** diff --git a/lib/facebook-graph-sdk/src/Facebook/Helpers/FacebookSignedRequestFromInputHelper.php b/lib/facebook-graph-sdk/src/Facebook/Helpers/FacebookSignedRequestFromInputHelper.php index aafa246..4044da1 100644 --- a/lib/facebook-graph-sdk/src/Facebook/Helpers/FacebookSignedRequestFromInputHelper.php +++ b/lib/facebook-graph-sdk/src/Facebook/Helpers/FacebookSignedRequestFromInputHelper.php @@ -1,6 +1,6 @@ setHttpResponseCodeFromHeader($line); } else { - list($key, $value) = explode(': ', $line); + list($key, $value) = explode(': ', $line, 2); $this->headers[$key] = $value; } } diff --git a/lib/facebook-graph-sdk/src/Facebook/Http/RequestBodyInterface.php b/lib/facebook-graph-sdk/src/Facebook/Http/RequestBodyInterface.php index 97e0a2e..1c03f4f 100644 --- a/lib/facebook-graph-sdk/src/Facebook/Http/RequestBodyInterface.php +++ b/lib/facebook-graph-sdk/src/Facebook/Http/RequestBodyInterface.php @@ -1,6 +1,6 @@ $url, CURLOPT_CONNECTTIMEOUT => 10, CURLOPT_TIMEOUT => $timeOut, - CURLOPT_RETURNTRANSFER => true, // Follow 301 redirects + CURLOPT_RETURNTRANSFER => true, // Return response as string CURLOPT_HEADER => true, // Enable header processing CURLOPT_SSL_VERIFYHOST => 2, CURLOPT_SSL_VERIFYPEER => true, @@ -164,47 +154,10 @@ class FacebookCurlHttpClient implements FacebookHttpClientInterface */ public function extractResponseHeadersAndBody() { - $headerSize = $this->getHeaderSize(); - - $rawHeaders = mb_substr($this->rawResponse, 0, $headerSize); - $rawBody = mb_substr($this->rawResponse, $headerSize); + $parts = explode("\r\n\r\n", $this->rawResponse); + $rawBody = array_pop($parts); + $rawHeaders = implode("\r\n\r\n", $parts); return [trim($rawHeaders), trim($rawBody)]; } - - /** - * Return proper header size - * - * @return integer - */ - private function getHeaderSize() - { - $headerSize = $this->facebookCurl->getinfo(CURLINFO_HEADER_SIZE); - // This corrects a Curl bug where header size does not account - // for additional Proxy headers. - if ($this->needsCurlProxyFix()) { - // Additional way to calculate the request body size. - if (preg_match('/Content-Length: (\d+)/', $this->rawResponse, $m)) { - $headerSize = mb_strlen($this->rawResponse) - $m[1]; - } elseif (stripos($this->rawResponse, self::CONNECTION_ESTABLISHED) !== false) { - $headerSize += mb_strlen(self::CONNECTION_ESTABLISHED); - } - } - - return $headerSize; - } - - /** - * Detect versions of Curl which report incorrect header lengths when - * using Proxies. - * - * @return boolean - */ - private function needsCurlProxyFix() - { - $ver = $this->facebookCurl->version(); - $version = $ver['version_number']; - - return $version < self::CURL_PROXY_QUIRK_VER; - } } diff --git a/lib/facebook-graph-sdk/src/Facebook/HttpClients/FacebookGuzzleHttpClient.php b/lib/facebook-graph-sdk/src/Facebook/HttpClients/FacebookGuzzleHttpClient.php index 6f2a1c6..8feb7cb 100644 --- a/lib/facebook-graph-sdk/src/Facebook/HttpClients/FacebookGuzzleHttpClient.php +++ b/lib/facebook-graph-sdk/src/Facebook/HttpClients/FacebookGuzzleHttpClient.php @@ -1,6 +1,6 @@ stream); - $this->responseHeaders = $http_response_header; + $this->responseHeaders = $http_response_header ?: []; return $rawResponse; } diff --git a/lib/facebook-graph-sdk/src/Facebook/HttpClients/FacebookStreamHttpClient.php b/lib/facebook-graph-sdk/src/Facebook/HttpClients/FacebookStreamHttpClient.php index b157514..1cdfd53 100644 --- a/lib/facebook-graph-sdk/src/Facebook/HttpClients/FacebookStreamHttpClient.php +++ b/lib/facebook-graph-sdk/src/Facebook/HttpClients/FacebookStreamHttpClient.php @@ -1,6 +1,6 @@ facebookStream->fileGetContents($url); $rawHeaders = $this->facebookStream->getResponseHeaders(); - if ($rawBody === false || !$rawHeaders) { + if ($rawBody === false || empty($rawHeaders)) { throw new FacebookSDKException('Stream returned an empty response', 660); } diff --git a/lib/facebook-graph-sdk/src/Facebook/HttpClients/HttpClientsFactory.php b/lib/facebook-graph-sdk/src/Facebook/HttpClients/HttpClientsFactory.php new file mode 100644 index 0000000..d9f2a8d --- /dev/null +++ b/lib/facebook-graph-sdk/src/Facebook/HttpClients/HttpClientsFactory.php @@ -0,0 +1,99 @@ +validateLength($length); + + return $this->binToHex(random_bytes($length), $length); + } +} diff --git a/lib/facebook-graph-sdk/src/Facebook/PseudoRandomString/UrandomPseudoRandomStringGenerator.php b/lib/facebook-graph-sdk/src/Facebook/PseudoRandomString/UrandomPseudoRandomStringGenerator.php index 0f9cacd..5ab434e 100644 --- a/lib/facebook-graph-sdk/src/Facebook/PseudoRandomString/UrandomPseudoRandomStringGenerator.php +++ b/lib/facebook-graph-sdk/src/Facebook/PseudoRandomString/UrandomPseudoRandomStringGenerator.php @@ -1,6 +1,6 @@ getHeader('X_FORWARDED_HOST')) { - $elements = explode(',', $host); + $header = $this->getHeader('X_FORWARDED_HOST'); + if ($header && $this->isValidForwardedHost($header)) { + $elements = explode(',', $header); $host = $elements[count($elements) - 1]; } elseif (!$host = $this->getHeader('HOST')) { if (!$host = $this->getServerVar('SERVER_NAME')) { @@ -160,4 +161,22 @@ class FacebookUrlDetectionHandler implements UrlDetectionInterface { return $this->getServerVar('HTTP_' . $key); } + + /** + * Checks if the value in X_FORWARDED_HOST is a valid hostname + * Could prevent unintended redirections + * + * @param string $header + * + * @return boolean + */ + protected function isValidForwardedHost($header) + { + $elements = explode(',', $header); + $host = $elements[count($elements) - 1]; + + return preg_match("/^([a-z\d](-*[a-z\d])*)(\.([a-z\d](-*[a-z\d])*))*$/i", $host) //valid chars check + && 0 < strlen($host) && strlen($host) < 254 //overall length check + && preg_match("/^[^\.]{1,63}(\.[^\.]{1,63})*$/", $host); //length of each label + } } diff --git a/lib/facebook-graph-sdk/src/Facebook/Url/FacebookUrlManipulator.php b/lib/facebook-graph-sdk/src/Facebook/Url/FacebookUrlManipulator.php index 20a0299..daeab9c 100644 --- a/lib/facebook-graph-sdk/src/Facebook/Url/FacebookUrlManipulator.php +++ b/lib/facebook-graph-sdk/src/Facebook/Url/FacebookUrlManipulator.php @@ -1,6 +1,6 @@ [ + 'app_id' => '123', + 'application' => 'Foo App', + 'error' => [ + 'code' => 190, + 'message' => 'Foo error message.', + 'subcode' => 463, + ], + 'issued_at' => 1422110200, + 'expires_at' => 1422115200, + 'is_valid' => false, + 'metadata' => [ + 'sso' => 'iphone-sso', + 'auth_type' => 'rerequest', + 'auth_nonce' => 'no-replicatey', + ], + 'scopes' => ['public_profile', 'basic_info', 'user_friends'], + 'profile_id' => '1000', + 'user_id' => '1337', + ], + ]; + + public function testDatesGetCastToDateTime() + { + $metadata = new AccessTokenMetadata($this->graphResponseData); + + $expires = $metadata->getExpiresAt(); + $issuedAt = $metadata->getIssuedAt(); + + $this->assertInstanceOf('DateTime', $expires); + $this->assertInstanceOf('DateTime', $issuedAt); + } + + public function testAllTheGettersReturnTheProperValue() + { + $metadata = new AccessTokenMetadata($this->graphResponseData); + + $this->assertEquals('123', $metadata->getAppId()); + $this->assertEquals('Foo App', $metadata->getApplication()); + $this->assertTrue($metadata->isError(), 'Expected an error'); + $this->assertEquals('190', $metadata->getErrorCode()); + $this->assertEquals('Foo error message.', $metadata->getErrorMessage()); + $this->assertEquals('463', $metadata->getErrorSubcode()); + $this->assertFalse($metadata->getIsValid(), 'Expected the access token to not be valid'); + $this->assertEquals('iphone-sso', $metadata->getSso()); + $this->assertEquals('rerequest', $metadata->getAuthType()); + $this->assertEquals('no-replicatey', $metadata->getAuthNonce()); + $this->assertEquals('1000', $metadata->getProfileId()); + $this->assertEquals(['public_profile', 'basic_info', 'user_friends'], $metadata->getScopes()); + $this->assertEquals('1337', $metadata->getUserId()); + } + + /** + * @expectedException \Facebook\Exceptions\FacebookSDKException + */ + public function testInvalidMetadataWillThrow() + { + new AccessTokenMetadata(['foo' => 'bar']); + } + + public function testAnExpectedAppIdWillNotThrow() + { + $metadata = new AccessTokenMetadata($this->graphResponseData); + $metadata->validateAppId('123'); + } + + /** + * @expectedException \Facebook\Exceptions\FacebookSDKException + */ + public function testAnUnexpectedAppIdWillThrow() + { + $metadata = new AccessTokenMetadata($this->graphResponseData); + $metadata->validateAppId('foo'); + } + + public function testAnExpectedUserIdWillNotThrow() + { + $metadata = new AccessTokenMetadata($this->graphResponseData); + $metadata->validateUserId('1337'); + } + + /** + * @expectedException \Facebook\Exceptions\FacebookSDKException + */ + public function testAnUnexpectedUserIdWillThrow() + { + $metadata = new AccessTokenMetadata($this->graphResponseData); + $metadata->validateUserId('foo'); + } + + public function testAnActiveAccessTokenWillNotThrow() + { + $this->graphResponseData['data']['expires_at'] = time() + 1000; + $metadata = new AccessTokenMetadata($this->graphResponseData); + $metadata->validateExpiration(); + } + + /** + * @expectedException \Facebook\Exceptions\FacebookSDKException + */ + public function testAnExpiredAccessTokenWillThrow() + { + $this->graphResponseData['data']['expires_at'] = time() - 1000; + $metadata = new AccessTokenMetadata($this->graphResponseData); + $metadata->validateExpiration(); + } +} diff --git a/lib/facebook-graph-sdk/tests/Authentication/AccessTokenTest.php b/lib/facebook-graph-sdk/tests/Authentication/AccessTokenTest.php index d66a5ba..39e42d4 100644 --- a/lib/facebook-graph-sdk/tests/Authentication/AccessTokenTest.php +++ b/lib/facebook-graph-sdk/tests/Authentication/AccessTokenTest.php @@ -1,6 +1,6 @@ client = new FooFacebookClientForOAuth2Test(); diff --git a/lib/facebook-graph-sdk/tests/Exceptions/FacebookResponseExceptionTest.php b/lib/facebook-graph-sdk/tests/Exceptions/FacebookResponseExceptionTest.php index 107a9b9..ae18fde 100644 --- a/lib/facebook-graph-sdk/tests/Exceptions/FacebookResponseExceptionTest.php +++ b/lib/facebook-graph-sdk/tests/Exceptions/FacebookResponseExceptionTest.php @@ -1,6 +1,6 @@ request = new FacebookRequest(new FacebookApp('123', 'foo')); } diff --git a/lib/facebook-graph-sdk/tests/FacebookAppTest.php b/lib/facebook-graph-sdk/tests/FacebookAppTest.php index d1b453d..de08477 100644 --- a/lib/facebook-graph-sdk/tests/FacebookAppTest.php +++ b/lib/facebook-graph-sdk/tests/FacebookAppTest.php @@ -1,6 +1,6 @@ app = new FacebookApp('id', 'secret'); } @@ -63,4 +63,19 @@ class FacebookAppTest extends \PHPUnit_Framework_TestCase $this->assertEquals('id', $newApp->getId()); $this->assertEquals('secret', $newApp->getSecret()); } + + /** + * @expectedException \Facebook\Exceptions\FacebookSDKException + */ + public function testOverflowIntegersWillThrow() + { + new FacebookApp(PHP_INT_MAX + 1, "foo"); + } + + public function testUnserializedIdsWillBeString() + { + $newApp = unserialize(serialize(new FacebookApp(1, "foo"))); + + $this->assertSame('1', $newApp->getId()); + } } diff --git a/lib/facebook-graph-sdk/tests/FacebookBatchRequestTest.php b/lib/facebook-graph-sdk/tests/FacebookBatchRequestTest.php index cef0586..a77e754 100755 --- a/lib/facebook-graph-sdk/tests/FacebookBatchRequestTest.php +++ b/lib/facebook-graph-sdk/tests/FacebookBatchRequestTest.php @@ -1,6 +1,6 @@ app = new FacebookApp('123', 'foo_secret'); } @@ -280,6 +280,31 @@ class FacebookBatchRequestTest extends \PHPUnit_Framework_TestCase ], $batchRequestArray); } + public function testBatchRequestsWithOptionsGetConvertedToAnArray() + { + $request = new FacebookRequest(null, null, 'GET', '/bar'); + $batchRequest = $this->createBatchRequest(); + $batchRequest->add($request, [ + 'name' => 'foo_name', + 'omit_response_on_success' => false, + ]); + + $requests = $batchRequest->getRequests(); + + $options = $requests[0]['options']; + $options['name'] = $requests[0]['name']; + + $batchRequestArray = $batchRequest->requestEntityToBatchArray($requests[0]['request'], $options); + + $this->assertEquals([ + 'headers' => $this->defaultHeaders(), + 'method' => 'GET', + 'relative_url' => '/' . Facebook::DEFAULT_GRAPH_VERSION . '/bar?access_token=foo_token&appsecret_proof=df4256903ba4e23636cc142117aa632133d75c642bd2a68955be1443bd14deb9', + 'name' => 'foo_name', + 'omit_response_on_success' => false, + ], $batchRequestArray); + } + public function testPreppingABatchRequestProperlySetsThePostParams() { $batchRequest = $this->createBatchRequest(); @@ -328,6 +353,30 @@ class FacebookBatchRequestTest extends \PHPUnit_Framework_TestCase $this->assertEquals($expectedBatchParams, $params); } + public function testPreppingABatchRequestWithOptionsProperlySetsThePostParams() + { + $batchRequest = $this->createBatchRequest(); + $batchRequest->add(new FacebookRequest(null, null, 'GET', '/foo'), [ + 'name' => 'foo_name', + 'omit_response_on_success' => false, + ]); + + $batchRequest->prepareRequestsForBatch(); + $params = $batchRequest->getParams(); + + $expectedHeaders = json_encode($this->defaultHeaders()); + $version = Facebook::DEFAULT_GRAPH_VERSION; + + $expectedBatchParams = [ + 'batch' => '[{"headers":' . $expectedHeaders . ',"method":"GET","relative_url":"\\/' . $version . '\\/foo?access_token=foo_token&appsecret_proof=df4256903ba4e23636cc142117aa632133d75c642bd2a68955be1443bd14deb9",' + . '"name":"foo_name","omit_response_on_success":false}]', + 'include_headers' => true, + 'access_token' => 'foo_token', + 'appsecret_proof' => 'df4256903ba4e23636cc142117aa632133d75c642bd2a68955be1443bd14deb9', + ]; + $this->assertEquals($expectedBatchParams, $params); + } + private function assertRequestContainsAppAndToken(FacebookRequest $request, FacebookApp $expectedApp, $expectedToken) { $app = $request->getApp(); @@ -373,7 +422,9 @@ class FacebookBatchRequestTest extends \PHPUnit_Framework_TestCase foreach ($requests as $name => $request) { $expectedRequests[] = [ 'name' => $name, - 'request' => $request + 'request' => $request, + 'attached_files' => null, + 'options' => [], ]; } $this->assertEquals($expectedRequests, $formattedRequests); diff --git a/lib/facebook-graph-sdk/tests/FacebookBatchResponseTest.php b/lib/facebook-graph-sdk/tests/FacebookBatchResponseTest.php index dec92a1..8f4e5a8 100755 --- a/lib/facebook-graph-sdk/tests/FacebookBatchResponseTest.php +++ b/lib/facebook-graph-sdk/tests/FacebookBatchResponseTest.php @@ -1,6 +1,6 @@ app = new FacebookApp('123', 'foo_secret'); $this->request = new FacebookRequest( @@ -135,4 +135,30 @@ class FacebookBatchResponseTest extends \PHPUnit_Framework_TestCase $this->assertEquals('foo_token_two', $batchResponse[1]->getAccessToken()); $this->assertEquals('foo_token_three', $batchResponse[2]->getAccessToken()); } + + public function testHeadersFromBatchRequestCanBeAccessed() + { + $graphResponseJson = '['; + $graphResponseJson .= '{"code":200,"headers":[{"name":"Facebook-API-Version","value":"v2.0"},{"name":"ETag","value":"\"fooTag\""}],"body":"{\"foo\":\"bar\"}"}'; + $graphResponseJson .= ',{"code":200,"headers":[{"name":"Facebook-API-Version","value":"v2.5"},{"name":"ETag","value":"\"barTag\""}],"body":"{\"foo\":\"bar\"}"}'; + $graphResponseJson .= ']'; + $response = new FacebookResponse($this->request, $graphResponseJson, 200); + + $requests = [ + new FacebookRequest($this->app, 'foo_token_one', 'GET', '/me'), + new FacebookRequest($this->app, 'foo_token_two', 'GET', '/you'), + ]; + + $batchRequest = new FacebookBatchRequest($this->app, $requests); + $batchResponse = new FacebookBatchResponse($batchRequest, $response); + + $this->assertEquals('v2.0', $batchResponse[0]->getGraphVersion()); + $this->assertEquals('"fooTag"', $batchResponse[0]->getETag()); + $this->assertEquals('v2.5', $batchResponse[1]->getGraphVersion()); + $this->assertEquals('"barTag"', $batchResponse[1]->getETag()); + $this->assertEquals([ + 'Facebook-API-Version' => 'v2.5', + 'ETag' => '"barTag"', + ], $batchResponse[1]->getHeaders()); + } } diff --git a/lib/facebook-graph-sdk/tests/FacebookClientTest.php b/lib/facebook-graph-sdk/tests/FacebookClientTest.php index 6e9bb6c..9a08fb6 100644 --- a/lib/facebook-graph-sdk/tests/FacebookClientTest.php +++ b/lib/facebook-graph-sdk/tests/FacebookClientTest.php @@ -1,6 +1,6 @@ fbApp = new FacebookApp('id', 'shhhh!'); $this->fbClient = new FacebookClient(new MyFooClientHandler()); @@ -94,7 +72,7 @@ class FacebookClientTest extends \PHPUnit_Framework_TestCase $client = new FacebookClient($handler); $httpHandler = $client->getHttpClientHandler(); - $this->assertInstanceOf('Facebook\Tests\MyFooClientHandler', $httpHandler); + $this->assertInstanceOf('Facebook\Tests\Fixtures\MyFooClientHandler', $httpHandler); } public function testTheHttpClientWillFallbackToDefault() @@ -218,6 +196,14 @@ class FacebookClientTest extends \PHPUnit_Framework_TestCase $this->assertContains('multipart/form-data; boundary=', $headersSent['Content-Type']); } + public function testAFacebookRequestValidatesTheAccessTokenWhenOneIsNotProvided() + { + $this->setExpectedException('Facebook\Exceptions\FacebookSDKException'); + + $fbRequest = new FacebookRequest($this->fbApp, null, 'GET', '/foo'); + $this->fbClient->sendRequest($fbRequest); + } + /** * @group integration */ diff --git a/lib/facebook-graph-sdk/tests/FacebookRequestTest.php b/lib/facebook-graph-sdk/tests/FacebookRequestTest.php index fdea644..697fd94 100755 --- a/lib/facebook-graph-sdk/tests/FacebookRequestTest.php +++ b/lib/facebook-graph-sdk/tests/FacebookRequestTest.php @@ -1,6 +1,6 @@ request = new FacebookRequest( diff --git a/lib/facebook-graph-sdk/tests/FacebookTest.php b/lib/facebook-graph-sdk/tests/FacebookTest.php index 3648665..035e8d7 100644 --- a/lib/facebook-graph-sdk/tests/FacebookTest.php +++ b/lib/facebook-graph-sdk/tests/FacebookTest.php @@ -1,6 +1,6 @@ 'foo_secret', ]; - $fb = new Facebook($config); + new Facebook($config); } /** @@ -103,7 +64,7 @@ class FacebookTest extends \PHPUnit_Framework_TestCase $config = [ 'app_id' => 'foo_id', ]; - $fb = new Facebook($config); + new Facebook($config); } /** @@ -114,11 +75,14 @@ class FacebookTest extends \PHPUnit_Framework_TestCase $config = array_merge($this->config, [ 'http_client_handler' => 'foo_handler', ]); - $fb = new Facebook($config); + new Facebook($config); } public function testCurlHttpClientHandlerCanBeForced() { + if (!extension_loaded('curl')) { + $this->markTestSkipped('cURL must be installed to test cURL client handler.'); + } $config = array_merge($this->config, [ 'http_client_handler' => 'curl' ]); @@ -161,7 +125,7 @@ class FacebookTest extends \PHPUnit_Framework_TestCase $config = array_merge($this->config, [ 'persistent_data_handler' => 'foo_handler', ]); - $fb = new Facebook($config); + new Facebook($config); } public function testPersistentDataHandlerCanBeForced() @@ -176,15 +140,18 @@ class FacebookTest extends \PHPUnit_Framework_TestCase ); } - /** - * @expectedException \InvalidArgumentException - */ public function testSettingAnInvalidUrlHandlerThrows() { + $expectedException = (PHP_MAJOR_VERSION > 5 && class_exists('TypeError')) + ? 'TypeError' + : 'PHPUnit_Framework_Error'; + + $this->setExpectedException($expectedException); + $config = array_merge($this->config, [ 'url_detection_handler' => 'foo_handler', ]); - $fb = new Facebook($config); + new Facebook($config); } public function testTheUrlHandlerWillDefaultToTheFacebookImplementation() @@ -224,6 +191,25 @@ class FacebookTest extends \PHPUnit_Framework_TestCase new Facebook($config); } + public function testRandomBytesCsprgCanBeForced() + { + if (!function_exists('random_bytes')) { + $this->markTestSkipped( + 'Must have PHP 7 or paragonie/random_compat installed to test random_bytes().' + ); + } + + $config = array_merge($this->config, [ + 'persistent_data_handler' => 'memory', // To keep session errors from happening + 'pseudo_random_string_generator' => 'random_bytes' + ]); + $fb = new Facebook($config); + $this->assertInstanceOf( + 'Facebook\PseudoRandomString\RandomBytesPseudoRandomStringGenerator', + $fb->getRedirectLoginHelper()->getPseudoRandomStringGenerator() + ); + } + public function testMcryptCsprgCanBeForced() { if (!function_exists('mcrypt_create_iv')) { @@ -295,7 +281,7 @@ class FacebookTest extends \PHPUnit_Framework_TestCase $config = array_merge($this->config, [ 'default_access_token' => 123, ]); - $fb = new Facebook($config); + new Facebook($config); } public function testCreatingANewRequestWillDefaultToTheProperConfig() @@ -318,6 +304,28 @@ class FacebookTest extends \PHPUnit_Framework_TestCase ); } + public function testCreatingANewBatchRequestWillDefaultToTheProperConfig() + { + $config = array_merge($this->config, [ + 'default_access_token' => 'foo_token', + 'enable_beta_mode' => true, + 'default_graph_version' => 'v1337', + ]); + $fb = new Facebook($config); + + $batchRequest = $fb->newBatchRequest(); + $this->assertEquals('1337', $batchRequest->getApp()->getId()); + $this->assertEquals('foo_secret', $batchRequest->getApp()->getSecret()); + $this->assertEquals('foo_token', (string)$batchRequest->getAccessToken()); + $this->assertEquals('v1337', $batchRequest->getGraphVersion()); + $this->assertEquals( + FacebookClient::BASE_GRAPH_URL_BETA, + $fb->getClient()->getBaseGraphUrl() + ); + $this->assertInstanceOf('Facebook\FacebookBatchRequest', $batchRequest); + $this->assertEquals(0, count($batchRequest->getRequests())); + } + public function testCanInjectCustomHandlers() { $config = array_merge($this->config, [ @@ -329,19 +337,19 @@ class FacebookTest extends \PHPUnit_Framework_TestCase $fb = new Facebook($config); $this->assertInstanceOf( - 'Facebook\Tests\FooClientInterface', + 'Facebook\Tests\Fixtures\FooClientInterface', $fb->getClient()->getHttpClientHandler() ); $this->assertInstanceOf( - 'Facebook\Tests\FooPersistentDataInterface', + 'Facebook\Tests\Fixtures\FooPersistentDataInterface', $fb->getRedirectLoginHelper()->getPersistentDataHandler() ); $this->assertInstanceOf( - 'Facebook\Tests\FooUrlDetectionInterface', + 'Facebook\Tests\Fixtures\FooUrlDetectionInterface', $fb->getRedirectLoginHelper()->getUrlDetectionHandler() ); $this->assertInstanceOf( - 'Facebook\Tests\FooBarPseudoRandomStringGenerator', + 'Facebook\Tests\Fixtures\FooBarPseudoRandomStringGenerator', $fb->getRedirectLoginHelper()->getPseudoRandomStringGenerator() ); } @@ -363,6 +371,8 @@ class FacebookTest extends \PHPUnit_Framework_TestCase 'after' => 'bar_after_cursor', 'before' => 'bar_before_cursor', ], + 'previous' => 'previous_url', + 'next' => 'next_url', ] ], '/1337/photos', @@ -378,4 +388,32 @@ class FacebookTest extends \PHPUnit_Framework_TestCase $this->assertInstanceOf('Facebook\FacebookResponse', $lastResponse); $this->assertEquals(1337, $lastResponse->getHttpStatusCode()); } + + public function testCanGetSuccessfulTransferWithMaxTries() + { + $config = array_merge($this->config, [ + 'http_client_handler' => new FakeGraphApiForResumableUpload(), + ]); + $fb = new Facebook($config); + $response = $fb->uploadVideo('me', __DIR__.'/foo.txt', [], 'foo-token', 3); + $this->assertEquals([ + 'video_id' => '1337', + 'success' => true, + ], $response); + } + + /** + * @expectedException \Facebook\Exceptions\FacebookResponseException + */ + public function testMaxingOutRetriesWillThrow() + { + $client = new FakeGraphApiForResumableUpload(); + $client->failOnTransfer(); + + $config = array_merge($this->config, [ + 'http_client_handler' => $client, + ]); + $fb = new Facebook($config); + $fb->uploadVideo('4', __DIR__.'/foo.txt', [], 'foo-token', 3); + } } diff --git a/lib/facebook-graph-sdk/tests/FacebookTestCredentials.php.dist b/lib/facebook-graph-sdk/tests/FacebookTestCredentials.php.dist index e5b66f7..4d2878a 100644 --- a/lib/facebook-graph-sdk/tests/FacebookTestCredentials.php.dist +++ b/lib/facebook-graph-sdk/tests/FacebookTestCredentials.php.dist @@ -1,6 +1,6 @@ testFile = __DIR__ . '/../foo.txt'; } @@ -43,6 +42,14 @@ class FacebookFileTest extends \PHPUnit_Framework_TestCase $this->assertEquals('This is a text file used for testing. Let\'s dance.', $fileContents); } + public function testPartialFilesCanBeCreated() + { + $file = new FacebookFile($this->testFile, 14, 5); + $fileContents = $file->getContents(); + + $this->assertEquals('is a text file', $fileContents); + } + /** * @expectedException \Facebook\Exceptions\FacebookSDKException */ diff --git a/lib/facebook-graph-sdk/tests/FileUpload/FacebookResumableUploaderTest.php b/lib/facebook-graph-sdk/tests/FileUpload/FacebookResumableUploaderTest.php new file mode 100644 index 0000000..c32b7fb --- /dev/null +++ b/lib/facebook-graph-sdk/tests/FileUpload/FacebookResumableUploaderTest.php @@ -0,0 +1,101 @@ +fbApp = new FacebookApp('app_id', 'app_secret'); + $this->graphApi = new FakeGraphApiForResumableUpload(); + $this->client = new FacebookClient($this->graphApi); + $this->file = new FacebookFile(__DIR__.'/../foo.txt'); + } + + public function testResumableUploadCanStartTransferAndFinish() + { + $uploader = new FacebookResumableUploader($this->fbApp, $this->client, 'access_token', 'v2.4'); + $endpoint = '/me/videos'; + $chunk = $uploader->start($endpoint, $this->file); + $this->assertInstanceOf('Facebook\FileUpload\FacebookTransferChunk', $chunk); + $this->assertEquals('42', $chunk->getUploadSessionId()); + $this->assertEquals('1337', $chunk->getVideoId()); + + $newChunk = $uploader->transfer($endpoint, $chunk); + $this->assertEquals(20, $newChunk->getStartOffset()); + $this->assertNotSame($newChunk, $chunk); + + $finalResponse = $uploader->finish($endpoint, $chunk->getUploadSessionId(), []); + $this->assertTrue($finalResponse); + } + + /** + * @expectedException \Facebook\Exceptions\FacebookResponseException + */ + public function testStartWillLetErrorResponsesThrow() + { + $this->graphApi->failOnStart(); + $uploader = new FacebookResumableUploader($this->fbApp, $this->client, 'access_token', 'v2.4'); + + $uploader->start('/me/videos', $this->file); + } + + public function testFailedResumableTransferWillNotThrowAndReturnSameChunk() + { + $this->graphApi->failOnTransfer(); + $uploader = new FacebookResumableUploader($this->fbApp, $this->client, 'access_token', 'v2.4'); + + $chunk = new FacebookTransferChunk($this->file, '1', '2', '3', '4'); + $newChunk = $uploader->transfer('/me/videos', $chunk); + $this->assertSame($newChunk, $chunk); + } +} diff --git a/lib/facebook-graph-sdk/tests/FileUpload/MimetypesTest.php b/lib/facebook-graph-sdk/tests/FileUpload/MimetypesTest.php index c2092c1..14fc2b9 100644 --- a/lib/facebook-graph-sdk/tests/FileUpload/MimetypesTest.php +++ b/lib/facebook-graph-sdk/tests/FileUpload/MimetypesTest.php @@ -1,6 +1,6 @@ respondWith = 'FAIL_ON_START'; + } + + public function failOnTransfer() + { + $this->respondWith = 'FAIL_ON_TRANSFER'; + } + + public function send($url, $method, $body, array $headers, $timeOut) + { + // Could be start, transfer or finish + if (strpos($body, 'transfer') !== false) { + return $this->respondTransfer(); + } elseif (strpos($body, 'finish') !== false) { + return $this->respondFinish(); + } + + return $this->respondStart(); + } + + private function respondStart() + { + if ($this->respondWith == 'FAIL_ON_START') { + return new GraphRawResponse( + "HTTP/1.1 500 OK\r\nFoo: Bar", + '{"error":{"message":"Error validating access token: Session has expired on Monday, ' . + '10-Aug-15 01:00:00 PDT. The current time is Monday, 10-Aug-15 01:14:23 PDT.",' . + '"type":"OAuthException","code":190,"error_subcode":463}}' + ); + } + + return new GraphRawResponse( + "HTTP/1.1 200 OK\r\nFoo: Bar", + '{"video_id":"1337","start_offset":"0","end_offset":"20","upload_session_id":"42"}' + ); + } + + private function respondTransfer() + { + if ($this->respondWith == 'FAIL_ON_TRANSFER') { + return new GraphRawResponse( + "HTTP/1.1 500 OK\r\nFoo: Bar", + '{"error":{"message":"There was a problem uploading your video. Please try uploading it again.",' . + '"type":"FacebookApiException","code":6000,"error_subcode":1363019}}' + ); + } + + switch ($this->transferCount) { + case 0: + $data = ['start_offset' => 20, 'end_offset' => 40]; + break; + case 1: + $data = ['start_offset' => 40, 'end_offset' => 50]; + break; + default: + $data = ['start_offset' => 50, 'end_offset' => 50]; + break; + } + + $this->transferCount++; + + return new GraphRawResponse( + "HTTP/1.1 200 OK\r\nFoo: Bar", + json_encode($data) + ); + } + + private function respondFinish() + { + return new GraphRawResponse( + "HTTP/1.1 200 OK\r\nFoo: Bar", + '{"success":true}' + ); + } +} diff --git a/lib/facebook-graph-sdk/tests/Fixtures/FooBarPseudoRandomStringGenerator.php b/lib/facebook-graph-sdk/tests/Fixtures/FooBarPseudoRandomStringGenerator.php new file mode 100644 index 0000000..17448b6 --- /dev/null +++ b/lib/facebook-graph-sdk/tests/Fixtures/FooBarPseudoRandomStringGenerator.php @@ -0,0 +1,34 @@ +getParams(); + $rawResponse = json_encode([ + 'access_token' => 'foo_access_token_from:' . $params['code'], + ]); + + return new FacebookResponse($request, $rawResponse, 200); + } +} diff --git a/lib/facebook-graph-sdk/tests/Fixtures/FooUrlDetectionInterface.php b/lib/facebook-graph-sdk/tests/Fixtures/FooUrlDetectionInterface.php new file mode 100644 index 0000000..8ee70c3 --- /dev/null +++ b/lib/facebook-graph-sdk/tests/Fixtures/FooUrlDetectionInterface.php @@ -0,0 +1,34 @@ + '\Facebook\Tests\Fixtures\MyFooSubClassGraphNode', + ]; +} diff --git a/lib/facebook-graph-sdk/tests/Fixtures/MyFooSubClassGraphNode.php b/lib/facebook-graph-sdk/tests/Fixtures/MyFooSubClassGraphNode.php new file mode 100644 index 0000000..d03b308 --- /dev/null +++ b/lib/facebook-graph-sdk/tests/Fixtures/MyFooSubClassGraphNode.php @@ -0,0 +1,30 @@ +responseMock = m::mock('\Facebook\FacebookResponse'); diff --git a/lib/facebook-graph-sdk/tests/GraphNodes/CollectionTest.php b/lib/facebook-graph-sdk/tests/GraphNodes/CollectionTest.php index af3eba8..14af476 100755 --- a/lib/facebook-graph-sdk/tests/GraphNodes/CollectionTest.php +++ b/lib/facebook-graph-sdk/tests/GraphNodes/CollectionTest.php @@ -1,6 +1,6 @@ assertEquals('faz', $property); } + public function testFalseDefaultsWillReturnSameType() + { + $graphNode = new Collection(['foo' => 'bar']); + + $field = $graphNode->getField('baz', ''); + $this->assertSame('', $field); + + $field = $graphNode->getField('baz', 0); + $this->assertSame(0, $field); + + $field = $graphNode->getField('baz', false); + $this->assertSame(false, $field); + } + public function testTheKeysFromTheCollectionCanBeReturned() { $graphNode = new Collection([ diff --git a/lib/facebook-graph-sdk/tests/GraphNodes/GraphAchievementTest.php b/lib/facebook-graph-sdk/tests/GraphNodes/GraphAchievementTest.php index d5e276e..5be1140 100644 --- a/lib/facebook-graph-sdk/tests/GraphNodes/GraphAchievementTest.php +++ b/lib/facebook-graph-sdk/tests/GraphNodes/GraphAchievementTest.php @@ -1,6 +1,6 @@ responseMock = m::mock('\\Facebook\\FacebookResponse'); } diff --git a/lib/facebook-graph-sdk/tests/GraphNodes/GraphEdgeTest.php b/lib/facebook-graph-sdk/tests/GraphNodes/GraphEdgeTest.php index 4e70f52..3afaf9c 100644 --- a/lib/facebook-graph-sdk/tests/GraphNodes/GraphEdgeTest.php +++ b/lib/facebook-graph-sdk/tests/GraphNodes/GraphEdgeTest.php @@ -1,6 +1,6 @@ 'https://graph.facebook.com/v7.12/998899/photos?pretty=0&limit=25&after=foo_after_cursor', 'previous' => 'https://graph.facebook.com/v7.12/998899/photos?pretty=0&limit=25&before=foo_before_cursor', ]; - protected $cursorPagination = [ - 'cursors' => [ - 'after' => 'bar_after_cursor', - 'before' => 'bar_before_cursor', - ], - ]; - public function setUp() + protected function setUp() { $app = new FacebookApp('123', 'foo_app_secret'); $this->request = new FacebookRequest( @@ -75,7 +70,7 @@ class GraphEdgeTest extends \PHPUnit_Framework_TestCase $graphEdge = new GraphEdge( $this->request, [], - ['paging' => $this->basePagination] + ['paging' => $this->pagination] ); $nextPage = $graphEdge->getPaginationUrl('next'); $prevPage = $graphEdge->getPaginationUrl('previous'); @@ -84,37 +79,52 @@ class GraphEdgeTest extends \PHPUnit_Framework_TestCase $this->assertEquals('/998899/photos?pretty=0&limit=25&before=foo_before_cursor', $prevPage); } - public function testCanGeneratePaginationEndpointsFromACursor() + public function testCanInstantiateNewPaginationRequest() { $graphEdge = new GraphEdge( $this->request, [], - ['paging' => $this->cursorPagination], + ['paging' => $this->pagination], '/1234567890/likes' ); - $nextPage = $graphEdge->getPaginationUrl('next'); - $prevPage = $graphEdge->getPaginationUrl('previous'); + $nextPage = $graphEdge->getNextPageRequest(); + $prevPage = $graphEdge->getPreviousPageRequest(); - $this->assertEquals('/1234567890/likes?access_token=foo_token&after=bar_after_cursor&appsecret_proof=857d5f035a894f16b4180f19966e055cdeab92d4d53017b13dccd6d43b6497af&foo=bar&keep=me', $nextPage); - $this->assertEquals('/1234567890/likes?access_token=foo_token&appsecret_proof=857d5f035a894f16b4180f19966e055cdeab92d4d53017b13dccd6d43b6497af&before=bar_before_cursor&foo=bar&keep=me', $prevPage); + $this->assertInstanceOf('Facebook\FacebookRequest', $nextPage); + $this->assertInstanceOf('Facebook\FacebookRequest', $prevPage); + $this->assertNotSame($this->request, $nextPage); + $this->assertNotSame($this->request, $prevPage); + $this->assertEquals('/v1337/998899/photos?access_token=foo_token&after=foo_after_cursor&appsecret_proof=857d5f035a894f16b4180f19966e055cdeab92d4d53017b13dccd6d43b6497af&foo=bar&limit=25&pretty=0', $nextPage->getUrl()); + $this->assertEquals('/v1337/998899/photos?access_token=foo_token&appsecret_proof=857d5f035a894f16b4180f19966e055cdeab92d4d53017b13dccd6d43b6497af&before=foo_before_cursor&foo=bar&limit=25&pretty=0', $prevPage->getUrl()); } - public function testCanInstantiateNewPaginationRequest() + public function testCanMapOverNodes() { $graphEdge = new GraphEdge( $this->request, - [], - ['paging' => $this->cursorPagination], + [ + new GraphNode(['name' => 'dummy']), + new GraphNode(['name' => 'dummy']), + ], + ['paging' => $this->pagination], '/1234567890/likes' ); - $nextPage = $graphEdge->getNextPageRequest(); - $prevPage = $graphEdge->getPreviousPageRequest(); - $this->assertInstanceOf('Facebook\FacebookRequest', $nextPage); - $this->assertInstanceOf('Facebook\FacebookRequest', $prevPage); - $this->assertNotSame($this->request, $nextPage); - $this->assertNotSame($this->request, $prevPage); - $this->assertEquals('/v1337/1234567890/likes?access_token=foo_token&after=bar_after_cursor&appsecret_proof=857d5f035a894f16b4180f19966e055cdeab92d4d53017b13dccd6d43b6497af&foo=bar&keep=me', $nextPage->getUrl()); - $this->assertEquals('/v1337/1234567890/likes?access_token=foo_token&appsecret_proof=857d5f035a894f16b4180f19966e055cdeab92d4d53017b13dccd6d43b6497af&before=bar_before_cursor&foo=bar&keep=me', $prevPage->getUrl()); + $graphEdge = $graphEdge->map(function (GraphNode $node) { + $node['name'] = str_replace('dummy', 'foo', $node['name']); + return $node; + }); + + $graphEdgeToCompare = new GraphEdge( + $this->request, + [ + new GraphNode(['name' => 'foo']), + new GraphNode(['name' => 'foo']) + ], + ['paging' => $this->pagination], + '/1234567890/likes' + ); + + $this->assertEquals($graphEdgeToCompare, $graphEdge); } } diff --git a/lib/facebook-graph-sdk/tests/GraphNodes/GraphEventTest.php b/lib/facebook-graph-sdk/tests/GraphNodes/GraphEventTest.php index 98ccd85..7c6f127 100644 --- a/lib/facebook-graph-sdk/tests/GraphNodes/GraphEventTest.php +++ b/lib/facebook-graph-sdk/tests/GraphNodes/GraphEventTest.php @@ -1,6 +1,6 @@ responseMock = m::mock('\Facebook\FacebookResponse'); } diff --git a/lib/facebook-graph-sdk/tests/GraphNodes/GraphGroupTest.php b/lib/facebook-graph-sdk/tests/GraphNodes/GraphGroupTest.php index 21893b5..c62d50f 100644 --- a/lib/facebook-graph-sdk/tests/GraphNodes/GraphGroupTest.php +++ b/lib/facebook-graph-sdk/tests/GraphNodes/GraphGroupTest.php @@ -1,6 +1,6 @@ responseMock = m::mock('\Facebook\FacebookResponse'); } diff --git a/lib/facebook-graph-sdk/tests/GraphNodes/GraphNodeFactoryTest.php b/lib/facebook-graph-sdk/tests/GraphNodes/GraphNodeFactoryTest.php index 7d2f023..a4aa5e1 100644 --- a/lib/facebook-graph-sdk/tests/GraphNodes/GraphNodeFactoryTest.php +++ b/lib/facebook-graph-sdk/tests/GraphNodes/GraphNodeFactoryTest.php @@ -1,6 +1,6 @@ '\Facebook\Tests\GraphNodes\MyFooSubClassGraphNode', - ]; -} class GraphNodeFactoryTest extends \PHPUnit_Framework_TestCase { @@ -47,7 +35,7 @@ class GraphNodeFactoryTest extends \PHPUnit_Framework_TestCase */ protected $request; - public function setUp() + protected function setUp() { $app = new FacebookApp('123', 'foo_app_secret'); $this->request = new FacebookRequest( @@ -126,7 +114,7 @@ class GraphNodeFactoryTest extends \PHPUnit_Framework_TestCase { GraphNodeFactory::validateSubclass('\Facebook\GraphNodes\GraphNode'); GraphNodeFactory::validateSubclass('\Facebook\GraphNodes\GraphAlbum'); - GraphNodeFactory::validateSubclass('\Facebook\Tests\GraphNodes\MyFooGraphNode'); + GraphNodeFactory::validateSubclass('\Facebook\Tests\Fixtures\MyFooGraphNode'); } public function testCastingAsASubClassObjectWillInstantiateTheSubClass() @@ -135,9 +123,9 @@ class GraphNodeFactoryTest extends \PHPUnit_Framework_TestCase $res = new FacebookResponse($this->request, $data); $factory = new GraphNodeFactory($res); - $mySubClassObject = $factory->makeGraphNode('\Facebook\Tests\GraphNodes\MyFooGraphNode'); + $mySubClassObject = $factory->makeGraphNode('\Facebook\Tests\Fixtures\MyFooGraphNode'); - $this->assertInstanceOf('\Facebook\Tests\GraphNodes\MyFooGraphNode', $mySubClassObject); + $this->assertInstanceOf('\Facebook\Tests\Fixtures\MyFooGraphNode', $mySubClassObject); } public function testASubClassMappingWillAutomaticallyInstantiateSubClass() @@ -146,11 +134,11 @@ class GraphNodeFactoryTest extends \PHPUnit_Framework_TestCase $res = new FacebookResponse($this->request, $data); $factory = new GraphNodeFactory($res); - $mySubClassObject = $factory->makeGraphNode('\Facebook\Tests\GraphNodes\MyFooGraphNode'); + $mySubClassObject = $factory->makeGraphNode('\Facebook\Tests\Fixtures\MyFooGraphNode'); $fooObject = $mySubClassObject->getField('foo_object'); - $this->assertInstanceOf('\Facebook\Tests\GraphNodes\MyFooGraphNode', $mySubClassObject); - $this->assertInstanceOf('\Facebook\Tests\GraphNodes\MyFooSubClassGraphNode', $fooObject); + $this->assertInstanceOf('\Facebook\Tests\Fixtures\MyFooGraphNode', $mySubClassObject); + $this->assertInstanceOf('\Facebook\Tests\Fixtures\MyFooSubClassGraphNode', $fooObject); } public function testAnUnknownGraphNodeWillBeCastAsAGenericGraphNode() @@ -167,12 +155,12 @@ class GraphNodeFactoryTest extends \PHPUnit_Framework_TestCase $factory = new GraphNodeFactory($res); - $mySubClassObject = $factory->makeGraphNode('\Facebook\Tests\GraphNodes\MyFooGraphNode'); + $mySubClassObject = $factory->makeGraphNode('\Facebook\Tests\Fixtures\MyFooGraphNode'); $unknownObject = $mySubClassObject->getField('unknown_object'); - $this->assertInstanceOf('\Facebook\Tests\GraphNodes\MyFooGraphNode', $mySubClassObject); + $this->assertInstanceOf('\Facebook\Tests\Fixtures\MyFooGraphNode', $mySubClassObject); $this->assertInstanceOf('\Facebook\GraphNodes\GraphNode', $unknownObject); - $this->assertNotInstanceOf('\Facebook\Tests\GraphNodes\MyFooGraphNode', $unknownObject); + $this->assertNotInstanceOf('\Facebook\Tests\Fixtures\MyFooGraphNode', $unknownObject); } public function testAListFromGraphWillBeCastAsAGraphEdge() diff --git a/lib/facebook-graph-sdk/tests/GraphNodes/GraphNodeTest.php b/lib/facebook-graph-sdk/tests/GraphNodes/GraphNodeTest.php index 50f58ae..67444fa 100644 --- a/lib/facebook-graph-sdk/tests/GraphNodes/GraphNodeTest.php +++ b/lib/facebook-graph-sdk/tests/GraphNodes/GraphNodeTest.php @@ -1,6 +1,6 @@ request = new FacebookRequest( diff --git a/lib/facebook-graph-sdk/tests/GraphNodes/GraphPageTest.php b/lib/facebook-graph-sdk/tests/GraphNodes/GraphPageTest.php index a3a88e9..c7ce163 100644 --- a/lib/facebook-graph-sdk/tests/GraphNodes/GraphPageTest.php +++ b/lib/facebook-graph-sdk/tests/GraphNodes/GraphPageTest.php @@ -1,6 +1,6 @@ responseMock = m::mock('\\Facebook\\FacebookResponse'); } diff --git a/lib/facebook-graph-sdk/tests/GraphNodes/GraphSessionInfoTest.php b/lib/facebook-graph-sdk/tests/GraphNodes/GraphSessionInfoTest.php index 2960c28..b2e56fa 100644 --- a/lib/facebook-graph-sdk/tests/GraphNodes/GraphSessionInfoTest.php +++ b/lib/facebook-graph-sdk/tests/GraphNodes/GraphSessionInfoTest.php @@ -1,6 +1,6 @@ responseMock = m::mock('\\Facebook\\FacebookResponse'); } diff --git a/lib/facebook-graph-sdk/tests/GraphNodes/GraphUserTest.php b/lib/facebook-graph-sdk/tests/GraphNodes/GraphUserTest.php index ca75573..a3230fa 100644 --- a/lib/facebook-graph-sdk/tests/GraphNodes/GraphUserTest.php +++ b/lib/facebook-graph-sdk/tests/GraphNodes/GraphUserTest.php @@ -1,6 +1,6 @@ responseMock = m::mock('\\Facebook\\FacebookResponse'); } @@ -42,7 +42,25 @@ class GraphUserTest extends \PHPUnit_Framework_TestCase public function testDatesGetCastToDateTime() { $dataFromGraph = [ - 'birthday' => '1984-01-01', + 'updated_time' => '2016-04-26 13:22:05', + ]; + + $this->responseMock + ->shouldReceive('getDecodedBody') + ->once() + ->andReturn($dataFromGraph); + $factory = new GraphNodeFactory($this->responseMock); + $graphNode = $factory->makeGraphUser(); + + $updatedTime = $graphNode->getField('updated_time'); + + $this->assertInstanceOf('DateTime', $updatedTime); + } + + public function testBirthdaysGetCastToBirthday() + { + $dataFromGraph = [ + 'birthday' => '1984/01/01', ]; $this->responseMock @@ -54,7 +72,53 @@ class GraphUserTest extends \PHPUnit_Framework_TestCase $birthday = $graphNode->getBirthday(); + // Test to ensure BC $this->assertInstanceOf('DateTime', $birthday); + + $this->assertInstanceOf('\\Facebook\\GraphNodes\\Birthday', $birthday); + $this->assertTrue($birthday->hasDate()); + $this->assertTrue($birthday->hasYear()); + $this->assertEquals('1984/01/01', $birthday->format('Y/m/d')); + } + + public function testBirthdayCastHandlesDateWithoutYear() + { + $dataFromGraph = [ + 'birthday' => '03/21', + ]; + + $this->responseMock + ->shouldReceive('getDecodedBody') + ->once() + ->andReturn($dataFromGraph); + $factory = new GraphNodeFactory($this->responseMock); + $graphNode = $factory->makeGraphUser(); + + $birthday = $graphNode->getBirthday(); + + $this->assertTrue($birthday->hasDate()); + $this->assertFalse($birthday->hasYear()); + $this->assertEquals('03/21', $birthday->format('m/d')); + } + + public function testBirthdayCastHandlesYearWithoutDate() + { + $dataFromGraph = [ + 'birthday' => '1984', + ]; + + $this->responseMock + ->shouldReceive('getDecodedBody') + ->once() + ->andReturn($dataFromGraph); + $factory = new GraphNodeFactory($this->responseMock); + $graphNode = $factory->makeGraphUser(); + + $birthday = $graphNode->getBirthday(); + + $this->assertTrue($birthday->hasYear()); + $this->assertFalse($birthday->hasDate()); + $this->assertEquals('1984', $birthday->format('Y')); } public function testPagePropertiesWillGetCastAsGraphPageObjects() diff --git a/lib/facebook-graph-sdk/tests/Helpers/FacebookCanvasHelperTest.php b/lib/facebook-graph-sdk/tests/Helpers/FacebookCanvasHelperTest.php index 294440e..f03d66f 100644 --- a/lib/facebook-graph-sdk/tests/Helpers/FacebookCanvasHelperTest.php +++ b/lib/facebook-graph-sdk/tests/Helpers/FacebookCanvasHelperTest.php @@ -1,6 +1,6 @@ helper = new FacebookCanvasHelper($app, new FacebookClient()); diff --git a/lib/facebook-graph-sdk/tests/Helpers/FacebookJavaScriptHelperTest.php b/lib/facebook-graph-sdk/tests/Helpers/FacebookJavaScriptHelperTest.php index 3f9cb88..5218758 100644 --- a/lib/facebook-graph-sdk/tests/Helpers/FacebookJavaScriptHelperTest.php +++ b/lib/facebook-graph-sdk/tests/Helpers/FacebookJavaScriptHelperTest.php @@ -1,6 +1,6 @@ persistentDataHandler = new FacebookMemoryPersistentDataHandler(); @@ -110,12 +97,18 @@ class FacebookRedirectLoginHelperTest extends \PHPUnit_Framework_TestCase public function testAnAccessTokenCanBeObtainedFromRedirect() { $this->persistentDataHandler->set('state', 'foo_state'); - $_GET['state'] = 'foo_state'; - $_GET['code'] = 'foo_code'; + $_GET['state'] = static::FOO_STATE; + $_GET['code'] = static::FOO_CODE; + + $fullUrl = self::REDIRECT_URL . '?state=' . static::FOO_STATE . '&code=' . static::FOO_CODE . '&' . static::FOO_PARAM; + + $accessToken = $this->redirectLoginHelper->getAccessToken($fullUrl); - $accessToken = $this->redirectLoginHelper->getAccessToken(self::REDIRECT_URL); + // code and state should be stripped from the URL + $expectedUrl = self::REDIRECT_URL . '?' . static::FOO_PARAM; + $expectedString = 'foo_token_from_code|' . static::FOO_CODE . '|' . $expectedUrl; - $this->assertEquals('foo_token_from_code|foo_code|' . self::REDIRECT_URL, (string)$accessToken); + $this->assertEquals($expectedString, $accessToken->getValue()); } public function testACustomCsprsgCanBeInjected() diff --git a/lib/facebook-graph-sdk/tests/Helpers/FacebookSignedRequestFromInputHelperTest.php b/lib/facebook-graph-sdk/tests/Helpers/FacebookSignedRequestFromInputHelperTest.php index d9bd803..ffaa5e3 100644 --- a/lib/facebook-graph-sdk/tests/Helpers/FacebookSignedRequestFromInputHelperTest.php +++ b/lib/facebook-graph-sdk/tests/Helpers/FacebookSignedRequestFromInputHelperTest.php @@ -1,6 +1,6 @@ getParams(); - $rawResponse = json_encode([ - 'access_token' => 'foo_access_token_from:' . $params['code'], - ]); - - return new FacebookResponse($request, $rawResponse, 200); - } -} +use Facebook\Tests\Fixtures\FooSignedRequestHelper; +use Facebook\Tests\Fixtures\FooSignedRequestHelperFacebookClient; class FacebookSignedRequestFromInputHelperTest extends \PHPUnit_Framework_TestCase { @@ -61,7 +38,7 @@ class FacebookSignedRequestFromInputHelperTest extends \PHPUnit_Framework_TestCa public $rawSignedRequestAuthorizedWithCode = 'oBtmZlsFguNQvGRETDYQQu1-PhwcArgbBBEK4urbpRA=.eyJjb2RlIjoiZm9vX2NvZGUiLCJhbGdvcml0aG0iOiJITUFDLVNIQTI1NiIsImlzc3VlZF9hdCI6MTQwNjMxMDc1MiwidXNlcl9pZCI6IjEyMyJ9'; public $rawSignedRequestUnauthorized = 'KPlyhz-whtYAhHWr15N5TkbS_avz-2rUJFpFkfXKC88=.eyJhbGdvcml0aG0iOiJITUFDLVNIQTI1NiIsImlzc3VlZF9hdCI6MTQwMjU1MTA4Nn0='; - public function setUp() + protected function setUp() { $app = new FacebookApp('123', 'foo_app_secret'); $this->helper = new FooSignedRequestHelper($app, new FooSignedRequestHelperFacebookClient()); diff --git a/lib/facebook-graph-sdk/tests/Http/GraphRawResponseTest.php b/lib/facebook-graph-sdk/tests/Http/GraphRawResponseTest.php index ecad26f..3b18b56 100644 --- a/lib/facebook-graph-sdk/tests/Http/GraphRawResponseTest.php +++ b/lib/facebook-graph-sdk/tests/Http/GraphRawResponseTest.php @@ -1,6 +1,6 @@ '*', ]; + protected $jsonFakeHeader = 'x-fb-ads-insights-throttle: {"app_id_util_pct": 0.00,"acc_id_util_pct": 0.00}'; + protected $jsonFakeHeaderAsArray = ['x-fb-ads-insights-throttle' => '{"app_id_util_pct": 0.00,"acc_id_util_pct": 0.00}']; + public function testCanSetTheHeadersFromAnArray() { $myHeaders = [ @@ -79,4 +82,12 @@ HEADER; $this->assertEquals($this->fakeHeadersAsArray, $headers); $this->assertEquals(200, $httpResponseCode); } + + public function testCanTransformJsonHeaderValues() + { + $response = new GraphRawResponse($this->jsonFakeHeader, ''); + $headers = $response->getHeaders(); + + $this->assertEquals($this->jsonFakeHeaderAsArray['x-fb-ads-insights-throttle'], $headers['x-fb-ads-insights-throttle']); + } } diff --git a/lib/facebook-graph-sdk/tests/Http/RequestBodyMultipartTest.php b/lib/facebook-graph-sdk/tests/Http/RequestBodyMultipartTest.php index 267cc49..1a23c46 100644 --- a/lib/facebook-graph-sdk/tests/Http/RequestBodyMultipartTest.php +++ b/lib/facebook-graph-sdk/tests/Http/RequestBodyMultipartTest.php @@ -1,6 +1,6 @@ markTestSkipped('cURL must be installed to test cURL client handler.'); + } $this->curlMock = m::mock('Facebook\HttpClients\FacebookCurl'); $this->curlClient = new FacebookCurlHttpClient($this->curlMock); } @@ -146,15 +149,6 @@ class FacebookCurlHttpClientTest extends AbstractTestHttpClient public function testIsolatesTheHeaderAndBody() { - $this->curlMock - ->shouldReceive('getinfo') - ->with(CURLINFO_HEADER_SIZE) - ->once() - ->andReturn(strlen($this->fakeRawHeader)); - $this->curlMock - ->shouldReceive('version') - ->once() - ->andReturn(['version_number' => self::CURL_VERSION_STABLE]); $this->curlMock ->shouldReceive('exec') ->once() @@ -170,15 +164,6 @@ class FacebookCurlHttpClientTest extends AbstractTestHttpClient public function testProperlyHandlesProxyHeaders() { $rawHeader = $this->fakeRawProxyHeader . $this->fakeRawHeader; - $this->curlMock - ->shouldReceive('getinfo') - ->with(CURLINFO_HEADER_SIZE) - ->once() - ->andReturn(mb_strlen($rawHeader)); - $this->curlMock - ->shouldReceive('version') - ->once() - ->andReturn(['version_number' => self::CURL_VERSION_STABLE]); $this->curlMock ->shouldReceive('exec') ->once() @@ -194,15 +179,6 @@ class FacebookCurlHttpClientTest extends AbstractTestHttpClient public function testProperlyHandlesProxyHeadersWithCurlBug() { $rawHeader = $this->fakeRawProxyHeader . $this->fakeRawHeader; - $this->curlMock - ->shouldReceive('getinfo') - ->with(CURLINFO_HEADER_SIZE) - ->once() - ->andReturn(mb_strlen($this->fakeRawHeader)); // Mimic bug that doesn't count proxy header - $this->curlMock - ->shouldReceive('version') - ->once() - ->andReturn(['version_number' => self::CURL_VERSION_BUGGY]); $this->curlMock ->shouldReceive('exec') ->once() @@ -218,15 +194,6 @@ class FacebookCurlHttpClientTest extends AbstractTestHttpClient public function testProperlyHandlesProxyHeadersWithCurlBug2() { $rawHeader = $this->fakeRawProxyHeader2 . $this->fakeRawHeader; - $this->curlMock - ->shouldReceive('getinfo') - ->with(CURLINFO_HEADER_SIZE) - ->once() - ->andReturn(mb_strlen($this->fakeRawHeader)); // Mimic bug that doesn't count proxy header - $this->curlMock - ->shouldReceive('version') - ->once() - ->andReturn(['version_number' => self::CURL_VERSION_BUGGY]); $this->curlMock ->shouldReceive('exec') ->once() @@ -242,15 +209,6 @@ class FacebookCurlHttpClientTest extends AbstractTestHttpClient public function testProperlyHandlesRedirectHeaders() { $rawHeader = $this->fakeRawRedirectHeader . $this->fakeRawHeader; - $this->curlMock - ->shouldReceive('getinfo') - ->with(CURLINFO_HEADER_SIZE) - ->once() - ->andReturn(mb_strlen($rawHeader)); - $this->curlMock - ->shouldReceive('version') - ->once() - ->andReturn(['version_number' => self::CURL_VERSION_STABLE]); $this->curlMock ->shouldReceive('exec') ->once() @@ -281,15 +239,6 @@ class FacebookCurlHttpClientTest extends AbstractTestHttpClient ->shouldReceive('errno') ->once() ->andReturn(null); - $this->curlMock - ->shouldReceive('getinfo') - ->with(CURLINFO_HEADER_SIZE) - ->once() - ->andReturn(mb_strlen($this->fakeRawHeader)); - $this->curlMock - ->shouldReceive('version') - ->once() - ->andReturn(['version_number' => self::CURL_VERSION_STABLE]); $this->curlMock ->shouldReceive('close') ->once() diff --git a/lib/facebook-graph-sdk/tests/HttpClients/FacebookGuzzleHttpClientTest.php b/lib/facebook-graph-sdk/tests/HttpClients/FacebookGuzzleHttpClientTest.php index 12eb36a..f14ad96 100644 --- a/lib/facebook-graph-sdk/tests/HttpClients/FacebookGuzzleHttpClientTest.php +++ b/lib/facebook-graph-sdk/tests/HttpClients/FacebookGuzzleHttpClientTest.php @@ -1,6 +1,6 @@ guzzleMock = m::mock('GuzzleHttp\Client'); $this->guzzleClient = new FacebookGuzzleHttpClient($this->guzzleMock); diff --git a/lib/facebook-graph-sdk/tests/HttpClients/FacebookStreamHttpClientTest.php b/lib/facebook-graph-sdk/tests/HttpClients/FacebookStreamHttpClientTest.php index 9102b08..3749960 100644 --- a/lib/facebook-graph-sdk/tests/HttpClients/FacebookStreamHttpClientTest.php +++ b/lib/facebook-graph-sdk/tests/HttpClients/FacebookStreamHttpClientTest.php @@ -1,6 +1,6 @@ streamMock = m::mock('Facebook\HttpClients\FacebookStream'); $this->streamClient = new FacebookStreamHttpClient($this->streamMock); diff --git a/lib/facebook-graph-sdk/tests/HttpClients/HttpClientsFactoryTest.php b/lib/facebook-graph-sdk/tests/HttpClients/HttpClientsFactoryTest.php new file mode 100644 index 0000000..4d49489 --- /dev/null +++ b/lib/facebook-graph-sdk/tests/HttpClients/HttpClientsFactoryTest.php @@ -0,0 +1,72 @@ +assertInstanceOf(self::COMMON_INTERFACE, $httpClient); + $this->assertInstanceOf($expected, $httpClient); + } + + /** + * @return array + */ + public function httpClientsProvider() + { + $clients = [ + ['guzzle', self::COMMON_NAMESPACE . 'FacebookGuzzleHttpClient'], + ['stream', self::COMMON_NAMESPACE . 'FacebookStreamHttpClient'], + [new Client(), self::COMMON_NAMESPACE . 'FacebookGuzzleHttpClient'], + [new FacebookGuzzleHttpClient(), self::COMMON_NAMESPACE . 'FacebookGuzzleHttpClient'], + [new FacebookStreamHttpClient(), self::COMMON_NAMESPACE . 'FacebookStreamHttpClient'], + [null, self::COMMON_INTERFACE], + ]; + if (extension_loaded('curl')) { + $clients[] = ['curl', self::COMMON_NAMESPACE . 'FacebookCurlHttpClient']; + $clients[] = [new FacebookCurlHttpClient(), self::COMMON_NAMESPACE . 'FacebookCurlHttpClient']; + } + + return $clients; + } +} diff --git a/lib/facebook-graph-sdk/tests/PersistentData/FacebookMemoryPersistentDataHandlerTest.php b/lib/facebook-graph-sdk/tests/PersistentData/FacebookMemoryPersistentDataHandlerTest.php index 2b09d29..89717f8 100644 --- a/lib/facebook-graph-sdk/tests/PersistentData/FacebookMemoryPersistentDataHandlerTest.php +++ b/lib/facebook-graph-sdk/tests/PersistentData/FacebookMemoryPersistentDataHandlerTest.php @@ -1,6 +1,6 @@ assertInstanceOf(self::COMMON_INTERFACE, $persistentDataHandler); + $this->assertInstanceOf($expected, $persistentDataHandler); + } + + /** + * @return array + */ + public function persistentDataHandlerProviders() + { + $handlers = [ + ['memory', self::COMMON_NAMESPACE . 'FacebookMemoryPersistentDataHandler'], + [new FacebookMemoryPersistentDataHandler(), self::COMMON_NAMESPACE . 'FacebookMemoryPersistentDataHandler'], + [new FacebookSessionPersistentDataHandler(false), self::COMMON_NAMESPACE . 'FacebookSessionPersistentDataHandler'], + [null, self::COMMON_INTERFACE], + ]; + + if (session_status() === PHP_SESSION_ACTIVE) { + $handlers[] = ['session', self::COMMON_NAMESPACE . 'FacebookSessionPersistentDataHandler']; + } + + return $handlers; + } +} diff --git a/lib/facebook-graph-sdk/tests/PseudoRandomString/McryptPseudoRandomStringGeneratorTest.php b/lib/facebook-graph-sdk/tests/PseudoRandomString/McryptPseudoRandomStringGeneratorTest.php index a45a3cf..f5e0336 100644 --- a/lib/facebook-graph-sdk/tests/PseudoRandomString/McryptPseudoRandomStringGeneratorTest.php +++ b/lib/facebook-graph-sdk/tests/PseudoRandomString/McryptPseudoRandomStringGeneratorTest.php @@ -1,6 +1,6 @@ =')) { + $this->markTestSkipped('Skipping test mcrypt is deprecated from 7.1'); + } + if (!function_exists('mcrypt_create_iv')) { $this->markTestSkipped( 'Mcrypt must be installed to test mcrypt_create_iv().' diff --git a/lib/facebook-graph-sdk/tests/PseudoRandomString/OpenSslPseudoRandomStringGeneratorTest.php b/lib/facebook-graph-sdk/tests/PseudoRandomString/OpenSslPseudoRandomStringGeneratorTest.php index c740d0b..3ab4edc 100644 --- a/lib/facebook-graph-sdk/tests/PseudoRandomString/OpenSslPseudoRandomStringGeneratorTest.php +++ b/lib/facebook-graph-sdk/tests/PseudoRandomString/OpenSslPseudoRandomStringGeneratorTest.php @@ -1,6 +1,6 @@ assertInstanceOf(self::COMMON_INTERFACE, $pseudoRandomStringGenerator); + $this->assertInstanceOf($expected, $pseudoRandomStringGenerator); + } + + /** + * @return array + */ + public function csprngProvider() + { + $providers = [ + [null, self::COMMON_INTERFACE], + ]; + if (function_exists('random_bytes')) { + $providers[] = ['random_bytes', self::COMMON_NAMESPACE . 'RandomBytesPseudoRandomStringGenerator']; + } + if (function_exists('mcrypt_create_iv')) { + $providers[] = ['mcrypt', self::COMMON_NAMESPACE . 'McryptPseudoRandomStringGenerator']; + } + if (function_exists('openssl_random_pseudo_bytes')) { + $providers[] = ['openssl', self::COMMON_NAMESPACE . 'OpenSslPseudoRandomStringGenerator']; + } + if (!ini_get('open_basedir') && is_readable('/dev/urandom')) { + $providers[] = ['urandom', self::COMMON_NAMESPACE . 'UrandomPseudoRandomStringGenerator']; + } + + return $providers; + } +} diff --git a/lib/facebook-graph-sdk/tests/PseudoRandomString/PseudoRandomStringGeneratorTraitTest.php b/lib/facebook-graph-sdk/tests/PseudoRandomString/PseudoRandomStringGeneratorTraitTest.php index ea3a1f8..16165d9 100644 --- a/lib/facebook-graph-sdk/tests/PseudoRandomString/PseudoRandomStringGeneratorTraitTest.php +++ b/lib/facebook-graph-sdk/tests/PseudoRandomString/PseudoRandomStringGeneratorTraitTest.php @@ -1,6 +1,6 @@ markTestSkipped( + 'Must have PHP 7 or paragonie/random_compat installed to test random_bytes().' + ); + } + + $csprng = new RandomBytesPseudoRandomStringGenerator; + $randomString = $csprng->getPseudoRandomString(10); + + $this->assertEquals(1, preg_match('/^([0-9a-f]+)$/', $randomString)); + $this->assertEquals(10, strlen($randomString)); + } +} diff --git a/lib/facebook-graph-sdk/tests/PseudoRandomString/UrandomPseudoRandomStringGeneratorTest.php b/lib/facebook-graph-sdk/tests/PseudoRandomString/UrandomPseudoRandomStringGeneratorTest.php index 9e12a58..e67136f 100644 --- a/lib/facebook-graph-sdk/tests/PseudoRandomString/UrandomPseudoRandomStringGeneratorTest.php +++ b/lib/facebook-graph-sdk/tests/PseudoRandomString/UrandomPseudoRandomStringGeneratorTest.php @@ -1,6 +1,6 @@ 'bar', ]; - public function setUp() + protected function setUp() { $this->app = new FacebookApp('123', 'foo_app_secret'); } diff --git a/lib/facebook-graph-sdk/tests/Url/FacebookUrlDetectionHandlerTest.php b/lib/facebook-graph-sdk/tests/Url/FacebookUrlDetectionHandlerTest.php index c3127ef..b623c05 100644 --- a/lib/facebook-graph-sdk/tests/Url/FacebookUrlDetectionHandlerTest.php +++ b/lib/facebook-graph-sdk/tests/Url/FacebookUrlDetectionHandlerTest.php @@ -1,6 +1,6 @@