Просмотр исходного кода

#298 Update Facebook SDK from 5.0.0 to 5.2.0

Alex Trofimov 10 лет назад
Родитель
Сommit
6d7025e072
84 измененных файлов с 1051 добавлено и 670 удалено
  1. 0 4
      plugins/facebook-php-sdk/.gitignore
  2. 0 8
      plugins/facebook-php-sdk/.scrutinizer.yml
  3. 0 24
      plugins/facebook-php-sdk/.travis.yml
  4. 0 153
      plugins/facebook-php-sdk/CHANGELOG.md
  5. 0 54
      plugins/facebook-php-sdk/CONTRIBUTING.md
  6. 1 1
      plugins/facebook-php-sdk/LICENSE
  7. 0 89
      plugins/facebook-php-sdk/README.md
  8. 3 3
      plugins/facebook-php-sdk/composer.json
  9. 0 22
      plugins/facebook-php-sdk/phpunit.xml.dist
  10. 1 1
      plugins/facebook-php-sdk/src/Facebook/Authentication/AccessToken.php
  11. 2 2
      plugins/facebook-php-sdk/src/Facebook/Authentication/AccessTokenMetadata.php
  12. 4 4
      plugins/facebook-php-sdk/src/Facebook/Authentication/OAuth2Client.php
  13. 1 1
      plugins/facebook-php-sdk/src/Facebook/Exceptions/FacebookAuthenticationException.php
  14. 1 1
      plugins/facebook-php-sdk/src/Facebook/Exceptions/FacebookAuthorizationException.php
  15. 1 1
      plugins/facebook-php-sdk/src/Facebook/Exceptions/FacebookClientException.php
  16. 1 1
      plugins/facebook-php-sdk/src/Facebook/Exceptions/FacebookOtherException.php
  17. 9 3
      plugins/facebook-php-sdk/src/Facebook/Exceptions/FacebookResponseException.php
  18. 33 0
      plugins/facebook-php-sdk/src/Facebook/Exceptions/FacebookResumableUploadException.php
  19. 1 1
      plugins/facebook-php-sdk/src/Facebook/Exceptions/FacebookSDKException.php
  20. 1 1
      plugins/facebook-php-sdk/src/Facebook/Exceptions/FacebookServerException.php
  21. 1 1
      plugins/facebook-php-sdk/src/Facebook/Exceptions/FacebookThrottleException.php
  22. 105 80
      plugins/facebook-php-sdk/src/Facebook/Facebook.php
  23. 13 4
      plugins/facebook-php-sdk/src/Facebook/FacebookApp.php
  24. 1 1
      plugins/facebook-php-sdk/src/Facebook/FacebookBatchRequest.php
  25. 22 2
      plugins/facebook-php-sdk/src/Facebook/FacebookBatchResponse.php
  26. 3 3
      plugins/facebook-php-sdk/src/Facebook/FacebookClient.php
  27. 3 5
      plugins/facebook-php-sdk/src/Facebook/FacebookRequest.php
  28. 1 1
      plugins/facebook-php-sdk/src/Facebook/FacebookResponse.php
  29. 37 3
      plugins/facebook-php-sdk/src/Facebook/FileUpload/FacebookFile.php
  30. 167 0
      plugins/facebook-php-sdk/src/Facebook/FileUpload/FacebookResumableUploader.php
  31. 133 0
      plugins/facebook-php-sdk/src/Facebook/FileUpload/FacebookTransferChunk.php
  32. 1 1
      plugins/facebook-php-sdk/src/Facebook/FileUpload/FacebookVideo.php
  33. 1 1
      plugins/facebook-php-sdk/src/Facebook/FileUpload/Mimetypes.php
  34. 85 0
      plugins/facebook-php-sdk/src/Facebook/GraphNodes/Birthday.php
  35. 2 2
      plugins/facebook-php-sdk/src/Facebook/GraphNodes/Collection.php
  36. 2 2
      plugins/facebook-php-sdk/src/Facebook/GraphNodes/GraphAchievement.php
  37. 1 1
      plugins/facebook-php-sdk/src/Facebook/GraphNodes/GraphAlbum.php
  38. 1 1
      plugins/facebook-php-sdk/src/Facebook/GraphNodes/GraphApplication.php
  39. 1 1
      plugins/facebook-php-sdk/src/Facebook/GraphNodes/GraphCoverPhoto.php
  40. 4 26
      plugins/facebook-php-sdk/src/Facebook/GraphNodes/GraphEdge.php
  41. 1 1
      plugins/facebook-php-sdk/src/Facebook/GraphNodes/GraphEvent.php
  42. 1 2
      plugins/facebook-php-sdk/src/Facebook/GraphNodes/GraphGroup.php
  43. 1 1
      plugins/facebook-php-sdk/src/Facebook/GraphNodes/GraphList.php
  44. 1 1
      plugins/facebook-php-sdk/src/Facebook/GraphNodes/GraphLocation.php
  45. 15 3
      plugins/facebook-php-sdk/src/Facebook/GraphNodes/GraphNode.php
  46. 1 1
      plugins/facebook-php-sdk/src/Facebook/GraphNodes/GraphNodeFactory.php
  47. 1 1
      plugins/facebook-php-sdk/src/Facebook/GraphNodes/GraphObject.php
  48. 2 2
      plugins/facebook-php-sdk/src/Facebook/GraphNodes/GraphObjectFactory.php
  49. 1 1
      plugins/facebook-php-sdk/src/Facebook/GraphNodes/GraphPage.php
  50. 1 1
      plugins/facebook-php-sdk/src/Facebook/GraphNodes/GraphPicture.php
  51. 1 1
      plugins/facebook-php-sdk/src/Facebook/GraphNodes/GraphSessionInfo.php
  52. 1 1
      plugins/facebook-php-sdk/src/Facebook/GraphNodes/GraphUser.php
  53. 1 1
      plugins/facebook-php-sdk/src/Facebook/Helpers/FacebookCanvasHelper.php
  54. 1 1
      plugins/facebook-php-sdk/src/Facebook/Helpers/FacebookJavaScriptHelper.php
  55. 1 1
      plugins/facebook-php-sdk/src/Facebook/Helpers/FacebookPageTabHelper.php
  56. 16 52
      plugins/facebook-php-sdk/src/Facebook/Helpers/FacebookRedirectLoginHelper.php
  57. 1 1
      plugins/facebook-php-sdk/src/Facebook/Helpers/FacebookSignedRequestFromInputHelper.php
  58. 1 1
      plugins/facebook-php-sdk/src/Facebook/Http/GraphRawResponse.php
  59. 1 1
      plugins/facebook-php-sdk/src/Facebook/Http/RequestBodyInterface.php
  60. 1 1
      plugins/facebook-php-sdk/src/Facebook/Http/RequestBodyMultipart.php
  61. 1 1
      plugins/facebook-php-sdk/src/Facebook/Http/RequestBodyUrlEncoded.php
  62. 1 1
      plugins/facebook-php-sdk/src/Facebook/HttpClients/FacebookCurl.php
  63. 4 51
      plugins/facebook-php-sdk/src/Facebook/HttpClients/FacebookCurlHttpClient.php
  64. 1 1
      plugins/facebook-php-sdk/src/Facebook/HttpClients/FacebookGuzzleHttpClient.php
  65. 1 1
      plugins/facebook-php-sdk/src/Facebook/HttpClients/FacebookHttpClientInterface.php
  66. 4 4
      plugins/facebook-php-sdk/src/Facebook/HttpClients/FacebookStream.php
  67. 2 2
      plugins/facebook-php-sdk/src/Facebook/HttpClients/FacebookStreamHttpClient.php
  68. 99 0
      plugins/facebook-php-sdk/src/Facebook/HttpClients/HttpClientsFactory.php
  69. 1 1
      plugins/facebook-php-sdk/src/Facebook/PersistentData/FacebookMemoryPersistentDataHandler.php
  70. 1 1
      plugins/facebook-php-sdk/src/Facebook/PersistentData/FacebookSessionPersistentDataHandler.php
  71. 65 0
      plugins/facebook-php-sdk/src/Facebook/PersistentData/PersistentDataFactory.php
  72. 1 1
      plugins/facebook-php-sdk/src/Facebook/PersistentData/PersistentDataInterface.php
  73. 1 1
      plugins/facebook-php-sdk/src/Facebook/PseudoRandomString/McryptPseudoRandomStringGenerator.php
  74. 1 1
      plugins/facebook-php-sdk/src/Facebook/PseudoRandomString/OpenSslPseudoRandomStringGenerator.php
  75. 93 0
      plugins/facebook-php-sdk/src/Facebook/PseudoRandomString/PseudoRandomStringGeneratorFactory.php
  76. 1 1
      plugins/facebook-php-sdk/src/Facebook/PseudoRandomString/PseudoRandomStringGeneratorInterface.php
  77. 3 2
      plugins/facebook-php-sdk/src/Facebook/PseudoRandomString/PseudoRandomStringGeneratorTrait.php
  78. 1 1
      plugins/facebook-php-sdk/src/Facebook/PseudoRandomString/UrandomPseudoRandomStringGenerator.php
  79. 3 9
      plugins/facebook-php-sdk/src/Facebook/SignedRequest.php
  80. 21 3
      plugins/facebook-php-sdk/src/Facebook/Url/FacebookUrlDetectionHandler.php
  81. 2 2
      plugins/facebook-php-sdk/src/Facebook/Url/FacebookUrlManipulator.php
  82. 1 1
      plugins/facebook-php-sdk/src/Facebook/Url/UrlDetectionInterface.php
  83. 1 1
      plugins/facebook-php-sdk/src/Facebook/autoload.php
  84. 49 0
      plugins/facebook-php-sdk/src/Facebook/polyfills.php

