diff --git a/.gitignore b/.gitignore index e683c24..b3cda34 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +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/composer.json b/composer.json index a38b8c4..d8b97fa 100644 --- a/composer.json +++ b/composer.json @@ -9,8 +9,8 @@ ], "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 ." }, diff --git a/composer.lock b/composer.lock index 561ee61..9c5d64e 100644 --- a/composer.lock +++ b/composer.lock @@ -1162,4 +1162,4 @@ "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 986fd87..0000000 --- a/examples/transmission/send_transmission_all_fields.php +++ /dev/null @@ -1,69 +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), - ], - ], - ]); - - 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 7479c4a..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 7ad2a7b..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..6f8ecbe --- /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()); +} 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..6c6e476 --- /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()); +} 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..dc893ed --- /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()); +} 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..3cb1233 --- /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()); +} 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 d3a44c5..0000000 --- a/examples/unwrapped/create_transmission.php +++ /dev/null @@ -1,46 +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/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 e76bcd0..cbf761f 100644 --- a/lib/SparkPost/SparkPost.php +++ b/lib/SparkPost/SparkPost.php @@ -32,7 +32,6 @@ class SparkPost 'port' => 443, 'key' => '', 'version' => 'v1', - 'timeout' => 10, 'async' => true, ]; @@ -230,10 +229,10 @@ public function setOptions($options) } /** - * Sets up any endpoints from custom classes e.g. $this->transmissions. + * Sets up any endpoints to custom classes e.g. $this->transmissions. */ private function setupEndpoints() { - // $this->transmissions = new Transmission($this); + $this->transmissions = new Transmission($this); } } diff --git a/lib/SparkPost/SparkPostPromise.php b/lib/SparkPost/SparkPostPromise.php index 15f129f..df715d5 100644 --- a/lib/SparkPost/SparkPostPromise.php +++ b/lib/SparkPost/SparkPostPromise.php @@ -29,12 +29,14 @@ public function __construct(HttpPromise $promise) */ public function then(callable $onFulfilled = null, callable $onRejected = null) { - return $this->promise->then(function($response) use ($onFulfilled) { - if (isset($onFulfilled)) + return $this->promise->then(function ($response) use ($onFulfilled) { + if (isset($onFulfilled)) { $onFulfilled(new SparkPostResponse($response)); - }, function($exception) use ($onRejected) { - if (isset($onRejected)) + } + }, function ($exception) use ($onRejected) { + if (isset($onRejected)) { $onRejected(new SparkPostException($exception)); + } }); } @@ -61,6 +63,7 @@ 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 index 9104b33..e6a8fd1 100644 --- a/lib/SparkPost/SparkPostResponse.php +++ b/lib/SparkPost/SparkPostResponse.php @@ -34,10 +34,12 @@ public function getBody() $json = json_decode($body_string, true); - return $json; + return $json; } - // pass these down to the response given in the constructor + /** + * pass these down to the response given in the constructor. + */ public function getProtocolVersion() { return $this->response->getProtocolVersion(); diff --git a/lib/SparkPost/Transmission.php b/lib/SparkPost/Transmission.php new file mode 100644 index 0000000..6c45c7e --- /dev/null +++ b/lib/SparkPost/Transmission.php @@ -0,0 +1,192 @@ +formatPayload($payload); + + return parent::post($payload, $headers); + } + + /** + * Runs the given payload through the formatting functions. + * + * @param array $payload - the request body + * + * @return array - the modified request body + */ + 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; + } + + /** + * Formats bcc list into recipients list. + * + * @param array $payload - the request body + * + * @return array - the modified request body + */ + private function formatBlindCarbonCopy($payload) + { + + //If there's a list of BCC recipients, move then into the correct format + if (isset($payload['bcc'])) { + $payload = $this->addListToRecipients($payload, 'bcc'); + } + + return $payload; + } + + /** + * Formats cc list into recipients list and adds the CC header to the content. + * + * @param array $payload - the request body + * + * @return array - the modified request body + */ + private function formatCarbonCopy($payload) + { + 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'); + } + + 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 $payload; + } + + /** + * Loops through the given listName in the payload and adds all the recipients to the recipients list after removing their names. + * + * @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 - 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 + */ + private function isEmail($email) + { + if (filter_var($email, FILTER_VALIDATE_EMAIL)) { + return true; + } else { + return false; + } + } +} diff --git a/test/unit/SparkPostResponseTest.php b/test/unit/SparkPostResponseTest.php index db8600a..efdec1a 100644 --- a/test/unit/SparkPostResponseTest.php +++ b/test/unit/SparkPostResponseTest.php @@ -1,14 +1,13 @@ returnValue = 'some_value_to_return'; + $this->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->responseMock->shouldReceive('getProtocolVersion')->andReturn($this->returnValue); + $sparkpostResponse = new SparkPostResponse($this->responseMock); $this->assertEquals($this->responseMock->getProtocolVersion(), $sparkpostResponse->getProtocolVersion()); } public function testWithProtocolVersion() - { - $param = 'protocol version'; + { + $param = 'protocol version'; - $this->responseMock->shouldReceive('withProtocolVersion')->andReturn($this->returnValue); - $sparkpostResponse = new SparkPostResponse($this->responseMock); + $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->responseMock->shouldReceive('getHeaders')->andReturn($this->returnValue); + $sparkpostResponse = new SparkPostResponse($this->responseMock); $this->assertEquals($this->responseMock->getHeaders(), $sparkpostResponse->getHeaders()); } public function testHasHeader() - { - $param = 'header'; + { + $param = 'header'; - $this->responseMock->shouldReceive('hasHeader')->andReturn($this->returnValue); - $sparkpostResponse = new SparkPostResponse($this->responseMock); + $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'; + $param = 'header'; - $this->responseMock->shouldReceive('getHeader')->andReturn($this->returnValue); - $sparkpostResponse = new SparkPostResponse($this->responseMock); + $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'; + $param = 'header'; - $this->responseMock->shouldReceive('getHeaderLine')->andReturn($this->returnValue); - $sparkpostResponse = new SparkPostResponse($this->responseMock); + $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'; + $param = 'header'; + $param2 = 'value'; - $this->responseMock->shouldReceive('withHeader')->andReturn($this->returnValue); - $sparkpostResponse = new SparkPostResponse($this->responseMock); + $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'; - + $param = 'header'; + $param2 = 'value'; - $this->responseMock->shouldReceive('withAddedHeader')->andReturn($this->returnValue); - $sparkpostResponse = new SparkPostResponse($this->responseMock); + $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'; + { + $param = 'header'; - $this->responseMock->shouldReceive('withoutHeader')->andReturn($this->returnValue); - $sparkpostResponse = new SparkPostResponse($this->responseMock); + $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'); + $param = Mockery::mock('Psr\Http\Message\StreamInterface'); - $this->responseMock->shouldReceive('withBody')->andReturn($this->returnValue); - $sparkpostResponse = new SparkPostResponse($this->responseMock); + $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->responseMock->shouldReceive('getStatusCode')->andReturn($this->returnValue); + $sparkpostResponse = new SparkPostResponse($this->responseMock); $this->assertEquals($this->responseMock->getStatusCode(), $sparkpostResponse->getStatusCode()); } public function testWithStatus() { - $param = 'status'; + $param = 'status'; - $this->responseMock->shouldReceive('withStatus')->andReturn($this->returnValue); - $sparkpostResponse = new SparkPostResponse($this->responseMock); + $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->responseMock->shouldReceive('getReasonPhrase')->andReturn($this->returnValue); + $sparkpostResponse = new SparkPostResponse($this->responseMock); $this->assertEquals($this->responseMock->getReasonPhrase(), $sparkpostResponse->getReasonPhrase()); } } -?> \ No newline at end of file diff --git a/test/unit/SparkPostTest.php b/test/unit/SparkPostTest.php index c5dca08..f1c8a56 100644 --- a/test/unit/SparkPostTest.php +++ b/test/unit/SparkPostTest.php @@ -3,16 +3,10 @@ namespace SparkPost\Test; use SparkPost\SparkPost; -use SparkPost\SparkPostResponse; use SparkPost\SparkPostPromise; -use Psr\Http\Message\ResponseInterface; -use Http\Promise\Promise; -use GuzzleHttp\Promise\Promise as GuzzlePromise; use GuzzleHttp\Promise\FulfilledPromise as GuzzleFulfilledPromise; use GuzzleHttp\Promise\RejectedPromise as GuzzleRejectedPromise; use Http\Adapter\Guzzle6\Promise as GuzzleAdapterPromise; -use Http\Client\Exception\HttpException; -use Http\Adapter\Guzzle6\Client; use Mockery; use SparkPost\Test\TestUtils\ClassUtils; @@ -25,18 +19,18 @@ class SparkPostTest extends \PHPUnit_Framework_TestCase private $postTransmissionPayload = [ 'content' => [ - 'from' => [ 'name' => 'Sparkpost Team', 'email' => 'postmaster@sendmailfor.me' ], + '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'] - ] + ['address' => 'avi.goldman@sparkpost.com'], + ], ]; - + private $getTransmissionPayload = [ - 'campaign_id' => 'thanksgiving' + 'campaign_id' => 'thanksgiving', ]; /** @@ -60,12 +54,12 @@ public function tearDown() Mockery::close(); } - public function testRequest() { + 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]); @@ -155,7 +149,7 @@ public function testUnsuccessfulAsyncRequestWithWait() once()-> with(Mockery::type('GuzzleHttp\Psr7\Request'))-> andReturn($promiseMock); - + $promiseMock->shouldReceive('wait')->andThrow($exceptionMock); $exceptionMock->shouldReceive('getResponse->getStatusCode')->andReturn(500); @@ -171,7 +165,8 @@ public function testUnsuccessfulAsyncRequestWithWait() } } - public function testSuccessfulAsyncRequestWithThen() { + public function testSuccessfulAsyncRequestWithThen() + { $responseBody = ['results' => 'yay']; $responseMock = Mockery::mock('Psr\Http\Message\ResponseInterface'); $responseBodyMock = Mockery::mock(); @@ -180,26 +175,27 @@ public function testSuccessfulAsyncRequestWithThen() { $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) { + $promise->then(function ($exception) use ($responseBody) { $this->assertEquals(200, $exception->getStatusCode()); $this->assertEquals($responseBody, $exception->getBody()); }, null)->wait(); } - public function testUnsuccessfulAsyncRequestWithThen() { + public function testUnsuccessfulAsyncRequestWithThen() + { $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) { + $promise->then(null, function ($exception) use ($responseBody) { $this->assertEquals(500, $exception->getCode()); $this->assertEquals($responseBody, $exception->getBody()); })->wait(); @@ -220,7 +216,7 @@ public function testPromise() $this->assertEquals($promiseMock->getState(), $promise->getState()); $promiseMock->shouldReceive('getState')->once()->andReturn('rejected'); - $this->assertEquals('rejected', $promise->getState()); + $this->assertEquals('rejected', $promise->getState()); } /** @@ -228,7 +224,6 @@ public function testPromise() */ public function testUnsupportedAsyncRequest() { - $this->resource->setHttpClient(Mockery::mock('Http\Client\HttpClient')); $this->resource->asyncRequest('POST', 'transmissions', $this->postTransmissionPayload); @@ -237,7 +232,7 @@ public function testUnsupportedAsyncRequest() public function testGetHttpHeaders() { $headers = $this->resource->getHttpHeaders([ - 'Custom-Header' => 'testing' + 'Custom-Header' => 'testing', ]); $version = self::$utils->getProperty($this->resource, 'version'); @@ -276,5 +271,4 @@ public function testSetBadOptions() 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 new file mode 100644 index 0000000..84f16f0 --- /dev/null +++ b/test/unit/TransmissionTest.php @@ -0,0 +1,177 @@ + [ + '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). + * + * @before + * + * @see PHPUnit_Framework_TestCase::setUp() + */ + public function setUp() + { + //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); + } + + public function tearDown() + { + Mockery::close(); + } + + /** + * @expectedException Exception + */ + public function testInvalidEmailFormat() + { + $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->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->transmissions->get($this->getTransmissionPayload); + + $this->assertEquals($responseBody, $response->getBody()); + $this->assertEquals(200, $response->getStatusCode()); + } + + public function testPut() + { + $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->transmissions->put($this->getTransmissionPayload); + + $this->assertEquals($responseBody, $response->getBody()); + $this->assertEquals(200, $response->getStatusCode()); + } + + public function testPost() + { + $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->transmissions->post($this->postTransmissionPayload); + + $this->assertEquals($responseBody, $response->getBody()); + $this->assertEquals(200, $response->getStatusCode()); + } + + public function testDelete() + { + $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->transmissions->delete($this->getTransmissionPayload); + + $this->assertEquals($responseBody, $response->getBody()); + $this->assertEquals(200, $response->getStatusCode()); + } + + public function testFormatPayload() + { + $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); + + $formattedPayload = $this->resource->transmissions->formatPayload($this->postTransmissionPayload); + $this->assertEquals($correctFormattedPayload, $formattedPayload); + } +}