diff --git a/.gitignore b/.gitignore index 0a84bbb..b3cda34 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ .settings .buildpath test/output/ -examples/example-config.json +examples/example-options.json .idea /composer.phar +test.php \ No newline at end of file diff --git a/AUTHORS.md b/AUTHORS.md index 34f2ee0..29226af 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -13,3 +13,5 @@ php-sparkpost is maintained by Message Systems. * Chris Wilson, [@yepher](https://github.com/yepher) * Maxim Dzhuliy, [@max-si-m](https://github.com/max-si-m) * [@chandon](https://github.com/chandon) +* Avi Goldman, [@avrahamgoldman](https://github.com/avrahamgoldman) +* Vincent Song, [@vwsong](https://github.com/vwsong) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1bc3c40..1bbdaf9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -26,7 +26,7 @@ Add composer install directory to $PATH `~/.composer/vendor/bin/` #### Install PHPUnit for Testing ``` -composer global require "phpunit/phpunit=4.3.*" +composer global require "phpunit/phpunit=4.8.*" ``` We recommend increasing PHP’s memory limit, by default it uses 128MB. We ran into some issues during local development without doing so. You can do this by editing your php.ini file and modifying `memory_limit`. We set ours to `memory_limit = 1024M`. diff --git a/README.md b/README.md index 3a8098f..932763c 100644 --- a/README.md +++ b/README.md @@ -7,9 +7,7 @@ [![Travis CI](https://travis-ci.org/SparkPost/php-sparkpost.svg?branch=master)](https://travis-ci.org/SparkPost/php-sparkpost) [![Coverage Status](https://coveralls.io/repos/SparkPost/php-sparkpost/badge.svg?branch=master&service=github)](https://coveralls.io/github/SparkPost/php-sparkpost?branch=master) [![Slack Status](http://slack.sparkpost.com/badge.svg)](http://slack.sparkpost.com) -The official PHP library for using [the SparkPost REST API](https://developers.sparkpost.com). - -**Note: We understand that the ivory-http-adapter we use in this library is deprecated in favor of httplug. We use Ivory internally to make it simple for you to use whatever HTTP library you want. The deprecation won't affect or limit our ongoing support of this PHP library.** +The official PHP library for using [the SparkPost REST API](https://developers.sparkpost.com/api/). Before using this library, you must have a valid API Key. To get an API Key, please log in to your SparkPost account and generate one in the Settings page. @@ -38,107 +36,204 @@ use SparkPost\SparkPost; Because of dependency collision, we have opted to use a request adapter rather than requiring a request library. This means that your application will need to pass in -a request adapter to the constructor of the SparkPost Library. We use the [Ivory HTTP Adapter] (https://github.com/egeloen/ivory-http-adapter) in SparkPost. Please visit their repo -for a list of supported adapters. If you don't currently use a request library, you will -need to require one and create an adapter from it and pass it along. The example below uses the -GuzzleHttp Client Library. +a request adapter to the constructor of the SparkPost Library. We use the [HTTPlug](https://github.com/php-http/httplug) in SparkPost. Please visit their repo for a list of supported adapters. If you don't currently use a request library, you will +need to require one and create an adapter from it and pass it along. The example below uses the GuzzleHttp Client Library. An Adapter can be setup like so: ```php +'YOUR API KEY']); +$httpClient = new GuzzleAdapter(new Client()); +$sparky = new SparkPost($httpClient, ['key'=>'YOUR_API_KEY']); +?> ``` -## Getting Started: Your First Mailing -For this example to work as is, [Guzzle 6 will need to be installed](http://docs.guzzlephp.org/en/latest/overview.html#installation). Otherwise another adapter can be used for your specific setup. See "Setting up a Request Adapter" above. - +## Initialization +#### new Sparkpost(httpClient, options) +* `httpClient` + * Required: Yes + * HTTP client or adapter supported by HTTPlug +* `options` + * Required: Yes + * Type: `String` or `Array` + * A valid Sparkpost API key or an array of options +* `options.key` + * Required: Yes + * Type: `String` + * A valid Sparkpost API key +* `options.host` + * Required: No + * Type: `String` + * Default: `api.sparkpost.com` +* `options.protocol` + * Required: No + * Type: `String` + * Default: `https` +* `options.port` + * Required: No + * Type: `Number` + * Default: 443 +* `options.version` + * Required: No + * Type: `String` + * Default: `v1` +* `options.timeout` + * Required: No + * Type: `Number` + * Default: `10` + + +## Methods +### request(method, uri [, payload [, headers]]) +* `method` + * Required: Yes + * Type: `String` + * HTTP method for request +* `uri` + * Required: Yes + * Type: `String` + * The URI to recieve the request +* `payload` + * Required: No + * Type: `Array` + * If the method is `GET` the values are encoded into the URL. Otherwise, if the method is `POST`, `PUT`, or `DELETE` the payload is used for the request body. +* `headers` + * Required: No + * Type: `Array` + * Custom headers to be sent with the request. + +### setHttpClient(httpClient) +* `httpClient` + * Required: Yes + * HTTP client or adapter supported by HTTPlug + +### setOptions(options) +* `options` + * Required: Yes + * Type: `Array` + * See initialization + + +## Endpoints +### transmissions +* **get([transmissionID] [, payload])** + * `transmissionID` - see `uri` request options + * `payload` - see request options +* **post(payload)** + * `payload` - see request options + * `payload.cc` + * Required: No + * Type: `Array` + * Recipients to recieve a carbon copy of the transmission + * `payload.bcc` + * Required: No + * Type: `Array` + * Recipients to descreetly recieve a carbon copy of the transmission +* **delete(transmissionID)** + * `transmissionID` - see `uri` request options + +## Examples + +### Send An Email Using The Transmissions Endpoint ```php -require 'vendor/autoload.php'; - +'YOUR API KEY']); +$httpClient = new GuzzleAdapter(new Client()); +$sparky = new SparkPost($httpClient, ['key'=>'YOUR_API_KEY']); -try { - // Build your email and send it! - $results = $sparky->transmission->send([ - 'from'=>[ - 'name' => 'From Envelope', - 'email' => 'from@sparkpostbox.com>' +$promise = $sparky->transmissions->post([ + 'content' => [ + 'from'=> [ + 'name' => 'Sparkpost Team', + 'email' => 'from@sparkpostbox.com' ], - 'html'=>'

Congratulations, {{name}}!

You just sent your very first mailing!

', - 'text'=>'Congratulations, {{name}}!! You just sent your very first mailing!', - 'substitutionData'=>['name'=>'YOUR FIRST NAME'], 'subject'=>'First Mailing From PHP', - 'recipients'=>[ - [ - 'address'=>[ - 'name'=>'YOUR FULL NAME', - 'email'=>'YOUR EMAIL ADDRESS' - ] - ] - ] - ]); - echo 'Woohoo! You just sent your first mailing!'; -} catch (\Exception $err) { - echo 'Whoops! Something went wrong'; - var_dump($err); + 'html'=>'

Congratulations, {{name}}!

You just sent your very first mailing!

', + 'text'=>'Congratulations, {{name}}!! You just sent your very first mailing!' + ], + 'substitution_data'=> ['name'=>'YOUR_FIRST_NAME'], + 'recipients'=> [ + [ 'address' => '' ] + ], + 'bcc' => [ + ['address' => '' ] + ] +]); +?> +``` + +### Send An API Call Using The Base Request Function +We may not wrap every resource available in the SparkPost Client Library, for example the PHP Client Library does not wrap the Metrics resource. To allow you to use the full power of our API we created the `request` function which allows you to access the unwrapped resources. +```php +'YOUR_API_KEY']); + +$promise = $sparky->request('GET', 'metrics/ip-pools', [ + 'from' => '2015-12-01T08:00', + 'to' => '2014-12-01T09:00', + 'timezone' => 'America/New_York', + 'limit' => '5' +]); +?> +``` + + +## Handling Responses +The all API calls return a promise. You can wait for the promise to be fulfilled or you can handle it asynchronously. + +##### Wait (Synchronous) +```php +wait(); + echo $response->getStatusCode(); + echo $response->getBody(); +} catch (Exception $e) { + echo $e->getCode(); + echo $e->getMessage(); } +?> ``` -## Learn More -* For more detailed examples, check our examples: - * [Transmissions](https://github.com/SparkPost/php-sparkpost/tree/master/examples/transmission) -* Read our REST API documentation - - -## Field Descriptions -### Transmissions -| Field Name | Required? | Description | Data Type | -| ------------ | ----------- | ------------- | ----------- | -| attachments | no | Field for attaching files - see Attachment Attributes in the [Transmssions API docs](https://developers.sparkpost.com/api/#/reference/transmissions) | Array of Objects | -| campaign | no | Field for assigning a given transmission to a specific campaign, which is a logical container for similar transmissions | String | -| customHeaders | no | Field for specifying additional headers to be applied to a given transmission (other than Subject, From, To, and Reply-To) | Object (Simple) | -| description | no | Field for describing what this transmission is for the user | String | -| from | yes** | Field for setting the from line of a given transmission | Object | -| html | yes** | Field for setting the HTML content of a given transmission | String | -| inlineCss | no | Field for enabling/disabling CSS inlining | Boolean | -| inlineImages | no | Field for providing inline images - see Inline Image Attributes in the [Transmssions API docs](https://developers.sparkpost.com/api/#/reference/transmissions) | Array of Objects | -| metadata | no | Field for adding arbitrary key/value pairs which will be included in open/click tracking | Object (Simple) | -| recipientList | no** | Field for specifying a stored recipient list ID to be used for a given transmission | String | -| recipients | yes** | Field for specifying who a given transmission should be sent to | Array of Objects | -| replyTo | no | Field for specifying the email address that should be used when a recipient hits the reply button | String | -| rfc822 | no** | Field for setting the RFC-822 encoded content of a given transmission | String | -| subject | yes | Field for setting the subject line of a given transmission | String | -| substitutionData | no | Field for adding transmission level substitution data, which can be used in a variety of fields and in content | Object (Complex) | -| template | no** | Field for specifying the Template ID of a stored template to be used when sending a given transmission | String | -| text | yes** | Field for setting the Plain Text content of a given transmission | String | -| trackClicks | no | Field for enabling/disabling transmission level click tracking (default: true) | Boolean | -| trackOpens | no | Field for enabling/disabling transmission level open tracking (default: true) | Boolean | -| transactional | no | Field for marking email as transactional (default: false) | Boolean | -| useDraftTemplate | no | Field for allowing the sending of a transmission using a draft of a stored template (default: false) | Boolean | - -** - If using inline content then html or text are required. If using RFC-822 Inline Content, then rfc822 is required. If using a stored recipient list, then recipientList is required. If using a stored template, then template is required but from is not as the values from the template will be used. - -## Tips and Tricks -### General -* You _must_ provide at least an API key when instantiating the SparkPost Library - `[ 'key'=>'184ac5480cfdd2bb2859e4476d2e5b1d2bad079bf' ]` -* The library's features are namespaced under the various SparkPost API names. - -### Transmissions -* If you specify a stored recipient list and inline recipients in a Transmission, you will receive an error. -* If you specify HTML and/or Plain Text content and then provide RFC-822 encoded content, you will receive an error. - * RFC-822 content is not valid with any other content type. -* If you specify a stored template and also provide inline content via `html` or `text`, you will receive an error. -* By default, open and click tracking are enabled for a transmission. -* By default, a transmission will use the published version of a stored template. +##### Then (Asynchronous) +```php +then( + // Success callback + function ($response) { + echo $response->getStatusCode(); + echo $response->getBody(); + }, + // Failure callback + function (Exception $e) { + echo $e->getCode(); + echo $e->getMessage(); + } +); +?> +``` + +## Handling Exceptions +The promise will throw an exception if the server returns a status code of `400` or higher. + +### Exception +* **getCode()** + * Returns the response status code of `400` or higher +* **getMessage()** + * Returns the body of response as an `Array` + ### Contributing -See [contributing](https://github.com/SparkPost/php-sparkpost/blob/master/CONTRIBUTING.md). +See [contributing](https://github.com/SparkPost/php-sparkpost/blob/master/CONTRIBUTING.md). \ No newline at end of file diff --git a/composer.json b/composer.json index 4ad389e..d8b97fa 100644 --- a/composer.json +++ b/composer.json @@ -9,26 +9,26 @@ ], "minimum-stability": "stable", "scripts": { - "post-install-cmd": "if [ ! -f 'examples/example-config.json' ]; then echo '{\n\t\"api-key\":\"Your API Key\"\n}' >> examples/example-config.json; fi", - "post-update-cmd": "if [ ! -f 'examples/example-config.json' ]; then echo '{\n\t\"api-key\":\"Your API Key\"\n}' >> examples/example-config.json; fi", + "post-install-cmd": "if [ ! -f 'examples/example-options.json' ]; then echo '{\n\t\"key\":\"YOUR_API_KEY\"\n}' >> examples/example-options.json; fi", + "post-update-cmd": "if [ ! -f 'examples/example-options.json' ]; then echo '{\n\t\"key\":\"YOUR_API_KEY\"\n}' >> examples/example-options.json; fi", "test": "phpunit ./test/unit/", "fix-style": "php-cs-fixer fix ." }, "require": { "php": ">=5.5.0", - "egeloen/http-adapter": "*" + "php-http/client-implementation": "^1.0", + "guzzlehttp/psr7": "1.3.*" }, "require-dev": { - "phpunit/phpunit": "4.3.*", "guzzlehttp/guzzle": "6.*", + "php-http/guzzle6-adapter": "*", + "php-http/message": "*", "mockery/mockery": "^0.9.4", - "satooshi/php-coveralls": "dev-master", "fabpot/php-cs-fixer": "^1.11" }, "autoload": { "psr-4": { "SparkPost\\": "lib/SparkPost/", - "SparkPost\\SendGridCompatibility\\": "lib/SendGridCompatibility/", "SparkPost\\Test\\TestUtils\\": "test/unit/TestUtils/" } } diff --git a/composer.lock b/composer.lock index b1d62a9..9c5d64e 100644 --- a/composer.lock +++ b/composer.lock @@ -4,66 +4,45 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "b07df33073385ce325ea9ef15b5f0da9", - "content-hash": "c5283ab83042f99acd4dd5b012446822", + "hash": "7b514c4fd3556635eab6298f14e03c47", + "content-hash": "2a019c7c9fe0fa211dd763cb9c1bcd62", "packages": [ { - "name": "egeloen/http-adapter", - "version": "0.8.0", + "name": "guzzlehttp/guzzle", + "version": "6.2.0", "source": { "type": "git", - "url": "https://github.com/egeloen/ivory-http-adapter.git", - "reference": "9641f11487ec26b24c6bbcee4f267cf62f60b855" + "url": "https://github.com/guzzle/guzzle.git", + "reference": "d094e337976dff9d8e2424e8485872194e768662" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/egeloen/ivory-http-adapter/zipball/9641f11487ec26b24c6bbcee4f267cf62f60b855", - "reference": "9641f11487ec26b24c6bbcee4f267cf62f60b855", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/d094e337976dff9d8e2424e8485872194e768662", + "reference": "d094e337976dff9d8e2424e8485872194e768662", "shasum": "" }, "require": { - "php": ">=5.4.8", - "zendframework/zend-diactoros": "^1.1" + "guzzlehttp/promises": "~1.0", + "guzzlehttp/psr7": "~1.1", + "php": ">=5.5.0" }, "require-dev": { - "cakephp/cakephp": "^3.0.3", "ext-curl": "*", - "guzzle/guzzle": "^3.9.4@dev", - "guzzlehttp/guzzle": "^4.1.4|^5.0|^6.0", - "kriswallsmith/buzz": "^0.13", - "nategood/httpful": "^0.2.17", - "phpunit/phpunit": "^4.0", - "phpunit/phpunit-mock-objects": "dev-matcher-verify as 2.3.x-dev", - "psr/log": "^1.0", - "react/dns": "^0.4.1", - "react/http-client": "^0.4", - "satooshi/php-coveralls": "^0.6", - "symfony/event-dispatcher": "^2.0", - "zendframework/zend-http": "^2.3.4", - "zendframework/zendframework1": ">=1.12.9,<=1.12.14|^1.12.16" - }, - "suggest": { - "ext-curl": "Allows you to use the cURL adapter", - "ext-http": "Allows you to use the PECL adapter", - "guzzle/guzzle": "Allows you to use the Guzzle 3 adapter", - "guzzlehttp/guzzle": "Allows you to use the Guzzle 4 adapter", - "kriswallsmith/buzz": "Allows you to use the Buzz adapter", - "nategood/httpful": "Allows you to use the httpful adapter", - "psr/log": "Allows you to use the logger event subscriber", - "symfony/event-dispatcher": "Allows you to use the event lifecycle", - "symfony/stopwatch": "Allows you to use the stopwatch http adapter and event subscriber", - "zendframework/zend-http": "Allows you to use the Zend 2 adapter", - "zendframework/zendframework1": "Allows you to use the Zend 1 adapter" + "phpunit/phpunit": "~4.0", + "psr/log": "~1.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "0.8-dev" + "dev-master": "6.2-dev" } }, "autoload": { + "files": [ + "src/functions_include.php" + ], "psr-4": { - "Ivory\\HttpAdapter\\": "src/" + "GuzzleHttp\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -72,47 +51,57 @@ ], "authors": [ { - "name": "Eric GELOEN", - "email": "geloen.eric@gmail.com" + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" } ], - "description": "Issue HTTP request for PHP 5.3+.", + "description": "Guzzle is a PHP HTTP client library", + "homepage": "http://guzzlephp.org/", "keywords": [ + "client", + "curl", + "framework", "http", - "http-adapter", - "http-client", - "psr-7" + "http client", + "rest", + "web service" ], - "abandoned": "php-http/httplug", - "time": "2015-08-12 09:35:40" + "time": "2016-03-21 20:02:09" }, { - "name": "psr/http-message", - "version": "1.0", + "name": "guzzlehttp/promises", + "version": "1.2.0", "source": { "type": "git", - "url": "https://github.com/php-fig/http-message.git", - "reference": "85d63699f0dbedb190bbd4b0d2b9dc707ea4c298" + "url": "https://github.com/guzzle/promises.git", + "reference": "c10d860e2a9595f8883527fa0021c7da9e65f579" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/85d63699f0dbedb190bbd4b0d2b9dc707ea4c298", - "reference": "85d63699f0dbedb190bbd4b0d2b9dc707ea4c298", + "url": "https://api.github.com/repos/guzzle/promises/zipball/c10d860e2a9595f8883527fa0021c7da9e65f579", + "reference": "c10d860e2a9595f8883527fa0021c7da9e65f579", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": ">=5.5.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.0-dev" } }, "autoload": { "psr-4": { - "Psr\\Http\\Message\\": "src/" - } + "GuzzleHttp\\Promise\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -120,106 +109,111 @@ ], "authors": [ { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" } ], - "description": "Common interface for HTTP messages", + "description": "Guzzle promises library", "keywords": [ - "http", - "http-message", - "psr", - "psr-7", - "request", - "response" + "promise" ], - "time": "2015-05-04 20:22:00" + "time": "2016-05-18 16:56:05" }, { - "name": "zendframework/zend-diactoros", - "version": "1.3.3", + "name": "guzzlehttp/psr7", + "version": "1.3.0", "source": { "type": "git", - "url": "https://github.com/zendframework/zend-diactoros.git", - "reference": "4d54fde709664562eb63356f0250d527824d05de" + "url": "https://github.com/guzzle/psr7.git", + "reference": "31382fef2889136415751badebbd1cb022a4ed72" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zendframework/zend-diactoros/zipball/4d54fde709664562eb63356f0250d527824d05de", - "reference": "4d54fde709664562eb63356f0250d527824d05de", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/31382fef2889136415751badebbd1cb022a4ed72", + "reference": "31382fef2889136415751badebbd1cb022a4ed72", "shasum": "" }, "require": { - "php": ">=5.4", + "php": ">=5.4.0", "psr/http-message": "~1.0" }, "provide": { - "psr/http-message-implementation": "~1.0.0" + "psr/http-message-implementation": "1.0" }, "require-dev": { - "phpunit/phpunit": "~4.6", - "squizlabs/php_codesniffer": "^2.3.1" + "phpunit/phpunit": "~4.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.3-dev", - "dev-develop": "1.4-dev" + "dev-master": "1.0-dev" } }, "autoload": { "psr-4": { - "Zend\\Diactoros\\": "src/" - } + "GuzzleHttp\\Psr7\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-2-Clause" + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } ], - "description": "PSR HTTP Message implementations", - "homepage": "https://github.com/zendframework/zend-diactoros", + "description": "PSR-7 message implementation", "keywords": [ "http", - "psr", - "psr-7" + "message", + "stream", + "uri" ], - "time": "2016-01-04 21:37:32" - } - ], - "packages-dev": [ + "time": "2016-04-13 19:56:01" + }, { - "name": "doctrine/instantiator", - "version": "1.0.5", + "name": "php-http/guzzle6-adapter", + "version": "v1.1.1", "source": { "type": "git", - "url": "https://github.com/doctrine/instantiator.git", - "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" + "url": "https://github.com/php-http/guzzle6-adapter.git", + "reference": "a56941f9dc6110409cfcddc91546ee97039277ab" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", - "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", + "url": "https://api.github.com/repos/php-http/guzzle6-adapter/zipball/a56941f9dc6110409cfcddc91546ee97039277ab", + "reference": "a56941f9dc6110409cfcddc91546ee97039277ab", "shasum": "" }, "require": { - "php": ">=5.3,<8.0-DEV" + "guzzlehttp/guzzle": "^6.0", + "php": ">=5.5.0", + "php-http/httplug": "^1.0" + }, + "provide": { + "php-http/async-client-implementation": "1.0", + "php-http/client-implementation": "1.0" }, "require-dev": { - "athletic/athletic": "~0.1.8", - "ext-pdo": "*", - "ext-phar": "*", - "phpunit/phpunit": "~4.0", - "squizlabs/php_codesniffer": "~2.0" + "ext-curl": "*", + "php-http/adapter-integration-tests": "^0.4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.2-dev" } }, "autoload": { "psr-4": { - "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + "Http\\Adapter\\Guzzle6\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -228,54 +222,54 @@ ], "authors": [ { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com", - "homepage": "http://ocramius.github.com/" + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" + }, + { + "name": "David de Boer", + "email": "david@ddeboer.nl" } ], - "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "homepage": "https://github.com/doctrine/instantiator", + "description": "Guzzle 6 HTTP Adapter", + "homepage": "http://httplug.io", "keywords": [ - "constructor", - "instantiate" + "Guzzle", + "http" ], - "time": "2015-06-14 21:17:01" + "time": "2016-05-10 06:13:32" }, { - "name": "fabpot/php-cs-fixer", - "version": "v1.11.2", + "name": "php-http/httplug", + "version": "v1.0.0", "source": { "type": "git", - "url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git", - "reference": "41f70154642ec0f9ea9ea9c290943f3b5dfa76fc" + "url": "https://github.com/php-http/httplug.git", + "reference": "2061047ca53a08a6b8f52e997b2a76f386b397dd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/41f70154642ec0f9ea9ea9c290943f3b5dfa76fc", - "reference": "41f70154642ec0f9ea9ea9c290943f3b5dfa76fc", + "url": "https://api.github.com/repos/php-http/httplug/zipball/2061047ca53a08a6b8f52e997b2a76f386b397dd", + "reference": "2061047ca53a08a6b8f52e997b2a76f386b397dd", "shasum": "" }, "require": { - "ext-tokenizer": "*", - "php": ">=5.3.6", - "sebastian/diff": "~1.1", - "symfony/console": "~2.3|~3.0", - "symfony/event-dispatcher": "~2.1|~3.0", - "symfony/filesystem": "~2.1|~3.0", - "symfony/finder": "~2.1|~3.0", - "symfony/process": "~2.3|~3.0", - "symfony/stopwatch": "~2.5|~3.0" + "php": ">=5.4", + "php-http/promise": "^1.0", + "psr/http-message": "^1.0" }, "require-dev": { - "satooshi/php-coveralls": "0.7.*@dev" + "henrikbjorn/phpspec-code-coverage": "^1.0", + "phpspec/phpspec": "^2.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } }, - "bin": [ - "php-cs-fixer" - ], - "type": "application", "autoload": { "psr-4": { - "Symfony\\CS\\": "Symfony/CS/" + "Http\\Client\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -284,79 +278,49 @@ ], "authors": [ { - "name": "Dariusz Rumiński", - "email": "dariusz.ruminski@gmail.com" + "name": "Eric GELOEN", + "email": "geloen.eric@gmail.com" }, { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" } ], - "description": "A tool to automatically fix PHP code style", - "time": "2016-02-26 07:37:29" + "description": "HTTPlug, the HTTP client abstraction for PHP", + "homepage": "http://httplug.io", + "keywords": [ + "client", + "http" + ], + "time": "2016-01-26 14:34:50" }, { - "name": "guzzle/guzzle", - "version": "v3.8.1", + "name": "php-http/promise", + "version": "v1.0.0", "source": { "type": "git", - "url": "https://github.com/guzzle/guzzle.git", - "reference": "4de0618a01b34aa1c8c33a3f13f396dcd3882eba" + "url": "https://github.com/php-http/promise.git", + "reference": "dc494cdc9d7160b9a09bd5573272195242ce7980" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/4de0618a01b34aa1c8c33a3f13f396dcd3882eba", - "reference": "4de0618a01b34aa1c8c33a3f13f396dcd3882eba", + "url": "https://api.github.com/repos/php-http/promise/zipball/dc494cdc9d7160b9a09bd5573272195242ce7980", + "reference": "dc494cdc9d7160b9a09bd5573272195242ce7980", "shasum": "" }, - "require": { - "ext-curl": "*", - "php": ">=5.3.3", - "symfony/event-dispatcher": ">=2.1" - }, - "replace": { - "guzzle/batch": "self.version", - "guzzle/cache": "self.version", - "guzzle/common": "self.version", - "guzzle/http": "self.version", - "guzzle/inflection": "self.version", - "guzzle/iterator": "self.version", - "guzzle/log": "self.version", - "guzzle/parser": "self.version", - "guzzle/plugin": "self.version", - "guzzle/plugin-async": "self.version", - "guzzle/plugin-backoff": "self.version", - "guzzle/plugin-cache": "self.version", - "guzzle/plugin-cookie": "self.version", - "guzzle/plugin-curlauth": "self.version", - "guzzle/plugin-error-response": "self.version", - "guzzle/plugin-history": "self.version", - "guzzle/plugin-log": "self.version", - "guzzle/plugin-md5": "self.version", - "guzzle/plugin-mock": "self.version", - "guzzle/plugin-oauth": "self.version", - "guzzle/service": "self.version", - "guzzle/stream": "self.version" - }, "require-dev": { - "doctrine/cache": "*", - "monolog/monolog": "1.*", - "phpunit/phpunit": "3.7.*", - "psr/log": "1.0.*", - "symfony/class-loader": "*", - "zendframework/zend-cache": "<2.3", - "zendframework/zend-log": "<2.3" + "henrikbjorn/phpspec-code-coverage": "^1.0", + "phpspec/phpspec": "^2.4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.8-dev" + "dev-master": "1.1-dev" } }, "autoload": { - "psr-0": { - "Guzzle": "src/", - "Guzzle\\Tests": "tests/" + "psr-4": { + "Http\\Promise\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -365,64 +329,47 @@ ], "authors": [ { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" }, { - "name": "Guzzle Community", - "homepage": "https://github.com/guzzle/guzzle/contributors" + "name": "Joel Wurtz", + "email": "joel.wurtz@gmail.com" } ], - "description": "Guzzle is a PHP HTTP client library and framework for building RESTful web service clients", - "homepage": "http://guzzlephp.org/", + "description": "Promise used for asynchronous HTTP requests", + "homepage": "http://httplug.io", "keywords": [ - "client", - "curl", - "framework", - "http", - "http client", - "rest", - "web service" + "promise" ], - "time": "2014-01-28 22:29:15" + "time": "2016-01-26 13:27:02" }, { - "name": "guzzlehttp/guzzle", - "version": "6.1.0", + "name": "psr/http-message", + "version": "1.0", "source": { "type": "git", - "url": "https://github.com/guzzle/guzzle.git", - "reference": "66fd14b4d0b8f2389eaf37c5458608c7cb793a81" + "url": "https://github.com/php-fig/http-message.git", + "reference": "85d63699f0dbedb190bbd4b0d2b9dc707ea4c298" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/66fd14b4d0b8f2389eaf37c5458608c7cb793a81", - "reference": "66fd14b4d0b8f2389eaf37c5458608c7cb793a81", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/85d63699f0dbedb190bbd4b0d2b9dc707ea4c298", + "reference": "85d63699f0dbedb190bbd4b0d2b9dc707ea4c298", "shasum": "" }, "require": { - "guzzlehttp/promises": "~1.0", - "guzzlehttp/psr7": "~1.1", - "php": ">=5.5.0" - }, - "require-dev": { - "ext-curl": "*", - "phpunit/phpunit": "~4.0", - "psr/log": "~1.0" + "php": ">=5.3.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "6.1-dev" + "dev-master": "1.0.x-dev" } }, "autoload": { - "files": [ - "src/functions_include.php" - ], "psr-4": { - "GuzzleHttp\\": "src/" + "Psr\\Http\\Message\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -431,56 +378,47 @@ ], "authors": [ { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" } ], - "description": "Guzzle is a PHP HTTP client library", - "homepage": "http://guzzlephp.org/", + "description": "Common interface for HTTP messages", "keywords": [ - "client", - "curl", - "framework", "http", - "http client", - "rest", - "web service" + "http-message", + "psr", + "psr-7", + "request", + "response" ], - "time": "2015-09-08 17:36:26" - }, + "time": "2015-05-04 20:22:00" + } + ], + "packages-dev": [ { - "name": "guzzlehttp/promises", - "version": "1.0.3", + "name": "clue/stream-filter", + "version": "v1.3.0", "source": { "type": "git", - "url": "https://github.com/guzzle/promises.git", - "reference": "b1e1c0d55f8083c71eda2c28c12a228d708294ea" + "url": "https://github.com/clue/php-stream-filter.git", + "reference": "e3bf9415da163d9ad6701dccb407ed501ae69785" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/b1e1c0d55f8083c71eda2c28c12a228d708294ea", - "reference": "b1e1c0d55f8083c71eda2c28c12a228d708294ea", + "url": "https://api.github.com/repos/clue/php-stream-filter/zipball/e3bf9415da163d9ad6701dccb407ed501ae69785", + "reference": "e3bf9415da163d9ad6701dccb407ed501ae69785", "shasum": "" }, "require": { - "php": ">=5.5.0" - }, - "require-dev": { - "phpunit/phpunit": "~4.0" + "php": ">=5.3" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, "autoload": { "psr-4": { - "GuzzleHttp\\Promise\\": "src/" + "Clue\\StreamFilter\\": "src/" }, "files": [ - "src/functions_include.php" + "src/functions.php" ] }, "notification-url": "https://packagist.org/downloads/", @@ -489,863 +427,155 @@ ], "authors": [ { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - } - ], - "description": "Guzzle promises library", - "keywords": [ - "promise" - ], - "time": "2015-10-15 22:28:00" - }, - { - "name": "guzzlehttp/psr7", - "version": "1.2.3", - "source": { - "type": "git", - "url": "https://github.com/guzzle/psr7.git", - "reference": "2e89629ff057ebb49492ba08e6995d3a6a80021b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/2e89629ff057ebb49492ba08e6995d3a6a80021b", - "reference": "2e89629ff057ebb49492ba08e6995d3a6a80021b", - "shasum": "" - }, - "require": { - "php": ">=5.4.0", - "psr/http-message": "~1.0" - }, - "provide": { - "psr/http-message-implementation": "1.0" - }, - "require-dev": { - "phpunit/phpunit": "~4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "psr-4": { - "GuzzleHttp\\Psr7\\": "src/" - }, - "files": [ - "src/functions_include.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - } - ], - "description": "PSR-7 message implementation", - "keywords": [ - "http", - "message", - "stream", - "uri" - ], - "time": "2016-02-18 21:54:00" - }, - { - "name": "hamcrest/hamcrest-php", - "version": "v1.2.2", - "source": { - "type": "git", - "url": "https://github.com/hamcrest/hamcrest-php.git", - "reference": "b37020aa976fa52d3de9aa904aa2522dc518f79c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/hamcrest/hamcrest-php/zipball/b37020aa976fa52d3de9aa904aa2522dc518f79c", - "reference": "b37020aa976fa52d3de9aa904aa2522dc518f79c", - "shasum": "" - }, - "require": { - "php": ">=5.3.2" - }, - "replace": { - "cordoval/hamcrest-php": "*", - "davedevelopment/hamcrest-php": "*", - "kodova/hamcrest-php": "*" - }, - "require-dev": { - "phpunit/php-file-iterator": "1.3.3", - "satooshi/php-coveralls": "dev-master" - }, - "type": "library", - "autoload": { - "classmap": [ - "hamcrest" - ], - "files": [ - "hamcrest/Hamcrest.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD" - ], - "description": "This is the PHP port of Hamcrest Matchers", - "keywords": [ - "test" - ], - "time": "2015-05-11 14:41:42" - }, - { - "name": "mockery/mockery", - "version": "0.9.4", - "source": { - "type": "git", - "url": "https://github.com/padraic/mockery.git", - "reference": "70bba85e4aabc9449626651f48b9018ede04f86b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/padraic/mockery/zipball/70bba85e4aabc9449626651f48b9018ede04f86b", - "reference": "70bba85e4aabc9449626651f48b9018ede04f86b", - "shasum": "" - }, - "require": { - "hamcrest/hamcrest-php": "~1.1", - "lib-pcre": ">=7.0", - "php": ">=5.3.2" - }, - "require-dev": { - "phpunit/phpunit": "~4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "0.9.x-dev" - } - }, - "autoload": { - "psr-0": { - "Mockery": "library/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Pádraic Brady", - "email": "padraic.brady@gmail.com", - "homepage": "http://blog.astrumfutura.com" - }, - { - "name": "Dave Marshall", - "email": "dave.marshall@atstsolutions.co.uk", - "homepage": "http://davedevelopment.co.uk" - } - ], - "description": "Mockery is a simple yet flexible PHP mock object framework for use in unit testing with PHPUnit, PHPSpec or any other testing framework. Its core goal is to offer a test double framework with a succinct API capable of clearly defining all possible object operations and interactions using a human readable Domain Specific Language (DSL). Designed as a drop in alternative to PHPUnit's phpunit-mock-objects library, Mockery is easy to integrate with PHPUnit and can operate alongside phpunit-mock-objects without the World ending.", - "homepage": "http://github.com/padraic/mockery", - "keywords": [ - "BDD", - "TDD", - "library", - "mock", - "mock objects", - "mockery", - "stub", - "test", - "test double", - "testing" - ], - "time": "2015-04-02 19:54:00" - }, - { - "name": "phpunit/php-code-coverage", - "version": "2.2.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/eabf68b476ac7d0f73793aada060f1c1a9bf8979", - "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979", - "shasum": "" - }, - "require": { - "php": ">=5.3.3", - "phpunit/php-file-iterator": "~1.3", - "phpunit/php-text-template": "~1.2", - "phpunit/php-token-stream": "~1.3", - "sebastian/environment": "^1.3.2", - "sebastian/version": "~1.0" - }, - "require-dev": { - "ext-xdebug": ">=2.1.4", - "phpunit/phpunit": "~4" - }, - "suggest": { - "ext-dom": "*", - "ext-xdebug": ">=2.2.1", - "ext-xmlwriter": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.2.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", - "homepage": "https://github.com/sebastianbergmann/php-code-coverage", - "keywords": [ - "coverage", - "testing", - "xunit" - ], - "time": "2015-10-06 15:47:00" - }, - { - "name": "phpunit/php-file-iterator", - "version": "1.3.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "acd690379117b042d1c8af1fafd61bde001bf6bb" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/acd690379117b042d1c8af1fafd61bde001bf6bb", - "reference": "acd690379117b042d1c8af1fafd61bde001bf6bb", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "type": "library", - "autoload": { - "classmap": [ - "File/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "" - ], - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "FilterIterator implementation that filters files based on a list of suffixes.", - "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", - "keywords": [ - "filesystem", - "iterator" - ], - "time": "2013-10-10 15:34:57" - }, - { - "name": "phpunit/php-text-template", - "version": "1.2.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Simple template engine.", - "homepage": "https://github.com/sebastianbergmann/php-text-template/", - "keywords": [ - "template" - ], - "time": "2015-06-21 13:50:34" - }, - { - "name": "phpunit/php-timer", - "version": "1.0.7", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "3e82f4e9fc92665fafd9157568e4dcb01d014e5b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3e82f4e9fc92665fafd9157568e4dcb01d014e5b", - "reference": "3e82f4e9fc92665fafd9157568e4dcb01d014e5b", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "Utility class for timing", - "homepage": "https://github.com/sebastianbergmann/php-timer/", - "keywords": [ - "timer" - ], - "time": "2015-06-21 08:01:12" - }, - { - "name": "phpunit/php-token-stream", - "version": "1.4.8", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da", - "reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da", - "shasum": "" - }, - "require": { - "ext-tokenizer": "*", - "php": ">=5.3.3" - }, - "require-dev": { - "phpunit/phpunit": "~4.2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Wrapper around PHP's tokenizer extension.", - "homepage": "https://github.com/sebastianbergmann/php-token-stream/", - "keywords": [ - "tokenizer" - ], - "time": "2015-09-15 10:49:45" - }, - { - "name": "phpunit/phpunit", - "version": "4.3.5", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "2dab9d593997db4abcf58d0daf798eb4e9cecfe1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/2dab9d593997db4abcf58d0daf798eb4e9cecfe1", - "reference": "2dab9d593997db4abcf58d0daf798eb4e9cecfe1", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-json": "*", - "ext-pcre": "*", - "ext-reflection": "*", - "ext-spl": "*", - "php": ">=5.3.3", - "phpunit/php-code-coverage": "~2.0", - "phpunit/php-file-iterator": "~1.3.2", - "phpunit/php-text-template": "~1.2", - "phpunit/php-timer": "~1.0.2", - "phpunit/phpunit-mock-objects": "~2.3", - "sebastian/comparator": "~1.0", - "sebastian/diff": "~1.1", - "sebastian/environment": "~1.0", - "sebastian/exporter": "~1.0", - "sebastian/version": "~1.0", - "symfony/yaml": "~2.0" - }, - "suggest": { - "phpunit/php-invoker": "~1.1" - }, - "bin": [ - "phpunit" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.3.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "", - "../../symfony/yaml/" - ], - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "The PHP Unit Testing framework.", - "homepage": "http://www.phpunit.de/", - "keywords": [ - "phpunit", - "testing", - "xunit" - ], - "time": "2014-11-11 10:11:09" - }, - { - "name": "phpunit/phpunit-mock-objects", - "version": "2.3.8", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/ac8e7a3db35738d56ee9a76e78a4e03d97628983", - "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.0.2", - "php": ">=5.3.3", - "phpunit/php-text-template": "~1.2", - "sebastian/exporter": "~1.2" - }, - "require-dev": { - "phpunit/phpunit": "~4.4" - }, - "suggest": { - "ext-soap": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.3.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "Mock Object library for PHPUnit", - "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", - "keywords": [ - "mock", - "xunit" - ], - "time": "2015-10-02 06:51:40" - }, - { - "name": "psr/log", - "version": "1.0.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/fe0936ee26643249e916849d48e3a51d5f5e278b", - "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b", - "shasum": "" - }, - "type": "library", - "autoload": { - "psr-0": { - "Psr\\Log\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Common interface for logging libraries", - "keywords": [ - "log", - "psr", - "psr-3" - ], - "time": "2012-12-21 11:40:51" - }, - { - "name": "satooshi/php-coveralls", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/satooshi/php-coveralls.git", - "reference": "2fbf803803d179ab1082807308a67bbd5a760c70" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/satooshi/php-coveralls/zipball/50c60bb64054974f8ed7540ae6e75fd7981a5fd3", - "reference": "2fbf803803d179ab1082807308a67bbd5a760c70", - "shasum": "" - }, - "require": { - "ext-json": "*", - "ext-simplexml": "*", - "guzzle/guzzle": ">=2.7", - "php": ">=5.3", - "psr/log": "1.0.0", - "symfony/config": ">=2.0", - "symfony/console": ">=2.0", - "symfony/stopwatch": ">=2.2", - "symfony/yaml": ">=2.0" - }, - "require-dev": { - "apigen/apigen": "2.8.*@stable", - "pdepend/pdepend": "dev-master as 2.0.0", - "phpmd/phpmd": "dev-master", - "phpunit/php-invoker": ">=1.1.0,<1.2.0", - "phpunit/phpunit": "3.7.*@stable", - "sebastian/finder-facade": "dev-master", - "sebastian/phpcpd": "1.4.*@stable", - "squizlabs/php_codesniffer": "1.4.*@stable", - "theseer/fdomdocument": "dev-master" - }, - "suggest": { - "symfony/http-kernel": "Allows Symfony integration" - }, - "bin": [ - "composer/bin/coveralls" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "0.7-dev" - } - }, - "autoload": { - "psr-0": { - "Satooshi\\Component": "src/", - "Satooshi\\Bundle": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Kitamura Satoshi", - "email": "with.no.parachute@gmail.com", - "homepage": "https://www.facebook.com/satooshi.jp" - } - ], - "description": "PHP client library for Coveralls API", - "homepage": "https://github.com/satooshi/php-coveralls", - "keywords": [ - "ci", - "coverage", - "github", - "test" - ], - "time": "2014-11-11 15:35:34" - }, - { - "name": "sebastian/comparator", - "version": "1.2.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "937efb279bd37a375bcadf584dec0726f84dbf22" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/937efb279bd37a375bcadf584dec0726f84dbf22", - "reference": "937efb279bd37a375bcadf584dec0726f84dbf22", - "shasum": "" - }, - "require": { - "php": ">=5.3.3", - "sebastian/diff": "~1.2", - "sebastian/exporter": "~1.2" - }, - "require-dev": { - "phpunit/phpunit": "~4.4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.2.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "name": "Christian Lück", + "email": "christian@lueck.tv" } ], - "description": "Provides the functionality to compare PHP values for equality", - "homepage": "http://www.github.com/sebastianbergmann/comparator", + "description": "A simple and modern approach to stream filtering in PHP", + "homepage": "https://github.com/clue/php-stream-filter", "keywords": [ - "comparator", - "compare", - "equality" + "bucket brigade", + "callback", + "filter", + "php_user_filter", + "stream", + "stream_filter_append", + "stream_filter_register" ], - "time": "2015-07-26 15:48:44" + "time": "2015-11-08 23:41:30" }, { - "name": "sebastian/diff", - "version": "1.4.1", + "name": "fabpot/php-cs-fixer", + "version": "v1.11.4", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e" + "url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git", + "reference": "eeb280e909834603ffe03524dbe0066e77c83084" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/13edfd8706462032c2f52b4b862974dd46b71c9e", - "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e", + "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/eeb280e909834603ffe03524dbe0066e77c83084", + "reference": "eeb280e909834603ffe03524dbe0066e77c83084", "shasum": "" }, "require": { - "php": ">=5.3.3" + "ext-tokenizer": "*", + "php": ">=5.3.6", + "sebastian/diff": "~1.1", + "symfony/console": "~2.3|~3.0", + "symfony/event-dispatcher": "~2.1|~3.0", + "symfony/filesystem": "~2.1|~3.0", + "symfony/finder": "~2.1|~3.0", + "symfony/process": "~2.3|~3.0", + "symfony/stopwatch": "~2.5|~3.0" }, "require-dev": { - "phpunit/phpunit": "~4.8" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4-dev" - } + "satooshi/php-coveralls": "0.7.*@dev" }, + "bin": [ + "php-cs-fixer" + ], + "type": "application", "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "Symfony\\CS\\": "Symfony/CS/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" + "name": "Dariusz Rumiński", + "email": "dariusz.ruminski@gmail.com" }, { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" } ], - "description": "Diff implementation", - "homepage": "https://github.com/sebastianbergmann/diff", - "keywords": [ - "diff" - ], - "time": "2015-12-08 07:14:41" + "description": "A tool to automatically fix PHP code style", + "abandoned": "friendsofphp/php-cs-fixer", + "time": "2016-06-07 07:51:27" }, { - "name": "sebastian/environment", - "version": "1.3.5", + "name": "hamcrest/hamcrest-php", + "version": "v1.2.2", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "dc7a29032cf72b54f36dac15a1ca5b3a1b6029bf" + "url": "https://github.com/hamcrest/hamcrest-php.git", + "reference": "b37020aa976fa52d3de9aa904aa2522dc518f79c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/dc7a29032cf72b54f36dac15a1ca5b3a1b6029bf", - "reference": "dc7a29032cf72b54f36dac15a1ca5b3a1b6029bf", + "url": "https://api.github.com/repos/hamcrest/hamcrest-php/zipball/b37020aa976fa52d3de9aa904aa2522dc518f79c", + "reference": "b37020aa976fa52d3de9aa904aa2522dc518f79c", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.3.2" + }, + "replace": { + "cordoval/hamcrest-php": "*", + "davedevelopment/hamcrest-php": "*", + "kodova/hamcrest-php": "*" }, "require-dev": { - "phpunit/phpunit": "~4.4" + "phpunit/php-file-iterator": "1.3.3", + "satooshi/php-coveralls": "dev-master" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.3.x-dev" - } - }, "autoload": { "classmap": [ - "src/" + "hamcrest" + ], + "files": [ + "hamcrest/Hamcrest.php" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } + "BSD" ], - "description": "Provides functionality to handle HHVM/PHP environments", - "homepage": "http://www.github.com/sebastianbergmann/environment", + "description": "This is the PHP port of Hamcrest Matchers", "keywords": [ - "Xdebug", - "environment", - "hhvm" + "test" ], - "time": "2016-02-26 18:40:46" + "time": "2015-05-11 14:41:42" }, { - "name": "sebastian/exporter", - "version": "1.2.1", + "name": "mockery/mockery", + "version": "0.9.5", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "7ae5513327cb536431847bcc0c10edba2701064e" + "url": "https://github.com/padraic/mockery.git", + "reference": "4db079511a283e5aba1b3c2fb19037c645e70fc2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/7ae5513327cb536431847bcc0c10edba2701064e", - "reference": "7ae5513327cb536431847bcc0c10edba2701064e", + "url": "https://api.github.com/repos/padraic/mockery/zipball/4db079511a283e5aba1b3c2fb19037c645e70fc2", + "reference": "4db079511a283e5aba1b3c2fb19037c645e70fc2", "shasum": "" }, "require": { - "php": ">=5.3.3", - "sebastian/recursion-context": "~1.0" + "hamcrest/hamcrest-php": "~1.1", + "lib-pcre": ">=7.0", + "php": ">=5.3.2" }, "require-dev": { - "phpunit/phpunit": "~4.4" + "phpunit/phpunit": "~4.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.2.x-dev" + "dev-master": "0.9.x-dev" } }, "autoload": { - "classmap": [ - "src/" - ] + "psr-0": { + "Mockery": "library/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -1353,187 +583,212 @@ ], "authors": [ { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "name": "Pádraic Brady", + "email": "padraic.brady@gmail.com", + "homepage": "http://blog.astrumfutura.com" }, { - "name": "Adam Harvey", - "email": "aharvey@php.net" + "name": "Dave Marshall", + "email": "dave.marshall@atstsolutions.co.uk", + "homepage": "http://davedevelopment.co.uk" } ], - "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "http://www.github.com/sebastianbergmann/exporter", + "description": "Mockery is a simple yet flexible PHP mock object framework for use in unit testing with PHPUnit, PHPSpec or any other testing framework. Its core goal is to offer a test double framework with a succinct API capable of clearly defining all possible object operations and interactions using a human readable Domain Specific Language (DSL). Designed as a drop in alternative to PHPUnit's phpunit-mock-objects library, Mockery is easy to integrate with PHPUnit and can operate alongside phpunit-mock-objects without the World ending.", + "homepage": "http://github.com/padraic/mockery", "keywords": [ - "export", - "exporter" + "BDD", + "TDD", + "library", + "mock", + "mock objects", + "mockery", + "stub", + "test", + "test double", + "testing" ], - "time": "2015-06-21 07:55:53" + "time": "2016-05-22 21:52:33" }, { - "name": "sebastian/recursion-context", - "version": "1.0.2", + "name": "php-http/message", + "version": "v1.2.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "913401df809e99e4f47b27cdd781f4a258d58791" + "url": "https://github.com/php-http/message.git", + "reference": "c8fadec9533f5e34a8a730a947fa76363f3aa620" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/913401df809e99e4f47b27cdd781f4a258d58791", - "reference": "913401df809e99e4f47b27cdd781f4a258d58791", + "url": "https://api.github.com/repos/php-http/message/zipball/c8fadec9533f5e34a8a730a947fa76363f3aa620", + "reference": "c8fadec9533f5e34a8a730a947fa76363f3aa620", "shasum": "" }, "require": { - "php": ">=5.3.3" + "clue/stream-filter": "^1.3", + "php": ">=5.4", + "php-http/message-factory": "^1.0.2", + "psr/http-message": "^1.0" }, "require-dev": { - "phpunit/phpunit": "~4.4" + "coduo/phpspec-data-provider-extension": "^1.0", + "ext-zlib": "*", + "guzzlehttp/psr7": "^1.0", + "henrikbjorn/phpspec-code-coverage": "^1.0", + "phpspec/phpspec": "^2.4", + "zendframework/zend-diactoros": "^1.0" + }, + "suggest": { + "ext-zlib": "Used with compressor/decompressor streams", + "guzzlehttp/psr7": "Used with Guzzle PSR-7 Factories", + "zendframework/zend-diactoros": "Used with Diactoros Factories" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.3-dev" } }, "autoload": { - "classmap": [ - "src/" + "psr-4": { + "Http\\Message\\": "src/" + }, + "files": [ + "src/filters.php" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" } ], - "description": "Provides functionality to recursively process PHP variables", - "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "time": "2015-11-11 19:50:13" + "description": "HTTP Message related tools", + "homepage": "http://php-http.org", + "keywords": [ + "http", + "message", + "psr-7" + ], + "time": "2016-03-29 20:44:24" }, { - "name": "sebastian/version", - "version": "1.0.6", + "name": "php-http/message-factory", + "version": "v1.0.2", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/version.git", - "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6" + "url": "https://github.com/php-http/message-factory.git", + "reference": "a478cb11f66a6ac48d8954216cfed9aa06a501a1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", - "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", + "url": "https://api.github.com/repos/php-http/message-factory/zipball/a478cb11f66a6ac48d8954216cfed9aa06a501a1", + "reference": "a478cb11f66a6ac48d8954216cfed9aa06a501a1", "shasum": "" }, + "require": { + "php": ">=5.4", + "psr/http-message": "^1.0" + }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "Http\\Message\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" } ], - "description": "Library that helps with managing the version number of Git-hosted PHP projects", - "homepage": "https://github.com/sebastianbergmann/version", - "time": "2015-06-21 13:59:46" + "description": "Factory interfaces for PSR-7 HTTP Message", + "homepage": "http://php-http.org", + "keywords": [ + "factory", + "http", + "message", + "stream", + "uri" + ], + "time": "2015-12-19 14:08:53" }, { - "name": "symfony/config", - "version": "v3.0.3", + "name": "sebastian/diff", + "version": "1.4.1", "source": { "type": "git", - "url": "https://github.com/symfony/config.git", - "reference": "79a97025f7bf4bbf8352b5df1905aa136a531066" + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/79a97025f7bf4bbf8352b5df1905aa136a531066", - "reference": "79a97025f7bf4bbf8352b5df1905aa136a531066", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/13edfd8706462032c2f52b4b862974dd46b71c9e", + "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e", "shasum": "" }, "require": { - "php": ">=5.5.9", - "symfony/filesystem": "~2.8|~3.0" + "php": ">=5.3.3" }, - "suggest": { - "symfony/yaml": "To use the yaml reference dumper" + "require-dev": { + "phpunit/phpunit": "~4.8" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "1.4-dev" } }, "autoload": { - "psr-4": { - "Symfony\\Component\\Config\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" + "classmap": [ + "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" }, { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" } ], - "description": "Symfony Config Component", - "homepage": "https://symfony.com", - "time": "2016-02-23 15:16:06" + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff" + ], + "time": "2015-12-08 07:14:41" }, { "name": "symfony/console", - "version": "v3.0.3", + "version": "v3.1.0", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "2ed5e2706ce92313d120b8fe50d1063bcfd12e04" + "reference": "f62db5b8afec27073a4609b8c84b1f9936652259" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/2ed5e2706ce92313d120b8fe50d1063bcfd12e04", - "reference": "2ed5e2706ce92313d120b8fe50d1063bcfd12e04", + "url": "https://api.github.com/repos/symfony/console/zipball/f62db5b8afec27073a4609b8c84b1f9936652259", + "reference": "f62db5b8afec27073a4609b8c84b1f9936652259", "shasum": "" }, "require": { @@ -1553,7 +808,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "3.1-dev" } }, "autoload": { @@ -1580,20 +835,20 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2016-02-28 16:24:34" + "time": "2016-05-30 06:58:39" }, { "name": "symfony/event-dispatcher", - "version": "v3.0.3", + "version": "v3.1.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "4dd5df31a28c0f82b41cb1e1599b74b5dcdbdafa" + "reference": "0343b2cedd0edb26cdc791212a8eb645c406018b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/4dd5df31a28c0f82b41cb1e1599b74b5dcdbdafa", - "reference": "4dd5df31a28c0f82b41cb1e1599b74b5dcdbdafa", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/0343b2cedd0edb26cdc791212a8eb645c406018b", + "reference": "0343b2cedd0edb26cdc791212a8eb645c406018b", "shasum": "" }, "require": { @@ -1613,7 +868,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "3.1-dev" } }, "autoload": { @@ -1640,20 +895,20 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", - "time": "2016-01-27 05:14:46" + "time": "2016-04-12 18:27:47" }, { "name": "symfony/filesystem", - "version": "v3.0.3", + "version": "v3.1.0", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "23ae8f9648d0a7fe94a47c8e20e5bf37c489a451" + "reference": "5751e80d6f94b7c018f338a4a7be0b700d6f3058" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/23ae8f9648d0a7fe94a47c8e20e5bf37c489a451", - "reference": "23ae8f9648d0a7fe94a47c8e20e5bf37c489a451", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/5751e80d6f94b7c018f338a4a7be0b700d6f3058", + "reference": "5751e80d6f94b7c018f338a4a7be0b700d6f3058", "shasum": "" }, "require": { @@ -1662,7 +917,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "3.1-dev" } }, "autoload": { @@ -1689,20 +944,20 @@ ], "description": "Symfony Filesystem Component", "homepage": "https://symfony.com", - "time": "2016-02-23 15:16:06" + "time": "2016-04-12 18:27:47" }, { "name": "symfony/finder", - "version": "v3.0.3", + "version": "v3.1.0", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "623bda0abd9aa29e529c8e9c08b3b84171914723" + "reference": "40d17ed287bf51a2f884c4619ce8ff2a1c5cd219" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/623bda0abd9aa29e529c8e9c08b3b84171914723", - "reference": "623bda0abd9aa29e529c8e9c08b3b84171914723", + "url": "https://api.github.com/repos/symfony/finder/zipball/40d17ed287bf51a2f884c4619ce8ff2a1c5cd219", + "reference": "40d17ed287bf51a2f884c4619ce8ff2a1c5cd219", "shasum": "" }, "require": { @@ -1711,7 +966,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "3.1-dev" } }, "autoload": { @@ -1738,20 +993,20 @@ ], "description": "Symfony Finder Component", "homepage": "https://symfony.com", - "time": "2016-01-27 05:14:46" + "time": "2016-05-13 18:06:41" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.1.0", + "version": "v1.2.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "1289d16209491b584839022f29257ad859b8532d" + "reference": "dff51f72b0706335131b00a7f49606168c582594" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/1289d16209491b584839022f29257ad859b8532d", - "reference": "1289d16209491b584839022f29257ad859b8532d", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/dff51f72b0706335131b00a7f49606168c582594", + "reference": "dff51f72b0706335131b00a7f49606168c582594", "shasum": "" }, "require": { @@ -1763,7 +1018,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1-dev" + "dev-master": "1.2-dev" } }, "autoload": { @@ -1797,20 +1052,20 @@ "portable", "shim" ], - "time": "2016-01-20 09:13:37" + "time": "2016-05-18 14:26:46" }, { "name": "symfony/process", - "version": "v3.0.3", + "version": "v3.1.0", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "dfecef47506179db2501430e732adbf3793099c8" + "reference": "1574f3451b40fa9bbae518ef71d19a56f409cac0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/dfecef47506179db2501430e732adbf3793099c8", - "reference": "dfecef47506179db2501430e732adbf3793099c8", + "url": "https://api.github.com/repos/symfony/process/zipball/1574f3451b40fa9bbae518ef71d19a56f409cac0", + "reference": "1574f3451b40fa9bbae518ef71d19a56f409cac0", "shasum": "" }, "require": { @@ -1819,7 +1074,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "3.1-dev" } }, "autoload": { @@ -1846,20 +1101,20 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2016-02-02 13:44:19" + "time": "2016-04-12 19:11:33" }, { "name": "symfony/stopwatch", - "version": "v3.0.3", + "version": "v3.1.0", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", - "reference": "4a204804952ff267ace88cf499e0b4bb302a475e" + "reference": "4670f122fa32a4900003a6802f6b8575f3f0b17e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/4a204804952ff267ace88cf499e0b4bb302a475e", - "reference": "4a204804952ff267ace88cf499e0b4bb302a475e", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/4670f122fa32a4900003a6802f6b8575f3f0b17e", + "reference": "4670f122fa32a4900003a6802f6b8575f3f0b17e", "shasum": "" }, "require": { @@ -1868,7 +1123,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "3.1-dev" } }, "autoload": { @@ -1895,67 +1150,16 @@ ], "description": "Symfony Stopwatch Component", "homepage": "https://symfony.com", - "time": "2016-01-03 15:35:16" - }, - { - "name": "symfony/yaml", - "version": "v2.8.3", - "source": { - "type": "git", - "url": "https://github.com/symfony/yaml.git", - "reference": "2a4ee40acb880c56f29fb1b8886e7ffe94f3b995" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/2a4ee40acb880c56f29fb1b8886e7ffe94f3b995", - "reference": "2a4ee40acb880c56f29fb1b8886e7ffe94f3b995", - "shasum": "" - }, - "require": { - "php": ">=5.3.9" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.8-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\Yaml\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Yaml Component", - "homepage": "https://symfony.com", - "time": "2016-02-23 07:41:20" + "time": "2016-03-04 07:56:56" } ], "aliases": [], "minimum-stability": "stable", - "stability-flags": { - "satooshi/php-coveralls": 20 - }, + "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, "platform": { "php": ">=5.5.0" }, "platform-dev": [] -} +} \ No newline at end of file diff --git a/examples/bootstrap.php b/examples/bootstrap.php index 688d53e..1110ed3 100644 --- a/examples/bootstrap.php +++ b/examples/bootstrap.php @@ -1,3 +1,7 @@ $config['api-key']]); - -try { - $results = $sparky->transmission->delete('transmission-id'); - echo 'Transmission deleted!'; -} catch (\Exception $exception) { - echo $exception->getAPIMessage()."\n"; - echo $exception->getAPICode()."\n"; - echo $exception->getAPIDescription()."\n"; -} diff --git a/examples/transmission/get_all_transmissions.php b/examples/transmission/get_all_transmissions.php deleted file mode 100644 index c037b2d..0000000 --- a/examples/transmission/get_all_transmissions.php +++ /dev/null @@ -1,25 +0,0 @@ - $config['api-key']]); - -try { - $results = $sparky->transmission->all(); - echo 'Congrats! You got a list of all your transmissions from SparkPost!'; -} catch (\Exception $exception) { - echo $exception->getAPIMessage()."\n"; - echo $exception->getAPICode()."\n"; - echo $exception->getAPIDescription()."\n"; -} diff --git a/examples/transmission/get_transmission.php b/examples/transmission/get_transmission.php deleted file mode 100644 index 5d59740..0000000 --- a/examples/transmission/get_transmission.php +++ /dev/null @@ -1,25 +0,0 @@ - $config['api-key']]); - -try { - $results = $sparky->transmission->find('Your Transmission ID'); - echo 'Congrats! You retrieved your transmission from SparkPost!'; -} catch (\Exception $exception) { - echo $exception->getAPIMessage()."\n"; - echo $exception->getAPICode()."\n"; - echo $exception->getAPIDescription()."\n"; -} diff --git a/examples/transmission/rfc822.php b/examples/transmission/rfc822.php deleted file mode 100644 index df2b06b..0000000 --- a/examples/transmission/rfc822.php +++ /dev/null @@ -1,34 +0,0 @@ - $config['api-key']]); - -try { - $results = $sparky->transmission->send([ - 'recipients' => [ - [ - 'address' => [ - 'email' => 'john.doe@example.com', - ], - ], - ], - 'rfc822' => "Content-Type: text/plain\nFrom: From Envelope \nSubject: Example Email\n\nHello World", - ]); - echo 'Congrats! You sent an email using SparkPost!'; -} catch (\Exception $exception) { - echo $exception->getAPIMessage()."\n"; - echo $exception->getAPICode()."\n"; - echo $exception->getAPIDescription()."\n"; -} diff --git a/examples/transmission/send_transmission_all_fields.php b/examples/transmission/send_transmission_all_fields.php deleted file mode 100644 index 84dfa9b..0000000 --- a/examples/transmission/send_transmission_all_fields.php +++ /dev/null @@ -1,76 +0,0 @@ - $config['api-key'], 'timeout' => 0]]); - -$data = file_get_contents('/path/to/test.csv'); - -try { - $results = $sparky->transmission->send([ - 'campaign' => 'my-campaign', - 'metadata' => [ - 'sample_campaign' => true, - 'type' => 'these are custom fields', - ], - 'substitutionData' => [ - 'name' => 'Test Name', - ], - 'description' => 'my description', - 'replyTo' => 'reply@test.com', - 'customHeaders' => [ - 'X-Custom-Header' => 'Sample Custom Header', - ], - 'trackOpens' => false, - 'trackClicks' => false, - 'sandbox' => false, - 'inlineCss' => true, - 'transactional' => true, - 'startTime' => '2016-03-17T08:00:00-04:00', - 'from' => [ - 'name' => 'From Envelope', - 'email' => 'from@sparkpostbox.com', - ], - 'html' => '

Hello World! Your name is: {{name}}

', - 'text' => 'Hello World!', - 'subject' => 'Example Email: {{name}}', - 'recipients' => [ - [ - 'address' => [ - 'email' => 'john.doe@example.com', - ], - ], - ], - 'attachments' => [ - [ - 'type' => 'text/csv', - 'name' => 'testing.csv', - 'data' => base64_encode($data), - ], - ], - 'inlineImages' => [ - [ - 'type' => 'image/png', - 'name' => 'cid-name', - 'data' => base64_encode($data), - ], - ], - ]); - - echo 'Congrats! You sent an email using SparkPost!'; -} catch (\Exception $exception) { - echo $exception->getAPIMessage()."\n"; - echo $exception->getAPICode()."\n"; - echo $exception->getAPIDescription()."\n"; -} diff --git a/examples/transmission/send_with_bcc.php b/examples/transmission/send_with_bcc.php deleted file mode 100644 index ce67862..0000000 --- a/examples/transmission/send_with_bcc.php +++ /dev/null @@ -1,58 +0,0 @@ - $config['api-key']]); - -try { - $results = $sparky->transmission->send([ - 'from' => [ - 'name' => 'From Envelope', - 'email' => 'from@sparkpostbox.com', - ], - 'html' => '

An example email using bcc with SparkPost to the {{recipient_type}} recipient.

', - 'text' => 'An example email using bcc with SparkPost to the {{recipient_type}} recipient.', - 'subject' => 'Example email using bcc', - 'recipients' => [ - [ - 'address' => [ - 'name' => 'Original Recipient', - 'email' => 'original.recipient@example.com', - ], - 'substitution_data' => [ - 'recipient_type' => 'Original' - ] - ], - [ - 'address' => [ - 'email' => 'bcc.recipient@example.com', - 'header_to' => '"Original Recipient" ', - ], - 'substitution_data' => [ - 'recipient_type' => 'BCC' - ] - ], - ], - ]); - echo 'Congrats! You sent an email with bcc using SparkPost!'; -} catch (\Exception $exception) { - echo $exception->getAPIMessage()."\n"; - echo $exception->getAPICode()."\n"; - echo $exception->getAPIDescription()."\n"; -} diff --git a/examples/transmission/send_with_cc.php b/examples/transmission/send_with_cc.php deleted file mode 100644 index fa1d9e9..0000000 --- a/examples/transmission/send_with_cc.php +++ /dev/null @@ -1,62 +0,0 @@ - $config['api-key']]); - -try { - $results = $sparky->transmission->send([ - 'from' => [ - 'name' => 'From Envelope', - 'email' => 'from@sparkpostbox.com', - ], - 'html' => '

An example email using cc with SparkPost to the {{recipient_type}} recipient.

', - 'text' => 'An example email using cc with SparkPost to the {{recipient_type}} recipient.', - 'subject' => 'Example email using cc', - 'recipients' => [ - [ - 'address' => [ - 'name' => 'Original Recipient', - 'email' => 'original.recipient@example.com', - ], - 'substitution_data' => [ - 'recipient_type' => 'Original' - ] - ], - [ - 'address' => [ - 'name' => 'Carbon Copy Recipient', - 'email' => 'cc.recipient@example.com', - 'header_to' => '"Original Recipient" ', - ], - 'substitution_data' => [ - 'recipient_type' => 'CC' - ] - ], - ], - 'customHeaders' => [ - 'CC' => '"Carbon Copy Recipient" ' - ] - ]); - echo 'Congrats! You sent an email with cc using SparkPost!'; -} catch (\Exception $exception) { - echo $exception->getAPIMessage()."\n"; - echo $exception->getAPICode()."\n"; - echo $exception->getAPIDescription()."\n"; -} diff --git a/examples/transmission/simple_send.php b/examples/transmission/simple_send.php deleted file mode 100644 index 6bd0336..0000000 --- a/examples/transmission/simple_send.php +++ /dev/null @@ -1,40 +0,0 @@ - $config['api-key']]); - -try { - $results = $sparky->transmission->send([ - 'from' => [ - 'name' => 'From Envelope', - 'email' => 'from@sparkpostbox.com', - ], - 'html' => '

Hello World!

', - 'text' => 'Hello World!', - 'subject' => 'Example Email', - 'recipients' => [ - [ - 'address' => [ - 'email' => 'john.doe@example.com', - ], - ], - ], - ]); - echo 'Congrats! You sent an email using SparkPost!'; -} catch (\Exception $exception) { - echo $exception->getAPIMessage()."\n"; - echo $exception->getAPICode()."\n"; - echo $exception->getAPIDescription()."\n"; -} diff --git a/examples/transmission/stored_recipients_inline_content.php b/examples/transmission/stored_recipients_inline_content.php deleted file mode 100644 index 503908b..0000000 --- a/examples/transmission/stored_recipients_inline_content.php +++ /dev/null @@ -1,36 +0,0 @@ - $config['api-key']]); - -try { - $results = $sparky->transmission->send([ - 'campaign' => 'my-campaign', - 'from' => [ - 'name' => 'From Envelope', - 'email' => 'from@sparkpostbox.com', - ], - 'html' => '

Hello World! Your name is: {{name}}

', - 'text' => 'Hello World!', - 'subject' => 'Example Email: {{name}}', - 'recipientList' => 'Example List', - ]); - - echo 'Congrats! You sent an email using SparkPost!'; -} catch (\Exception $exception) { - echo $exception->getAPIMessage()."\n"; - echo $exception->getAPICode()."\n"; - echo $exception->getAPIDescription()."\n"; -} diff --git a/examples/transmission/stored_template_send.php b/examples/transmission/stored_template_send.php deleted file mode 100644 index 5ce48e4..0000000 --- a/examples/transmission/stored_template_send.php +++ /dev/null @@ -1,38 +0,0 @@ - $config['api-key']]); - -try { - $results = $sparky->transmission->send([ - 'from' => [ - 'name' => 'From Envelope', - 'email' => 'from@sparkpostbox.com', - ], - 'recipients' => [ - [ - 'address' => [ - 'email' => 'john.doe@example.com', - ], - ], - ], - 'template' => 'my-first-email', - ]); - echo 'Congrats! You sent an email using SparkPost!'; -} catch (\Exception $exception) { - echo $exception->getAPIMessage()."\n"; - echo $exception->getAPICode()."\n"; - echo $exception->getAPIDescription()."\n"; -} diff --git a/examples/transmissions/create_transmission.php b/examples/transmissions/create_transmission.php new file mode 100644 index 0000000..61478a8 --- /dev/null +++ b/examples/transmissions/create_transmission.php @@ -0,0 +1,46 @@ +transmissions->post([ + 'content' => [ + 'from' => [ + 'name' => 'SparkPost Team', + 'email' => 'from@sparkpostbox.com', + ], + 'subject' => 'First Mailing From PHP', + 'html' => '

Congratulations, {{name}}!

You just sent your very first mailing!

', + 'text' => 'Congratulations, {{name}}!! You just sent your very first mailing!', + ], + 'substitution_data' => ['name' => 'YOUR_FIRST_NAME'], + 'recipients' => [ + [ + 'address' => [ + 'name' => 'YOUR_NAME', + 'email' => 'YOUR_EMAIL', + ], + ], + ], +]); + +try { + $response = $promise->wait(); + echo $response->getStatusCode()."\n"; + print_r($response->getBody())."\n"; +} catch (\Exception $e) { + echo $e->getCode()."\n"; + echo $e->getMessage()."\n"; +} diff --git a/examples/transmissions/create_transmission_with_cc_and_bcc.php b/examples/transmissions/create_transmission_with_cc_and_bcc.php new file mode 100644 index 0000000..eab64b8 --- /dev/null +++ b/examples/transmissions/create_transmission_with_cc_and_bcc.php @@ -0,0 +1,62 @@ +transmissions->post([ + 'content' => [ + 'from' => [ + 'name' => 'SparkPost Team', + 'email' => 'from@sparkpostbox.com', + ], + 'subject' => 'First Mailing From PHP', + 'html' => '

Congratulations, {{name}}!

You just sent your very first mailing!

', + 'text' => 'Congratulations, {{name}}!! You just sent your very first mailing!', + ], + 'substitution_data' => ['name' => 'YOUR_FIRST_NAME'], + 'recipients' => [ + [ + 'address' => [ + 'name' => 'YOUR_NAME', + 'email' => 'YOUR_EMAIL', + ], + ], + ], + 'cc' => [ + [ + 'address' => [ + 'name' => 'ANOTHER_NAME', + 'email' => 'ANOTHER_EMAIL', + ], + ], + ], + 'bcc' => [ + [ + 'address' => [ + 'name' => 'AND_ANOTHER_NAME', + 'email' => 'AND_ANOTHER_EMAIL', + ], + ], + ], +]); + +try { + $response = $promise->wait(); + echo $response->getStatusCode()."\n"; + print_r($response->getBody())."\n"; +} catch (\Exception $e) { + echo $e->getCode()."\n"; + echo $e->getMessage()."\n"; +} diff --git a/examples/transmissions/delete_transmission.php b/examples/transmissions/delete_transmission.php new file mode 100644 index 0000000..ad0cc64 --- /dev/null +++ b/examples/transmissions/delete_transmission.php @@ -0,0 +1,27 @@ +transmissions->delete('TRANSMISSION_ID'); + +try { + $response = $promise->wait(); + echo $response->getStatusCode()."\n"; + print_r($response->getBody())."\n"; +} catch (\Exception $e) { + echo $e->getCode()."\n"; + echo $e->getMessage()."\n"; +} diff --git a/examples/transmissions/get_all_transmissions.php b/examples/transmissions/get_all_transmissions.php new file mode 100644 index 0000000..0b4eb7f --- /dev/null +++ b/examples/transmissions/get_all_transmissions.php @@ -0,0 +1,27 @@ +transmissions->get(); + +try { + $response = $promise->wait(); + echo $response->getStatusCode()."\n"; + print_r($response->getBody())."\n"; +} catch (\Exception $e) { + echo $e->getCode()."\n"; + echo $e->getMessage()."\n"; +} diff --git a/examples/unwrapped/create_template.php b/examples/unwrapped/create_template.php deleted file mode 100644 index 89523f1..0000000 --- a/examples/unwrapped/create_template.php +++ /dev/null @@ -1,35 +0,0 @@ - $config['api-key']]); - -try { - // define the endpoint - $sparky->setupUnwrapped('templates'); - - $templateConfig = [ - 'name' => 'Summer Sale!', - 'id' => 'summer-sale', - 'content' => [ - 'from' => 'from@sparkpostbox.com', - 'subject' => 'Summer deals', - 'html' => 'Check out these deals!', - ], - ]; - $results = $sparky->templates->create($templateConfig); - echo 'Congrats! You created a template using SparkPost!'; -} catch (\Exception $exception) { - echo $exception->getMessage(); -} diff --git a/examples/unwrapped/create_transmission.php b/examples/unwrapped/create_transmission.php deleted file mode 100644 index f19ee6e..0000000 --- a/examples/unwrapped/create_transmission.php +++ /dev/null @@ -1,47 +0,0 @@ - $config['api-key']]); - -try { - // define the endpoint - $sparky->setupUnwrapped('transmissions'); - - $message = [ - 'recipients' => [ - [ - 'address' => [ - 'email' => 'john.doe@example.com', - ] - ] - ], - 'content' => [ - 'from' => [ - 'name' => 'From Envelope', - 'email' => 'from@sparkpostbox.com', - ], - 'html' => '

Hello World!

', - 'text' => 'Hello World!', - 'subject' => 'Example Email' - ] - ]; - $results = $sparky->transmissions->create($message); - echo 'Congrats! You sent a message using SparkPost!'; -} catch (\Exception $exception) { - echo $exception->getAPIMessage()."\n"; - echo $exception->getAPICode()."\n"; - echo $exception->getAPIDescription()."\n"; -} - diff --git a/examples/unwrapped/get_webhooks.php b/examples/unwrapped/get_webhooks.php deleted file mode 100644 index 90f7a9c..0000000 --- a/examples/unwrapped/get_webhooks.php +++ /dev/null @@ -1,28 +0,0 @@ - $config['api-key']]); - -try { - $sparky->setupUnwrapped('webhooks'); - - $results = $sparky->webhooks->get(); - - echo 'Congrats! You got a list of all your webhooks from SparkPost!'; -} catch (\Exception $exception) { - echo $exception->getAPIMessage()."\n"; - echo $exception->getAPICode()."\n"; - echo $exception->getAPIDescription()."\n"; -} diff --git a/lib/SendGridCompatibility/Email.php b/lib/SendGridCompatibility/Email.php deleted file mode 100644 index 3ca2466..0000000 --- a/lib/SendGridCompatibility/Email.php +++ /dev/null @@ -1,259 +0,0 @@ -model = array(); - } - - /** - * adds addresses as recipients. - * - * @param string $address - * @param string $name optional - * - * @return $this - */ - public function addTo($address, $name = null) - { - if (!isset($this->model['recipients'])) { - $this->model['recipients'] = array(); - } - - if (isset($name)) { - $address = array('address' => array('email' => $address, 'name' => $name)); - } else { - $address = array('address' => array('email' => $address)); - } - - array_push($this->model['recipients'], $address); - - return $this; - } - - /** - * explicitly sets a list of addresses. - * - * @param array $addresses - * - * @return $this - */ - public function setTos(array $addresses) - { - $this->model['recipients'] = $addresses; - - return $this; - } - - /** - * sets the from address. - * - * @param string $address - * - * @return $this - */ - public function setFrom($address) - { - $this->model['from'] = array('email' => $address); - - return $this; - } - - /** - * Sets the name for the from address. - * - * @param string $name - * - * @return $this - * - * @throws \Exception - */ - public function setFromName($name) - { - if (!isset($this->model['from'])) { - throw new \Exception('Must set \'From\' prior to setting \'From Name\'.'); - } - $this->model['from']['name'] = $name; - - return $this; - } - - /** - * sets the reply to field. - * - * @param string $address - * - * @return $this - */ - public function setReplyTo($address) - { - $this->model['replyTo'] = $address; - - return $this; - } - - /** - * throws an error because bcc fields are not yet implemented. - * - * @throws \Exception - * - * @param string $address - * - * @return $this - */ - public function addBcc($address) - { - throw new \Exception('Adding bcc recipients is not yet supported, try adding them as a \'to\' address'); - } - - /** - * sets the subject header. - * - * @param string $subject - * - * @return $this - */ - public function setSubject($subject) - { - $this->model['subject'] = $subject; - - return $this; - } - - /** - * sets the text body. - * - * @param string $text - * - * @return $this - */ - public function setText($text) - { - $this->model['text'] = $text; - - return $this; - } - - /** - * sets the html body. - * - * @param string $html - * - * @return $this - */ - public function setHtml($html) - { - $this->model['html'] = $html; - - return $this; - } - - /** - * Throws an exception since adding categories is not yet supported. - * - * @param string $category - * - * @throws \Exception - */ - public function addCategory($category) - { - throw new \Exception('Adding categories is not yet supported'); - } - - /** - * Throws an exception since adding attachments is not yet supported. - * - * @throws \Exception - * - * @param mixed $attachment - */ - public function addAttachment($attachment) - { - throw new \Exception('Adding attachments is not yet supported'); - } - - /** - * Adds transmission level substitution data. - * - * @param string $name - * @param mixed $values - * - * @return $this - */ - public function addSubstitution($name, $values) - { - if (!isset($this->model['substitutionData'])) { - $this->model['substitutionData'] = array(); - } - $this->model['substitutionData'][$name] = $values; - - return $this; - } - - /** - * Adds transmission level substitution data. - * - * @param string $name - * @param mixed $values - */ - public function addSection($name, $values) - { - $this->addSubstitution($name, $values); - } - - /** - * Throws an exception because arguments for third party systems is not supported. - * - * @throws \Exception - * - * @param mixed $value - */ - public function addUniqueArg($key, $value) - { - throw new \Exception('Adding Unique Arguments is not yet supported'); - } - - /** - * Throws an exception because arguments for third party systems is not supported. - * - * @throws \Exception - * - * @param mixed $values - */ - public function setUniqueArgs(array $values) - { - throw new \Exception('Setting Unique Arguments is not yet supported'); - } - - /** - * Adds custom headers to the email header. - * - * @param string $name - * @param string $value - */ - public function addHeader($name, $value) - { - if (!isset($this->model['customHeaders'])) { - $this->model['customHeaders'] = array(); - } - $this->model['customHeaders'][$name] = $value; - } - - /** - * converts this object to a configuration for a SparkPost transmission. - * - * @return array - */ - public function toSparkPostTransmission() - { - return $this->model; - } -} diff --git a/lib/SendGridCompatibility/SendGrid.php b/lib/SendGridCompatibility/SendGrid.php deleted file mode 100644 index c5e84c1..0000000 --- a/lib/SendGridCompatibility/SendGrid.php +++ /dev/null @@ -1,26 +0,0 @@ - $password); - if (!is_null($options)) { - $opts = array_merge($opts, $options); - } - - $this->sparky = new SparkPost($httpAdapter, $opts); - } - - public function send(Email $email) - { - $this->sparky->transmission->send($email->toSparkPostTransmission()); - } -} diff --git a/lib/SparkPost/APIResource.php b/lib/SparkPost/APIResource.php deleted file mode 100644 index 36b03a8..0000000 --- a/lib/SparkPost/APIResource.php +++ /dev/null @@ -1,265 +0,0 @@ -sparkpost = $sparkpost; - } - - /** - * Private Method helper to reference parameter mappings and set the right value for the right parameter. - * - * @param array $model (pass by reference) the set of values to map - * @param string $mapKey a dot syntax path determining which value to set - * @param mixed $value value for the given path - */ - protected function setMappedValue(&$model, $mapKey, $value) - { - //get mapping - if (empty(static::$parameterMappings)) { - // if parameterMappings is empty we can assume that no wrapper is defined - // for the current endpoint and we will use the mapKey to define the mappings directly - $mapPath = $mapKey; - } elseif (array_key_exists($mapKey, static::$parameterMappings)) { - // use only defined parameter mappings to construct $model - $mapPath = static::$parameterMappings[$mapKey]; - } else { - return; - } - - $path = explode('.', $mapPath); - $temp = &$model; - foreach ($path as $key) { - if (!isset($temp[$key])) { - $temp[$key] = null; - } - $temp = &$temp[$key]; - } - $temp = $value; - } - - /** - * maps values from the passed in model to those needed for the request. - * - * @param array $requestConfig the passed in model - * @param array $model the set of defaults - * - * @return array A model ready for the body of a request - */ - protected function buildRequestModel(array $requestConfig, array $model = []) - { - foreach ($requestConfig as $key => $value) { - $this->setMappedValue($model, $key, $value); - } - - return $model; - } - - /** - * posts to the api with a supplied body. - * - * @param array $body post body for the request - * - * @return array Result of the request - */ - public function create(array $body = []) - { - return $this->callResource('post', null, ['body' => $body]); - } - - /** - * Makes a put request to the api with a supplied body. - * - * @param $resourcePath - * @param array $body Put body for the request - * - * @return array Result of the request - * - * @throws APIResponseException - */ - public function update($resourcePath, array $body = []) - { - return $this->callResource('put', $resourcePath, ['body' => $body]); - } - - /** - * Wrapper method for issuing GET request to current API endpoint. - * - * @param string $resourcePath (optional) string resource path of specific resource - * @param array $query (optional) query string parameters - * - * @return array Result of the request - */ - public function get($resourcePath = null, array $query = []) - { - return $this->callResource('get', $resourcePath, ['query' => $query]); - } - - /** - * Wrapper method for issuing DELETE request to current API endpoint. - * - * @param string $resourcePath (optional) string resource path of specific resource - * @param array $query (optional) query string parameters - * - * @return array Result of the request - */ - public function delete($resourcePath = null, array $query = []) - { - return $this->callResource('delete', $resourcePath, ['query' => $query]); - } - - /** - * assembles a URL for a request. - * - * @param string $resourcePath path after the initial endpoint - * @param array $options array with an optional value of query with values to build a querystring from. Any - * query elements that are themselves arrays will be imploded into a comma separated list. - * - * @return string the assembled URL - */ - private function buildUrl($resourcePath, $options) - { - $url = "/{$this->endpoint}/"; - if (!is_null($resourcePath)) { - $url .= $resourcePath; - } - - if (!empty($options['query'])) { - // check each query element - if it's an array, implode it to match the API-accepted format - foreach ($options['query'] as &$element) { - if (is_array($element)) { - $element = implode(',', $element); - } - } - - $queryString = http_build_query($options['query']); - $url .= '?'.$queryString; - } - - return $url; - } - - /** - * Prepares a body for put and post requests. - * - * @param array $options array with an optional value of body with values to build a request body from. - * - * @return string|null A json encoded string or null if no body was provided - */ - private function buildBody($options) - { - $body = null; - if (!empty($options['body'])) { - $model = static::$structure; - $requestModel = $this->buildRequestModel($options['body'], $model); - $body = json_encode($requestModel); - } - - return $body; - } - - /** - * Private Method for issuing GET and DELETE request to current API endpoint. - * - * This method is responsible for getting the collection _and_ - * a specific entity from the API endpoint - * - * If resourcePath parameter is omitted, then we fetch the collection - * - * @param string $action HTTP method type - * @param string $resourcePath (optional) string resource path of specific resource - * @param array $options (optional) query string parameters - * - * @return array Result set of action performed on resource - * - * @throws APIResponseException - */ - private function callResource($action, $resourcePath = null, $options = []) - { - $action = strtoupper($action); // normalize - - $url = $this->buildUrl($resourcePath, $options); - $body = $this->buildBody($options); - - //make request - try { - $response = $this->sparkpost->httpAdapter->send($url, $action, $this->sparkpost->getHttpHeaders(), $body); - - $statusCode = $response->getStatusCode(); - - // Handle 4XX responses, 5XX responses will throw an HttpAdapterException - if ($statusCode < 400) { - return json_decode($response->getBody()->getContents(), true); - } elseif ($statusCode === 403) { - $response = json_decode($response->getBody(), true); - throw new APIResponseException( - 'Request forbidden', - $statusCode, - isset($response['errors'][0]['message']) ? $response['errors'][0]['message'] : 'Request forbidden', - isset($response['errors'][0]['code']) ? $response['errors'][0]['code'] : 1100, - isset($response['errors'][0]['description']) ? $response['errors'][0]['description'] : 'Does this API Key have the correct permissions?' - ); - } elseif ($statusCode === 404) { - throw new APIResponseException('The specified resource does not exist', 404); - } else { - $response = json_decode($response->getBody(), true); - throw new APIResponseException( - 'Received bad response from '.ucfirst($this->endpoint), - $statusCode, - isset($response['errors'][0]['message']) ? $response['errors'][0]['message'] : '', - isset($response['errors'][0]['code']) ? $response['errors'][0]['code'] : 0, - isset($response['errors'][0]['description']) ? $response['errors'][0]['description'] : '' - ); - } - } - - /* - * Configuration Errors, and a catch all for other errors - */ - catch (\Exception $exception) { - if ($exception instanceof APIResponseException) { - throw $exception; - } - - throw new APIResponseException('Unable to contact '.ucfirst($this->endpoint).' API: '.$exception->getMessage(), $exception->getCode()); - } - } -} diff --git a/lib/SparkPost/APIResponseException.php b/lib/SparkPost/APIResponseException.php deleted file mode 100644 index a491b3c..0000000 --- a/lib/SparkPost/APIResponseException.php +++ /dev/null @@ -1,62 +0,0 @@ -apiMessage = $apiMessage; - $this->apiCode = $apiCode; - $this->apiDescription = $apiDescription; - parent::__construct($message, $code); - } - - /** - * Gets the Exception message. - * - * @return string the Exception message as a string. - */ - public function getAPIMessage() - { - return $this->apiMessage; - } - - /** - * Gets the API Exception code. - * - * @return int the exception code as integer. - */ - public function getAPICode() - { - return $this->apiCode; - } - - /** - * Gets the Exception description. - * - * @return string the Exception description as a string. - */ - public function getAPIDescription() - { - return $this->apiDescription; - } -} diff --git a/lib/SparkPost/MessageEvents.php b/lib/SparkPost/MessageEvents.php deleted file mode 100644 index d44a30f..0000000 --- a/lib/SparkPost/MessageEvents.php +++ /dev/null @@ -1,64 +0,0 @@ -format(\DateTime::ATOM), 0, 16); - } - } - - return $this->get(null, $queryParams); - } - - /** - * List descriptions of the event fields that could be included in a response from the MessageEvent::search() method. - * - * @return array The event field descriptions. - */ - public function documentation() - { - return $this->get('events/documentation'); - } - - /** - * List examples of the event data that will be included in a response from the MessageEvent::search() method. - * - * @param array $events (optional) Event types for which to get a sample payload. If not provided, samples - * for all events will be returned. - * - * @return array Sample events. - */ - public function samples(array $events = []) - { - return $this->get('events/samples', ['events' => $events]); - } -} diff --git a/lib/SparkPost/Resource.php b/lib/SparkPost/Resource.php new file mode 100644 index 0000000..7c88743 --- /dev/null +++ b/lib/SparkPost/Resource.php @@ -0,0 +1,88 @@ +sparkpost = $sparkpost; + $this->endpoint = $endpoint; + } + + /** + * Sends get request to API at the set endpoint. + * + * @see SparkPost->request() + */ + public function get($uri = '', $payload = [], $headers = []) + { + return $this->request('GET', $uri, $payload, $headers); + } + + /** + * Sends put request to API at the set endpoint. + * + * @see SparkPost->request() + */ + public function put($uri = '', $payload = [], $headers = []) + { + return $this->request('PUT', $uri, $payload, $headers); + } + + /** + * Sends post request to API at the set endpoint. + * + * @see SparkPost->request() + */ + public function post($payload = [], $headers = []) + { + return $this->request('POST', '', $payload, $headers); + } + + /** + * Sends delete request to API at the set endpoint. + * + * @see SparkPost->request() + */ + public function delete($uri = '', $payload = [], $headers = []) + { + return $this->request('DELETE', $uri, $payload, $headers); + } + + /** + * Sends requests to SparkPost object to the resource endpoint. + * + * @see SparkPost->request() + * + * @return SparkPostPromise or SparkPostResponse depending on sync or async request + */ + public function request($method = 'GET', $uri = '', $payload = [], $headers = []) + { + if (is_array($uri)) { + $headers = $payload; + $payload = $uri; + $uri = ''; + } + + $uri = $this->endpoint.'/'.$uri; + + return $this->sparkpost->request($method, $uri, $payload, $headers); + } +} diff --git a/lib/SparkPost/SparkPost.php b/lib/SparkPost/SparkPost.php index ff8b456..cbf761f 100644 --- a/lib/SparkPost/SparkPost.php +++ b/lib/SparkPost/SparkPost.php @@ -2,151 +2,237 @@ namespace SparkPost; -use Ivory\HttpAdapter\Configuration; -use Ivory\HttpAdapter\HttpAdapterInterface; +use Http\Client\HttpClient; +use Http\Client\HttpAsyncClient; +use GuzzleHttp\Psr7\Request as Request; class SparkPost { - public $transmission; - public $messageEvents; - /** * Library version, used for setting User-Agent. */ - private $version = '1.2.1'; + private $version = '2.0.0'; /** - * Connection config for making requests. + * HttpClient used to make requests. */ - private $config; + public $httpClient; /** - * @var \Ivory\HttpAdapter\HttpAdapterInterface to make requests through. + * Options for requests. */ - public $httpAdapter; + private $options; /** - * Default config values. Passed in values will override these. + * Default options for requests that can be overridden with the setOptions function. */ - private static $apiDefaults = [ + private static $defaultOptions = [ 'host' => 'api.sparkpost.com', 'protocol' => 'https', 'port' => 443, - 'strictSSL' => true, 'key' => '', 'version' => 'v1', - 'timeout' => 10 + 'async' => true, ]; /** - * Sets up httpAdapter and config. - * - * Sets up instances of sub libraries. + * Instance of Transmission class. + */ + public $transmissions; + + /** + * Sets up the SparkPost instance. + * + * @param HttpClient $httpClient - An httplug client or adapter + * @param array $options - An array to overide default options or a string to be used as an API key + */ + public function __construct(HttpClient $httpClient, $options) + { + $this->setOptions($options); + $this->setHttpClient($httpClient); + $this->setupEndpoints(); + } + + /** + * Sends either sync or async request based on async option. * - * @param \Ivory\HttpAdapter\HttpAdapterInterface $httpAdapter - An adapter for making http requests - * @param string | array $settingsConfig - Hashmap that contains config values - * for the SDK to connect to SparkPost. If its a string we assume that - * its just they API Key. + * @param string $method + * @param string $uri + * @param array $payload - either used as the request body or url query params + * @param array $headers + * + * @return SparkPostPromise or SparkPostResponse depending on sync or async request */ - public function __construct($httpAdapter, $settingsConfig) + public function request($method = 'GET', $uri = '', $payload = [], $headers = []) { - //config needs to be setup before adapter because of default adapter settings - $this->setConfig($settingsConfig); - $this->setHttpAdapter($httpAdapter); + if ($this->options['async'] === true) { + return $this->asyncRequest($method, $uri, $payload, $headers); + } else { + return $this->syncRequest($method, $uri, $payload, $headers); + } + } - $this->transmission = new Transmission($this); - $this->messageEvents = new MessageEvents($this); + /** + * Sends sync request to SparkPost API. + * + * @param string $method + * @param string $uri + * @param array $payload + * @param array $headers + * + * @return SparkPostResponse + * + * @throws SparkPostException + */ + public function syncRequest($method = 'GET', $uri = '', $payload = [], $headers = []) + { + $request = $this->buildRequest($method, $uri, $payload, $headers); + try { + return new SparkPostResponse($this->httpClient->sendRequest($request)); + } catch (\Exception $exception) { + throw new SparkPostException($exception); + } } /** - * Creates an unwrapped api interface for endpoints that aren't yet supported. - * The new resource is attached to this object as well as returned. + * Sends async request to SparkPost API. * - * @param string $endpoint + * @param string $method + * @param string $uri + * @param array $payload + * @param array $headers + * + * @return SparkPostPromise + */ + public function asyncRequest($method = 'GET', $uri = '', $payload = [], $headers = []) + { + if ($this->httpClient instanceof HttpAsyncClient) { + $request = $this->buildRequest($method, $uri, $payload, $headers); + + return new SparkPostPromise($this->httpClient->sendAsyncRequest($request)); + } else { + throw new \Exception('Your http client does not support asynchronous requests. Please use a different client or use synchronous requests.'); + } + } + + /** + * Builds request from given params. + * + * @param string $method + * @param string $uri + * @param array $payload + * @param array $headers * - * @return APIResource - the unwrapped resource + * @return GuzzleHttp\Psr7\Request - A Psr7 compliant request */ - public function setupUnwrapped($endpoint) + public function buildRequest($method, $uri, $payload, $headers) { - $this->{$endpoint} = new APIResource($this); - $this->{$endpoint}->endpoint = $endpoint; + $method = trim(strtoupper($method)); + + if ($method === 'GET') { + $params = $payload; + $body = []; + } else { + $params = []; + $body = $payload; + } - return $this->{$endpoint}; + $url = $this->getUrl($uri, $params); + $headers = $this->getHttpHeaders($headers); + + return new Request($method, $url, $headers, json_encode($body)); } /** - * Merges passed in headers with default headers for http requests. + * Returns an array for the request headers. + * + * @param array $headers - any custom headers for the request + * + * @return array $headers - headers for the request */ - public function getHttpHeaders() + public function getHttpHeaders($headers = []) { - $defaultOptions = [ - 'Authorization' => $this->config['key'], + $constantHeaders = [ + 'Authorization' => $this->options['key'], 'Content-Type' => 'application/json', + 'User-Agent' => 'php-sparkpost/'.$this->version, ]; - return $defaultOptions; + foreach ($constantHeaders as $key => $value) { + $headers[$key] = $value; + } + + return $headers; } /** - * Helper function for getting the configuration for http requests. + * Builds the request url from the options and given params. * - * @param array $config + * @param string $path - the path in the url to hit + * @param array $params - query parameters to be encoded into the url * - * @return Configuration + * @return string $url - the url to send the desired request to */ - private function getHttpConfig($config) + public function getUrl($path, $params = []) { - // create Configuration for http adapter - $httpConfig = new Configuration(); - $baseUrl = $config['protocol'].'://'.$config['host'].($config['port'] ? ':'.$config['port'] : '').'/api/'.$config['version']; - $httpConfig->setBaseUri($baseUrl); - $httpConfig->setTimeout($this->config['timeout']); - $httpConfig->setUserAgent('php-sparkpost/'.$this->version); - - return $httpConfig; + $options = $this->options; + + $paramsArray = []; + foreach ($params as $key => $value) { + if (is_array($value)) { + $value = implode(',', $value); + } + + array_push($paramsArray, $key.'='.$value); + } + + $paramsString = implode('&', $paramsArray); + + return $options['protocol'].'://'.$options['host'].($options['port'] ? ':'.$options['port'] : '').'/api/'.$options['version'].'/'.$path.($paramsString ? '?'.$paramsString : ''); } - /** - * Validates and sets up the httpAdapter. - * - * @param $httpAdapter \Ivory\HttpAdapter\HttpAdapterInterface to make requests through. + /** + * Sets $httpClient to be used for request. * - * @throws \Exception + * @param Http\Client\HttpClient $httpClient - the client to be used for request */ - public function setHttpAdapter(HttpAdapterInterface $httpAdapter) + public function setHttpClient(HttpClient $httpClient) { - $this->httpAdapter = $httpAdapter; - $this->httpAdapter->setConfiguration($this->getHttpConfig($this->config)); + $this->httpClient = $httpClient; } /** - * Allows the user to pass in values to override the defaults and set their API key. - * - * @param string | array $settingsConfig - Hashmap that contains config values - * for the SDK to connect to SparkPost. If its a string we assume that - * its just they API Key. + * Sets the options from the param and defaults for the SparkPost object. * - * @throws \Exception + * @param array $options - either an string API key or an array of options */ - public function setConfig($settingsConfig) + public function setOptions($options) { - // if the config map is a string we should assume that its an api key - if (is_string($settingsConfig)) { - $settingsConfig = ['key' => $settingsConfig]; + // if the options map is a string we should assume that its an api key + if (is_string($options)) { + $options = ['key' => $options]; } // Validate API key because its required - if (!isset($settingsConfig['key']) || !preg_match('/\S/', $settingsConfig['key'])) { + if (!isset($this->options['key']) && (!isset($options['key']) || !preg_match('/\S/', $options['key']))) { throw new \Exception('You must provide an API key'); } - $this->config = self::$apiDefaults; + $this->options = isset($this->options) ? $this->options : self::$defaultOptions; - // set config, overriding defaults - foreach ($settingsConfig as $configOption => $configValue) { - if (key_exists($configOption, $this->config)) { - $this->config[$configOption] = $configValue; + // set options, overriding defaults + foreach ($options as $option => $value) { + if (key_exists($option, $this->options)) { + $this->options[$option] = $value; } } } + + /** + * Sets up any endpoints to custom classes e.g. $this->transmissions. + */ + private function setupEndpoints() + { + $this->transmissions = new Transmission($this); + } } diff --git a/lib/SparkPost/SparkPostException.php b/lib/SparkPost/SparkPostException.php new file mode 100644 index 0000000..ca92e24 --- /dev/null +++ b/lib/SparkPost/SparkPostException.php @@ -0,0 +1,41 @@ +getMessage(); + $code = $exception->getCode(); + if ($exception instanceof HttpException) { + $message = $exception->getResponse()->getBody()->__toString(); + $this->body = json_decode($message, true); + $code = $exception->getResponse()->getStatusCode(); + } + + parent::__construct($message, $code, $exception->getPrevious()); + } + + /** + * Returns the body. + * + * @return array $body - the json decoded body from the http response + */ + public function getBody() + { + return $this->body; + } +} diff --git a/lib/SparkPost/SparkPostPromise.php b/lib/SparkPost/SparkPostPromise.php new file mode 100644 index 0000000..df715d5 --- /dev/null +++ b/lib/SparkPost/SparkPostPromise.php @@ -0,0 +1,72 @@ +promise = $promise; + } + + /** + * Hand off the response functions to the original promise and return a custom response or exception. + * + * @param callable $onFulfilled - function to be called if the promise is fulfilled + * @param callable $onRejected - function to be called if the promise is rejected + */ + public function then(callable $onFulfilled = null, callable $onRejected = null) + { + return $this->promise->then(function ($response) use ($onFulfilled) { + if (isset($onFulfilled)) { + $onFulfilled(new SparkPostResponse($response)); + } + }, function ($exception) use ($onRejected) { + if (isset($onRejected)) { + $onRejected(new SparkPostException($exception)); + } + }); + } + + /** + * Hand back the state. + * + * @return $state - returns the state of the promise + */ + public function getState() + { + return $this->promise->getState(); + } + + /** + * Wraps the wait function and returns a custom response or throws a custom exception. + * + * @param bool $unwrap + * + * @return SparkPostResponse + * + * @throws SparkPostException + */ + public function wait($unwrap = true) + { + try { + $response = $this->promise->wait($unwrap); + + return $response ? new SparkPostResponse($response) : $response; + } catch (\Exception $exception) { + throw new SparkPostException($exception); + } + } +} diff --git a/lib/SparkPost/SparkPostResponse.php b/lib/SparkPost/SparkPostResponse.php new file mode 100644 index 0000000..e6a8fd1 --- /dev/null +++ b/lib/SparkPost/SparkPostResponse.php @@ -0,0 +1,107 @@ +response = $response; + } + + /** + * Returns the body. + * + * @return array $body - the json decoded body from the http response + */ + public function getBody() + { + $body = $this->response->getBody(); + $body_string = $body->__toString(); + + $json = json_decode($body_string, true); + + return $json; + } + + /** + * pass these down to the response given in the constructor. + */ + public function getProtocolVersion() + { + return $this->response->getProtocolVersion(); + } + + public function withProtocolVersion($version) + { + return $this->response->withProtocolVersion($version); + } + + public function getHeaders() + { + return $this->response->getHeaders(); + } + + public function hasHeader($name) + { + return $this->response->hasHeader($name); + } + + public function getHeader($name) + { + return $this->response->getHeader($name); + } + + public function getHeaderLine($name) + { + return $this->response->getHeaderLine($name); + } + + public function withHeader($name, $value) + { + return $this->response->withHeader($name, $value); + } + + public function withAddedHeader($name, $value) + { + return $this->response->withAddedHeader($name, $value); + } + + public function withoutHeader($name) + { + return $this->response->withoutHeader($name); + } + + public function withBody(StreamInterface $body) + { + return $this->response->withBody($body); + } + + public function getStatusCode() + { + return $this->response->getStatusCode(); + } + + public function withStatus($code, $reasonPhrase = '') + { + return $this->response->withStatus($code, $reasonPhrase); + } + + public function getReasonPhrase() + { + return $this->response->getReasonPhrase(); + } +} diff --git a/lib/SparkPost/Transmission.php b/lib/SparkPost/Transmission.php index ff63722..6c45c7e 100644 --- a/lib/SparkPost/Transmission.php +++ b/lib/SparkPost/Transmission.php @@ -2,135 +2,191 @@ namespace SparkPost; -/** - * SDK interface for managing transmissions. - */ -class Transmission extends APIResource +class Transmission extends Resource { - public $endpoint = 'transmissions'; + public function __construct(SparkPost $sparkpost) + { + parent::__construct($sparkpost, 'transmissions'); + } /** - * Mapping for values passed into the send method to the values needed for the Transmission API. + * Send post request to transmission endpoint after formatting cc, bcc, and expanding the shorthand emails. * - * @var array + * @return SparkPostPromise or SparkPostResponse depending on sync or async request */ - protected static $parameterMappings = [ - 'attachments' => 'content.attachments', - 'campaign' => 'campaign_id', - 'customHeaders' => 'content.headers', - 'description' => 'description', - 'from' => 'content.from', - 'html' => 'content.html', - 'inlineCss' => 'options.inline_css', - 'inlineImages' => 'content.inline_images', - 'metadata' => 'metadata', - 'recipientList' => 'recipients.list_id', - 'recipients' => 'recipients', - 'replyTo' => 'content.reply_to', - 'returnPath' => 'return_path', - 'rfc822' => 'content.email_rfc822', - 'sandbox' => 'options.sandbox', - 'startTime' => 'options.start_time', - 'subject' => 'content.subject', - 'substitutionData' => 'substitution_data', - 'template' => 'content.template_id', - 'text' => 'content.text', - 'trackClicks' => 'options.click_tracking', - 'trackOpens' => 'options.open_tracking', - 'transactional' => 'options.transactional', - 'useDraftTemplate' => 'use_draft_template', - ]; + public function post($payload = [], $headers = []) + { + $payload = $this->formatPayload($payload); + + return parent::post($payload, $headers); + } /** - * Sets up default structure and default values for the model that is acceptable by the API. + * Runs the given payload through the formatting functions. + * + * @param array $payload - the request body * - * @var array + * @return array - the modified request body */ - protected static $structure = [ - 'return_path' => 'default@sparkpostmail.com', - 'content' => [ - 'html' => null, - 'text' => null, - 'email_rfc822' => null, - ], - 'use_draft_template' => false, - ]; + public function formatPayload($payload) + { + $payload = $this->formatBlindCarbonCopy($payload); //Fixes BCCs into payload + $payload = $this->formatCarbonCopy($payload); //Fixes CCs into payload + $payload = $this->formatShorthandRecipients($payload); //Fixes shorthand recipients format + + return $payload; + } /** - * Method for issuing POST request to the Transmissions API. + * Formats bcc list into recipients list. * - * This method assumes that all the appropriate fields have - * been populated by the user through configuration. Acceptable - * configuration values are: - * 'attachments': array, - * 'campaign': string, - * 'customHeaders': array, - * 'description': string, - * 'from': string, - * 'html': string, - * 'inlineCss': boolean, - * 'inlineImages': array, - * 'metadata': array, - * 'recipientList': string, - * 'recipients': array, - * 'replyTo': string, - * 'rfc822': string, - * 'sandbox': boolean, - * 'startTime': string | \DateTime, - * 'subject': string, - * 'substitutionData': array, - * 'template': string, - * 'text': string, - * 'trackClicks': boolean, - * 'trackOpens': boolean, - * 'transactional': boolean, - * 'useDraftTemplate': boolean + * @param array $payload - the request body * - * @param array $transmissionConfig - * - * @return array API repsonse represented as key-value pairs + * @return array - the modified request body */ - public function send($transmissionConfig) + private function formatBlindCarbonCopy($payload) { - if (isset($transmissionConfig['startTime']) && $transmissionConfig['startTime'] instanceof \DateTime) { - $transmissionConfig['startTime'] = $transmissionConfig['startTime']->format(\DateTime::ATOM); + + //If there's a list of BCC recipients, move then into the correct format + if (isset($payload['bcc'])) { + $payload = $this->addListToRecipients($payload, 'bcc'); } - return $this->create($transmissionConfig); + return $payload; } /** - * Method for retrieving information about all transmissions - * Wrapper method for a cleaner interface. + * Formats cc list into recipients list and adds the CC header to the content. * - * @param null|string $campaignID - * @param null|string $templateID + * @param array $payload - the request body * - * @return array result Set of transmissions + * @return array - the modified request body */ - public function all($campaignID = null, $templateID = null) + private function formatCarbonCopy($payload) { - $options = []; - if ($campaignID !== null) { - $options['campaign_id'] = $campaignID; + if (isset($payload['cc'])) { + $ccAddresses = []; + for ($i = 0; $i < count($payload['cc']); ++$i) { + array_push($ccAddresses, $this->toAddressString($payload['cc'][$i]['address'])); + } + + // set up the content headers as either what it was before or an empty array + $payload['content']['headers'] = isset($payload['content']['headers']) ? $payload['content']['headers'] : []; + // add cc header + $payload['content']['headers']['CC'] = implode(',', $ccAddresses); + + $payload = $this->addListToRecipients($payload, 'cc'); } - if ($templateID !== null) { - $options['template_id'] = $templateID; + + return $payload; + } + + /** + * Formats all recipients into the long form of [ "name" => "John", "email" => "john@exmmple.com" ]. + * + * @param array $payload - the request body + * + * @return array - the modified request body + */ + private function formatShorthandRecipients($payload) + { + $payload['content']['from'] = $this->toAddressObject($payload['content']['from']); + + for ($i = 0; $i < count($payload['recipients']); ++$i) { + $payload['recipients'][$i]['address'] = $this->toAddressObject($payload['recipients'][$i]['address']); } - return $this->get(null, $options); + return $payload; } /** - * Method for retrieving information about a single transmission - * Wrapper method for a cleaner interface. + * Loops through the given listName in the payload and adds all the recipients to the recipients list after removing their names. * - * @param string $transmissionID Identifier of the transmission to be found + * @param array $payload - the request body + * @param array $listName - the name of the array in the payload to be moved to the recipients list * - * @return array result Single transmission represented in key-value pairs + * @return array - the modified request body + */ + private function addListToRecipients($payload, $listName) + { + $originalAddress = $this->toAddressString($payload['recipients'][0]['address']); + foreach ($payload[$listName] as $recipient) { + $recipient['address'] = $this->toAddressObject($recipient['address']); + $recipient['address']['header_to'] = $originalAddress; + + // remove name from address - name is only put in the header for cc and not at all for bcc + if (isset($recipient['address']['name'])) { + unset($recipient['address']['name']); + } + + array_push($payload['recipients'], $recipient); + } + + //Delete the original object from the payload. + unset($payload[$listName]); + + return $payload; + } + + /** + * Takes the shorthand form of an email address and converts it to the long form. + * + * @param $address - the shorthand form of an email address "Name " + * + * @return array - the longhand form of an email address [ "name" => "John", "email" => "john@exmmple.com" ] + */ + private function toAddressObject($address) + { + $formatted = $address; + if (is_string($formatted)) { + $formatted = []; + + if ($this->isEmail($address)) { + $formatted['email'] = $address; + } elseif (preg_match('/"?(.[^"]*)?"?\s*<(.+)>/', $address, $matches)) { + $name = trim($matches[1]); + $formatted['name'] = $matches[1]; + $formatted['email'] = $matches[2]; + } else { + throw new \Exception('Invalid address format: '.$address); + } + } + + return $formatted; + } + + /** + * Takes the longhand form of an email address and converts it to the shorthand form. + * + * @param $address - the longhand form of an email address [ "name" => "John", "email" => "john@exmmple.com" ] + * @param string - the shorthand form of an email address "Name " + */ + private function toAddressString($address) + { + // convert object to string + if (!is_string($address)) { + if (isset($address['name'])) { + $address = '"'.$address['name'].'" <'.$address['email'].'>'; + } else { + $address = $address['email']; + } + } + + return $address; + } + + /** + * Checks if a string is an email. + * + * @param string $email - a string that might be an email address + * @param bool - true if the given string is an email */ - public function find($transmissionID) + private function isEmail($email) { - return $this->get($transmissionID); + if (filter_var($email, FILTER_VALIDATE_EMAIL)) { + return true; + } else { + return false; + } } } diff --git a/test/unit/APIResourceExceptionTest.php b/test/unit/APIResourceExceptionTest.php deleted file mode 100644 index 8ae80de..0000000 --- a/test/unit/APIResourceExceptionTest.php +++ /dev/null @@ -1,43 +0,0 @@ -message = 'Test message'; - $this->code = 400; - $this->description = 'Test description'; - $this->exception = new APIResponseException(null, 0, $this->message, $this->code, $this->description); - } - - public function testAPIMessage() - { - $this->assertEquals($this->message, $this->exception->getAPIMessage()); - } - - public function testAPICode() - { - $this->assertEquals($this->code, $this->exception->getAPICode()); - } - - public function testAPIDescription() - { - $this->assertEquals($this->description, $this->exception->getAPIDescription()); - } -} diff --git a/test/unit/APIResourceTest.php b/test/unit/APIResourceTest.php deleted file mode 100644 index 67c37ab..0000000 --- a/test/unit/APIResourceTest.php +++ /dev/null @@ -1,196 +0,0 @@ -shouldReceive('getStatusCode')->andReturn($statusCode); - $exception->setResponse($response); - - return $exception; - } - - /** - * (non-PHPdoc). - * - * @before - * - * @see PHPUnit_Framework_TestCase::setUp() - */ - public function setUp() - { - $this->sparkPostMock = Mockery::mock('SparkPost\SparkPost', function ($mock) { - $mock->shouldReceive('getHttpHeaders')->andReturn([]); - }); - $this->sparkPostMock->httpAdapter = Mockery::mock(); - $this->resource = new APIResource($this->sparkPostMock); - self::$utils = new ClassUtils($this->resource); - self::$utils->setProperty($this->resource, 'sparkpost', $this->sparkPostMock); - } - - public function tearDown() - { - Mockery::close(); - } - - public function testConstructorSetsUpSparkPostObject() - { - $this->sparkPostMock->newProp = 'new value'; - $this->assertEquals($this->sparkPostMock, self::$utils->getProperty($this->resource, 'sparkpost')); - } - - public function testCreate() - { - $testInput = ['test' => 'body']; - $testBody = ['results' => ['my' => 'test']]; - $responseMock = Mockery::mock(); - $this->sparkPostMock->httpAdapter->shouldReceive('send')-> - once()-> - with(Mockery::type('string'), 'POST', Mockery::type('array'), json_encode($testInput))-> - andReturn($responseMock); - $responseMock->shouldReceive('getStatusCode')->andReturn(200); - $responseMock->shouldReceive('getBody->getContents')->andReturn(json_encode($testBody)); - - $this->assertEquals($testBody, $this->resource->create($testInput)); - } - - public function testUpdate() - { - $testInput = ['test' => 'body']; - $testBody = ['results' => ['my' => 'test']]; - $responseMock = Mockery::mock(); - $this->sparkPostMock->httpAdapter->shouldReceive('send')-> - once()-> - with('/.*\/test/', 'PUT', Mockery::type('array'), json_encode($testInput))-> - andReturn($responseMock); - $responseMock->shouldReceive('getStatusCode')->andReturn(200); - $responseMock->shouldReceive('getBody->getContents')->andReturn(json_encode($testBody)); - - $this->assertEquals($testBody, $this->resource->update('test', $testInput)); - } - - public function testGet() - { - $testBody = ['results' => ['my' => 'test']]; - $responseMock = Mockery::mock(); - $this->sparkPostMock->httpAdapter->shouldReceive('send')-> - once()-> - with('/.*\/test/', 'GET', Mockery::type('array'), null)-> - andReturn($responseMock); - $responseMock->shouldReceive('getStatusCode')->andReturn(200); - $responseMock->shouldReceive('getBody->getContents')->andReturn(json_encode($testBody)); - - $this->assertEquals($testBody, $this->resource->get('test')); - } - - public function testGetCommaSeparated() - { - $testBody = ['results' => ['my' => 'test']]; - $requestArray = [ - 'param1' => 'param1val', - 'param2' => ['param2val1', 'param2val2'], - ]; - $expectedGetParams = 'param1=param1val¶m2='.urlencode('param2val1,param2val2'); - - $responseMock = Mockery::mock(); - $this->sparkPostMock->httpAdapter->shouldReceive('send')-> - once()-> - with(matchesPattern("/.*\/test\?{$expectedGetParams}/"), 'GET', Mockery::type('array'), null)-> - andReturn($responseMock); - $responseMock->shouldReceive('getStatusCode')->andReturn(200); - $responseMock->shouldReceive('getBody->getContents')->andReturn(json_encode($testBody)); - - $this->assertEquals($testBody, $this->resource->get('test', $requestArray)); - } - - public function testDelete() - { - $responseMock = Mockery::mock(); - $this->sparkPostMock->httpAdapter->shouldReceive('send')-> - once()-> - with('/.*\/test/', 'DELETE', Mockery::type('array'), null)-> - andReturn($responseMock); - $responseMock->shouldReceive('getStatusCode')->andReturn(200); - $responseMock->shouldReceive('getBody->getContents')->andReturn(''); - - $this->assertEquals(null, $this->resource->delete('test')); - } - - public function testAdapter404Exception() - { - try { - $responseMock = Mockery::mock(); - $this->sparkPostMock->httpAdapter->shouldReceive('send')-> - once()-> - andReturn($responseMock); - $responseMock->shouldReceive('getStatusCode')->andReturn(404); - - $this->resource->get('test'); - } catch (\Exception $e) { - $this->assertRegExp('/.*resource does not exist.*/', $e->getMessage()); - } - } - - public function testAdapter403Exception() - { - $testBody = ['errors' => [ - [ - 'message' => 'Forbidden.', - ], - ]]; - try { - $responseMock = Mockery::mock(); - $this->sparkPostMock->httpAdapter->shouldReceive('send')-> - once()-> - andReturn($responseMock); - $responseMock->shouldReceive('getStatusCode')->andReturn(403); - $responseMock->shouldReceive('getBody')->andReturn(json_encode($testBody)); - - $this->resource->get('test'); - } catch (\Exception $e) { - $this->assertRegExp('/Request forbidden/', $e->getMessage()); - } - } - - public function testAdapter4XXException() - { - try { - $testBody = ['errors' => ['my' => 'test']]; - $responseMock = Mockery::mock(); - $this->sparkPostMock->httpAdapter->shouldReceive('send')-> - once()-> - andReturn($responseMock); - $responseMock->shouldReceive('getStatusCode')->andReturn(400); - $responseMock->shouldReceive('getBody')->andReturn(json_encode($testBody)); - - $this->resource->get('test'); - } catch (\Exception $e) { - $this->assertRegExp('/Received bad response.*/', $e->getMessage()); - } - } - - public function testAdapter5XXException() - { - try { - $this->sparkPostMock->httpAdapter->shouldReceive('send')-> - once()-> - andThrow(new \Exception('Something went wrong.')); - - $this->resource->get('test'); - } catch (\Exception $e) { - $this->assertRegExp('/Unable to contact.*API.*/', $e->getMessage()); - } - } -} diff --git a/test/unit/MessageEventTest.php b/test/unit/MessageEventTest.php deleted file mode 100644 index 3d92412..0000000 --- a/test/unit/MessageEventTest.php +++ /dev/null @@ -1,74 +0,0 @@ -sparkPostMock = Mockery::mock('SparkPost\SparkPost', function ($mock) { - $mock->shouldReceive('getHttpHeaders')->andReturn([]); - }); - $this->sparkPostMock->httpAdapter = Mockery::mock(); - $this->sut = new MessageEvents($this->sparkPostMock); - } - - public function testDateTimeConversion() - { - $testBody = ['results' => ['my' => 'test']]; - $testFrom = new \DateTime('1978-08-27 04:05:02'); - $testFromStr = urlencode('1978-08-27T04:05'); - $testTo = new \DateTime('2016-04-04 19:00'); - $testToStr = urlencode('2016-04-04T19:00'); - - $responseMock = Mockery::mock(); - $this->sparkPostMock->httpAdapter->shouldReceive('send')-> - once()-> - with("/message-events/?from={$testFromStr}&to={$testToStr}", 'GET', Mockery::type('array'), null)-> - andReturn($responseMock); - $responseMock->shouldReceive('getStatusCode')->andReturn(200); - $responseMock->shouldReceive('getBody->getContents')->andReturn(json_encode($testBody)); - - $this->assertEquals($testBody, $this->sut->search(['from' => $testFrom, 'to' => $testTo])); - } - - public function testDocumentation() - { - $testBody = ['results' => ['my' => 'test']]; - $responseMock = Mockery::mock(); - $this->sparkPostMock->httpAdapter->shouldReceive('send')-> - once()-> - with('/message-events/events/documentation', 'GET', Mockery::type('array'), null)-> - andReturn($responseMock); - $responseMock->shouldReceive('getStatusCode')->andReturn(200); - $responseMock->shouldReceive('getBody->getContents')->andReturn(json_encode($testBody)); - - $this->assertEquals($testBody, $this->sut->documentation()); - } - - public function testSamples() - { - $testBody = ['results' => ['my' => 'test']]; - $responseMock = Mockery::mock(); - $this->sparkPostMock->httpAdapter->shouldReceive('send')-> - once()-> - with('/message-events/events/samples?events='.urlencode('delivery,bounce'), 'GET', Mockery::type('array'), null)-> - andReturn($responseMock); - $responseMock->shouldReceive('getStatusCode')->andReturn(200); - $responseMock->shouldReceive('getBody->getContents')->andReturn(json_encode($testBody)); - - $this->assertEquals($testBody, $this->sut->samples(['delivery', 'bounce'])); - } -} diff --git a/test/unit/SendGridCompatibiility/EmailTest.php b/test/unit/SendGridCompatibiility/EmailTest.php deleted file mode 100644 index 2846e9e..0000000 --- a/test/unit/SendGridCompatibiility/EmailTest.php +++ /dev/null @@ -1,178 +0,0 @@ -email = new Email(); - } - - public function testConstruct() - { - $email = new Email(); - - $this->assertInstanceOf('SparkPost\SendGridCompatibility\Email', $email); - $this->assertInternalType('array', $email->model); - } - - public function testAddTo() - { - $fakeEmail = 'joe.schmoe@test.com'; - $this->email->addTo($fakeEmail); - - $this->assertEquals(array(array('address' => array('email' => $fakeEmail))), $this->email->model['recipients']); - } - - public function testAddToWithName() - { - $fakeEmail = 'joe.schmoe@test.com'; - $fakeName = 'Joe Schmoe'; - $this->email->addTo($fakeEmail, $fakeName); - - $this->assertEquals(array(array('address' => array('email' => $fakeEmail, 'name' => $fakeName))), $this->email->model['recipients']); - } - - public function testSetTos() - { - $tos = array(); - array_push($tos, array('address' => array('email' => 'joe.schmoe@test.com', 'name' => 'Joe Schmoe'))); - array_push($tos, array('address' => array('email' => 'jill.schmoe@test.com', 'name' => 'Jill Schmoe'))); - $this->email->setTos($tos); - - $this->assertEquals($tos, $this->email->model['recipients']); - } - - public function testSetFrom() - { - $this->email->setFrom('test@email.com'); - - $this->assertEquals(array('email' => 'test@email.com'), $this->email->model['from']); - } - - public function testSetFromName() - { - $this->email->setFrom('test@email.com'); - $this->email->setFromName('Test Bot'); - - $this->assertEquals(array('email' => 'test@email.com', 'name' => 'Test Bot'), $this->email->model['from']); - } - - /** - * @desc Tests that setting the fromName prior to setting the From field throws an exception - * @expectedException Exception - * @expectedExceptionMessage Must set 'From' prior to setting 'From Name'. - */ - public function testSetFromNameWithoutAddress() - { - $this->email->setFromName('Test Bot'); - } - - public function testSetReplyto() - { - $this->email->setReplyTo('test@email.com'); - - $this->assertEquals('test@email.com', $this->email->model['replyTo']); - } - /** - * @expectedException Exception - * @expectedExceptionMessage Adding bcc recipients is not yet supported, try adding them as a 'to' address - */ - public function testAddBcc() - { - $this->email->addBcc('test@email.com'); - } - - public function testSetSubject() - { - $this->email->setSubject('Awesome Subject'); - - $this->assertEquals('Awesome Subject', $this->email->model['subject']); - } - - public function testSetText() - { - $value = 'This is some plain/text'; - $this->email->setText($value); - - $this->assertEquals($value, $this->email->model['text']); - } - - public function testSetHtml() - { - $value = '

This is some html

'; - $this->email->setHtml($value); - - $this->assertEquals($value, $this->email->model['html']); - } - - /** - * @desc test that adding a category throws an exception since we don't support tags at transmission level yet - * @expectedException Exception - * @expectedExceptionMessage Adding categories is not yet supported - */ - public function testAddCategory() - { - $this->email->addCategory(''); - } - - /** - * @desc Tests that setting an attachment throws a meaningful exception - * @expectedException Exception - * @expectedExceptionMessage Adding attachments is not yet supported - */ - public function testAddAttachment() - { - $this->email->addAttachment('blah'); - } - - public function testAddSubstitution() - { - $this->email->addSubstitution('item', 'baseball bat'); - - $this->assertEquals(array('item' => 'baseball bat'), $this->email->model['substitutionData']); - } - - public function testAddSection() - { - $this->email->addSection('item', 'baseball bat'); - - $this->assertEquals(array('item' => 'baseball bat'), $this->email->model['substitutionData']); - } - - /** - * @desc Tests that setting an attachment throws a meaningful exception - * @expectedException Exception - * @expectedExceptionMessage Adding Unique Arguments is not yet supported - */ - public function testAddUniqueArguement() - { - $this->email->addUniqueArg('blah', 'someblah'); - } - - /** - * @desc Tests that setting an unique argument throws a meaningful exception - * @expectedException Exception - * @expectedExceptionMessage Setting Unique Arguments is not yet supported - */ - public function testSetUniqueArgs() - { - $this->email->setUniqueArgs(array('blah', 'andBlah')); - } - - public function testAddHeader() - { - $value = 'My Header'; - $this->email->addHeader('X-header', $value); - - $this->assertEquals(array('X-header' => $value), $this->email->model['customHeaders']); - } - - public function testToSparkPostTransmission() - { - $this->assertInternalType('array', $this->email->toSparkPostTransmission()); - } -} diff --git a/test/unit/SparkPostResponseTest.php b/test/unit/SparkPostResponseTest.php new file mode 100644 index 0000000..efdec1a --- /dev/null +++ b/test/unit/SparkPostResponseTest.php @@ -0,0 +1,133 @@ +returnValue = 'some_value_to_return'; + $this->responseMock = Mockery::mock('Psr\Http\Message\ResponseInterface'); + } + + public function testGetProtocolVersion() + { + $this->responseMock->shouldReceive('getProtocolVersion')->andReturn($this->returnValue); + $sparkpostResponse = new SparkPostResponse($this->responseMock); + $this->assertEquals($this->responseMock->getProtocolVersion(), $sparkpostResponse->getProtocolVersion()); + } + + public function testWithProtocolVersion() + { + $param = 'protocol version'; + + $this->responseMock->shouldReceive('withProtocolVersion')->andReturn($this->returnValue); + $sparkpostResponse = new SparkPostResponse($this->responseMock); + $this->assertEquals($this->responseMock->withProtocolVersion($param), $sparkpostResponse->withProtocolVersion($param)); + } + + public function testGetHeaders() + { + $this->responseMock->shouldReceive('getHeaders')->andReturn($this->returnValue); + $sparkpostResponse = new SparkPostResponse($this->responseMock); + $this->assertEquals($this->responseMock->getHeaders(), $sparkpostResponse->getHeaders()); + } + + public function testHasHeader() + { + $param = 'header'; + + $this->responseMock->shouldReceive('hasHeader')->andReturn($this->returnValue); + $sparkpostResponse = new SparkPostResponse($this->responseMock); + $this->assertEquals($this->responseMock->hasHeader($param), $sparkpostResponse->hasHeader($param)); + } + + public function testGetHeader() + { + $param = 'header'; + + $this->responseMock->shouldReceive('getHeader')->andReturn($this->returnValue); + $sparkpostResponse = new SparkPostResponse($this->responseMock); + $this->assertEquals($this->responseMock->getHeader($param), $sparkpostResponse->getHeader($param)); + } + + public function testGetHeaderLine() + { + $param = 'header'; + + $this->responseMock->shouldReceive('getHeaderLine')->andReturn($this->returnValue); + $sparkpostResponse = new SparkPostResponse($this->responseMock); + $this->assertEquals($this->responseMock->getHeaderLine($param), $sparkpostResponse->getHeaderLine($param)); + } + + public function testWithHeader() + { + $param = 'header'; + $param2 = 'value'; + + $this->responseMock->shouldReceive('withHeader')->andReturn($this->returnValue); + $sparkpostResponse = new SparkPostResponse($this->responseMock); + $this->assertEquals($this->responseMock->withHeader($param, $param2), $sparkpostResponse->withHeader($param, $param2)); + } + + public function testWithAddedHeader() + { + $param = 'header'; + $param2 = 'value'; + + $this->responseMock->shouldReceive('withAddedHeader')->andReturn($this->returnValue); + $sparkpostResponse = new SparkPostResponse($this->responseMock); + $this->assertEquals($this->responseMock->withAddedHeader($param, $param2), $sparkpostResponse->withAddedHeader($param, $param2)); + } + + public function testWithoutHeader() + { + $param = 'header'; + + $this->responseMock->shouldReceive('withoutHeader')->andReturn($this->returnValue); + $sparkpostResponse = new SparkPostResponse($this->responseMock); + $this->assertEquals($this->responseMock->withoutHeader($param), $sparkpostResponse->withoutHeader($param)); + } + + public function testWithBody() + { + $param = Mockery::mock('Psr\Http\Message\StreamInterface'); + + $this->responseMock->shouldReceive('withBody')->andReturn($this->returnValue); + $sparkpostResponse = new SparkPostResponse($this->responseMock); + $this->assertEquals($this->responseMock->withBody($param), $sparkpostResponse->withBody($param)); + } + + public function testGetStatusCode() + { + $this->responseMock->shouldReceive('getStatusCode')->andReturn($this->returnValue); + $sparkpostResponse = new SparkPostResponse($this->responseMock); + $this->assertEquals($this->responseMock->getStatusCode(), $sparkpostResponse->getStatusCode()); + } + + public function testWithStatus() + { + $param = 'status'; + + $this->responseMock->shouldReceive('withStatus')->andReturn($this->returnValue); + $sparkpostResponse = new SparkPostResponse($this->responseMock); + $this->assertEquals($this->responseMock->withStatus($param), $sparkpostResponse->withStatus($param)); + } + + public function testGetReasonPhrase() + { + $this->responseMock->shouldReceive('getReasonPhrase')->andReturn($this->returnValue); + $sparkpostResponse = new SparkPostResponse($this->responseMock); + $this->assertEquals($this->responseMock->getReasonPhrase(), $sparkpostResponse->getReasonPhrase()); + } +} diff --git a/test/unit/SparkPostTest.php b/test/unit/SparkPostTest.php index 26563c3..f1c8a56 100644 --- a/test/unit/SparkPostTest.php +++ b/test/unit/SparkPostTest.php @@ -2,18 +2,37 @@ namespace SparkPost\Test; -use Ivory\HttpAdapter\CurlHttpAdapter; -use Mockery; use SparkPost\SparkPost; +use SparkPost\SparkPostPromise; +use GuzzleHttp\Promise\FulfilledPromise as GuzzleFulfilledPromise; +use GuzzleHttp\Promise\RejectedPromise as GuzzleRejectedPromise; +use Http\Adapter\Guzzle6\Promise as GuzzleAdapterPromise; +use Mockery; use SparkPost\Test\TestUtils\ClassUtils; class SparkPostTest extends \PHPUnit_Framework_TestCase { private static $utils; - private $adapterMock; + private $clientMock; /** @var SparkPost */ private $resource; + private $postTransmissionPayload = [ + 'content' => [ + 'from' => ['name' => 'Sparkpost Team', 'email' => 'postmaster@sendmailfor.me'], + 'subject' => 'First Mailing From PHP', + 'text' => 'Congratulations, {{name}}!! You just sent your very first mailing!', + ], + 'substitution_data' => ['name' => 'Avi'], + 'recipients' => [ + ['address' => 'avi.goldman@sparkpost.com'], + ], + ]; + + private $getTransmissionPayload = [ + 'campaign_id' => 'thanksgiving', + ]; + /** * (non-PHPdoc). * @@ -24,14 +43,10 @@ class SparkPostTest extends \PHPUnit_Framework_TestCase public function setUp() { //setup mock for the adapter - $this->adapterMock = Mockery::mock('Ivory\HttpAdapter\HttpAdapterInterface', function ($mock) { - $mock->shouldReceive('setConfiguration'); - $mock->shouldReceive('getConfiguration->getUserAgent')->andReturn('php-sparkpost/0.2.0'); - }); + $this->clientMock = Mockery::mock('Http\Adapter\Guzzle6\Client'); - $this->resource = new SparkPost($this->adapterMock, ['key' => 'a key']); + $this->resource = new SparkPost($this->clientMock, ['key' => 'SPARKPOST_API_KEY']); self::$utils = new ClassUtils($this->resource); - self::$utils->setProperty($this->resource, 'httpAdapter', $this->adapterMock); } public function tearDown() @@ -39,45 +54,221 @@ public function tearDown() Mockery::close(); } - /** - * @desc Ensures that the configuration class is not instantiable. - */ - public function testConstructorSetsUpTransmissions() + public function testRequest() + { + $responseMock = Mockery::mock('Psr\Http\Message\ResponseInterface'); + $this->resource->setOptions(['async' => false]); + $this->resource->httpClient->shouldReceive('sendRequest')->andReturn($responseMock); + $this->assertInstanceOf('SparkPost\SparkPostResponse', $this->resource->request('POST', 'transmissions', $this->postTransmissionPayload)); + + $promiseMock = Mockery::mock('Http\Promise\Promise'); + $this->resource->setOptions(['async' => true]); + $this->resource->httpClient->shouldReceive('sendAsyncRequest')->andReturn($promiseMock); + $this->assertInstanceOf('SparkPost\SparkPostPromise', $this->resource->request('GET', 'transmissions', $this->getTransmissionPayload)); + } + + public function testSuccessfulSyncRequest() + { + $responseMock = Mockery::mock('Psr\Http\Message\ResponseInterface'); + $responseBodyMock = Mockery::mock(); + + $responseBody = ['results' => 'yay']; + + $this->resource->httpClient->shouldReceive('sendRequest')-> + once()-> + with(Mockery::type('GuzzleHttp\Psr7\Request'))-> + andReturn($responseMock); + + $responseMock->shouldReceive('getStatusCode')->andReturn(200); + $responseMock->shouldReceive('getBody')->andReturn($responseBodyMock); + $responseBodyMock->shouldReceive('__toString')->andReturn(json_encode($responseBody)); + + $response = $this->resource->syncRequest('POST', 'transmissions', $this->postTransmissionPayload); + + $this->assertEquals($responseBody, $response->getBody()); + $this->assertEquals(200, $response->getStatusCode()); + } + + public function testUnsuccessfulSyncRequest() + { + $exceptionMock = Mockery::mock('Http\Client\Exception\HttpException'); + + $responseBody = ['results' => 'failed']; + + $this->resource->httpClient->shouldReceive('sendRequest')-> + once()-> + with(Mockery::type('GuzzleHttp\Psr7\Request'))-> + andThrow($exceptionMock); + + $exceptionMock->shouldReceive('getResponse->getStatusCode')->andReturn(500); + $exceptionMock->shouldReceive('getResponse->getBody->__toString')->andReturn(json_encode($responseBody)); + + try { + $this->resource->syncRequest('POST', 'transmissions', $this->postTransmissionPayload); + } catch (\Exception $e) { + $this->assertEquals($responseBody, $e->getBody()); + $this->assertEquals(500, $e->getCode()); + } + } + + public function testSuccessfulAsyncRequestWithWait() + { + $promiseMock = Mockery::mock('Http\Promise\Promise'); + $responseMock = Mockery::mock('Psr\Http\Message\ResponseInterface'); + $responseBodyMock = Mockery::mock(); + + $responseBody = ['results' => 'yay']; + + $this->resource->httpClient->shouldReceive('sendAsyncRequest')-> + once()-> + with(Mockery::type('GuzzleHttp\Psr7\Request'))-> + andReturn($promiseMock); + + $promiseMock->shouldReceive('wait')->andReturn($responseMock); + + $responseMock->shouldReceive('getStatusCode')->andReturn(200); + $responseMock->shouldReceive('getBody')->andReturn($responseBodyMock); + $responseBodyMock->shouldReceive('__toString')->andReturn(json_encode($responseBody)); + + $promise = $this->resource->asyncRequest('POST', 'transmissions', $this->postTransmissionPayload); + + $response = $promise->wait(); + + $this->assertEquals($responseBody, $response->getBody()); + $this->assertEquals(200, $response->getStatusCode()); + } + + public function testUnsuccessfulAsyncRequestWithWait() + { + $promiseMock = Mockery::mock('Http\Promise\Promise'); + $exceptionMock = Mockery::mock('Http\Client\Exception\HttpException'); + + $responseBody = ['results' => 'failed']; + + $this->resource->httpClient->shouldReceive('sendAsyncRequest')-> + once()-> + with(Mockery::type('GuzzleHttp\Psr7\Request'))-> + andReturn($promiseMock); + + $promiseMock->shouldReceive('wait')->andThrow($exceptionMock); + + $exceptionMock->shouldReceive('getResponse->getStatusCode')->andReturn(500); + $exceptionMock->shouldReceive('getResponse->getBody->__toString')->andReturn(json_encode($responseBody)); + + $promise = $this->resource->asyncRequest('POST', 'transmissions', $this->postTransmissionPayload); + + try { + $response = $promise->wait(); + } catch (\Exception $e) { + $this->assertEquals($responseBody, $e->getBody()); + $this->assertEquals(500, $e->getCode()); + } + } + + public function testSuccessfulAsyncRequestWithThen() + { + $responseBody = ['results' => 'yay']; + $responseMock = Mockery::mock('Psr\Http\Message\ResponseInterface'); + $responseBodyMock = Mockery::mock(); + $responseMock->shouldReceive('getStatusCode')->andReturn(200); + $responseMock->shouldReceive('getBody')->andReturn($responseBodyMock); + $responseBodyMock->shouldReceive('__toString')->andReturn(json_encode($responseBody)); + + $guzzlePromise = new GuzzleFulfilledPromise($responseMock); + + $promise = new SparkPostPromise(new GuzzleAdapterPromise($guzzlePromise, $this->resource->buildRequest('POST', 'transmissions', $this->postTransmissionPayload, []))); + + $promise->then(function ($exception) use ($responseBody) { + $this->assertEquals(200, $exception->getStatusCode()); + $this->assertEquals($responseBody, $exception->getBody()); + }, null)->wait(); + } + + public function testUnsuccessfulAsyncRequestWithThen() { - $sparky = new SparkPost(new CurlHttpAdapter(), ['key' => 'a key']); - $this->assertEquals('SparkPost\Transmission', get_class($sparky->transmission)); - $adapter = self::$utils->getProperty($this->resource, 'httpAdapter'); - $this->assertRegExp('/php-sparkpost.*/', $adapter->getConfiguration()->getUserAgent()); + $responseBody = ['results' => 'failed']; + $exceptionMock = Mockery::mock('Http\Client\Exception\HttpException'); + $exceptionMock->shouldReceive('getResponse->getStatusCode')->andReturn(500); + $exceptionMock->shouldReceive('getResponse->getBody->__toString')->andReturn(json_encode($responseBody)); + + $guzzlePromise = new GuzzleRejectedPromise($exceptionMock); + + $promise = new SparkPostPromise(new GuzzleAdapterPromise($guzzlePromise, $this->resource->buildRequest('POST', 'transmissions', $this->postTransmissionPayload, []))); + + $promise->then(null, function ($exception) use ($responseBody) { + $this->assertEquals(500, $exception->getCode()); + $this->assertEquals($responseBody, $exception->getBody()); + })->wait(); } - public function testSetConfigStringKey() + public function testPromise() { - $this->resource->setConfig('a key'); - $config = self::$utils->getProperty($this->resource, 'config'); - $this->assertEquals('a key', $config['key']); + $promiseMock = Mockery::mock('Http\Promise\Promise'); + + $this->resource->httpClient->shouldReceive('sendAsyncRequest')-> + once()-> + with(Mockery::type('GuzzleHttp\Psr7\Request'))-> + andReturn($promiseMock); + + $promise = $this->resource->asyncRequest('POST', 'transmissions', $this->postTransmissionPayload); + + $promiseMock->shouldReceive('getState')->twice()->andReturn('pending'); + $this->assertEquals($promiseMock->getState(), $promise->getState()); + + $promiseMock->shouldReceive('getState')->once()->andReturn('rejected'); + $this->assertEquals('rejected', $promise->getState()); } /** * @expectedException Exception - * @expectedExceptionMessageRegExp /API key/ */ - public function testSetBadConfig() + public function testUnsupportedAsyncRequest() + { + $this->resource->setHttpClient(Mockery::mock('Http\Client\HttpClient')); + + $this->resource->asyncRequest('POST', 'transmissions', $this->postTransmissionPayload); + } + + public function testGetHttpHeaders() + { + $headers = $this->resource->getHttpHeaders([ + 'Custom-Header' => 'testing', + ]); + + $version = self::$utils->getProperty($this->resource, 'version'); + + $this->assertEquals('SPARKPOST_API_KEY', $headers['Authorization']); + $this->assertEquals('application/json', $headers['Content-Type']); + $this->assertEquals('testing', $headers['Custom-Header']); + $this->assertEquals('php-sparkpost/'.$version, $headers['User-Agent']); + } + + public function testGetUrl() { - $this->resource->setConfig(['not' => 'a key']); + $url = 'https://api.sparkpost.com:443/api/v1/transmissions?key=value 1,value 2,value 3'; + $testUrl = $this->resource->getUrl('transmissions', ['key' => ['value 1', 'value 2', 'value 3']]); + $this->assertEquals($url, $testUrl); } - public function testGetHeaders() + public function testSetHttpClient() { - $results = $this->resource->getHttpHeaders(); - $this->assertEquals('a key', $results['Authorization']); - $this->assertEquals('application/json', $results['Content-Type']); + $this->resource->setHttpClient($this->clientMock); + $this->assertEquals($this->clientMock, self::$utils->getProperty($this->resource, 'httpClient')); } - public function testSetUnwrapped() + public function testSetOptionsStringKey() + { + $this->resource->setOptions('SPARKPOST_API_KEY'); + $options = self::$utils->getProperty($this->resource, 'options'); + $this->assertEquals('SPARKPOST_API_KEY', $options['key']); + } + + /** + * @expectedException Exception + */ + public function testSetBadOptions() { - $results = $this->resource->setupUnwrapped('ASweetEndpoint'); - $this->assertEquals($this->resource->ASweetEndpoint, $results); - $this->assertInstanceOf('SparkPost\APIResource', $results); - $this->assertEquals('ASweetEndpoint', $results->endpoint); + self::$utils->setProperty($this->resource, 'options', []); + $this->resource->setOptions(['not' => 'SPARKPOST_API_KEY']); } } diff --git a/test/unit/TransmissionTest.php b/test/unit/TransmissionTest.php index d606c53..84f16f0 100644 --- a/test/unit/TransmissionTest.php +++ b/test/unit/TransmissionTest.php @@ -2,16 +2,50 @@ namespace SparkPost\Test; -use SparkPost\Transmission; -use SparkPost\Test\TestUtils\ClassUtils; +use SparkPost\SparkPost; use Mockery; +use SparkPost\Test\TestUtils\ClassUtils; class TransmissionTest extends \PHPUnit_Framework_TestCase { private static $utils; - private $sparkPostMock; + private $clientMock; + /** @var SparkPost */ private $resource; + private $postTransmissionPayload = [ + 'content' => [ + 'from' => ['name' => 'Sparkpost Team', 'email' => 'postmaster@sendmailfor.me'], + 'subject' => 'First Mailing From PHP', + 'text' => 'Congratulations, {{name}}!! You just sent your very first mailing!', + ], + 'substitution_data' => ['name' => 'Avi'], + 'recipients' => [ + [ + 'address' => [ + 'name' => 'Vincent', + 'email' => 'vincent.song@sparkpost.com', + ], + ], + ['address' => 'test@example.com'], + ], + 'cc' => [ + [ + 'address' => [ + 'email' => 'avi.goldman@sparkpost.com', + ], + ], + ], + 'bcc' => [ + ['address' => 'Emely Giraldo '], + ], + + ]; + + private $getTransmissionPayload = [ + 'campaign_id' => 'thanksgiving', + ]; + /** * (non-PHPdoc). * @@ -21,11 +55,10 @@ class TransmissionTest extends \PHPUnit_Framework_TestCase */ public function setUp() { - $this->sparkPostMock = Mockery::mock('SparkPost\SparkPost', function ($mock) { - $mock->shouldReceive('getHttpHeaders')->andReturn([]); - }); - $this->sparkPostMock->httpAdapter = Mockery::mock(); - $this->resource = new Transmission($this->sparkPostMock); + //setup mock for the adapter + $this->clientMock = Mockery::mock('Http\Adapter\Guzzle6\Client'); + + $this->resource = new SparkPost($this->clientMock, ['key' => 'SPARKPOST_API_KEY', 'async' => false]); self::$utils = new ClassUtils($this->resource); } @@ -34,81 +67,111 @@ public function tearDown() Mockery::close(); } - public function testSend() + /** + * @expectedException Exception + */ + public function testInvalidEmailFormat() { - $responseMock = Mockery::mock(); - $body = ['text' => 'awesomesauce', 'content' => ['subject' => 'awesomeness']]; + $this->postTransmissionPayload['recipients'][] = [ + 'address' => 'invalid email format', + ]; + + $response = $this->resource->transmissions->post($this->postTransmissionPayload); + } + + public function testGet() + { + $responseMock = Mockery::mock('Psr\Http\Message\ResponseInterface'); + $responseBodyMock = Mockery::mock(); + $responseBody = ['results' => 'yay']; - $this->sparkPostMock->httpAdapter->shouldReceive('send')-> + $this->resource->httpClient->shouldReceive('sendRequest')-> once()-> - with('/.*\/transmissions/', 'POST', Mockery::type('array'), Mockery::type('string'))-> + with(Mockery::type('GuzzleHttp\Psr7\Request'))-> andReturn($responseMock); + $responseMock->shouldReceive('getStatusCode')->andReturn(200); + $responseMock->shouldReceive('getBody')->andReturn($responseBodyMock); + $responseBodyMock->shouldReceive('__toString')->andReturn(json_encode($responseBody)); - $responseMock->shouldReceive('getBody->getContents')->andReturn(json_encode($responseBody)); + $response = $this->resource->transmissions->get($this->getTransmissionPayload); - $this->assertEquals($responseBody, $this->resource->send($body)); + $this->assertEquals($responseBody, $response->getBody()); + $this->assertEquals(200, $response->getStatusCode()); } - public function testSendDateTimeConversion() + public function testPut() { - $testStartTime = new \DateTime('2016-08-27 13:01:02', new \DateTimeZone('UTC')); + $responseMock = Mockery::mock('Psr\Http\Message\ResponseInterface'); + $responseBodyMock = Mockery::mock(); - $responseMock = Mockery::mock(); $responseBody = ['results' => 'yay']; - $this->sparkPostMock->httpAdapter->shouldReceive('send')-> + + $this->resource->httpClient->shouldReceive('sendRequest')-> once()-> - with('/.*\/transmissions/', 'POST', Mockery::type('array'), matchesPattern('/"start_time":"2016-08-27T13:01:02\+00:00"/'))-> + with(Mockery::type('GuzzleHttp\Psr7\Request'))-> andReturn($responseMock); + $responseMock->shouldReceive('getStatusCode')->andReturn(200); - $responseMock->shouldReceive('getBody->getContents')->andReturn(json_encode($responseBody)); + $responseMock->shouldReceive('getBody')->andReturn($responseBodyMock); + $responseBodyMock->shouldReceive('__toString')->andReturn(json_encode($responseBody)); + + $response = $this->resource->transmissions->put($this->getTransmissionPayload); - $this->assertEquals($responseBody, $this->resource->send(['startTime' => $testStartTime])); + $this->assertEquals($responseBody, $response->getBody()); + $this->assertEquals(200, $response->getStatusCode()); } - public function testAllWithFilter() + public function testPost() { - $responseMock = Mockery::mock(); + $responseMock = Mockery::mock('Psr\Http\Message\ResponseInterface'); + $responseBodyMock = Mockery::mock(); + $responseBody = ['results' => 'yay']; - $this->sparkPostMock->httpAdapter->shouldReceive('send')-> + + $this->resource->httpClient->shouldReceive('sendRequest')-> once()-> - with('/.*transmissions.*?campaign_id=campaign&template_id=template/', 'GET', Mockery::type('array'), null)-> + with(Mockery::type('GuzzleHttp\Psr7\Request'))-> andReturn($responseMock); + $responseMock->shouldReceive('getStatusCode')->andReturn(200); + $responseMock->shouldReceive('getBody')->andReturn($responseBodyMock); + $responseBodyMock->shouldReceive('__toString')->andReturn(json_encode($responseBody)); - $responseMock->shouldReceive('getBody->getContents')->andReturn(json_encode($responseBody)); + $response = $this->resource->transmissions->post($this->postTransmissionPayload); - $this->assertEquals($responseBody, $this->resource->all('campaign', 'template')); + $this->assertEquals($responseBody, $response->getBody()); + $this->assertEquals(200, $response->getStatusCode()); } - public function testAllWithOutFilter() + public function testDelete() { - $responseMock = Mockery::mock(); + $responseMock = Mockery::mock('Psr\Http\Message\ResponseInterface'); + $responseBodyMock = Mockery::mock(); + $responseBody = ['results' => 'yay']; - $this->sparkPostMock->httpAdapter->shouldReceive('send')-> + + $this->resource->httpClient->shouldReceive('sendRequest')-> once()-> - with('/.*\/transmissions/', 'GET', Mockery::type('array'), null)-> + with(Mockery::type('GuzzleHttp\Psr7\Request'))-> andReturn($responseMock); + $responseMock->shouldReceive('getStatusCode')->andReturn(200); + $responseMock->shouldReceive('getBody')->andReturn($responseBodyMock); + $responseBodyMock->shouldReceive('__toString')->andReturn(json_encode($responseBody)); - $responseMock->shouldReceive('getBody->getContents')->andReturn(json_encode($responseBody)); + $response = $this->resource->transmissions->delete($this->getTransmissionPayload); - $this->assertEquals($responseBody, $this->resource->all()); + $this->assertEquals($responseBody, $response->getBody()); + $this->assertEquals(200, $response->getStatusCode()); } - public function testFind() + public function testFormatPayload() { - $responseMock = Mockery::mock(); - $responseBody = ['results' => 'yay']; - $this->sparkPostMock->httpAdapter->shouldReceive('send')-> - once()-> - with('/.*\/transmissions.*\/test/', 'GET', Mockery::type('array'), null)-> - andReturn($responseMock); - $responseMock->shouldReceive('getStatusCode')->andReturn(200); - - $responseMock->shouldReceive('getBody->getContents')->andReturn(json_encode($responseBody)); + $correctFormattedPayload = json_decode('{"content":{"from":{"name":"Sparkpost Team","email":"postmaster@sendmailfor.me"},"subject":"First Mailing From PHP","text":"Congratulations, {{name}}!! You just sent your very first mailing!","headers":{"CC":"avi.goldman@sparkpost.com"}},"substitution_data":{"name":"Avi"},"recipients":[{"address":{"name":"Vincent","email":"vincent.song@sparkpost.com"}},{"address":{"email":"test@example.com"}},{"address":{"email":"emely.giraldo@sparkpost.com","header_to":"\"Vincent\" "}},{"address":{"email":"avi.goldman@sparkpost.com","header_to":"\"Vincent\" "}}]}', true); - $this->assertEquals($responseBody, $this->resource->find('test')); + $formattedPayload = $this->resource->transmissions->formatPayload($this->postTransmissionPayload); + $this->assertEquals($correctFormattedPayload, $formattedPayload); } }