+ 0 - 4
plugins/facebook-php-sdk/.gitignore

@@ -1,4 +0,0 @@
-vendor/
-composer.lock
-tests/FacebookTestCredentials.php
-

+ 0 - 8
plugins/facebook-php-sdk/.scrutinizer.yml

@@ -1,8 +0,0 @@
-filter:
-    paths:
-        - 'src/*'
-
-tools:
-    php_code_sniffer:
-        config:
-            standard: PSR2

+ 0 - 24
plugins/facebook-php-sdk/.travis.yml

@@ -1,24 +0,0 @@
-language: php
-
-php:
-  - 5.4
-  - 5.5
-  - 5.6
-  - 7.0
-  - hhvm
-
-sudo: false
-
-before_install:
-  - travis_retry composer self-update
-
-install:
-  - travis_retry composer install --prefer-source --no-interaction
-
-script:
-  - vendor/bin/phpunit --coverage-text --exclude-group integration
-
-matrix:
-  allow_failures:
-    - php: 7.0
-  fast_finish: true

+ 0 - 153
plugins/facebook-php-sdk/CHANGELOG.md

@@ -1,153 +0,0 @@
-# CHANGELOG
-
-Starting with version 5, the Facebook PHP SDK follows [SemVer](http://semver.org/).
-
-
-## 5.0.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-??-??)
-  - New features
-    - Added the `Facebook\Facebook` super service for an easier API
-    - Improved "reauthentication" and "rerequest" support
-    - Requests/Responses
-      - Added full batch support
-      - Added full file upload support for videos & photos
-      - Added methods to make pagination easier
-      - Added "deep" pagination support so that Graph edges embedded in a Graph node can be paginated over easily
-      - Beta support at `graph.beta.facebook.com`
-      - Added `getMetaData()` to `GraphEdge` to obtain all the metadata associated with a list of Graph nodes
-      - Full nested param support
-      - 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 
-  - Codebase changes
-    - Moved exception classes to `Exception\*` directory
-    - Moved response collection objects to `GraphNodes\*` directory
-    - Moved helpers to `Helpers\*` directory
-    - Killed `FacebookSession` in favor of the `AccessToken` entity
-    - Added `FacebookClient` service
-    - Renamed `FacebookRequestException` to `FacebookResponseException`
-    - Renamed `FacebookHttpable` to `FacebookHttpClientInterface`
-    - Added `FacebookApp` entity that contains info about the Facebook app
-    - Updated the API for the helpers
-  - Tests
-    - Added namespaces to the tests
-    - Grouped functional tests under `functional` group
-  - Other changes
-    - Made PSR-2 compliant
-    - Adopted SemVer
-    - Completely refactored request/response handling
-    - Refactored the OAuth 2.0 logic
-    - 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.
-
-- 4.0.23 (2015-04-03)
-  - Added support for new JSON response types in Graph v2.3 when requesting access tokens
-- 4.0.22 (2015-04-02)
-  - Fixed issues related to multidimensional params
-  - **Bumped default fallback Graph version to `v2.3`**
-- 4.0.21 (2015-03-31)
-  - Added a `FacebookPermissions` class to reference all the Facebook permissions
-- 4.0.20 (2015-03-02)
-  - Fixed a bug introduced in `4.0.19` related to CSRF comparisons
-- 4.0.19 (2015-03-02)
-  - Added stricter CSRF comparison checks to `SignedRequest` and `FacebookRedirectLoginHelper`
-- 4.0.18 (2015-02-24)
-  - [`FacebookHttpable`] Reverted a breaking change from `4.0.17` that changed the method signatures
-- 4.0.17 (2015-02-19)
-  - [`FacebookRedirectLoginHelper`] Added multiple auth types to `getLoginUrl()`
-  - [`GraphUser`] Added `getTimezone()`
-  - [`FacebookCurl`] Additional fix for `curl_init()` handling
-  - Added support for https://graph-video.facebook.com when path ends with `/videos`
-- 4.0.16 (2015-02-03)
-  - [`FacebookRedirectLoginHelper`] Added "reauthenticate" functionality to `getLoginUrl()`
-  - [`FacebookCurl`] Fixed `curl_init()` issue
-- 4.0.15 (2015-01-06)
-  - [`FacebookRedirectLoginHelper`] Added guard against accidental exposure of app secret via the logout link
-- 4.0.14 (2014-12-29)
-  - [`GraphUser`] Added `getGender()`
-  - [`FacebookRedirectLoginHelper`] Added CSRF protection for rerequest links
-  - [`GraphAlbum`] Fixed bugs in getter methods
-- 4.0.13 (2014-12-12)
-  - [`FacebookRedirectLoginHelper`] Added `$displayAsPopup` param to `getLoginUrl()`
-  - [`FacebookResponse`] Fixed minor pagination bug
-  - Removed massive cert bundle and replaced with `DigiCertHighAssuranceEVRootCA` for peer verification
-- 4.0.12 (2014-10-30)
-  - **Updated default fallback Graph version to `v2.2`**
-  - Fixed potential duplicate `type` param in URL's
-  - [`FacebookRedirectLoginHelper`] Added `getReRequestUrl()`
-  - [`GraphUser`] Added `getEmail()`
-- 4.0.11 (2014-08-25)
-  - [`FacebookCurlHttpClient`] Added a method to disable IPv6 resolution
-- 4.0.10 (2014-08-12)
-  - [`GraphObject`] Fixed improper usage of `stdClass`
-  - Fixed warnings when `open_basedir` directive set
-  - Fixed long lived sessions forgetting the signed request
-  - [`CanvasLoginHelper`] Removed GET processing
-  - Updated visibility on `FacebookSession::useAppSecretProof`
-- 4.0.9 (2014-06-27)
-  - [`FacebookPageTabHelper`] Added ability to fetch `app_data`
-  - Added `GraphUserPage` Graph node collection
-  - Cleaned up test files
-  - Decoupled signed request handling
-  - Added some stronger type hinting
-  - Explicitly added separator in `http_build_query()`
-  - [`FacebookCurlHttpClient`] Updated the calculation of the request body size
-  - Decoupled access token handling
-  - [`FacebookRedirectLoginHelper`] Implemented better CSPRNG
-  - Added autoloader for those poor non-composer peeps
-- 4.0.8 (2014-06-10)
-  - Enabled `appsecret_proof` by default
-  - Added stream wrapper and Guzzle HTTP client implementations
-- 4.0.7 (2014-05-31)
-  - Improved testing environment
-  - Added `FacebookPageTabHelper`
-  - [`FacebookSession`] Fixed issue where `validateSessionInfo()` would return incorrect results
-- 4.0.6 (2014-05-24)
-  - Added feature to inject custom HTTP clients
-  - [`FacebookCanvasLoginHelper`] Fixed bug that would throw when logging out
-  - Removed appToken from test credentials file
-  - [`FacebookRequest`] Added `appsecret_proof` handling
-- 4.0.5 (2014-05-19)
-  - Fixed bug in cURL where proxy headers are not included in header_size
-  - Added internal SDK error codes for thrown exceptions
-  - Added stream wrapper fallback for hosting environments without cURL
-  - Added getter methods for signed requests
-  - Fixed warning that showed up in tests
-  - Changed SDK error code for stream failure
-  - Added `GraphAlbum` Graph node collection
-- 4.0.4 (2014-05-15)
-  - Added more error codes to accommodate more Graph error responses
-  - [`JavaScriptLoginHelper`] Fixed bug that would try to get a new access token when one already existed
-- 4.0.3 (2014-05-14)
-  - Fixed bug for "Missing client_id parameter" error
-  - Fixed bug for eTag support when "Network is unreachable" error occurs
-  - Fixed pagination issue related to `sdtClass`
-- 4.0.2 (2014-05-07)
-  - [`composer.json`] Upgraded to use PSR-4 autoloading instead of Composer's `classmap`
-  - [`FacebookCanvasLoginHelper`] Abstracted access to super globals
-  - [`FacebookRequest`] Fixed bug that blindly appended params to a url
-  - [`FacebookRequest`] Added support for `DELETE` and `PUT` methods
-  - Added eTag support to Graph requests
-- 4.0.1 (2014-05-05)
-  - All exceptions are now extend from `FacebookSDKException`
-  - [`FacebookSession`] Signed request parsing will throw on malformed signed request input
-  - Excluded test credentials from tests
-  - [`FacebookRedirectLoginHelper`] Changed scope on `$state` property
-  - [`phpunit.xml`] Normalized
-- 4.0.0 (2014-04-30)
-  - Initial release. Yay!

+ 0 - 54
plugins/facebook-php-sdk/CONTRIBUTING.md

@@ -1,54 +0,0 @@
-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).
-
-
-## Pull Requests
-
-- **Sign the CLA** - For us to accept contributions you will have to first have signed the
-  [Contributor License Agreement](https://developers.facebook.com/opensource/cla).
-
-- **[PSR-2 Coding Standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)** - The easiest way to apply the conventions is to run [PHP Code Sniffer](#running-php-code-sniffer) as you code.
-
-- **Add tests!** - Your patch won't be accepted if it doesn't have tests.
-
-- **Document any change in behaviour** - Make sure the README and the [documentation](https://github.com/facebook/facebook-php-sdk-v4/tree/master/docs) are kept up-to-date.
-
-- **Consider our release cycle** - As of version 5.0.0, we try to follow [SemVer](http://semver.org/). Randomly breaking public APIs is not an option.
-
-- **Create topic branches** - Don't ask us to pull from your master branch.
-
-- **One pull request per feature** - If you want to do more than one thing, send multiple pull requests.
-
-- **Send coherent history** - Make sure each individual commit in your pull request is meaningful. If you had to make multiple intermediate commits while developing, please squash them before submitting.
-
-- **Ensure tests pass!** - Please [run the tests](#running-tests) before submitting your pull request, and make sure they pass. We won't accept a patch until all tests pass.
-
-- **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.
-
-``` bash
-$ 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
-```
-
-**Happy coding**!

+ 1 - 1
plugins/facebook-php-sdk/LICENSE

@@ -1,4 +1,4 @@
-Copyright 2014 Facebook, Inc.
+Copyright 2016 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

+ 0 - 89
plugins/facebook-php-sdk/README.md

@@ -1,89 +0,0 @@
-# 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)
-
-
-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.
-
-```json
-{
-    "require": {
-        "facebook/php-sdk-v4": "~5.0"
-    }
-}
-```
-
-
-## Usage
-
-> **Note:** This version of the Facebook SDK for PHP requires PHP 5.4 or greater.
-
-Simple GET example of a user's profile.
-
-```php
-$fb = new Facebook\Facebook([
-  'app_id' => '{app-id}',
-  'app_secret' => '{app-secret}',
-  'default_graph_version' => 'v2.4',
-  //'default_access_token' => '{access-token}', // optional
-]);
-
-// Use one of the helper classes to get a Facebook\Authentication\AccessToken entity.
-//   $helper = $fb->getRedirectLoginHelper();
-//   $helper = $fb->getJavaScriptHelper();
-//   $helper = $fb->getCanvasHelper();
-//   $helper = $fb->getPageTabHelper();
-
-try {
-  // 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) {
-  // When Graph returns an error
-  echo 'Graph returned an error: ' . $e->getMessage();
-  exit;
-} catch(Facebook\Exceptions\FacebookSDKException $e) {
-  // When validation fails or other local issues
-  echo 'Facebook SDK returned an error: ' . $e->getMessage();
-  exit;
-}
-
-$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)
-
-
-## Tests
-
-1. [Composer](https://getcomposer.org/) is a prerequisite for running the tests. Install composer globally, then run `composer install` to install required files.
-2. Create a test app on [Facebook Developers](https://developers.facebook.com), then create `tests/FacebookTestCredentials.php` from `tests/FacebookTestCredentials.php.dist` and edit it to add your credentials.
-3. The tests can be executed by running this command from the root directory:
-
-```bash
-$ ./vendor/bin/phpunit
-```
-
-By default the tests will send live HTTP requests to the Graph API. If you are without an internet connection you can skip these tests by excluding the `integration` group.
-
-```bash
-$ ./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.
-
-
-## License
-
-Please see the [license file](https://github.com/facebook/facebook-php-sdk-v4/blob/master/LICENSE) for more information.

+ 3 - 3
plugins/facebook-php-sdk/composer.json

@@ -12,8 +12,7 @@
         }
     ],
     "require": {
-        "php": ">=5.4.0",
-        "ext-mbstring": "*"
+        "php": "^5.4|^7.0"
     },
     "require-dev": {
         "phpunit/phpunit": "~4.0",
@@ -26,7 +25,8 @@
     "autoload": {
         "psr-4": {
             "Facebook\\": "src/Facebook/"
-        }
+        },
+        "files": ["src/Facebook/polyfills.php"]
     },
     "autoload-dev": {
         "psr-4": {

+ 0 - 22
plugins/facebook-php-sdk/phpunit.xml.dist

@@ -1,22 +0,0 @@
-<phpunit
-        colors="true"
-        stderr="true"
-        convertErrorsToExceptions="true"
-        convertNoticesToExceptions="true"
-        convertWarningsToExceptions="true"
-        stopOnFailure="false"
-        bootstrap="tests/bootstrap.php">
-    <testsuites>
-        <testsuite name="Facebook PHP SDK Test Suite">
-            <directory>./tests</directory>
-        </testsuite>
-    </testsuites>
-    <filter>
-        <whitelist>
-            <directory suffix=".php">./src/Facebook</directory>
-        </whitelist>
-    </filter>
-    <listeners>
-        <listener class="\Mockery\Adapter\Phpunit\TestListener"/>
-    </listeners>
-</phpunit>

+ 1 - 1
plugins/facebook-php-sdk/src/Facebook/Authentication/AccessToken.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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

+ 2 - 2
plugins/facebook-php-sdk/src/Facebook/Authentication/AccessTokenMetadata.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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
@@ -382,7 +382,7 @@ class AccessTokenMetadata
     private function castTimestampsToDateTime()
     {
         foreach (static::$dateProperties as $key) {
-            if (isset($this->metadata[$key])) {
+            if (isset($this->metadata[$key]) && $this->metadata[$key] !== 0) {
                 $this->metadata[$key] = $this->convertTimestampToDateTime($this->metadata[$key]);
             }
         }

+ 4 - 4
plugins/facebook-php-sdk/src/Facebook/Authentication/OAuth2Client.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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
@@ -250,9 +250,9 @@ class OAuth2Client
     /**
      * Send a request to Graph with an app access token.
      *
-     * @param string      $endpoint
-     * @param array       $params
-     * @param string|null $accessToken
+     * @param string                  $endpoint
+     * @param array                   $params
+     * @param AccessToken|string|null $accessToken
      *
      * @return FacebookResponse
      *

+ 1 - 1
plugins/facebook-php-sdk/src/Facebook/Exceptions/FacebookAuthenticationException.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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

+ 1 - 1
plugins/facebook-php-sdk/src/Facebook/Exceptions/FacebookAuthorizationException.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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

+ 1 - 1
plugins/facebook-php-sdk/src/Facebook/Exceptions/FacebookClientException.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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

+ 1 - 1
plugins/facebook-php-sdk/src/Facebook/Exceptions/FacebookOtherException.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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

+ 9 - 3
plugins/facebook-php-sdk/src/Facebook/Exceptions/FacebookResponseException.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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
@@ -77,8 +77,6 @@ class FacebookResponseException extends FacebookSDKException
         $code = isset($data['error']['code']) ? $data['error']['code'] : null;
         $message = isset($data['error']['message']) ? $data['error']['message'] : 'Unknown error from Graph.';
 
-        $previousException = null;
-
         if (isset($data['error']['error_subcode'])) {
             switch ($data['error']['error_subcode']) {
                 // Other authentication issues
@@ -89,6 +87,14 @@ class FacebookResponseException extends FacebookSDKException
                 case 464:
                 case 467:
                     return new static($response, new FacebookAuthenticationException($message, $code));
+                // Video upload resumable error
+                case 1363030:
+                case 1363019:
+                case 1363037:
+                case 1363033:
+                case 1363021:
+                case 1363041:
+                    return new static($response, new FacebookResumableUploadException($message, $code));
             }
         }
 

+ 33 - 0
plugins/facebook-php-sdk/src/Facebook/Exceptions/FacebookResumableUploadException.php

@@ -0,0 +1,33 @@
+<?php
+/**
+ * Copyright 2016 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
+ * form for use in connection with the web services and APIs provided by
+ * Facebook.
+ *
+ * As with any software that integrates with the Facebook platform, your use
+ * of this software is subject to the Facebook Developer Principles and
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
+ * shall be included in all copies or substantial portions of the software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+namespace Facebook\Exceptions;
+
+/**
+ * Class FacebookResumableUploadException
+ *
+ * @package Facebook
+ */
+class FacebookResumableUploadException extends FacebookSDKException
+{
+}

+ 1 - 1
plugins/facebook-php-sdk/src/Facebook/Exceptions/FacebookSDKException.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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

+ 1 - 1
plugins/facebook-php-sdk/src/Facebook/Exceptions/FacebookServerException.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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

+ 1 - 1
plugins/facebook-php-sdk/src/Facebook/Exceptions/FacebookThrottleException.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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

+ 105 - 80
plugins/facebook-php-sdk/src/Facebook/Facebook.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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
@@ -26,21 +26,17 @@ namespace Facebook;
 use Facebook\Authentication\AccessToken;
 use Facebook\Authentication\OAuth2Client;
 use Facebook\FileUpload\FacebookFile;
+use Facebook\FileUpload\FacebookResumableUploader;
+use Facebook\FileUpload\FacebookTransferChunk;
 use Facebook\FileUpload\FacebookVideo;
 use Facebook\GraphNodes\GraphEdge;
 use Facebook\Url\UrlDetectionInterface;
 use Facebook\Url\FacebookUrlDetectionHandler;
+use Facebook\PseudoRandomString\PseudoRandomStringGeneratorFactory;
 use Facebook\PseudoRandomString\PseudoRandomStringGeneratorInterface;
-use Facebook\PseudoRandomString\McryptPseudoRandomStringGenerator;
-use Facebook\PseudoRandomString\OpenSslPseudoRandomStringGenerator;
-use Facebook\PseudoRandomString\UrandomPseudoRandomStringGenerator;
-use Facebook\HttpClients\FacebookHttpClientInterface;
-use Facebook\HttpClients\FacebookCurlHttpClient;
-use Facebook\HttpClients\FacebookStreamHttpClient;
-use Facebook\HttpClients\FacebookGuzzleHttpClient;
+use Facebook\HttpClients\HttpClientsFactory;
+use Facebook\PersistentData\PersistentDataFactory;
 use Facebook\PersistentData\PersistentDataInterface;
-use Facebook\PersistentData\FacebookSessionPersistentDataHandler;
-use Facebook\PersistentData\FacebookMemoryPersistentDataHandler;
 use Facebook\Helpers\FacebookCanvasHelper;
 use Facebook\Helpers\FacebookJavaScriptHelper;
 use Facebook\Helpers\FacebookPageTabHelper;
@@ -57,12 +53,12 @@ class Facebook
     /**
      * @const string Version number of the Facebook PHP SDK.
      */
-    const VERSION = '5.0.0';
+    const VERSION = '5.2.0';
 
     /**
      * @const string Default Graph API version for requests.
      */
-    const DEFAULT_GRAPH_VERSION = 'v2.4';
+    const DEFAULT_GRAPH_VERSION = 'v2.6';
 
     /**
      * @const string The name of the environment variable that contains the app ID.
@@ -128,80 +124,43 @@ class Facebook
      */
     public function __construct(array $config = [])
     {
-        $appId = isset($config['app_id']) ? $config['app_id'] : getenv(static::APP_ID_ENV_NAME);
-        if (!$appId) {
+        $config = array_merge([
+            'app_id' => 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.
      *
@@ -586,4 +551,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);
+    }
 }

+ 13 - 4
plugins/facebook-php-sdk/src/Facebook/FacebookApp.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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
@@ -24,6 +24,7 @@
 namespace Facebook;
 
 use Facebook\Authentication\AccessToken;
+use Facebook\Exceptions\FacebookSDKException;
 
 class FacebookApp implements \Serializable
 {
@@ -40,10 +41,18 @@ class FacebookApp implements \Serializable
     /**
      * @param string $id
      * @param string $secret
+     *
+     * @throws FacebookSDKException
      */
     public function __construct($id, $secret)
     {
-        $this->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);
     }

+ 1 - 1
plugins/facebook-php-sdk/src/Facebook/FacebookBatchRequest.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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

+ 22 - 2
plugins/facebook-php-sdk/src/Facebook/FacebookBatchResponse.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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
@@ -102,7 +102,8 @@ class FacebookBatchResponse extends FacebookResponse implements IteratorAggregat
 
         $httpResponseBody = isset($response['body']) ? $response['body'] : null;
         $httpResponseCode = isset($response['code']) ? $response['code'] : null;
-        $httpResponseHeaders = isset($response['headers']) ? $response['headers'] : [];
+        // @TODO With PHP 5.5 support, this becomes array_column($response['headers'], 'value', 'name')
+        $httpResponseHeaders = isset($response['headers']) ? $this->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;
+    }
 }

+ 3 - 3
plugins/facebook-php-sdk/src/Facebook/FacebookClient.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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
@@ -124,7 +124,7 @@ class FacebookClient
      */
     public function detectHttpClientHandler()
     {
-        return function_exists('curl_init') ? new FacebookCurlHttpClient() : new FacebookStreamHttpClient();
+        return extension_loaded('curl') ? new FacebookCurlHttpClient() : new FacebookStreamHttpClient();
     }
 
     /**
@@ -197,7 +197,7 @@ class FacebookClient
      */
     public function sendRequest(FacebookRequest $request)
     {
-        if (get_class($request) === 'FacebookRequest') {
+        if (get_class($request) === 'Facebook\FacebookRequest') {
             $request->validateAccessToken();
         }
 

+ 3 - 5
plugins/facebook-php-sdk/src/Facebook/FacebookRequest.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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
@@ -154,7 +154,7 @@ class FacebookRequest
     }
 
     /**
-     * Return the access token for this request an an AccessToken entity.
+     * Return the access token for this request as an AccessToken entity.
      *
      * @return AccessToken|null
      */
@@ -214,8 +214,6 @@ class FacebookRequest
      * Set the HTTP method for this request.
      *
      * @param string
-     *
-     * @return FacebookRequest
      */
     public function setMethod($method)
     {
@@ -273,7 +271,7 @@ class FacebookRequest
     }
 
     /**
-     * Return the HTTP method for this request.
+     * Return the endpoint for this request.
      *
      * @return string
      */

+ 1 - 1
plugins/facebook-php-sdk/src/Facebook/FacebookResponse.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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

+ 37 - 3
plugins/facebook-php-sdk/src/Facebook/FileUpload/FacebookFile.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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
@@ -37,6 +37,16 @@ class FacebookFile
      */
     protected $path;
 
+    /**
+     * @var int The maximum bytes to read. Defaults to -1 (read all the remaining buffer).
+     */
+    private $maxLength;
+
+    /**
+     * @var int Seek to the specified offset before reading. If this number is negative, no seeking will occur and reading will start from the current position.
+     */
+    private $offset;
+
     /**
      * @var resource The stream pointing to the file.
      */
@@ -46,12 +56,16 @@ class FacebookFile
      * Creates a new FacebookFile entity.
      *
      * @param string $filePath
+     * @param int $maxLength
+     * @param int $offset
      *
      * @throws FacebookSDKException
      */
-    public function __construct($filePath)
+    public function __construct($filePath, $maxLength = -1, $offset = -1)
     {
         $this->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.
      *

+ 167 - 0
plugins/facebook-php-sdk/src/Facebook/FileUpload/FacebookResumableUploader.php

@@ -0,0 +1,167 @@
+<?php
+/**
+ * Copyright 2016 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
+ * form for use in connection with the web services and APIs provided by
+ * Facebook.
+ *
+ * As with any software that integrates with the Facebook platform, your use
+ * of this software is subject to the Facebook Developer Principles and
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
+ * shall be included in all copies or substantial portions of the software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+namespace Facebook\FileUpload;
+
+use Facebook\Authentication\AccessToken;
+use Facebook\Exceptions\FacebookResponseException;
+use Facebook\Exceptions\FacebookResumableUploadException;
+use Facebook\Exceptions\FacebookSDKException;
+use Facebook\FacebookApp;
+use Facebook\FacebookClient;
+use Facebook\FacebookRequest;
+
+/**
+ * Class FacebookResumableUploader
+ *
+ * @package Facebook
+ */
+class FacebookResumableUploader
+{
+    /**
+     * @var FacebookApp
+     */
+    protected $app;
+
+    /**
+     * @var string
+     */
+    protected $accessToken;
+
+    /**
+     * @var FacebookClient The Facebook client service.
+     */
+    protected $client;
+
+    /**
+     * @var string Graph version to use for this request.
+     */
+    protected $graphVersion;
+
+    /**
+     * @param FacebookApp             $app
+     * @param FacebookClient          $client
+     * @param AccessToken|string|null $accessToken
+     * @param string                  $graphVersion
+     */
+    public function __construct(FacebookApp $app, FacebookClient $client, $accessToken, $graphVersion)
+    {
+        $this->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();
+    }
+}

+ 133 - 0
plugins/facebook-php-sdk/src/Facebook/FileUpload/FacebookTransferChunk.php

@@ -0,0 +1,133 @@
+<?php
+/**
+ * Copyright 2016 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
+ * form for use in connection with the web services and APIs provided by
+ * Facebook.
+ *
+ * As with any software that integrates with the Facebook platform, your use
+ * of this software is subject to the Facebook Developer Principles and
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
+ * shall be included in all copies or substantial portions of the software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+namespace Facebook\FileUpload;
+
+/**
+ * Class FacebookTransferChunk
+ *
+ * @package Facebook
+ */
+class FacebookTransferChunk
+{
+    /**
+     * @var FacebookFile The file to chunk during upload.
+     */
+    private $file;
+
+    /**
+     * @var int The ID of the upload session.
+     */
+    private $uploadSessionId;
+
+    /**
+     * @var int Start byte position of the next file chunk.
+     */
+    private $startOffset;
+
+    /**
+     * @var int End byte position of the next file chunk.
+     */
+    private $endOffset;
+
+    /**
+     * @var int The ID of the video.
+     */
+    private $videoId;
+
+    /**
+     * @param FacebookFile $file
+     * @param int $uploadSessionId
+     * @param int $videoId
+     * @param int $startOffset
+     * @param int $endOffset
+     */
+    public function __construct(FacebookFile $file, $uploadSessionId, $videoId, $startOffset, $endOffset)
+    {
+        $this->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;
+    }
+}

+ 1 - 1
plugins/facebook-php-sdk/src/Facebook/FileUpload/FacebookVideo.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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

+ 1 - 1
plugins/facebook-php-sdk/src/Facebook/FileUpload/Mimetypes.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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

+ 85 - 0
plugins/facebook-php-sdk/src/Facebook/GraphNodes/Birthday.php

@@ -0,0 +1,85 @@
+<?php
+/**
+ * Copyright 2016 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
+ * form for use in connection with the web services and APIs provided by
+ * Facebook.
+ *
+ * As with any software that integrates with the Facebook platform, your use
+ * of this software is subject to the Facebook Developer Principles and
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
+ * shall be included in all copies or substantial portions of the software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+namespace Facebook\GraphNodes;
+
+use DateTime;
+
+/**
+ * Birthday object to handle various Graph return formats
+ *
+ * @package Facebook
+ */
+class Birthday extends DateTime
+{
+    /**
+     * @var bool
+     */
+    private $hasDate = false;
+
+    /**
+     * @var bool
+     */
+    private $hasYear = false;
+
+    /**
+     * Parses Graph birthday format to set indication flags, possible values:
+     *
+     *  MM/DD/YYYY
+     *  MM/DD
+     *  YYYY
+     *
+     * @link https://developers.facebook.com/docs/graph-api/reference/user
+     *
+     * @param string $date
+     */
+    public function __construct($date)
+    {
+        $parts = explode('/', $date);
+
+        $this->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;
+    }
+}

+ 2 - 2
plugins/facebook-php-sdk/src/Facebook/GraphNodes/Collection.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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
@@ -69,7 +69,7 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate
             return $this->items[$name];
         }
 
-        return $default ?: null;
+        return $default;
     }
 
     /**

+ 2 - 2
plugins/facebook-php-sdk/src/Facebook/GraphNodes/GraphAchievement.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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
@@ -92,7 +92,7 @@ class GraphAchievement extends GraphNode
     /**
      * Returns the type of achievement.
      *
-     * @see https://developers.facebook.com/docs/graph-api/reference/v2.2/achievement
+     * @see https://developers.facebook.com/docs/graph-api/reference/achievement
      *
      * @return string
      */

+ 1 - 1
plugins/facebook-php-sdk/src/Facebook/GraphNodes/GraphAlbum.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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

+ 1 - 1
plugins/facebook-php-sdk/src/Facebook/GraphNodes/GraphApplication.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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

+ 1 - 1
plugins/facebook-php-sdk/src/Facebook/GraphNodes/GraphCoverPhoto.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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

+ 4 - 26
plugins/facebook-php-sdk/src/Facebook/GraphNodes/GraphEdge.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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
@@ -153,35 +153,13 @@ class GraphEdge extends Collection
         $this->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) {
+        if (!isset($this->metaData['paging'][$direction])) {
             return null;
         }
 
-        // If we don't know the ID of the parent node, this ain't gonna work.
-        if (!$this->parentEdgeEndpoint) {
-            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);
-
-        // Pull in the original params
-        $originalUrl = $this->request->getUrl();
-        $pageUrl = FacebookUrlManipulator::mergeUrlParams($originalUrl, $pageUrl);
+        $pageUrl = $this->metaData['paging'][$direction];
 
-        return FacebookUrlManipulator::forceSlashPrefix($pageUrl);
+        return FacebookUrlManipulator::baseGraphUrlEndpoint($pageUrl);
     }
 
     /**

+ 1 - 1
plugins/facebook-php-sdk/src/Facebook/GraphNodes/GraphEvent.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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

+ 1 - 2
plugins/facebook-php-sdk/src/Facebook/GraphNodes/GraphGroup.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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
@@ -167,5 +167,4 @@ class GraphGroup extends GraphNode
     {
         return $this->getField('venue');
     }
-
 }

+ 1 - 1
plugins/facebook-php-sdk/src/Facebook/GraphNodes/GraphList.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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

+ 1 - 1
plugins/facebook-php-sdk/src/Facebook/GraphNodes/GraphLocation.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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

+ 15 - 3
plugins/facebook-php-sdk/src/Facebook/GraphNodes/GraphNode.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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
@@ -62,10 +62,11 @@ class GraphNode extends Collection
         foreach ($data as $k => $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.
      *

+ 1 - 1
plugins/facebook-php-sdk/src/Facebook/GraphNodes/GraphNodeFactory.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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

+ 1 - 1
plugins/facebook-php-sdk/src/Facebook/GraphNodes/GraphObject.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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

+ 2 - 2
plugins/facebook-php-sdk/src/Facebook/GraphNodes/GraphObjectFactory.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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
@@ -68,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');
     }
 
     /**

+ 1 - 1
plugins/facebook-php-sdk/src/Facebook/GraphNodes/GraphPage.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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

+ 1 - 1
plugins/facebook-php-sdk/src/Facebook/GraphNodes/GraphPicture.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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

+ 1 - 1
plugins/facebook-php-sdk/src/Facebook/GraphNodes/GraphSessionInfo.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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

+ 1 - 1
plugins/facebook-php-sdk/src/Facebook/GraphNodes/GraphUser.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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

+ 1 - 1
plugins/facebook-php-sdk/src/Facebook/Helpers/FacebookCanvasHelper.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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

+ 1 - 1
plugins/facebook-php-sdk/src/Facebook/Helpers/FacebookJavaScriptHelper.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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

+ 1 - 1
plugins/facebook-php-sdk/src/Facebook/Helpers/FacebookPageTabHelper.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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

+ 16 - 52
plugins/facebook-php-sdk/src/Facebook/Helpers/FacebookRedirectLoginHelper.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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
@@ -25,16 +25,14 @@ namespace Facebook\Helpers;
 
 use Facebook\Authentication\AccessToken;
 use Facebook\Authentication\OAuth2Client;
-use Facebook\Url\UrlDetectionInterface;
-use Facebook\Url\FacebookUrlDetectionHandler;
-use Facebook\Url\FacebookUrlManipulator;
-use Facebook\PersistentData\PersistentDataInterface;
+use Facebook\Exceptions\FacebookSDKException;
 use Facebook\PersistentData\FacebookSessionPersistentDataHandler;
+use Facebook\PersistentData\PersistentDataInterface;
+use Facebook\PseudoRandomString\PseudoRandomStringGeneratorFactory;
 use Facebook\PseudoRandomString\PseudoRandomStringGeneratorInterface;
-use Facebook\PseudoRandomString\McryptPseudoRandomStringGenerator;
-use Facebook\PseudoRandomString\OpenSslPseudoRandomStringGenerator;
-use Facebook\PseudoRandomString\UrandomPseudoRandomStringGenerator;
-use Facebook\Exceptions\FacebookSDKException;
+use Facebook\Url\FacebookUrlDetectionHandler;
+use Facebook\Url\FacebookUrlManipulator;
+use Facebook\Url\UrlDetectionInterface;
 
 /**
  * Class FacebookRedirectLoginHelper
@@ -79,7 +77,7 @@ class FacebookRedirectLoginHelper
         $this->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.
      *
@@ -263,27 +235,19 @@ class FacebookRedirectLoginHelper
     protected function validateCsrf()
     {
         $state = $this->getState();
-        $savedState = $this->persistentDataHandler->get('state');
-
-        if (!$state || !$savedState) {
-            throw new FacebookSDKException('Cross-site request forgery validation failed. Required param "state" missing.');
+        if (!$state) {
+            throw new FacebookSDKException('Cross-site request forgery validation failed. Required GET param "state" missing.');
         }
-
-        $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.');
+        $savedState = $this->persistentDataHandler->get('state');
+        if (!$savedState) {
+            throw new FacebookSDKException('Cross-site request forgery validation failed. Required param "state" missing from persistent data.');
         }
 
-        $result = 0;
-        for ($i = 0; $i < $savedLen; $i++) {
-            $result |= ord($state[$i]) ^ ord($savedState[$i]);
+        if (\hash_equals($savedState, $state)) {
+            return;
         }
 
-        if ($result !== 0) {
-            throw new FacebookSDKException('Cross-site request forgery validation failed. The "state" param from the URL and session do not match.');
-        }
+        throw new FacebookSDKException('Cross-site request forgery validation failed. The "state" param from the URL and session do not match.');
     }
 
     /**

+ 1 - 1
plugins/facebook-php-sdk/src/Facebook/Helpers/FacebookSignedRequestFromInputHelper.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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

+ 1 - 1
plugins/facebook-php-sdk/src/Facebook/Http/GraphRawResponse.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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

+ 1 - 1
plugins/facebook-php-sdk/src/Facebook/Http/RequestBodyInterface.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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

+ 1 - 1
plugins/facebook-php-sdk/src/Facebook/Http/RequestBodyMultipart.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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

+ 1 - 1
plugins/facebook-php-sdk/src/Facebook/Http/RequestBodyUrlEncoded.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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

+ 1 - 1
plugins/facebook-php-sdk/src/Facebook/HttpClients/FacebookCurl.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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

+ 4 - 51
plugins/facebook-php-sdk/src/Facebook/HttpClients/FacebookCurlHttpClient.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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
@@ -53,16 +53,6 @@ class FacebookCurlHttpClient implements FacebookHttpClientInterface
      */
     protected $facebookCurl;
 
-    /**
-     * @const Curl Version which is unaffected by the proxy header length error.
-     */
-    const CURL_PROXY_QUIRK_VER = 0x071E00;
-
-    /**
-     * @const "Connection Established" header text
-     */
-    const CONNECTION_ESTABLISHED = "HTTP/1.0 200 Connection established\r\n\r\n";
-
     /**
      * @param FacebookCurl|null Procedural curl as object
      */
@@ -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;
-    }
 }

+ 1 - 1
plugins/facebook-php-sdk/src/Facebook/HttpClients/FacebookGuzzleHttpClient.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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

+ 1 - 1
plugins/facebook-php-sdk/src/Facebook/HttpClients/FacebookHttpClientInterface.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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

+ 4 - 4
plugins/facebook-php-sdk/src/Facebook/HttpClients/FacebookStream.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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
@@ -41,7 +41,7 @@ class FacebookStream
     /**
      * @var array Response headers from the stream wrapper
      */
-    protected $responseHeaders;
+    protected $responseHeaders = [];
 
     /**
      * Make a new context stream reference instance
@@ -56,7 +56,7 @@ class FacebookStream
     /**
      * The response headers from the stream wrapper
      *
-     * @return array|null
+     * @return array
      */
     public function getResponseHeaders()
     {
@@ -73,7 +73,7 @@ class FacebookStream
     public function fileGetContents($url)
     {
         $rawResponse = file_get_contents($url, false, $this->stream);
-        $this->responseHeaders = $http_response_header;
+        $this->responseHeaders = $http_response_header ?: [];
 
         return $rawResponse;
     }

+ 2 - 2
plugins/facebook-php-sdk/src/Facebook/HttpClients/FacebookStreamHttpClient.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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
@@ -66,7 +66,7 @@ class FacebookStreamHttpClient implements FacebookHttpClientInterface
         $rawBody = $this->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);
         }
 

+ 99 - 0
plugins/facebook-php-sdk/src/Facebook/HttpClients/HttpClientsFactory.php

@@ -0,0 +1,99 @@
+<?php
+/**
+ * Copyright 2016 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
+ * form for use in connection with the web services and APIs provided by
+ * Facebook.
+ *
+ * As with any software that integrates with the Facebook platform, your use
+ * of this software is subject to the Facebook Developer Principles and
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
+ * shall be included in all copies or substantial portions of the software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+namespace Facebook\HttpClients;
+
+use GuzzleHttp\Client;
+use InvalidArgumentException;
+use Exception;
+
+class HttpClientsFactory
+{
+    private function __construct()
+    {
+        // a factory constructor should never be invoked
+    }
+
+    /**
+     * HTTP client generation.
+     *
+     * @param FacebookHttpClientInterface|Client|string|null $handler
+     *
+     * @throws Exception                If the cURL extension or the Guzzle client aren't available (if required).
+     * @throws InvalidArgumentException If the http client handler isn't "curl", "stream", "guzzle", or an instance of Facebook\HttpClients\FacebookHttpClientInterface.
+     *
+     * @return FacebookHttpClientInterface
+     */
+    public static function createHttpClient($handler)
+    {
+        if (!$handler) {
+            return self::detectDefaultClient();
+        }
+
+        if ($handler instanceof FacebookHttpClientInterface) {
+            return $handler;
+        }
+
+        if ('stream' === $handler) {
+            return new FacebookStreamHttpClient();
+        }
+        if ('curl' === $handler) {
+            if (!extension_loaded('curl')) {
+                throw new Exception('The cURL extension must be loaded in order to use the "curl" handler.');
+            }
+
+            return new FacebookCurlHttpClient();
+        }
+
+        if ('guzzle' === $handler && !class_exists('GuzzleHttp\Client')) {
+            throw new Exception('The Guzzle HTTP client must be included in order to use the "guzzle" handler.');
+        }
+
+        if ($handler instanceof Client) {
+            return new FacebookGuzzleHttpClient($handler);
+        }
+        if ('guzzle' === $handler) {
+            return new FacebookGuzzleHttpClient();
+        }
+
+        throw new InvalidArgumentException('The http client handler must be set to "curl", "stream", "guzzle", be an instance of GuzzleHttp\Client or an instance of Facebook\HttpClients\FacebookHttpClientInterface');
+    }
+
+    /**
+     * Detect default HTTP client.
+     *
+     * @return FacebookHttpClientInterface
+     */
+    private static function detectDefaultClient()
+    {
+        if (extension_loaded('curl')) {
+            return new FacebookCurlHttpClient();
+        }
+
+        if (class_exists('GuzzleHttp\Client')) {
+            return new FacebookGuzzleHttpClient();
+        }
+
+        return new FacebookStreamHttpClient();
+    }
+}

+ 1 - 1
plugins/facebook-php-sdk/src/Facebook/PersistentData/FacebookMemoryPersistentDataHandler.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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

+ 1 - 1
plugins/facebook-php-sdk/src/Facebook/PersistentData/FacebookSessionPersistentDataHandler.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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

+ 65 - 0
plugins/facebook-php-sdk/src/Facebook/PersistentData/PersistentDataFactory.php

@@ -0,0 +1,65 @@
+<?php
+/**
+ * Copyright 2016 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
+ * form for use in connection with the web services and APIs provided by
+ * Facebook.
+ *
+ * As with any software that integrates with the Facebook platform, your use
+ * of this software is subject to the Facebook Developer Principles and
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
+ * shall be included in all copies or substantial portions of the software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+namespace Facebook\PersistentData;
+
+use InvalidArgumentException;
+
+class PersistentDataFactory
+{
+    private function __construct()
+    {
+        // a factory constructor should never be invoked
+    }
+
+    /**
+     * PersistentData generation.
+     *
+     * @param PersistentDataInterface|string|null $handler
+     *
+     * @throws InvalidArgumentException If the persistent data handler isn't "session", "memory", or an instance of Facebook\PersistentData\PersistentDataInterface.
+     *
+     * @return PersistentDataInterface
+     */
+    public static function createPersistentDataHandler($handler)
+    {
+        if (!$handler) {
+            return session_status() === PHP_SESSION_ACTIVE
+                ? new FacebookSessionPersistentDataHandler()
+                : new FacebookMemoryPersistentDataHandler();
+        }
+
+        if ($handler instanceof PersistentDataInterface) {
+            return $handler;
+        }
+
+        if ('session' === $handler) {
+            return new FacebookSessionPersistentDataHandler();
+        }
+        if ('memory' === $handler) {
+            return new FacebookMemoryPersistentDataHandler();
+        }
+
+        throw new InvalidArgumentException('The persistent data handler must be set to "session", "memory", or be an instance of Facebook\PersistentData\PersistentDataInterface');
+    }
+}

+ 1 - 1
plugins/facebook-php-sdk/src/Facebook/PersistentData/PersistentDataInterface.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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

+ 1 - 1
plugins/facebook-php-sdk/src/Facebook/PseudoRandomString/McryptPseudoRandomStringGenerator.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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

+ 1 - 1
plugins/facebook-php-sdk/src/Facebook/PseudoRandomString/OpenSslPseudoRandomStringGenerator.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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

+ 93 - 0
plugins/facebook-php-sdk/src/Facebook/PseudoRandomString/PseudoRandomStringGeneratorFactory.php

@@ -0,0 +1,93 @@
+<?php
+/**
+ * Copyright 2016 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
+ * form for use in connection with the web services and APIs provided by
+ * Facebook.
+ *
+ * As with any software that integrates with the Facebook platform, your use
+ * of this software is subject to the Facebook Developer Principles and
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
+ * shall be included in all copies or substantial portions of the software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+namespace Facebook\PseudoRandomString;
+
+use Facebook\Exceptions\FacebookSDKException;
+use InvalidArgumentException;
+
+class PseudoRandomStringGeneratorFactory
+{
+    private function __construct()
+    {
+        // a factory constructor should never be invoked
+    }
+
+    /**
+     * Pseudo random string generator creation.
+     *
+     * @param PseudoRandomStringGeneratorInterface|string|null $generator
+     *
+     * @throws InvalidArgumentException If the pseudo random string generator must be set to "mcrypt", "openssl", or "urandom", or be an instance of Facebook\PseudoRandomString\PseudoRandomStringGeneratorInterface.
+     *
+     * @return PseudoRandomStringGeneratorInterface
+     */
+    public static function createPseudoRandomStringGenerator($generator)
+    {
+        if (!$generator) {
+            return self::detectDefaultPseudoRandomStringGenerator();
+        }
+
+        if ($generator instanceof PseudoRandomStringGeneratorInterface) {
+            return $generator;
+        }
+
+        if ('mcrypt' === $generator) {
+            return new McryptPseudoRandomStringGenerator();
+        }
+        if ('openssl' === $generator) {
+            return new OpenSslPseudoRandomStringGenerator();
+        }
+        if ('urandom' === $generator) {
+            return new UrandomPseudoRandomStringGenerator();
+        }
+
+        throw new InvalidArgumentException('The pseudo random string generator must be set to "mcrypt", "openssl", or "urandom", or be an instance of Facebook\PseudoRandomString\PseudoRandomStringGeneratorInterface');
+    }
+
+    /**
+     * Detects which pseudo-random string generator to use.
+     *
+     * @throws FacebookSDKException If unable to detect a cryptographically secure pseudo-random string generator.
+     *
+     * @return PseudoRandomStringGeneratorInterface
+     */
+    private static function detectDefaultPseudoRandomStringGenerator()
+    {
+        // 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.');
+    }
+}

