From 83ee6743f4b8cbb45dfadf8a61b519b9d83c50cf Mon Sep 17 00:00:00 2001 From: Navneet Rai Date: Wed, 4 May 2016 00:02:22 +0530 Subject: [PATCH] Forked From Base Code --- LICENSE | 20 ++ README.md | 312 +++++++++++++++++++ composer.json | 32 ++ src/Classes/Items/SubmissionImageItem.php | 66 ++++ src/Classes/Items/SubmissionLinkItem.php | 51 +++ src/Classes/Items/SubmissionStatusItem.php | 40 +++ src/Classes/Items/SubmissionVideoItem.php | 76 +++++ src/Classes/SubmissionCredentials.php | 40 +++ src/Classes/SubmissionResult.php | 40 +++ src/Classes/SubmissionToken.php | 67 ++++ src/Classes/SubmissionUser.php | 48 +++ src/Contracts/Service.php | 84 +++++ src/Events/SubmissionCredentialsReceived.php | 25 ++ src/Exceptions/InvalidPrivilegeException.php | 9 + src/Exceptions/InvalidTokenException.php | 9 + src/Exceptions/InvalidUploadException.php | 31 ++ src/Exceptions/MissingTokenException.php | 9 + src/Exceptions/SubmissionException.php | 9 + src/Facades/Submission.php | 8 + src/Mocks/MockService.php | 50 +++ src/Services/AbstractService.php | 212 +++++++++++++ src/Services/Facebook.php | 250 +++++++++++++++ src/Services/Twitter.php | 197 ++++++++++++ src/Services/Youtube.php | 175 +++++++++++ src/SubmissionFactory.php | 100 ++++++ src/SubmissionServiceProvider.php | 43 +++ src/Submitter.php | 31 ++ src/resources/config/submission.php | 42 +++ test/SubmissionFactoryTest.php | 141 +++++++++ test/SubmissionTest.php | 49 +++ 30 files changed, 2266 insertions(+) create mode 100644 LICENSE create mode 100644 README.md create mode 100644 composer.json create mode 100644 src/Classes/Items/SubmissionImageItem.php create mode 100644 src/Classes/Items/SubmissionLinkItem.php create mode 100644 src/Classes/Items/SubmissionStatusItem.php create mode 100644 src/Classes/Items/SubmissionVideoItem.php create mode 100644 src/Classes/SubmissionCredentials.php create mode 100644 src/Classes/SubmissionResult.php create mode 100644 src/Classes/SubmissionToken.php create mode 100644 src/Classes/SubmissionUser.php create mode 100644 src/Contracts/Service.php create mode 100644 src/Events/SubmissionCredentialsReceived.php create mode 100644 src/Exceptions/InvalidPrivilegeException.php create mode 100644 src/Exceptions/InvalidTokenException.php create mode 100644 src/Exceptions/InvalidUploadException.php create mode 100644 src/Exceptions/MissingTokenException.php create mode 100644 src/Exceptions/SubmissionException.php create mode 100644 src/Facades/Submission.php create mode 100644 src/Mocks/MockService.php create mode 100644 src/Services/AbstractService.php create mode 100644 src/Services/Facebook.php create mode 100644 src/Services/Twitter.php create mode 100644 src/Services/Youtube.php create mode 100644 src/SubmissionFactory.php create mode 100644 src/SubmissionServiceProvider.php create mode 100644 src/Submitter.php create mode 100644 src/resources/config/submission.php create mode 100644 test/SubmissionFactoryTest.php create mode 100644 test/SubmissionTest.php diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..3c20223 --- /dev/null +++ b/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2016 navneetrai + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission 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. diff --git a/README.md b/README.md new file mode 100644 index 0000000..7516116 --- /dev/null +++ b/README.md @@ -0,0 +1,312 @@ +# Submission Billing for Laravel 5 + +[![Build Status](https://travis-ci.org/navneetrai/laravel-submitter.svg)](https://travis-ci.org/navneetrai/laravel-submitter) +[![Coverage Status](https://coveralls.io/repos/navneetrai/laravel-submitter/badge.svg)](https://coveralls.io/r/navneetrai/laravel-submitter) +[![Total Downloads](https://poser.pugx.org/navneetrai/laravel-submitter/downloads.svg)](https://packagist.org/packages/navneetrai/laravel-submitter) +[![Latest Stable Version](https://poser.pugx.org/navneetrai/laravel-submitter/v/stable.svg)](https://packagist.org/packages/navneetrai/laravel-submitter) +[![Latest Unstable Version](https://poser.pugx.org/navneetrai/laravel-submitter/v/unstable.svg)](https://packagist.org/packages/navneetrai/laravel-submitter) +[![License](https://poser.pugx.org/navneetrai/laravel-submitter/license.svg)](https://packagist.org/packages/navneetrai/laravel-submitter) + +laravel-submitter is a simple laravel 5 library for uploading media (videos and images) and adding status updates and website link to a user account on popular social sites like [Facebook](https://www.facebook.com), [Twitter](https://twitter.com) and [Youtube](https://youtube.com). + +This library also help in obtaining user authentication tokens which can be used for delayed submissions. + +--- + +- [Supported services](#supported-services) +- [Installation](#installation) +- [Registering the Package](#registering-the-package) +- [Configuration](#configuration) +- [Usage](#usage) + +## Supported services + +The library supports [Facebook](https://www.facebook.com), [Twitter](https://twitter.com) and [Youtube](https://youtube.com). More services will be implemented soon. + +Included service implementations: + + - Facebook + - Twitter + - Youtube +- more to come! + + +## Installation + +Add laravel-submitter to your composer.json file: + +``` +"require": { + "navneetrai/laravel-submitter": "^1.0" +} +``` + +Use composer to install this package. + +``` +$ composer update +``` + +### Registering the Package + +Register the service provider within the ```providers``` array found in ```config/app.php```: + +```php +'providers' => [ + // ... + + Userdesk\Submission\SubmissionServiceProvider::class, +] +``` + +Add an alias within the ```aliases``` array found in ```config/app.php```: + + +```php +'aliases' => [ + // ... + + 'Submission' => Userdesk\Submission\Facades\Submission::class, +] +``` + +## Configuration + +There are two ways to configure laravel-submitter. + +#### Option 1 + +Create configuration file for package using artisan command + +``` +$ php artisan vendor:publish --provider="Userdesk\Submission\SubmissionServiceProvider" +``` + +#### Option 2 + +Create configuration file manually in config directory ``config/subscription.php`` and put there code from below. + +```php + [ + + 'facebook' => [ + 'client_id' => '', + 'client_secret' => '', + 'scope' => ['email', 'public_profile', 'publish_actions'], + ], + + 'twitter' => [ + 'client_id' => '', + 'client_secret' => '', + // No scope - oauth1 doesn't need scope + ], + + 'youtube' => [ + 'client_id' => '', + 'client_secret' => '', + 'scope' => [ + 'profile', 'email', + 'https://www.googleapis.com/auth/youtube', + 'https://www.googleapis.com/auth/youtube.upload', + 'https://www.googleapis.com/auth/youtube.readonly' + ], + ], + + ] + +]; +``` + +### Credentials + +Add your credentials to ``config/submission.php`` (depending on which option of configuration you choose) + + +## Usage + +### Basic usage + +Just follow the steps below and you will be able to get a submitter instance: + +```php +$submitter = Submission::submitter('twitter'); +``` + +#### Redirecting Users to Website for authentication + +To start the authentication process you can call the authenticate method of your submitter instance: + +```php +$submitter = Submission::submitter($website); +return $submitter->authenticate($state); +``` + +You should also pass an integer as ``$state`` to this method. This variable will act as a unique identifier for your request and you can use it later for storing user authentication token. + +You will get a Redirect Response which will take user to Website for Authentication. + +#### Completing Submission + +User authentication is an oauth based two-step process. Also the process for authentication differs from site to site. This package is designed to encapsulate these differences any provide a uniform interface across both Oauth 1 sites (like Twitter) and Oauth 2 sites (like Facebook) + +For this purpose you'll need to add a named route to your ``routes.php`` file in ``app\Http`` directory for authentication to automatically handle Oauth redirects. + +```php +Route::get('/any-base-url-of-your-liking/{website}/{state?}', ['as'=>'package.Userdesk.submission.authenticate', 'uses'=>'YourSubmissionController@authenticate']); +``` + +You can set redirection URL for each individual site as ``http://your-website-host.com/any-base-url-of-your-liking/website-name`` + +So, if we assume that your website host is ``http://www.example.com`` and you used ``authenticate`` as your base URL then in your Facebook developer profile you should set Redirection URL as ``http://www.example.com/authenticate/facebook`` + +This method called above will automatically redirect users, after authentication, to our named route. + +To complete the authentication process the ``authenticate`` function in ``YourSubmissionController`` should look like: + +```php +public function authenticate(Request $request, String $website, int $state = 0){ + $submitter = Submission::submitter($website); + $credentials = $submitter->completeAuthentication($request, $state); + + #####Fetch Information from Credentials Object + + $state = $credentials->getState(); + $user = $credentials->getUser(); + + $username = $user->getId(); + $info = $user->getProfile(); + + $token = $credentials->getToken(); + $tokenArray = $token->getTokenArray(); + + //You can now save tokenArray to your database for later use +} +``` + +#### Using Stored Token to Submit Videos + +You can use the token stored above to submit videos on the target website using this code: + +```php +$submitter = Submitter::submitter($website); + +try{ + $token = new SubmissionToken(); + $token->addTokenArray($tokenArray); + + $video = new SubmissionVideoItem($title, $description, $localThumb, $localVideo, $keywords); + + $submitter->addToken($token); + $result = $submitter->uploadVideo($video); + + $status = $result->getStaus(); + $url = $result->getUrl(); +}catch(Exception $e){ + +} +``` + +Keywords should be a comma separated string. Not all website uses keywords for Video Submission. + +Each website has its own policy for video uploads. Your video should confirm to website policy for upload to be successful. + +e.g. [For Twitter videos can't be longer than 30 seconds](https://dev.twitter.com/rest/media/uploading-media#videorecs) + + +#### Using Stored Token to Submit Images + +You can use the token stored above to submit images on the target website using this code: + +```php +$submitter = Submitter::submitter($website); + +try{ + $token = new SubmissionToken(); + $token->addTokenArray($tokenArray); + + $image = new SubmissionImageItem($title, $description, $localImage, $keywords); + + $submitter->addToken($token); + $result = $submitter->uploadImage($image); + + $status = $result->getStaus(); + $url = $result->getUrl(); +}catch(Exception $e){ + +} +``` +Keywords should be a comma separated string. Not all website uses keywords for Image Submission. + +Some websites like Youtube do not support image uploads. + +Each website has its own policy for image uploads. Your image should confirm to website policy for upload to be successful. + + +#### Using Stored Token to Submit Links + +You can use the token stored above to submit links on the target website using this code: + +```php +$submitter = Submitter::submitter($website); + +try{ + $token = new SubmissionToken(); + $token->addTokenArray($tokenArray); + + $link = new SubmissionLinkItem($title, $description, $link, $keywords); + + $submitter->addToken($token); + $result = $submitter->addLink($link); + + $status = $result->getStaus(); + $url = $result->getUrl(); +}catch(Exception $e){ + +} +``` +Keywords should be a comma separated string. Off the current websites only Facebook support link submission. + +Each website has its own policy for link submission. Your link should confirm to website policy for upload to be successful. + + +#### Using Stored Token to Add Status updates/Tweets + +You can use the token stored above to add status update/tweet on the target website using this code: + +```php +$submitter = Submitter::submitter($website); + +try{ + $token = new SubmissionToken(); + $token->addTokenArray($tokenArray); + + $update = new SubmissionStatusItem($title, $status, $keywords); + + $submitter->addToken($token); + $result = $submitter->addStatus($update); + + $status = $result->getStaus(); + $url = $result->getUrl(); +}catch(Exception $e){ + +} +``` + +Some websites like Youtube do not support status updates. + +Each website has its own policy for status updates. Your link should confirm to website policy for upload to be successful. + +e.g. Twitter needs status to be within 140 characters. \ No newline at end of file diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..108e37f --- /dev/null +++ b/composer.json @@ -0,0 +1,32 @@ +{ + "name": "navneetrai/laravel-submitter", + "type": "library", + "description": "Oauth based authenticator and file submitter for Laravel 5.2", + "keywords": ["laravel", "submitter", "submission", "facebook", "youtube", "twitter", "oauth"], + "homepage":"https://github.com/navneetrai/laravel-submitter", + "license": "MIT", + "authors": [ + { + "name": "Navneet Rai", + "email": "navneetrai@gmail.com" + } + ], + "require": { + "php": ">=5.4.0", + "google/apiclient": "1.1.*", + "facebook/php-sdk-v4": "^5.1", + "lusitanian/oauth": "~0.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.0", + "orchestra/testbench": "~3.2", + "mockery/mockery": "^0.9.4" + }, + "autoload": { + "psr-4": { + "Userdesk\\Submission\\": "src/", + "Userdesk\\Tests\\Submission\\": "tests/" + } + }, + "minimum-stability": "dev" +} \ No newline at end of file diff --git a/src/Classes/Items/SubmissionImageItem.php b/src/Classes/Items/SubmissionImageItem.php new file mode 100644 index 0000000..fdc1e1c --- /dev/null +++ b/src/Classes/Items/SubmissionImageItem.php @@ -0,0 +1,66 @@ +title = $title; + $this->description = $description; + $this->imagePath = $imagePath; + $this->keywords = $keywords; + } + + /** + * @return String + */ + public function getTitle() { + return $this->title; + } + + /** + * @return String + */ + public function getDescription() { + return $this->description; + } + + /** + * @return String + */ + public function getKeywords() { + return $this->keywords; + } + + /** + * @return String + */ + public function getImage() { + return $this->imagePath; + } + + /** + * @return String + */ + public function getType(){ + $pathinfo = pathinfo($this->imagePath); + $extension = strtolower($pathinfo['extension']); + + if(($extension == 'jpg')||($extension == 'jpeg')){ + return 'image/jpeg'; + }else if($extension == 'png'){ + return 'image/png'; + }else if($extension == 'gif'){ + return 'image/gif'; + } + } +} \ No newline at end of file diff --git a/src/Classes/Items/SubmissionLinkItem.php b/src/Classes/Items/SubmissionLinkItem.php new file mode 100644 index 0000000..cd804cc --- /dev/null +++ b/src/Classes/Items/SubmissionLinkItem.php @@ -0,0 +1,51 @@ +title = $title; + $this->description = $description; + $this->link = $link; + $this->keywords = $keywords; + } + + /** + * @return String + */ + public function getTitle() { + return $this->title; + } + + /** + * @return String + */ + public function getDescription() { + return $this->description; + } + + /** + * @return String + */ + public function getKeywords() { + return $this->keywords; + } + + /** + * @return String + */ + public function getLink() { + return $this->link; + } +} \ No newline at end of file diff --git a/src/Classes/Items/SubmissionStatusItem.php b/src/Classes/Items/SubmissionStatusItem.php new file mode 100644 index 0000000..0e6697c --- /dev/null +++ b/src/Classes/Items/SubmissionStatusItem.php @@ -0,0 +1,40 @@ +title = $title; + $this->status = $status; + $this->keywords = $keywords; + } + + /** + * @return String + */ + public function getTitle() { + return $this->title; + } + + /** + * @return String + */ + public function getStatus() { + return $this->status; + } + + /** + * @return String + */ + public function getKeywords() { + return $this->keywords; + } +} \ No newline at end of file diff --git a/src/Classes/Items/SubmissionVideoItem.php b/src/Classes/Items/SubmissionVideoItem.php new file mode 100644 index 0000000..91f2a42 --- /dev/null +++ b/src/Classes/Items/SubmissionVideoItem.php @@ -0,0 +1,76 @@ +title = $title; + $this->description = $description; + $this->thumbPath = $thumbPath; + $this->videoPath = $videoPath; + $this->keywords = $keywords; + } + + /** + * @return String + */ + public function getTitle() { + return $this->title; + } + + /** + * @return String + */ + public function getDescription() { + return $this->description; + } + + /** + * @return String + */ + public function getKeywords() { + return $this->keywords; + } + + /** + * @return String + */ + public function getThumb() { + return $this->thumbPath; + } + + /** + * @return String + */ + public function getVideo() { + return $this->videoPath; + } + + /** + * @return String + */ + public function getType(){ + $pathinfo = pathinfo($this->imagePath); + $extension = strtolower($pathinfo['extension']); + + if($extension == 'mp4'){ + return 'video/mp4'; + }else if($extension == 'avi'){ + return 'video/avi'; + }else if($extension == 'mov'){ + return 'video/quicktime'; + } + } +} \ No newline at end of file diff --git a/src/Classes/SubmissionCredentials.php b/src/Classes/SubmissionCredentials.php new file mode 100644 index 0000000..56b2fca --- /dev/null +++ b/src/Classes/SubmissionCredentials.php @@ -0,0 +1,40 @@ +state = $state; + $this->user = $user; + $this->token = $token; + } + + /** + * @return int + */ + public function getState() { + return $this->state; + } + + /** + * @return Userdesk\Submission\Classes\SubmissionUser + */ + public function getUser() { + return $this->user; + } + + /** + * @return Userdesk\Submission\Classes\SubmissionToken + */ + public function getToken() { + return $this->token; + } +} \ No newline at end of file diff --git a/src/Classes/SubmissionResult.php b/src/Classes/SubmissionResult.php new file mode 100644 index 0000000..7b54240 --- /dev/null +++ b/src/Classes/SubmissionResult.php @@ -0,0 +1,40 @@ +pass = $pass; + $this->url = $url; + $this->message = $message; + } + + /** + * @return boolean + */ + public function getStatus() { + return $this->pass?'Pass':'Fail'; + } + + /** + * @return String + */ + public function getUrl() { + return $this->url; + } + + /** + * @return String + */ + public function getMessage() { + return $this->message; + } +} \ No newline at end of file diff --git a/src/Classes/SubmissionToken.php b/src/Classes/SubmissionToken.php new file mode 100644 index 0000000..51c9632 --- /dev/null +++ b/src/Classes/SubmissionToken.php @@ -0,0 +1,67 @@ +token = $token; + $this->secret = $secret; + $this->accessToken = $accessToken; + $this->refreshToken = $refreshToken; + } + + /** + * @return String + */ + public function getToken() { + return $this->token; + } + + /** + * @return String + */ + public function getSecret() { + return $this->secret; + } + + /** + * @return String + */ + public function getAccessToken() { + return $this->accessToken; + } + + /** + * @return String + */ + public function getRefreshToken() { + return $this->refreshToken; + } + + /** + * @return array + */ + public function getTokenArray() { + return ['token'=> $this->getToken(), 'secret'=> $this->getSecret(), 'access_token'=> $this->getAccessToken(), 'refresh_token'=> $this->getRefreshToken()]; + } + + /** + * @param array + */ + public function addTokenArray(array $token) { + $this->token = array_get($token, 'token'); + $this->secret = array_get($token, 'secret'); + $this->accessToken = array_get($token, 'access_token'); + $this->refreshToken = array_get($token, 'refresh_token'); + } +} \ No newline at end of file diff --git a/src/Classes/SubmissionUser.php b/src/Classes/SubmissionUser.php new file mode 100644 index 0000000..8993387 --- /dev/null +++ b/src/Classes/SubmissionUser.php @@ -0,0 +1,48 @@ +id = $id; + $this->link = $link; + $this->profile = $profile; + } + + /** + * @return String + */ + public function getId() { + return $this->id; + } + + /** + * @return String + */ + public function getLink() { + return $this->link; + } + + /** + * @return array + */ + public function getProfile() { + $this->addProfileLink(); + return $this->profile; + } + + private function addProfileLink(){ + if(empty($this->profile['link'])){ + $this->profile['link'] = $this->link; + } + } +} \ No newline at end of file diff --git a/src/Contracts/Service.php b/src/Contracts/Service.php new file mode 100644 index 0000000..73b5dbb --- /dev/null +++ b/src/Contracts/Service.php @@ -0,0 +1,84 @@ +credentials = $credentials; + } +} diff --git a/src/Exceptions/InvalidPrivilegeException.php b/src/Exceptions/InvalidPrivilegeException.php new file mode 100644 index 0000000..8921a84 --- /dev/null +++ b/src/Exceptions/InvalidPrivilegeException.php @@ -0,0 +1,9 @@ +message = $message; + parent::__construct($message); + } + + /** + * Get the underlying response instance. + * + * @return string + */ + public function getMessage(){ + return $this->message; + } +} \ No newline at end of file diff --git a/src/Exceptions/MissingTokenException.php b/src/Exceptions/MissingTokenException.php new file mode 100644 index 0000000..c19f162 --- /dev/null +++ b/src/Exceptions/MissingTokenException.php @@ -0,0 +1,9 @@ +consumer('Mock', $this->config, $redirUrl); + } + + /** + * Get Authentication details. + * + * @param \Illuminate\Http\Request $request; + * @param int $state; + * + * @return \Userdesk\Submission\Classes\SubmissionCredentials; + */ + public function completeAuthentication(Request $request, int $state = 0){ + $user = new SubmissionUser('testUser', 'http://example.com', array()); + + $token = new SubmissionToken('test', 'best', '', ''); + + return new SubmissionCredentials($state, $user, $token); + } + + /** + * Redirect to Authentication URL. + * + * @param int $state; + * + * @return \Illuminate\Http\Response;; + */ + public function authenticate(int $state){ + $redirUrl = route('package.Userdesk.submission.authenticate', ['website'=>'mock', 'state'=>$state]); + return redirect($redirUrl); + } +} \ No newline at end of file diff --git a/src/Services/AbstractService.php b/src/Services/AbstractService.php new file mode 100644 index 0000000..421894d --- /dev/null +++ b/src/Services/AbstractService.php @@ -0,0 +1,212 @@ +config = $config; + + if (null === $serviceFactory) + { + // Create the service factory + $serviceFactory = new ServiceFactory(); + } + $this->serviceFactory = $serviceFactory; + } + + /** + * Add Submission Token to Service + * + * @param Userdesk\Submission\Classes\SubmissionToken $token + */ + public function addToken(SubmissionToken $token){ + $this->token = $token; + } + + /** + * Returs oauth provider name. + * + * @param String $redirUrl + * @return \OAuth\Common\Service\AbstractService + */ + abstract public function provider(String $redirUrl = ''); + + /** + * Get Authentication details. + * + * @param \Illuminate\Http\Request $request; + * @param int $state; + * + * @return \Userdesk\Submission\Classes\SubmissionCredentials; + */ + abstract public function completeAuthentication(Request $request, int $state = 0); + + /** + * Redirect to Authentication URL. + * + * @param int $state; + * + * @return \Illuminate\Http\Response;; + */ + abstract public function authenticate(int $state); + + /** + * Upload Video. + * + * @param \Userdesk\Submission\Classes\Items\SubmissionVideoItem $item; + * + * @return \Userdesk\Submission\Classes\SubmissionResult; + */ + public function uploadVideo(SubmissionVideoItem $item){ + throw new InvalidUploadException('This website do not support Video Uploads'); + } + + /** + * Upload Image. + * + * @param \Userdesk\Submission\Classes\Items\SubmissionImageItem $item; + * + * @return \Userdesk\Submission\Classes\SubmissionResult; + */ + public function uploadImage(SubmissionImageItem $item){ + throw new InvalidUploadException('This website do not support Image Uploads'); + } + + /** + * Update Status. + * + * @param \Userdesk\Submission\Classes\Items\SubmissionStatusItem $item; + * + * @return \Userdesk\Submission\Classes\SubmissionResult; + */ + public function addStatus(SubmissionStatusItem $item){ + throw new InvalidUploadException('This website do not support Status Updates'); + } + + /** + * Add Link. + * + * @param \Userdesk\Submission\Classes\Items\SubmissionLinkItem $item; + * + * @return \Userdesk\Submission\Classes\SubmissionResult; + */ + public function addLink(SubmissionLinkItem $item){ + throw new InvalidUploadException('This website do not support Link Addition'); + } + + /** + * Create storage instance + * + * @param string $storageName + * + * @return OAuth\Common\\Storage + */ + public function createStorageInstance($storageClass) + { + $storage = new $storageClass(); + return $storage; + } + + /** + * Set the http client object + * + * @param string $httpClientName + * + * @return void + */ + public function setHttpClient($httpClientName) + { + $httpClientClass = "\\OAuth\\Common\\Http\\Client\\$httpClientName"; + $this->serviceFactory->setHttpClient(new $httpClientClass()); + } + + /** + * @param string $service + * @param array $credentials + * @param string $url + * @param array $scope + * + * @return \OAuth\Common\Service\AbstractService + */ + protected function consumer($service, $credentials = array(), $url = null, $scope = null) { + + if(!empty($this->oauth)){ + return $this->oauth; + } + + $scope = array_get($credentials, "scope", []); + // get storage object + $storage = $this->createStorageInstance($this->storageClass); + + // return the service consumer object + $this->oauth = $this->serviceFactory->createService($service, $this->getCredentials($credentials, $url), $storage, $scope); + + return $this->oauth; + } + + /** + * @param array $credentials + * + * @return \OAuth\Common\Consumer\Credentials + */ + protected function getCredentials($credentials = array(), $url = null){ + $clientId = array_get($credentials, "client_id"); + $clientSecret = array_get($credentials, "client_secret"); + + return new Credentials( + $clientId, + $clientSecret, + $url ? : URL::current() + ); + } +} \ No newline at end of file diff --git a/src/Services/Facebook.php b/src/Services/Facebook.php new file mode 100644 index 0000000..986423a --- /dev/null +++ b/src/Services/Facebook.php @@ -0,0 +1,250 @@ +consumer('Facebook', $this->config, $redirUrl); + } + + /** + * Returns oauth provider object from saved token. + * + * @return \Facebook\Facebook + */ + public function providerFromToken(){ + if(empty($this->token)){ + throw new MissingTokenException('Token not Found'); + } + try{ + $config = array( + 'app_id' => array_get($this->config, 'client_id'), + 'app_secret' => array_get($this->config, 'client_secret'), + 'default_graph_version' => 'v2.6', + 'default_access_token' => $this->token->getAccessToken(), + ); + + return new \Facebook\Facebook($config); + }catch(Exception $e){ + throw new InvalidTokenException('Cannot verify saved token. User has either revoked the priveleges or created a new token.'); + } + } + + /** + * Upload Image. + * + * @param \Userdesk\Submission\Classes\SubmissionImageItem $item; + * + * @return \Userdesk\Submission\Classes\SubmissionResult; + */ + public function uploadImage(SubmissionImageItem $item){ + $facebook = $this->providerFromToken(); + + $params = array( + 'source' => $facebook->fileToUpload($item->getImage()) + 'title' => $item->getTitle(), + 'message' => $item->getDescription() + ); + + try { + $userId = $facebook->getUser(); + $response = $facebook->post('/'.$userId.'/videos', $params); + } catch(FacebookResponseException $e) { + throw new InvalidUploadException($e->getMessage()); + } catch(FacebookSDKException $e) { + throw new InvalidUploadException($e->getMessage()); + } catch(Exception$e) { + throw new InvalidUploadException($e->getMessage()); + } + + $graphNode = $response->getGraphNode(); + + if(!empty($graphNode['id'])){ + $url = "https://www.facebook.com/photo.php?v=".$graphNode['id']; + return new SubmissionResult(true, '', $url); + } + + return new SubmissionResult(false, 'Image Upload Failed'); + } + + + /** + * Upload Video. + * + * @param \Userdesk\Submission\Classes\SubmissionVideoItem $item; + * + * @return \Userdesk\Submission\Classes\SubmissionResult; + */ + public function uploadVideo(SubmissionVideoItem $item){ + $facebook = $this->providerFromToken(); + + $params = array( + 'content_category' => 'OTHER', + //'file_url' => $project->video, + 'source' => $facebook->videoToUpload($item->getVideo()), + 'title' => $item->getTitle(), + 'thumb' => $facebook->fileToUpload($item->getThumb()) + ); + + try { + $userId = $facebook->getUser(); + $response = $facebook->post('/'.$userId.'/videos', $params); + } catch(FacebookResponseException $e) { + throw new InvalidUploadException($e->getMessage()); + } catch(FacebookSDKException $e) { + throw new InvalidUploadException($e->getMessage()); + } catch(Exception$e) { + throw new InvalidUploadException($e->getMessage()); + } + + $graphNode = $response->getGraphNode(); + + if(!empty($graphNode['id'])){ + $url = "https://www.facebook.com/photo.php?v=".$graphNode['id']; + return new SubmissionResult(true, '', $url); + } + + return new SubmissionResult(false, 'Video Upload Failed'); + } + + /** + * Add Link. + * + * @param \Userdesk\Submission\Classes\SubmissionLinkItem $item; + * + * @return \Userdesk\Submission\Classes\SubmissionResult; + */ + public function addLink(SubmissionLinkItem $item){ + $facebook = $this->providerFromToken(); + + $params = array( + 'link' => $item->getLink(), + 'tags' => $item->getKeywords(), + 'message' => $item->getDescription() + ); + + try { + $userId = $facebook->getUser(); + $response = $facebook->post('/'.$userId.'/feed', $params); + } catch(FacebookResponseException $e) { + throw new InvalidUploadException($e->getMessage()); + } catch(FacebookSDKException $e) { + throw new InvalidUploadException($e->getMessage()); + } catch(Exception$e) { + throw new InvalidUploadException($e->getMessage()); + } + + $graphNode = $response->getGraphNode(); + + if(!empty($graphNode['id'])){ + $url = "https://www.facebook.com/photo.php?v=".$graphNode['id']; + return new SubmissionResult(true, '', $url); + } + + return new SubmissionResult(false, 'Link Update Failed'); + } + + /** + * Add Status. + * + * @param \Userdesk\Submission\Classes\SubmissionStatusItem $item; + * + * @return \Userdesk\Submission\Classes\SubmissionResult; + */ + public function (SubmissionStatusItem $item){ + $facebook = $this->providerFromToken(); + + $params = array( + 'tags' => $item->getKeywords(), + 'message' => $item->getStatus() + ); + + try { + $userId = $facebook->getUser(); + $response = $facebook->post('/'.$userId.'/feed', $params); + } catch(FacebookResponseException $e) { + throw new InvalidUploadException($e->getMessage()); + } catch(FacebookSDKException $e) { + throw new InvalidUploadException($e->getMessage()); + } catch(Exception$e) { + throw new InvalidUploadException($e->getMessage()); + } + + $graphNode = $response->getGraphNode(); + + if(!empty($graphNode['id'])){ + $url = "https://www.facebook.com/photo.php?v=".$graphNode['id']; + return new SubmissionResult(true, '', $url); + } + + return new SubmissionResult(false, 'Status Update Failed'); + } + + /** + * Get Authentication details. + * + * @param \Illuminate\Http\Request $request; + * @param int $state; + * + * @return \Userdesk\Submission\Classes\SubmissionCredentials; + */ + public function completeAuthentication(Request $request, int $state = 0){ + $code = $request->get('code'); + $fb = $this->provider(); + + if (!is_null($code)) { + $state = $request->get('state'); + $token = $fb->requestAccessToken($code); + $result = json_decode($fb->request('/me'), true); + if(!empty($result)){ + $link = sprintf('https://www.facebook.com/%s', $result['id']); + $user = new SubmissionUser($result['id'], $link, $result); + + $token = new SubmissionToken('', '', $token->getAccessToken(), ''); + + return new SubmissionCredentials($state, $user, $token); + } + throw new InvalidPrivilegeException('Cannot verify user information. please check that user has given proper priveleges.'); + }else{ + throw new InvalidTokenException('Cannot verify token. Please check config'); + } + } + + /** + * Redirect to Authentication URL. + * + * @param int $state; + * + * @return \Illuminate\Http\Response;; + */ + public function authenticate(int $state){ + $redirUrl = route('package.Userdesk.submission.authenticate', ['website'=>'facebook']); + $fb = $this->provider($redirUrl); + $url = $fb->getAuthorizationUri(['state'=>$state]); + return redirect((string)$url); + } +} \ No newline at end of file diff --git a/src/Services/Twitter.php b/src/Services/Twitter.php new file mode 100644 index 0000000..aa5545c --- /dev/null +++ b/src/Services/Twitter.php @@ -0,0 +1,197 @@ +consumer('Twitter', $this->config, $redirUrl); + } + + /** + * Returns oauth provider object from saved token. + * + * @return \OAuth\Common\Service\AbstractService + */ + public function providerFromToken(){ + if(empty($this->token)){ + throw new MissingTokenException('Token not Found'); + } + try{ + $tw = $this->provider(); + $storage = $tw->getStorage(); + + $oToken = new StdOAuth1Token($this->token->getToken()); + //$token->setAccessToken(); + $token->setAccessTokenSecret($this->token->getSecret()); + + $storage->storeAccessToken('Twitter', $oToken); + + return $tw; + }catch(TokenResponseException $e){ + throw new InvalidTokenException('Cannot verify saved token. User has either revoked the priveleges or created a new token.'); + } + + } + + /** + * Upload Video. + * + * @param \Userdesk\Submission\Classes\SubmissionVideoItem $item; + * + * @return \Userdesk\Submission\Classes\SubmissionResult; + */ + public function uploadVideo(SubmissionVideoItem $item){ + $tw = $this->providerFromToken(); + + $video = file_get_contents($item->getVideo()); + $media_data = $tw->request('https://upload.twitter.com/1.1/media/upload.json', 'POST', array('command'=>'INIT', 'total_bytes'=>strlen($video), 'media_type'=>$item->getType())); + $media = json_decode($media_data, true); + $media_id = $media['media_id']; + + if($media_id){ + $tw->request('https://upload.twitter.com/1.1/media/upload.json', 'POST', array('command'=>'APPEND', 'segment_index'=>0, 'media_id'=>$media_id, 'media_data'=>base64_encode($video))); + $tw->request('https://upload.twitter.com/1.1/media/upload.json', 'POST', array('command'=>'FINALIZE', 'media_id'=>$media_id)); + + $response = $tw->request('statuses/update.json', 'POST', array('status' => $item->getTitle(), 'media_ids'=>$media_id)); + + $status = json_decode($response, true); + + if(!empty($status['id']) && !empty($status['user'])){ + $url = sprintf('https://twitter.com/%s/status/%s', $status['user']['screen_name'], $status['id']); + return new SubmissionResult(true, '', $url); + } + + return new SubmissionResult(false, 'Video Upload Failed'); + }else{ + throw new InvalidUploadException($e->getMessage()); + } + } + + /** + * Upload Image. + * + * @param \Userdesk\Submission\Classes\SubmissionImageItem $item; + * + * @return \Userdesk\Submission\Classes\SubmissionResult; + */ + public function uploadImage(SubmissionImageItem $item){ + $tw = $this->providerFromToken(); + + $image = file_get_contents($item->getImage()); + $media_data = $tw->request('https://upload.twitter.com/1.1/media/upload.json', 'POST', array('command'=>'INIT', 'total_bytes'=>strlen($image), 'media_type'=>$item->getType())); + $media = json_decode($media_data, true); + $media_id = $media['media_id']; + + if($media_id){ + $tw->request('https://upload.twitter.com/1.1/media/upload.json', 'POST', array('command'=>'APPEND', 'segment_index'=>0, 'media_id'=>$media_id, 'media_data'=>base64_encode($image))); + $tw->request('https://upload.twitter.com/1.1/media/upload.json', 'POST', array('command'=>'FINALIZE', 'media_id'=>$media_id)); + + $response = $tw->request('statuses/update.json', 'POST', array('status' => $item->getTitle(), 'media_ids'=>$media_id)); + + $status = json_decode($response, true); + + if(!empty($status['id']) && !empty($status['user'])){ + $url = sprintf('https://twitter.com/%s/status/%s', $status['user']['screen_name'], $status['id']); + return new SubmissionResult(true, '', $url); + } + + return new SubmissionResult(false, 'Image Upload Failed'); + }else{ + throw new InvalidUploadException($e->getMessage()); + } + } + + /** + * Add Status. + * + * @param \Userdesk\Submission\Classes\SubmissionStatusItem $item; + * + * @return \Userdesk\Submission\Classes\SubmissionResult; + */ + public function addStatus(SubmissionStatusItem $item) { + $tw = $this->providerFromToken(); + + $response = $tw->request('statuses/update.json', 'POST', array('status' => $item->getStatus())); + + $status = json_decode($response, true); + + if(!empty($status['id']) && !empty($status['user'])){ + $url = sprintf('https://twitter.com/%s/status/%s', $status['user']['screen_name'], $status['id']); + return new SubmissionResult(true, '', $url); + } + + return new SubmissionResult(false, 'status Update Failed'); + } + + /** + * Get Authentication details. + * + * @param \Illuminate\Http\Request $request; + * @param int $state; + * + * @return \Userdesk\Submission\Classes\SubmissionCredentials; + */ + public function completeAuthentication(Request $request, int $state = 0){ + $token = $request->get('oauth_token'); + $verify = $request->get('oauth_verifier'); + + $tw = $this->provider(); + + if (!is_null($token) && !is_null($verify)) { + $token = $tw->requestAccessToken($token, $verify); + $result = json_decode($tw->request('account/verify_credentials.json'), true); + if(!empty($result)){ + $link = sprintf('http://www.twitter.com/%s', $result['screen_name']); + $user = new SubmissionUser($result['id'], $link, $result); + + $token = new SubmissionToken($token->getAccessToken(), $token->getAccessTokenSecret(), '', ''); + + return new SubmissionCredentials($state, $user, $token); + } + throw new InvalidPrivilegeException('Cannot verify user information. please check that user has given proper priveleges.'); + }else{ + throw new InvalidTokenException('Cannot verify token. Please check config'); + } + } + + /** + * Redirect to Authentication URL. + * + * @param int $state; + * + * @return \Illuminate\Http\Response; + */ + public function authenticate(int $state){ + $redirUrl = route('package.Userdesk.submission.authenticate', ['website'=>'twitter', 'state'=>$state]); + + $tw = $this->provider($redirUrl); + + $reqToken = $tw->requestRequestToken(); + $url = $tw->getAuthorizationUri(['oauth_token' => $reqToken->getRequestToken()]); + return redirect((string)$url); + } +} \ No newline at end of file diff --git a/src/Services/Youtube.php b/src/Services/Youtube.php new file mode 100644 index 0000000..e9cfbdd --- /dev/null +++ b/src/Services/Youtube.php @@ -0,0 +1,175 @@ +consumer('Google', $this->config, $redirUrl); + } + + /** + * Returns oauth provider object from saved token. + * + * @return \Google_Client + */ + public function providerFromToken(){ + if(empty($this->token)){ + throw new MissingTokenException('Token not Found'); + } + try{ + $google = new \Google_Client (); + $google->setClientId (array_get($this->config, 'client_id')); + $google->setClientSecret (array_get($this->config, 'client_secret')); + $google->setScopes(array_get($this->config, 'scopes')); + $google->setAccessType ('offline'); + $redirUrl = route('package.Userdesk.submission.authenticate', ['website'=>'youtube']); + $google->setRedirectUri ($redirUrl ); + $google->refreshToken($this->token->getRefreshToken()); + + return $google; + }catch(Exception $e){ + throw new InvalidTokenException('Cannot verify saved token. User has either revoked the priveleges or created a new token.'); + } + + } + + /** + * Upload Video. + * + * @param \Userdesk\Submission\Classes\SubmissionVideoItem $item; + * + * @return \Userdesk\Submission\Classes\SubmissionResult; + */ + public function uploadVideo(SubmissionVideoItem $item){ + $google = $this->providerFromToken($token); + + try{ + $youtube = new \Google_Service_YouTube($google); + $videoPath = $item->getVideo(); + + if(!empty($videoPath)){ + // Create a snipet with title, description, tags and category id + $snippet = new \Google_Service_YouTube_VideoSnippet (); + $snippet->setTitle ($item->getTitle()); + $snippet->setDescription ($item->getDescription()); + $snippet->setTags (explode(',', $item->getKeywords())); + + // Numeric video category. See + // https://developers.google.com/youtube/v3/docs/videoCategories/list + $snippet->setCategoryId ("22"); + + $status = new \Google_Service_YouTube_VideoStatus(); + $status->privacyStatus = "public"; + + // Create a YouTube video with snippet and status + $video = new \Google_Service_YouTube_Video (); + $video->setSnippet ($snippet); + $video->setStatus ($status); + + // Size of each chunk of data in bytes. Setting it higher leads faster upload (less chunks, + // for reliable connections). Setting it lower leads better recovery (fine-grained chunks) + $chunkSizeBytes = 1 * 1024 * 1024; + + $google->setDefer(true); + + $insertRequest = $youtube->videos->insert("status,snippet", $video); + + // Create a MediaFileUpload with resumable uploads + $media = new \Google_Http_MediaFileUpload ($google, $insertRequest,'video/*', null, true, $chunkSizeBytes); + $media->setFileSize (filesize($videoPath)); + + // Create a video insert request + $uploadStatus = false; + + // Read file and upload chunk by chunk + $handle = fopen ($videoPath, "rb"); + + while (!$uploadStatus && !feof ($handle)) { + $chunk = fread ($handle, $chunkSizeBytes); + $uploadStatus = $media->nextChunk ($chunk); + } + + fclose ($handle); + + $google->setDefer(false); + + if(!empty($uploadStatus) && !empty($uploadStatus->id)){ + $url = "http://www.youtube.com/watch?v=".$uploadStatus->id; + return new SubmissionResult(true, '', $url); + } + + return new SubmissionResult(false, 'Video Upload Failed'); + } + } catch (\Google_ServiceException $e) { + throw new InvalidUploadException($e->getMessage()); + } catch (\Google_Exception $e) { + throw new InvalidUploadException($e->getMessage()); + } catch (Exception $e){ + throw new InvalidUploadException($e->getMessage()); + } + } + + /** + * Get Authentication details. + * + * @param \Illuminate\Http\Request $request; + * @param int $state; + * + * @return \Userdesk\Submission\Classes\SubmissionCredentials; + */ + public function completeAuthentication(Request $request, int $state = 0){ + $code = $request->get('code'); + $googleService = $this->provider(); + $googleService->setAccessType('offline'); + + if (!is_null($code)) { + $state = $request->get('state'); + $token = $googleService->requestAccessToken($code); + $result = json_decode($googleService->request('https://www.googleapis.com/oauth2/v1/userinfo'), true); + if(!empty($result)){ + $link = sprintf('https://plus.google.com/u/0/%s', $result['id']); + $user = new SubmissionUser($result['email'], $link, $result); + + $token = new SubmissionToken('', '', $token->getAccessToken(), $token->getRefreshToken()); + + return new SubmissionCredentials($state, $user, $token); + } + throw new InvalidPrivilegeException('Cannot verify user information. please check that user has given proper priveleges.'); + }else{ + throw new InvalidTokenException('Cannot verify token. Please check config'); + } + } + + /** + * Redirect to Authentication URL. + * + * @param int $state; + * + * @return \Illuminate\Http\Response;; + */ + public function authenticate(int $state){ + $redirUrl = route('package.Userdesk.submission.authenticate', ['website'=>'youtube']); + $googleService = $this->provider($redirUrl); + $googleService->setAccessType('offline'); + + $url = $googleService->getAuthorizationUri(['state'=>$state]); + return redirect((string)$url); + } +} \ No newline at end of file diff --git a/src/SubmissionFactory.php b/src/SubmissionFactory.php new file mode 100644 index 0000000..498a9fb --- /dev/null +++ b/src/SubmissionFactory.php @@ -0,0 +1,100 @@ +registerService($alias, 'Userdesk\\Submission\\Services\\'.$serviceName); + } + + /** + * Builds and returns submission services + * + * It will first try to build an submission service + * + * @param string $serviceName Name of service to create + * + * @return \Userdesk\Submission\Contracts\Service + */ + public function createService($serviceName){ + $config = Config::get(sprintf("submission.services.%s", $serviceName)); + + if(empty($config)){ + throw new SubmissionException(sprintf('No Config exists for Service %s.', $serviceName)); + } + + $fullyQualifiedServiceName = $this->getFullyQualifiedServiceName($serviceName); + if (class_exists($fullyQualifiedServiceName)) { + return $this->buildService($fullyQualifiedServiceName, $config); + } + + return null; + } + + /** + * Register a custom service to classname mapping. + * + * @param string $serviceName Name of the service + * @param string $className Class to instantiate + * + * @return SubmissionFactory + * + * @throws Exception If the class is nonexistent or does not implement a valid ServiceInterface + */ + public function registerService($serviceName, $className) { + if (!class_exists($className)) { + throw new SubmissionException(sprintf('Service class %s does not exist.', $className)); + } + $reflClass = new \ReflectionClass($className); + + if ($reflClass->implementsInterface('Userdesk\\Submission\\Contracts\\Service')) { + $this->serviceClassMap[ucfirst($serviceName)] = $className; + return $this; + } + + throw new SubmissionException(sprintf('Service class %s must implement ServiceInterface.', $className)); + } + + /** + * Gets the fully qualified name of the service + * + * @param string $serviceName The name of the service of which to get the fully qualified name + * + * @return string The fully qualified name of the service + */ + private function getFullyQualifiedServiceName($serviceName) { + $serviceName = ucfirst($serviceName); + if (isset($this->serviceClassMap[$serviceName])) { + return $this->serviceClassMap[$serviceName]; + } + return '\\Userdesk\\Submission\\Services\\' . $serviceName; + } + + /** + * Builds submission services + * + * @param string $serviceName The fully qualified service name + * + * @return SubmissionInterface + */ + private function buildService($serviceName, $config) { + return new $serviceName($config); + } +} \ No newline at end of file diff --git a/src/SubmissionServiceProvider.php b/src/SubmissionServiceProvider.php new file mode 100644 index 0000000..0efacc1 --- /dev/null +++ b/src/SubmissionServiceProvider.php @@ -0,0 +1,43 @@ +app->bind('submission', function(){ + return new Submitter; + }); + } + + /** + * Get the services provided by the provider. + * + * @return array + */ + public function provides(){ + return ['submission']; + } +} diff --git a/src/Submitter.php b/src/Submitter.php new file mode 100644 index 0000000..9d91144 --- /dev/null +++ b/src/Submitter.php @@ -0,0 +1,31 @@ +submissionFactory = $submissionFactory; + } + + /** + * @param string $service + * + * @return \Userdesk\Submission\Contracts\Service + */ + + public function submitter($service){ + return $this->submissionFactory->createService($service); + } +} \ No newline at end of file diff --git a/src/resources/config/submission.php b/src/resources/config/submission.php new file mode 100644 index 0000000..08e5c0a --- /dev/null +++ b/src/resources/config/submission.php @@ -0,0 +1,42 @@ + [ + + 'facebook' => [ + 'client_id' => '', + 'client_secret' => '', + 'scope' => ['email', 'public_profile', 'publish_actions'], + ], + + 'twitter' => [ + 'client_id' => '', + 'client_secret' => '', + // No scope - oauth1 doesn't need scope + ], + + 'youtube' => [ + 'client_id' => '', + 'client_secret' => '', + 'scope' => [ + 'profile', 'email', + 'https://www.googleapis.com/auth/youtube', + 'https://www.googleapis.com/auth/youtube.upload', + 'https://www.googleapis.com/auth/youtube.readonly' + ], + ], + + + ] + +]; \ No newline at end of file diff --git a/test/SubmissionFactoryTest.php b/test/SubmissionFactoryTest.php new file mode 100644 index 0000000..a127120 --- /dev/null +++ b/test/SubmissionFactoryTest.php @@ -0,0 +1,141 @@ +setExpectedException('\\toufee\Submission\Exceptions\SubmissionException'); + $factory = new SubmissionFactory(); + $service = $factory->createService('twitter'); + } + + /** + * @covers toufee\Submission\SubmissionFactory::createService + * @covers toufee\Submission\SubmissionFactory::fullyQualifiedServiceName + * @covers toufee\Submission\SubmissionFactory::buildService + */ + public function testCreateServiceNonExistentService() { + Config::set('submission.services.foo.email', 'test@best.com'); + + $factory = new SubmissionFactory(); + $service = $factory->createService('foo'); + + $this->assertNull($service); + } + + /** + * @covers toufee\Submission\SubmissionFactory::createService + * @covers toufee\Submission\SubmissionFactory::fullyQualifiedServiceName + * @covers toufee\Submission\SubmissionFactory::buildService + */ + public function testCreateServicePreLoaded(){ + Config::set('submission.services.twitter.client_id', 'test'); + Config::set('submission.services.twitter.client_secret', 'best'); + + $factory = new SubmissionFactory(); + $service = $factory->createService('twitter'); + + $this->assertInstanceOf('toufee\\Submission\\Services\\Twitter', $service); + } + + /** + * @covers toufee\Submission\SubmissionFactory::registerService + */ + public function testRegisterServiceThrowsExceptionIfNonExistentClass(){ + $this->setExpectedException('\\toufee\Submission\Exceptions\SubmissionException'); + $factory = new SubmissionFactory(); + $factory->registerService('foo', 'bar'); + } + + /** + * @covers toufee\Submission\SubmissionFactory::registerService + */ + public function testRegisterServiceThrowsExceptionIfClassNotFulfillsContract(){ + $this->setExpectedException('\\toufee\Submission\Exceptions\SubmissionException'); + $factory = new SubmissionFactory(); + $factory->registerService('foo', 'toufee\\Submission\\SubmissionFactory'); + } + + /** + * @covers toufee\Submission\SubmissionFactory::registerService + */ + public function testRegisterServiceSuccessIfClassFulfillsContract(){ + $factory = new SubmissionFactory(); + $this->assertInstanceOf( + 'toufee\\Submission\\SubmissionFactory', + $factory->registerService('foo', 'toufee\\Submission\\Mocks\\MockService') + ); + } + + /** + * @covers toufee\Submission\SubmissionFactory::registerServiceAlias + * @covers toufee\Submission\SubmissionFactory::registerService + */ + public function testRegisterServiceAlias(){ + Config::set('submission.services.twitter.client_id', 'test'); + Config::set('submission.services.twitter.client_secret', 'best'); + Config::set('submission.services.alias.client_id', 'test'); + Config::set('submission.services.alias.client_secret', 'best'); + + $factory = new SubmissionFactory(); + $service = $factory->createService('alias'); + + $this->assertNull($service); + + $factory->registerServiceAlias('twitter', 'alias'); + + $newService = $factory->createService('alias'); + + $this->assertInstanceOf('toufee\\Submission\\Services\\Twitter', $newService); + } + + /** + * @covers toufee\Submission\SubmissionFactory::createService + * @covers toufee\Submission\SubmissionFactory::fullyQualifiedServiceName + * @covers toufee\Submission\SubmissionFactory::registerService + * @covers toufee\Submission\SubmissionFactory::buildService + */ + public function testCreateServiceUserRegistered(){ + Config::set('submission.services.foo.email', 'test@best.com'); + + $factory = new SubmissionFactory(); + $service = $factory->createService('foo'); + + $this->assertNull($service); + + $factory->registerService('foo', 'toufee\Submission\Mocks\MockService'); + + $newService = $factory->createService('foo'); + + $this->assertInstanceOf('toufee\\Submission\\Contracts\\Service', $newService); + } + + /** + * @covers toufee\Submission\SubmissionFactory::createService + * @covers toufee\Submission\SubmissionFactory::fullyQualifiedServiceName + * @covers toufee\Submission\SubmissionFactory::registerService + * @covers toufee\Submission\SubmissionFactory::buildService + */ + public function testCreateServiceUserRegisteredOverridesPreLoaded(){ + Config::set('submission.services.twitter.client_id', 'test'); + Config::set('submission.services.twitter.client_secret', 'best'); + + $factory = new SubmissionFactory(); + $factory->registerService('twitter', 'toufee\Submission\Mocks\MockService'); + + $service = $factory->createService('twitter'); + + $this->assertInstanceOf('toufee\\Submission\\Mocks\\MockService', $service); + } +} diff --git a/test/SubmissionTest.php b/test/SubmissionTest.php new file mode 100644 index 0000000..9ff00b3 --- /dev/null +++ b/test/SubmissionTest.php @@ -0,0 +1,49 @@ + 'toufee\Submission\Facades\Submission' + ); + } + + /** + * @covers toufee\Submission\Submitter::submitter + */ + public function testCreateSubmitter() + { + Config::set('submission.services.twitter.client_id', 'test'); + Config::set('submission.services.twitter.client_secret', 'best'); + + $submissionFactory = Mockery::mock('toufee\Submission\SubmissionFactory[createService]'); + $submissionFactory->shouldReceive('createService')->passthru(); + + $submission = new Submitter($submissionFactory); + $submitter = $submission->submitter('twitter'); + $this->assertInstanceOf('toufee\Submission\Services\Twitter', $submitter); + } +}