From 4ea5815521850dd0b7b1a926ebc5c0ffd3624c67 Mon Sep 17 00:00:00 2001 From: SammyK Date: Fri, 13 Feb 2015 01:02:06 -0600 Subject: [PATCH] Upgrad to run on Laravel 5 and Facebook PHP SDK v4.1 --- .travis.yml | 3 +- CHANGELOG.md | 12 +- CONTRIBUTING.md | 26 +- README.md | 462 +++++++++++------- composer.json | 29 +- src/LaravelFacebookSdk/FacebookFacade.php | 9 +- src/LaravelFacebookSdk/FacebookableTrait.php | 107 ---- src/LaravelFacebookSdk/LaravelFacebookSdk.php | 99 +++- .../LaravelFacebookSdkServiceProvider.php | 34 +- .../LaravelFacebookSdkTableCommand.php | 78 --- .../LaravelPersistentDataHandler.php | 20 +- .../LaravelUrlDetectionHandler.php | 16 +- .../SyncableGraphNodeTrait.php | 102 ++++ src/LaravelFacebookSdk/stubs/migration.stub | 40 -- .../{config.php => laravel-facebook-sdk.php} | 35 +- src/routes.php | 13 - src/views/channel.blade.php | 1 - tests/LaravelFacebookSdkTest.php | 35 +- ...est.php => SyncableGraphNodeTraitTest.php} | 33 +- 19 files changed, 628 insertions(+), 526 deletions(-) delete mode 100644 src/LaravelFacebookSdk/FacebookableTrait.php delete mode 100755 src/LaravelFacebookSdk/LaravelFacebookSdkTableCommand.php create mode 100644 src/LaravelFacebookSdk/SyncableGraphNodeTrait.php delete mode 100755 src/LaravelFacebookSdk/stubs/migration.stub rename src/config/{config.php => laravel-facebook-sdk.php} (55%) delete mode 100755 src/routes.php delete mode 100644 src/views/channel.blade.php rename tests/{FacebookableTraitTest.php => SyncableGraphNodeTraitTest.php} (79%) diff --git a/.travis.yml b/.travis.yml index e38a990..90a7c0b 100755 --- a/.travis.yml +++ b/.travis.yml @@ -11,7 +11,8 @@ before_script: - composer install --prefer-source --no-interaction --dev script: - - phpunit --coverage-text + - ./vendor/bin/phpunit --coverage-text + - ./vendor/bin/phpcs src --standard=psr2 matrix: allow_failures: diff --git a/CHANGELOG.md b/CHANGELOG.md index ef9fd9e..80a519c 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,19 @@ # CHANGELOG -## 2.0.0 - TBD +## 2.0.0 - February 13, 2015 +- Upgraded to work on Laravel 5! Yay! - Upgraded to use the latest Facebook PHP SDK v4.1. +- Removed the [Facebook Query Builder](https://github.com/SammyK/FacebookQueryBuilder) dependency. +- Removed the migration stub since there's only one column we need to add for most cases. +- Removed the config, route & view for the `channel.html` since that seems to be deprecated. +- Renamed `FacebookableTrait` to `SyncableGraphNodeTrait` since the Graph API returns nodes, not objects. + - Renamed `createOrUpdateFacebookObject()` to `createOrUpdateGraphNode()` since that makes more since on Facebook's domain. +- Added support for re-requests and re-authentications. +- Removed `LaravelFacebookSdkException` to let all the native PHP SDK's exceptions fall through. +- Removed all the weird authentication crap that didn't make any sense. +- Bound the package to the IoC container as `SammyK\LaravelFacebookSdk\LaravelFacebookSdk` instead of the old `facebook-query-builder`. ## 1.1.1 - December 11, 2014 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 998f41b..56808fd 100755 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,13 +1,13 @@ -Contributing -============ +# Contributing Contributions are **welcome** and will be fully **credited**. We accept contributions via Pull Requests on [Github](https://github.com/SammyK/LaravelFacebookSdk). -Pull Requests -------------- +## Pull Requests + +- **[PSR-2 Coding Standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)** - Unlike Laravel, the LaravelFacebookSdk follows PSR-2. The easiest way to apply the conventions is to install [PHP Code Sniffer](http://pear.php.net/package/PHP_CodeSniffer). - **Add tests!** - Your patch won't be accepted if it doesn't have tests. And the tests must pass of course. @@ -21,5 +21,23 @@ 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 (see below) 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 using the PSR-2 standard (see below) 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 + +``` bash +$ ./vendor/bin/phpcs src --standard=psr2 -sp +``` + **Happy coding**! diff --git a/README.md b/README.md index d256a2a..2bbf513 100755 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ [![License](http://img.shields.io/badge/license-MIT-lightgrey.svg)](https://github.com/SammyK/LaravelFacebookSdk/blob/master/LICENSE) -A fully unit-tested package for easily integrating the [Facebook SDK v4.1](https://github.com/facebook/facebook-php-sdk-v4) into Laravel 4. +A fully unit-tested package for easily integrating the [Facebook SDK v4.1](https://github.com/facebook/facebook-php-sdk-v4) into Laravel 5. - [Installation](#installation) - [Facebook Login](#facebook-login) @@ -18,28 +18,22 @@ A fully unit-tested package for easily integrating the [Facebook SDK v4.1](https - [Credits](#credits) - [License](#license) +> **This is package for Laravel 5!** For Laravel 4.2, [see the 1.x branch](https://github.com/SammyK/LaravelFacebookSdk/tree/1.1). ## Installation - -### Composer - Add the Laravel Facebook SDK package to your `composer.json` file. +> **Note:** The `@dev` minimum stability flag can be removed once the Facebook releases version 4.1 of the SDK. Right now it's in a feature-freeze until it is released so there shouldn't be any breaking changes. :) + ```json { "require": { - "sammyk/laravel-facebook-sdk": "~2.0" + "sammyk/laravel-facebook-sdk": "~2.0@dev" } } ``` -Or via the command line in the root of your Laravel installation. - -```bash -$ composer require "sammyk/laravel-facebook-sdk:~2.0" -``` - ### Service Provider @@ -62,13 +56,35 @@ If you want to make use of the facade, add it to the aliases array in your app c ]; ``` +But there are [much better ways](#ioc-container) to use this package that [don't use facades](http://programmingarehard.com/2014/01/11/stop-using-facades.html). + ### IoC container -The main class is bound in the IoC container as `laravel-facebook-sdk`. +The IoC container will automatically resolve the `LaravelFacebookSdk` dependencies for you. You can grab an instance of `LaravelFacebookSdk` from the IoC container in a number of ways. ```php -$fb = App::make('laravel-facebook-sdk'); +// Directly from App::make(); +$fb = App::make('SammyK\LaravelFacebookSdk\LaravelFacebookSdk'); + +// From a constructor +class FooClass { + public function __construct(SammyK\LaravelFacebookSdk\LaravelFacebookSdk $fb) { + // . . . + } +} + +// From a method +class BarClass { + public function barMethod(SammyK\LaravelFacebookSdk\LaravelFacebookSdk $fb) { + // . . . + } +} + +// Or even a closure +Route::get('/facebook/login', function(SammyK\LaravelFacebookSdk\LaravelFacebookSdk $fb) { + // . . . +}); ``` @@ -77,22 +93,27 @@ $fb = App::make('laravel-facebook-sdk'); After [creating an app in Facebook](https://developers.facebook.com/apps), you'll need to provide the app ID and secret. First publish the configuration file. ```bash -$ php artisan config:publish sammyk/laravel-facebook-sdk +$ php artisan vendor:publish --provider="sammyk/laravel-facebook-sdk" --tag="config" ``` -Then you can update the `app_id` and `app_secret` values in the `app/config/packages/sammyk/laravel-facebook-sdk/config.php` file. +> **Where's the file?** Laravel 5 will publish the config file to `config/laravel-facebook-sdk.php`. + + +#### Required config values + +You'll need to update the `app_id` and `app_secret` values in the config file with [your app ID and secret](https://developers.facebook.com/apps). ## Facebook Login -When we say "log in with Facebook", we really mean "obtain a user access token to make calls to the Graph API on behalf of the user." There are a number of ways to log a user in with Facebook using what the Facbeook PHP SDK calls "[helpers](https://developers.facebook.com/docs/php/reference#helpers)". +When we say "log in with Facebook", we really mean "obtain a user access token to make calls to the Graph API on behalf of the user." This is done through Facebook via [OAuth 2.0](http://oauth.net/2/). There are a number of ways to log a user in with Facebook using what the Facbeook PHP SDK calls "[helpers](https://developers.facebook.com/docs/php/reference#helpers)". The four supported login methods are: -1. [Login From Redirect](#login-from-redirect) -2. [Login From JavaScript](#login-from-javascript) -3. [Login From App Canvas](#login-from-app-canvas) -4. [Login From Page Tab](#login-from-page-tab) +1. [Login From Redirect](#login-from-redirect) (OAuth 2.0) +2. [Login From JavaScript](#login-from-javascript) (with JS SDK cookie) +3. [Login From App Canvas](#login-from-app-canvas) (with signed request) +4. [Login From Page Tab](#login-from-page-tab) (with signed request) ### Login From Redirect @@ -109,11 +130,14 @@ The redirect helper can be obtained using the SDK's `getRedirectLoginHelper()` m You can get a login URL just like you you do with the Facebook PHP SDK v4.1. ```php -$fb = App::make('laravel-facebook-sdk'); - -$login_link = $fb->getRedirectLoginHelper()->getLoginUrl('http://my-callback/url', ['email', 'user_events']); +Route::get('/facebook/login', function(SammyK\LaravelFacebookSdk\LaravelFacebookSdk $fb) { + $login_link = $fb + ->getRedirectLoginHelper() + ->getLoginUrl('https://exmaple.com/facebook/callback', ['email', 'user_events']); + + echo 'Log in with Facebook'; +}); -echo 'Log in with Facebook'; ``` But if you set the `default_redirect_uri` callback URL in the config file, you can use the `getLoginUrl()` wrapper method which will default the callback URL (`default_redirect_uri`) and permission scope (`default_scope`) to whatever you set in the config file. @@ -127,7 +151,7 @@ Alternatively you can pass the permissions and a custom callback URL to the wrap > **Note:** Since the list of permissions sometimes changes but the callback URL usually stays the same, the permissions array is the first argument in the `getLoginUrl()` wrapper method which is the reverse of the SDK's method `getRedirectLoginHelper()->getLoginUrl($url, $permissions)`. ```php -$login_link = $fb->getLoginUrl(['email', 'user_status'], 'http://my-custom-callback/url'); +$login_link = $fb->getLoginUrl(['email', 'user_status'], 'https://exmaple.com/facebook/callback'); // Or, if you want to default to the callback URL set in the config $login_link = $fb->getLoginUrl(['email', 'user_status']); ``` @@ -140,34 +164,34 @@ After the user has clicked on the login link from above and confirmed or denied The standard "SDK" way to obtain an access token on the callback URL is as follows: ```php -$fb = App::make('laravel-facebook-sdk'); - -try -{ - $fbClient = $fb->getClient(); - $token = $fb->getRedirectLoginHelper()->getAccessToken($fbClient, 'http://my-custom-callback/url'); -} -catch (\Facebook\Exceptions\FacebookSDKException $e) -{ - // Failed to obtain access token - echo 'Error:' . $e->getMessage(); -} +Route::get('/facebook/callback', function(SammyK\LaravelFacebookSdk\LaravelFacebookSdk $fb) { + try { + $token = $fb + ->getRedirectLoginHelper() + ->getAccessToken('https://exmaple.com/facebook/callback'); + } catch (Facebook\Exceptions\FacebookSDKException $e) { + // Failed to obtain access token + dd($e->getMessage()); + } +}); ``` -There is a wrapper method for `getRedirectLoginHelper()->getAccessToken($callback_url)` in LaravelFacebookSdk called `getAccessTokenFromRedirect()` that defaults the callback URL to whatever is set in the config under `default_redirect_uri`. +There is a wrapper method for `getRedirectLoginHelper()->getAccessToken($callback_url)` in LaravelFacebookSdk called `getAccessTokenFromRedirect()` that defaults the callback URL to whatever the current URL is. ```php -$fb = App::make('laravel-facebook-sdk'); - -try -{ - $token = $fb->getAccessTokenFromRedirect(); -} -catch (\Facebook\Exceptions\FacebookSDKException $e) -{ - // Failed to obtain access token - echo 'Error:' . $e->getMessage(); -} +Route::get('/facebook/callback', function(SammyK\LaravelFacebookSdk\LaravelFacebookSdk $fb) { + try { + $token = $fb->getAccessTokenFromRedirect(); + } catch (Facebook\Exceptions\FacebookSDKException $e) { + // Failed to obtain access token + dd($e->getMessage()); + } + + // $token will be null if the user denied the request + if (! $token) { + // User denied the request + } +}); ``` @@ -185,20 +209,23 @@ FB.init({ }); ``` -After you have logged a user in with the JavaScript SDK using [`FB.login()`](https://developers.facebook.com/docs/reference/javascript/FB.login), the user access token that sits in a cookie can be obtained with the PHP SDK's JavaScript helper. +After you have logged a user in with the JavaScript SDK using [`FB.login()`](https://developers.facebook.com/docs/reference/javascript/FB.login), you can obtain a user access token from the signed request that is stored in the cookie that was set by the JavaScript SDK. ```php -$fb = App::make('laravel-facebook-sdk'); +Route::get('/facebook/javascript', function(SammyK\LaravelFacebookSdk\LaravelFacebookSdk $fb) { + try { + $token = $fb->getJavaScriptHelper()->getAccessToken(); + } catch (Facebook\Exceptions\FacebookSDKException $e) { + // Failed to obtain access token + dd($e->getMessage()); + } -try -{ - $token = $fb->getJavaScriptHelper()->getAccessToken(); -} -catch (\Facebook\Exceptions\FacebookSDKException $e) -{ - // Failed to obtain access token - echo 'Error:' . $e->getMessage(); -} + // $token will be null if no cookie was set or no OAuth data + // was found in the cookie's signed request data + if (! $token) { + // User hasn't logged in using the JS SDK yet + } +}); ``` @@ -211,17 +238,19 @@ If your app lives within the context of a Facebook app canvas, you can obtain an Use the SDK's canvas helper to obtain the access token from the signed request data. ```php -$fb = App::make('laravel-facebook-sdk'); +Route::get('/facebook/canvas', function(SammyK\LaravelFacebookSdk\LaravelFacebookSdk $fb) { + try { + $token = $fb->getCanvasHelper()->getAccessToken(); + } catch (Facebook\Exceptions\FacebookSDKException $e) { + // Failed to obtain access token + dd($e->getMessage()); + } -try -{ - $token = $fb->getCanvasHelper()->getAccessToken(); -} -catch (\Facebook\Exceptions\FacebookSDKException $e) -{ - // Failed to obtain access token - echo 'Error:' . $e->getMessage(); -} + // $token will be null if the user hasn't authenticated your app yet + if (! $token) { + // . . . + } +}); ``` @@ -232,17 +261,52 @@ If your app lives within the context of a Facebook Page tab, that is the same as The SDK provides a Page tab helper to obtain an access token from the signed request data within the context of a Page tab. ```php -$fb = App::make('laravel-facebook-sdk'); +Route::get('/facebook/page-tab', function(SammyK\LaravelFacebookSdk\LaravelFacebookSdk $fb) { + try { + $token = $fb->getPageTabHelper()->getAccessToken(); + } catch (Facebook\Exceptions\FacebookSDKException $e) { + // Failed to obtain access token + dd($e->getMessage()); + } -try -{ - $token = $fb->getPageTabHelper()->getAccessToken(); -} -catch (\Facebook\Exceptions\FacebookSDKException $e) -{ - // Failed to obtain access token - echo 'Error:' . $e->getMessage(); -} + // $token will be null if the user hasn't authenticated your app yet + if (! $token) { + // . . . + } +}); +``` + +## Other authorization requests + +Facebook supports two other types of authorization URL's - rerequests and re-authentications. + +### Rerequests + +[Rerequests](https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow#reaskperms) (or re-requests?) ask the user again for permissions they have previously declined. It's important to use a rerequest URL for this instead of just redirecting them with the normal log in link because: + +> Once someone has declined a permission, the Login Dialog will not re-ask them for it unless you explicitly tell the dialog you're re-asking for a declined permission. - [Facebook Documentation](https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow#reaskperms) + +You can generate a rerequest URL using the `getReRequestUrl()` method. + +```php +$rerequest_link = $fb->getReRequestUrl(['email'], 'https://exmaple.com/facebook/login'); +// Or, if you want to default to the callback URL set in the config +$rerequest_link = $fb->getReRequestUrl(['email']); +``` + + +### Re-authentications + +[Re-authentications](https://developers.facebook.com/docs/facebook-login/reauthentication) force a user to confirm their identity by asking them to enter their Facebook account password again. This is useful for adding another layer of security before changing or view sensitive data on your web app. + +You can generate a re-authentication URL using the `getReAuthenticationUrl()` method. + +```php +$re_authentication_link = $fb->getReAuthenticationUrl(['email'], 'https://exmaple.com/facebook/login'); +// Or, if you want to default to the callback URL set in the config +$re_authentication_link = $fb->getReAuthenticationUrl(['email']); +// Or without permissions +$re_authentication_link = $fb->getReAuthenticationUrl(); ``` @@ -266,38 +330,52 @@ $fb->setDefaultAccessToken($token); ## Saving Data From Facebook In The Database -Saving data received from the Graph API to a database can sometimes be a tedious endeavor. Since the Graph API returns data in a predictable format, the `FacebookableTrait` can make saving the data to a database a painless process. +Saving data received from the Graph API to a database can sometimes be a tedious endeavor. Since the Graph API returns data in a predictable format, the `SyncableGraphNodeTrait` can make saving the data to a database a painless process. -Any Eloquent model that implements the `FacebookableTrait` will have the `createOrUpdateFacebookObject()` method applied to it. This method really makes it easy to take data that was returned directly from Facebook and create or update it in the local database. +Any Eloquent model that implements the `SyncableGraphNodeTrait` will have the `createOrUpdateGraphNode()` method applied to it. This method really makes it easy to take data that was returned directly from Facebook and create or update it in the local database. + +```php +use SammyK\LaravelFacebookSdk\SyncableGraphNodeTrait; + +class Event extends Eloquent { + use SyncableGraphNodeTrait; +} +``` For example if you have an Eloquent model named `Event`, here's how you might grab a specific event from the Graph API and insert it into the database as a new entry or update an existing entry with the new info. ```php -$fb = App::make('laravel-facebook-sdk'); - $response = $fb->get('/some-event-id?fields=id,name'); $facebook_event = $response->getGraphObject(); -// Create the event if not exists or update existing -$event = Event::createOrUpdateFacebookObject($facebook_event); +// A method called createOrUpdateGraphNode() on the `Event` eloquent model +// will create the event if it does not exist or it will update the existing +// record based on the ID from Facebook. +$event = Event::createOrUpdateGraphNode($facebook_event); ``` -The `createOrUpdateFacebookObject()` will automatically map the returned field names to the column names in your database. If, for example, your column names on the `events` table don't match the field names for an [Event](https://developers.facebook.com/docs/graph-api/reference/event) node, you can [map the fields](#field-mapping). +> **Heads up!** The Facebook PHP SDK calls nodes from the Graph API `GraphObject`'s. This is not a good name for them since the Graph API calls them nodes. This will [most likely be renamed](https://github.com/facebook/facebook-php-sdk-v4/issues/320) to `GraphNode` in a breaking change pretty soon. + +The `createOrUpdateGraphNode()` will automatically map the returned field names to the column names in your database. If, for example, your column names on the `events` table don't match the field names for an [Event](https://developers.facebook.com/docs/graph-api/reference/event) node, you can [map the fields](#field-mapping). ### Field Mapping -Since the names of the fields in your database might not match the names of the fields in Graph, you can map the field names in your `User` model using the `$facebook_field_aliases` static variable. +Since the names of the columns in your database might not match the names of the fields of the Graph nodes, you can map the field names in your `User` model using the `$graph_node_field_aliases` static variable. -The *keys* of the array are the names of the fields in Graph. The *values* of the array are the names of the columns in the local database. +The *keys* of the array are the names of the fields on the Graph node. The *values* of the array are the names of the columns in the local database. ```php +use SammyK\LaravelFacebookSdk\SyncableGraphNodeTrait; + class User extends Eloquent implements UserInterface { - protected static $facebook_field_aliases = [ - 'facebook_field_name' => 'database_column_name', + use SyncableGraphNodeTrait; + + protected static $graph_node_field_aliases = [ 'id' => 'facebook_user_id', 'name' => 'full_name', + 'graph_node_field_name' => 'database_column_name', ]; } ``` @@ -310,29 +388,71 @@ The Laravel Facebook SDK makes it easy to log a user in with Laravel's built-in ### Updating The Users Table -You'll need to make columns in your `users` table to store the user's Facebook id and access token. +In order to get Facebook authentication working with Laravel's built-in authentication, you'll need to store the Facebook user's ID in your user's table. + +Naturally you'll need to create a column for every other piece of information you want to keep about the user. -You could add these column manually, or just use the built-in migration script. +You can store the access token in the database if you need to make requests on behalf of the user when they are not browsing your app (like a 3AM cron job). But in general you won't need to store the access token in the database. -> **Note:** Make sure to change `users` to the name of your user table. +You'll need to generate a migration to modify your `users` table and add any new columns. + +> **Note:** Make sure to change `` to the name of your user table. + +```bash +$ php artisan make:migration add_facebook_columns_to_users_table --table="" +``` + +Now update the migration file to include the new fields you want to save on the user. At minimum you'll need to save the Facebook user ID. + +```php +use Illuminate\Database\Schema\Blueprint; +use Illuminate\Database\Migrations\Migration; + +class AddFacebookColumnsToUsersTable extends Migration +{ + public function up() + { + Schema::table('users', function(Blueprint $table) + { + // If the primary id in your you user table is different than the Facebook id + // Make sure it's an unsigned() bigInteger() + $table->bigInteger('facebook_user_id')->unsigned()->index(); + // Normally you won't need to store the access token in the database + $table->string('access_token')->nullable(); + }); + } + + public function down() + { + Schema::table('users', function(Blueprint $table) + { + $table->dropColumn( + 'facebook_user_id', + 'access_token' + ); + }); + } +} +``` + +Don't forget to run the migration. ```bash -$ php artisan laravel-facebook-sdk:table users $ php artisan migrate ``` -Check out the migration file that it generated. If you plan on using the Facebook user ID as the primary key, make sure you have a column called `id` that is an unsigned big integer and indexed. If you are storing the Facebook ID in a different field, make sure that field exists in the database and make sure to [map to it in your model](#field-mapping) to your custom id name. +If you plan on using the Facebook user ID as the primary key, make sure you have a column called `id` that is an unsigned big integer and indexed. If you are storing the Facebook ID in a different field, make sure that field exists in the database and make sure to [map to it in your model](#field-mapping) to your custom id name. -If you're using the Eloquent ORM, make sure to hide the `access_token` field from possible exposure in your `User` model. +If you're using the Eloquent ORM and storing the access token in the database, make sure to hide the `access_token` field from possible exposure in your `User` model. -Also add the [`FacebookableTrait`](#saving-data-from-facebook-in-the-database) to your `User` model to get some really great functionality for syncing your model with data returned from the Graph API. +Don't forget to add the [`SyncableGraphNodeTrait`](#saving-data-from-facebook-in-the-database) to your user model so you can sync your model with data returned from the Graph API. ```php -use SammyK\LaravelFacebookSdk\FacebookableTrait; +# User.php +use SammyK\LaravelFacebookSdk\SyncableGraphNodeTrait; -class User extends Eloquent implements UserInterface -{ - use FacebookableTrait; +class User extends Eloquent implements UserInterface { + use SyncableGraphNodeTrait; protected $hidden = ['access_token']; } @@ -344,43 +464,41 @@ class User extends Eloquent implements UserInterface After the user has logged in with Facebook and you've obtained the user ID from the Graph API, you can log the user into Laravel by passing the logged in user's `User` model to the `Auth::login()` method. ```php -$fb = App::make('laravel-facebook-sdk'); - -try -{ - $response = $fb->get('/me?fields=id,name'); -} -catch (\Facebook\Exceptions\FacebookSDKException $e) -{ - echo 'Error: ' . $e->getMessage(); - exit; +class FacebookController { + public function getUserInfo(SammyK\LaravelFacebookSdk\LaravelFacebookSdk $fb) { + try { + $response = $fb->get('/me?fields=id,name,email'); + } catch (Facebook\Exceptions\FacebookSDKException $e) { + dd($e->getMessage()); + } + + // Convert the response to a `Facebook/GraphNodes/GraphUser` collection + $facebook_user = $response->getGraphUser(); + + // Create the user if it does not exist or update the existing entry. + // This will only work if you've added the SyncableGraphNodeTrait to your User model. + $user = App\User::createOrUpdateGraphNode($facebook_user); + + // Log the user into Laravel + Auth::login($user); + } } - -// Convert the response to a `Facebook/GraphNodes/GraphUser` collection -$facebook_user = $response->getGraphUser(); - -// Create the user if it does not exist or update the existing entry. -// This will only work if you've added the FacebookableTrait to your User model. -$user = User::createOrUpdateFacebookObject($facebook_user); - -// Log the user into Laravel -Auth::login($user); ``` ## Error Handling -The Facebook PHP SDK throws `\Facebook\Exceptions\FacebookSDKException` exceptions. Whenever there is an error response from Graph, the SDK will throw a `\Facebook\Exceptions\FacebookResponseException` which extends from `\Facebook\Exceptions\FacebookSDKException`. If a `\Facebook\Exceptions\FacebookResponseException` is thrown there are a number of "horizontal" exceptions that can be obtained using `$e->getPrevious()`. +The Facebook PHP SDK throws `Facebook\Exceptions\FacebookSDKException` exceptions. Whenever there is an error response from Graph, the SDK will throw a `Facebook\Exceptions\FacebookResponseException` which extends from `Facebook\Exceptions\FacebookSDKException`. If a `Facebook\Exceptions\FacebookResponseException` is thrown you can grab a specific exception related to the error from the `getPrevious()` method. ```php try { // Stuffs here -} catch (\Facebook\Exceptions\FacebookResponseException $e) { +} catch (Facebook\Exceptions\FacebookResponseException $e) { $graphError = $e->getPrevious(); echo 'Graph API Error: ' . $e->getMessage(); echo ', Graph error code: ' . $graphError->getCode(); exit; -} catch (\Facebook\Exceptions\FacebookSDKException $e) { +} catch (Facebook\Exceptions\FacebookSDKException $e) { echo 'SDK Error: ' . $e->getMessage(); exit; } @@ -401,86 +519,90 @@ Finally it will log the user in using Laravel's built-in user authentication. ``` php // Generate a login URL -Route::get('/login', function() +Route::get('/facebook/login', function(SammyK\LaravelFacebookSdk\LaravelFacebookSdk $fb) { - $login_url = Facebook::getLoginUrl(['email']); + // Send an array of permissions to request + $login_url = $fb->getLoginUrl(['email']); + + // Obviously you'd do this in blade :) echo 'Login with Facebook'; }); // Endpoint that is redirected to after an authentication attempt -Route::get('/facebook/login', function() +Route::get('/facebook/callback', function(SammyK\LaravelFacebookSdk\LaravelFacebookSdk $fb) { - /** - * Obtain an access token. - */ - try - { - $token = Facebook::getAccessTokenFromRedirect(); + // Obtain an access token. + try { + $token = $fb->getAccessTokenFromRedirect(); + } catch (Facebook\Exceptions\FacebookSDKException $e) { + dd($e->getMessage()); + } - if ( ! $token) - { - dd('Unable to obtain access token.', $token); + // Access token will be null if the user denied the request + // or if someone just hit this URL outside of the OAuth flow. + if (! $token) { + // Get the redirect helper + $helper = $fb->getRedirectLoginHelper(); + + if (! $helper->getError()) { + abort(403, 'Unauthorized action.'); } - } - catch (\Facebook\Exceptions\FacebookSDKException $e) - { - dd($e->getMessage()); + + // User denied the request + dd( + $helper->getError(), + $helper->getErrorCode(), + $helper->getErrorReason(), + $helper->getErrorDescription() + ); } - if ( ! $token->isLongLived()) + if (! $token->isLongLived()) { - /** - * Extend the access token. - */ - try - { - // @TODO This is changing - $fbApp = Facebook::getApp(); - $fbClient = Facebook::getClient(); - $token = $token->extend($fbApp, $fbClient); - } - catch (\Facebook\Exceptions\FacebookSDKException $e) - { + // OAuth 2.0 client handler + $oauth_client = $fb->getOAuth2Client(); + + // Extend the access token. + try { + $token = $oauth_client->getLongLivedAccessToken($token); + } catch (Facebook\Exceptions\FacebookSDKException $e) { dd($e->getMessage()); } } - Facebook::setDefaultAccessToken($token); + $fb->setDefaultAccessToken($token); - /** - * Get basic info on the user from Facebook. - */ - try - { - $response = Facebook::get('/me?fields=id,name'); - } - catch (\Facebook\Exceptions\FacebookSDKException $e) - { + // Save for later + Session::put('fb_user_access_token', (string) $token); + + // Get basic info on the user from Facebook. + try { + $response = $fb->get('/me?fields=id,name,email'); + } catch (Facebook\Exceptions\FacebookSDKException $e) { dd($e->getMessage()); } // Convert the response to a `Facebook/GraphNodes/GraphUser` collection $facebook_user = $response->getGraphUser(); - + // Create the user if it does not exist or update the existing entry. // This will only work if you've added the FacebookableTrait to your User model. - $user = User::createOrUpdateFacebookObject($facebook_user); + $user = App\User::createOrUpdateGraphNode($facebook_user); // Log the user into Laravel Auth::login($user); - return Redirect::to('/')->with('message', 'Successfully logged in with Facebook'); + return redirect('/')->with('message', 'Successfully logged in with Facebook'); }); ``` ## Testing -The tests are written with `phpunit`. If you've installed `phpunit` globally, you can run the tests from the project directory. +The tests are written with `phpunit`. You can run the tests from the root of the project directory with the following command. ``` bash -$ cd /path/to/sammyk/laravel-facebook-sdk -$ phpunit +$ ./vendor/bin/phpunit ``` diff --git a/composer.json b/composer.json index c50bb1d..f614e1a 100755 --- a/composer.json +++ b/composer.json @@ -1,32 +1,43 @@ { "name": "sammyk/laravel-facebook-sdk", - "description": "Fully unit tested Facebook SDK v4 integration for Laravel", + "description": "Fully unit tested Facebook SDK v4.1 integration for Laravel 5", "keywords": ["facebook", "laravel", "sdk", "facebook sdk v4", "facebook query builder"], "homepage": "https://github.com/SammyK/LaravelFacebookSdk", "license": "MIT", "authors": [ { "name": "Sammy Kaye Powers", - "email": "sammyk@sammykmedia.com", + "email": "me@sammyk.me", "homepage": "http://sammyk.me", "role": "Developer" } ], "require": { "php": ">=5.4.0", - "illuminate/auth": "~4", - "illuminate/database": "~4", - "illuminate/support": "~4", - "illuminate/config": "~4", - "illuminate/session": "~4", + "illuminate/auth": "~5", + "illuminate/config": "~5", + "illuminate/database": "~5", + "illuminate/routing": "~5", + "illuminate/session": "~5", + "illuminate/support": "~5", "facebook/php-sdk-v4": "~4.1.0@dev" }, "require-dev": { - "mockery/mockery": "dev-master@dev" + "phpunit/phpunit": "~4.0", + "mockery/mockery": "~0.9", + "squizlabs/php_codesniffer": "~2.0" }, "autoload": { "psr-4": { - "SammyK\\LaravelFacebookSdk\\": ["src/LaravelFacebookSdk", "tests"] + "SammyK\\LaravelFacebookSdk\\": "src/LaravelFacebookSdk" } + }, + "autoload-dev": { + "psr-4": { + "SammyK\\LaravelFacebookSdk\\Test\\": "tests" + } + }, + "branch-alias": { + "dev-master": "2.x-dev" } } diff --git a/src/LaravelFacebookSdk/FacebookFacade.php b/src/LaravelFacebookSdk/FacebookFacade.php index 9f6716d..23865d3 100644 --- a/src/LaravelFacebookSdk/FacebookFacade.php +++ b/src/LaravelFacebookSdk/FacebookFacade.php @@ -7,12 +7,15 @@ */ class FacebookFacade extends Facade { - /** * Get the registered name of the component. * + * Don't use this. Just... don't. + * * @return string */ - protected static function getFacadeAccessor() { return 'laravel-facebook-sdk'; } - + protected static function getFacadeAccessor() + { + return 'Facebook\Exceptions\FacebookSDKException'; + } } diff --git a/src/LaravelFacebookSdk/FacebookableTrait.php b/src/LaravelFacebookSdk/FacebookableTrait.php deleted file mode 100644 index 0e49cc7..0000000 --- a/src/LaravelFacebookSdk/FacebookableTrait.php +++ /dev/null @@ -1,107 +0,0 @@ - $value) - { - $object->{static::fieldToColumnName($field)} = $value; - } - } - - /** - * Inserts or updates the Facebook object to the local database - * - * @param array|GraphObject $data - * - * @return Model - * - * @throws \InvalidArgumentException - */ - public static function createOrUpdateFacebookObject($data) - { - if ($data instanceof GraphObject) - { - $data = $data->asArray(); - } - - if ( ! isset($data['id'])) - { - throw new \InvalidArgumentException('Facebook object id is missing'); - } - - $attributes = [static::getFacebookObjectKeyName() => $data['id']]; - - $facebook_object = static::firstOrNewFacebookObject($attributes); - - static::mapFacebookFieldsToObject($facebook_object, $data); - - $facebook_object->save(); - - return $facebook_object; - } - - /** - * Like static::firstOrNew() but without mass assignment - * - * @param array $attributes - * - * @return Model - */ - public static function firstOrNewFacebookObject(array $attributes) - { - if (is_null($facebook_object = static::firstByAttributes($attributes))) - { - $facebook_object = new static(); - } - - return $facebook_object; - } - -} diff --git a/src/LaravelFacebookSdk/LaravelFacebookSdk.php b/src/LaravelFacebookSdk/LaravelFacebookSdk.php index 3db270e..47b07f1 100644 --- a/src/LaravelFacebookSdk/LaravelFacebookSdk.php +++ b/src/LaravelFacebookSdk/LaravelFacebookSdk.php @@ -1,69 +1,118 @@ config_handler = $config_handler; + $this->url = $url; parent::__construct($config); } /** - * Get a login URL for redirect. + * Generate an OAuth 2.0 authorization URL for authentication. * * @param array $scope * @param string $callback_url - * @param boolean $rerequest + * * @return string */ - public function getLoginUrl(array $scope = [], $callback_url = '', $rerequest = false) + public function getLoginUrl(array $scope = [], $callback_url = '') { - if (empty($scope)) - { - $scope = $this->config_handler->get('laravel-facebook-sdk::default_scope'); - } + $scope = $this->getScope($scope); + $callback_url = $this->getCallbackUrl($callback_url); - if (empty($callback_url)) - { - $callback_url = $this->config_handler->get('app.url') . $this->config_handler->get('laravel-facebook-sdk::default_redirect_uri'); - } + return $this->getRedirectLoginHelper()->getLoginUrl($callback_url, $scope); + } + + /** + * Generate a re-request authorization URL. + * + * @param array $scope + * @param string $callback_url + * + * @return string + */ + public function getReRequestUrl(array $scope, $callback_url = '') + { + $scope = $this->getScope($scope); + $callback_url = $this->getCallbackUrl($callback_url); - return $this->getRedirectLoginHelper()->getLoginUrl($callback_url, $scope, $rerequest); + return $this->getRedirectLoginHelper()->getReRequestUrl($callback_url, $scope); + } + + /** + * Generate a re-authentication authorization URL. + * + * @param array $scope + * @param string $callback_url + * + * @return string + */ + public function getReAuthenticationUrl(array $scope = [], $callback_url = '') + { + $scope = $this->getScope($scope); + $callback_url = $this->getCallbackUrl($callback_url); + + return $this->getRedirectLoginHelper()->getReAuthenticationUrl($callback_url, $scope); } /** * Get an access token from a redirect. * * @param string $callback_url - * @return \Facebook\AccessToken|null + * @return \Facebook\Authentication\AccessToken|null */ public function getAccessTokenFromRedirect($callback_url = '') { - if (empty($callback_url)) - { - $callback_url = $this->config_handler->get('app.url') . $this->config_handler->get('laravel-facebook-sdk::default_redirect_uri'); - } + $callback_url = $this->getCallbackUrl($callback_url); - // @TODO This will change - $client = $this->getClient(); + return $this->getRedirectLoginHelper()->getAccessToken($callback_url); + } - return $this->getRedirectLoginHelper()->getAccessToken($client, $callback_url); + /** + * Get the fallback scope if none provided. + * + * @param array $scope + * + * @return array + */ + private function getScope(array $scope) + { + return $scope ?: $this->config_handler->get('laravel-facebook-sdk.default_scope'); } + /** + * Get the fallback callback redirect URL if none provided. + * + * @param string $callback_url + * + * @return string + */ + private function getCallbackUrl($callback_url) + { + $callback_url = $callback_url ?: $this->config_handler->get('laravel-facebook-sdk.default_redirect_uri'); + + return $this->url->to($callback_url); + } } diff --git a/src/LaravelFacebookSdk/LaravelFacebookSdkServiceProvider.php b/src/LaravelFacebookSdk/LaravelFacebookSdkServiceProvider.php index 0b94509..7944818 100644 --- a/src/LaravelFacebookSdk/LaravelFacebookSdkServiceProvider.php +++ b/src/LaravelFacebookSdk/LaravelFacebookSdkServiceProvider.php @@ -4,7 +4,6 @@ class LaravelFacebookSdkServiceProvider extends ServiceProvider { - /** * Indicates if loading of the provider is deferred. * @@ -19,9 +18,11 @@ class LaravelFacebookSdkServiceProvider extends ServiceProvider */ public function boot() { - $this->package('sammyk/laravel-facebook-sdk', null, __DIR__.'/../'); + $this->publishes([ + __DIR__.'/../config/laravel-facebook-sdk.php' => config_path('laravel-facebook-sdk.php'), + ], 'config'); - include __DIR__.'/../routes.php'; + $this->loadViewsFrom(__DIR__.'/../views', 'laravel-facebook-sdk'); } /** @@ -32,23 +33,18 @@ public function boot() public function register() { // Main Service - $this->app->bindShared('laravel-facebook-sdk', function($app) - { - return new LaravelFacebookSdk($app['config'], [ - 'app_id' => $app['config']->get('laravel-facebook-sdk::app_id'), - 'app_secret' => $app['config']->get('laravel-facebook-sdk::app_secret'), - 'persistent_data_handler' => new LaravelPersistentDataHandler(), - 'url_detection_handler' => new LaravelUrlDetectionHandler(), - ]); - }); + $this->app->bind('SammyK\LaravelFacebookSdk\LaravelFacebookSdk', function($app) { + $config = $app['config']->get('laravel-facebook-sdk.facebook_config'); - // CLI - $this->app->bindShared('command.laravel-facebook-sdk.table', function() - { - return new LaravelFacebookSdkTableCommand(); - }); + if (! isset($config['persistent_data_handler'])) { + $config['persistent_data_handler'] = new LaravelPersistentDataHandler($app['session.store']); + } - $this->commands('command.laravel-facebook-sdk.table'); - } + if (! isset($config['url_detection_handler'])) { + $config['url_detection_handler'] = new LaravelUrlDetectionHandler($app['url']); + } + return new LaravelFacebookSdk($app['config'], $app['url'], $config); + }); + } } diff --git a/src/LaravelFacebookSdk/LaravelFacebookSdkTableCommand.php b/src/LaravelFacebookSdk/LaravelFacebookSdkTableCommand.php deleted file mode 100755 index 3bd249c..0000000 --- a/src/LaravelFacebookSdk/LaravelFacebookSdkTableCommand.php +++ /dev/null @@ -1,78 +0,0 @@ -createBaseMigration(); - - file_put_contents($fullPath, $this->getMigrationStub()); - - $this->info('Migration created successfully!'); - - $this->call('dump-autoload'); - } - - /** - * Create a base migration file. - * - * @return string - */ - protected function createBaseMigration() - { - $name = 'add_laravel_facebook_sdk_columns'; - - $path = $this->laravel['path'].'/database/migrations'; - - return $this->laravel['migration.creator']->create($name, $path); - } - - /** - * Get the contents of the migration stub. - * - * @return string - */ - protected function getMigrationStub() - { - $stub = file_get_contents(__DIR__.'/stubs/migration.stub'); - - return str_replace('facebook_user_table', $this->argument('table'), $stub); - } - - /** - * Get the console command arguments. - * - * @return array - */ - protected function getArguments() - { - return array( - array('table', InputArgument::REQUIRED, 'The name of your users table.'), - ); - } - -} diff --git a/src/LaravelFacebookSdk/LaravelPersistentDataHandler.php b/src/LaravelFacebookSdk/LaravelPersistentDataHandler.php index 5dad363..b2ef650 100644 --- a/src/LaravelFacebookSdk/LaravelPersistentDataHandler.php +++ b/src/LaravelFacebookSdk/LaravelPersistentDataHandler.php @@ -1,21 +1,34 @@ session = $session; + } + /** * @inheritdoc */ public function get($key) { - return \Session::get(static::SESSION_PREFIX . $key); + return $this->session->get(static::SESSION_PREFIX . $key); } /** @@ -23,7 +36,6 @@ public function get($key) */ public function set($key, $value) { - \Session::put(static::SESSION_PREFIX . $key, $value); + $this->session->put(static::SESSION_PREFIX . $key, $value); } - } diff --git a/src/LaravelFacebookSdk/LaravelUrlDetectionHandler.php b/src/LaravelFacebookSdk/LaravelUrlDetectionHandler.php index 6385d1a..eb6ea65 100644 --- a/src/LaravelFacebookSdk/LaravelUrlDetectionHandler.php +++ b/src/LaravelFacebookSdk/LaravelUrlDetectionHandler.php @@ -1,16 +1,28 @@ url = $url; + } /** * @inheritdoc */ public function getCurrentUrl() { - return \Request::url(); + return $this->url->current(); } - } diff --git a/src/LaravelFacebookSdk/SyncableGraphNodeTrait.php b/src/LaravelFacebookSdk/SyncableGraphNodeTrait.php new file mode 100644 index 0000000..73cc37e --- /dev/null +++ b/src/LaravelFacebookSdk/SyncableGraphNodeTrait.php @@ -0,0 +1,102 @@ +asArray(); + } + + if (! isset($data['id'])) { + throw new \InvalidArgumentException('Graph node id is missing'); + } + + $attributes = [static::getGraphNodeKeyName() => $data['id']]; + + $graph_node = static::firstOrNewGraphNode($attributes); + + static::mapGraphNodeFieldNamesToDatabaseColumnNames($graph_node, $data); + + $graph_node->save(); + + return $graph_node; + } + + /** + * Like static::firstOrNew() but without mass assignment + * + * @param array $attributes + * + * @return Model + */ + public static function firstOrNewGraphNode(array $attributes) + { + if (is_null($facebook_object = static::firstByAttributes($attributes))) { + $facebook_object = new static(); + } + + return $facebook_object; + } + + /** + * Convert a Graph node field name to a database column name + * + * @param string $field + * + * @return string + */ + public static function fieldToColumnName($field) + { + $model_name = get_class(new static()); + if (property_exists($model_name, 'graph_node_field_aliases') + && isset(static::$graph_node_field_aliases[$field])) { + return static::$graph_node_field_aliases[$field]; + } + + return $field; + } + + /** + * Get db column name of primary Graph node key + * + * @return string + */ + public static function getGraphNodeKeyName() + { + return static::fieldToColumnName('id'); + } + + /** + * Map Graph-node field names to local database column name + * + * @param Model $object + * @param array $fields + */ + public static function mapGraphNodeFieldNamesToDatabaseColumnNames(Model $object, array $fields) + { + foreach ($fields as $field => $value) { + $object->{static::fieldToColumnName($field)} = $value; + } + } +} diff --git a/src/LaravelFacebookSdk/stubs/migration.stub b/src/LaravelFacebookSdk/stubs/migration.stub deleted file mode 100755 index b8e321d..0000000 --- a/src/LaravelFacebookSdk/stubs/migration.stub +++ /dev/null @@ -1,40 +0,0 @@ -bigInteger('facebook_user_id')->unsigned()->index(); - $table->string('access_token')->nullable(); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - Schema::table('facebook_user_table', function(Blueprint $table) - { - $table->dropColumn( - // Uncomment if the primary id in your you user table is different than the Facebook id - //'facebook_user_id', - 'access_token' - ); - }); - } - -} diff --git a/src/config/config.php b/src/config/laravel-facebook-sdk.php similarity index 55% rename from src/config/config.php rename to src/config/laravel-facebook-sdk.php index 4fea3aa..5fd7a4e 100644 --- a/src/config/config.php +++ b/src/config/laravel-facebook-sdk.php @@ -1,16 +1,25 @@ ':your_facebook_app_id', - 'app_secret' => ':your_facebook_app_secret', + 'facebook_config' => [ + 'app_id' => 'your_facebook_app_id', + 'app_secret' => 'your_facebook_app_secret', + 'default_graph_version' => 'v2.2', + //'enable_beta_mode' => true, + //'http_client_handler' => 'guzzle', + ], /* * The default list of permissions that are @@ -32,23 +41,5 @@ * The default endpoint that Facebook will redirect to after * an authentication attempt. */ - 'default_redirect_uri' => '/facebook/login', - - /* - * For a full list of locales supported by Facebook visit: - * - * https://www.facebook.com/translations/FacebookLocales.xml - */ - 'locale' => 'en_US', - - /* - * Allows you to customize the channel endpoint. Most - * configurations won't need to change this but if you do, - * and you're using the JavaScript SDK, make sure you also - * update the "channelUrl" option in "FB.init()". - * - * https://developers.facebook.com/blog/post/2011/08/02/how-to--optimize-social-plugin-performance/ - */ - 'channel_endpoint' => '/channel.html', - + 'default_redirect_uri' => '/facebook/callback', ]; diff --git a/src/routes.php b/src/routes.php deleted file mode 100755 index 052158f..0000000 --- a/src/routes.php +++ /dev/null @@ -1,13 +0,0 @@ -addYear(); - - return Response::view('laravel-facebook-sdk::channel') - ->header('Pragma', 'public') - ->header('Cache-Control', 'max-age='.$cache_expire->timestamp) - ->header('Expires', $cache_expire->toRFC1123String()); -}); diff --git a/src/views/channel.blade.php b/src/views/channel.blade.php deleted file mode 100644 index 6eea741..0000000 --- a/src/views/channel.blade.php +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/tests/LaravelFacebookSdkTest.php b/tests/LaravelFacebookSdkTest.php index c1135e2..6a6946f 100644 --- a/tests/LaravelFacebookSdkTest.php +++ b/tests/LaravelFacebookSdkTest.php @@ -1,16 +1,21 @@ -config_mock = m::mock('Illuminate\Config\Repository'); - $this->laravel_facebook_sdk = new LaravelFacebookSdk($this->config_mock, [ + $this->url_mock = m::mock('Illuminate\Routing\UrlGenerator'); + $this->laravel_facebook_sdk = new LaravelFacebookSdk($this->config_mock, $this->url_mock, [ 'app_id' => 'foo_id', 'app_secret' => 'foo_secret', 'persistent_data_handler' => 'memory', @@ -34,19 +40,20 @@ public function tearDown() /** @test */ public function when_no_arguments_are_passed_the_get_login_url_method_will_default_to_config() { - $this->config_mock - ->shouldReceive('get') - ->with('laravel-facebook-sdk::default_scope') + $this->url_mock + ->shouldReceive('to') + ->with('/foo') ->once() - ->andReturn(['foo', 'bar']); + ->andReturn('https://foohost/foo'); + $this->config_mock ->shouldReceive('get') - ->with('app.url') + ->with('laravel-facebook-sdk.default_scope') ->once() - ->andReturn('https://foohost'); + ->andReturn(['foo', 'bar']); $this->config_mock ->shouldReceive('get') - ->with('laravel-facebook-sdk::default_redirect_uri') + ->with('laravel-facebook-sdk.default_redirect_uri') ->once() ->andReturn('/foo'); @@ -59,6 +66,12 @@ public function when_no_arguments_are_passed_the_get_login_url_method_will_defau /** @test */ public function the_default_config_can_be_overwritten_by_passing_arguments_to_get_login_url() { + $this->url_mock + ->shouldReceive('to') + ->with('https://poop.fart/callback') + ->once() + ->andReturn('https://poop.fart/callback'); + $this->config_mock ->shouldReceive('get') ->never(); diff --git a/tests/FacebookableTraitTest.php b/tests/SyncableGraphNodeTraitTest.php similarity index 79% rename from tests/FacebookableTraitTest.php rename to tests/SyncableGraphNodeTraitTest.php index d8149ed..61cff19 100644 --- a/tests/FacebookableTraitTest.php +++ b/tests/SyncableGraphNodeTraitTest.php @@ -1,18 +1,19 @@ -faz = 'Baz'; $obj->email = 'me@me.com'; + return $obj; } @@ -24,22 +25,22 @@ public function save() class MyEmptyModel extends FakeModel { - use FacebookableTrait; + use SyncableGraphNodeTrait; - protected static $facebook_field_aliases = []; + protected static $graph_node_field_aliases = []; } class MyUserModel extends FakeModel { - use FacebookableTrait; + use SyncableGraphNodeTrait; - protected static $facebook_field_aliases = [ + protected static $graph_node_field_aliases = [ 'id' => 'facebook_id', 'foo' => 'faz', ]; } -class FacebookableTraitTest extends PHPUnit_Framework_TestCase +class FacebookableTraitTest extends \PHPUnit_Framework_TestCase { public function testFieldToColumnNameReturnsFieldNameWhenNoAliasPresent() { @@ -63,7 +64,7 @@ public function testCanGetDefaultFacebookObjectKeyName() { $my_empty_model = new MyEmptyModel(); - $facebook_object_key = $my_empty_model::getFacebookObjectKeyName(); + $facebook_object_key = $my_empty_model::getGraphNodeKeyName(); $this->assertEquals('id', $facebook_object_key); } @@ -72,7 +73,7 @@ public function testCanGetCustomFacebookObjectKey() { $my_user_model = new MyUserModel(); - $facebook_object_key = $my_user_model::getFacebookObjectKeyName(); + $facebook_object_key = $my_user_model::getGraphNodeKeyName(); $this->assertEquals('facebook_id', $facebook_object_key); } @@ -82,7 +83,7 @@ public function testCanRemapFacebookFieldsToDatabaseArray() $my_user_model = new MyUserModel(); $my_object = new FakeModel(); - $my_user_model::mapFacebookFieldsToObject($my_object, [ + $my_user_model::mapGraphNodeFieldNamesToDatabaseColumnNames($my_object, [ 'id' => '1234567890', 'foo' => 'My Foo', 'email' => 'foo@bar.com', @@ -96,7 +97,7 @@ public function testCanRemapFacebookFieldsToDatabaseArray() public function testFirstOrNewFacebookObjectCreatesNewStaticObjectWhenOneDoesNotExist() { $my_user_model = new MyUserModel(); - $my_object = $my_user_model::firstOrNewFacebookObject([ + $my_object = $my_user_model::firstOrNewGraphNode([ 'facebook_id' => '1234567890', ]); @@ -106,7 +107,7 @@ public function testFirstOrNewFacebookObjectCreatesNewStaticObjectWhenOneDoesNot public function testFirstOrNewFacebookObjectReturnsExistingObject() { $my_user_model = new MyUserModel(); - $my_object = $my_user_model::firstOrNewFacebookObject([ + $my_object = $my_user_model::firstOrNewGraphNode([ 'facebook_id' => '1', ]); @@ -117,7 +118,7 @@ public function testInsertsNewFacebookObjectDataIntoDatabase() { $my_user_model = new MyUserModel(); - $user_object = $my_user_model::createOrUpdateFacebookObject([ + $user_object = $my_user_model::createOrUpdateGraphNode([ 'id' => '1234567890', 'foo' => 'My Foo', 'email' => 'foo@bar.com', @@ -132,7 +133,7 @@ public function testUpdatesExistingFacebookObjectDataInDatabase() { $my_user_model = new MyUserModel(); - $user_object = $my_user_model::createOrUpdateFacebookObject([ + $user_object = $my_user_model::createOrUpdateGraphNode([ 'id' => '1', 'foo' => 'My Foo', 'email' => 'foo@bar.com',