+ 1 - 1
plugins/facebook-php-sdk/src/Facebook/PseudoRandomString/PseudoRandomStringGeneratorInterface.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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

+ 3 - 2
plugins/facebook-php-sdk/src/Facebook/PseudoRandomString/PseudoRandomStringGeneratorTrait.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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
@@ -48,11 +48,12 @@ trait PseudoRandomStringGeneratorTrait
      *
      * @param string $binaryData The binary data to convert to hex.
      * @param int    $length     The length of the string to return.
+     * @throws \RuntimeException Throws an exception when multibyte support is not enabled
      *
      * @return string
      */
     public function binToHex($binaryData, $length)
     {
-        return mb_substr(bin2hex($binaryData), 0, $length);
+        return \substr(\bin2hex($binaryData), 0, $length);
     }
 }

+ 1 - 1
plugins/facebook-php-sdk/src/Facebook/PseudoRandomString/UrandomPseudoRandomStringGenerator.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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

+ 3 - 9
plugins/facebook-php-sdk/src/Facebook/SignedRequest.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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
@@ -268,14 +268,8 @@ class SignedRequest
      */
     protected function validateSignature($hashedSig, $sig)
     {
-        if (mb_strlen($hashedSig) === mb_strlen($sig)) {
-            $validate = 0;
-            for ($i = 0; $i < mb_strlen($sig); $i++) {
-                $validate |= ord($hashedSig[$i]) ^ ord($sig[$i]);
-            }
-            if ($validate === 0) {
-                return;
-            }
+        if (\hash_equals($hashedSig, $sig)) {
+            return;
         }
 
         throw new FacebookSDKException('Signed request has an invalid signature.', 602);

+ 21 - 3
plugins/facebook-php-sdk/src/Facebook/Url/FacebookUrlDetectionHandler.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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
@@ -95,8 +95,8 @@ class FacebookUrlDetectionHandler implements UrlDetectionInterface
     protected function getHostName()
     {
         // Check for proxy first
-        if ($host = $this->getHeader('X_FORWARDED_HOST')) {
-            $elements = explode(',', $host);
+        if ($header = $this->getHeader('X_FORWARDED_HOST') && $this->isValidForwardedHost($header)) {
+            $elements = explode(',', $header);
             $host = $elements[count($elements) - 1];
         } elseif (!$host = $this->getHeader('HOST')) {
             if (!$host = $this->getServerVar('SERVER_NAME')) {
@@ -160,4 +160,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
+    }
 }

+ 2 - 2
plugins/facebook-php-sdk/src/Facebook/Url/FacebookUrlManipulator.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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
@@ -76,7 +76,7 @@ class FacebookUrlManipulator
      */
     public static function appendParamsToUrl($url, array $newParams = [])
     {
-        if (!$newParams) {
+        if (empty($newParams)) {
             return $url;
         }
 

+ 1 - 1
plugins/facebook-php-sdk/src/Facebook/Url/UrlDetectionInterface.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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

+ 1 - 1
plugins/facebook-php-sdk/src/Facebook/autoload.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 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

+ 49 - 0
plugins/facebook-php-sdk/src/Facebook/polyfills.php

@@ -0,0 +1,49 @@
+<?php
+/**
+ * Copyright 2016 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
+ * form for use in connection with the web services and APIs provided by
+ * Facebook.
+ *
+ * As with any software that integrates with the Facebook platform, your use
+ * of this software is subject to the Facebook Developer Principles and
+ * Policies [http://developers.facebook.com/policy/]. This copyright notice
+ * shall be included in all copies or substantial portions of the software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+/**
+ * @see https://github.com/sarciszewski/php-future/blob/master/src/Security.php#L37-L51
+ */
+if (!function_exists('hash_equals')) {
+    function hash_equals($knownString, $userString)
+    {
+        if (function_exists('mb_strlen')) {
+            $kLen = mb_strlen($knownString, '8bit');
+            $uLen = mb_strlen($userString, '8bit');
+        } else {
+            $kLen = strlen($knownString);
+            $uLen = strlen($userString);
+        }
+        if ($kLen !== $uLen) {
+            return false;
+        }
+        $result = 0;
+        for ($i = 0; $i < $kLen; $i++) {
+            $result |= (ord($knownString[$i]) ^ ord($userString[$i]));
+        }
+
+        // They are only identical strings if $result is exactly 0...
+        return 0 === $result;
+    }
+}