├── .gitignore
├── examples
├── _autoload.php
└── user.php
├── composer.json
├── sailthru
├── Sailthru_Client_Exception.php
├── Sailthru_Util.php
└── Sailthru_Client.php
├── tests
├── Sailthru_Client_ExceptionTest.php
├── Sailthru_UtilTest.php
└── Sailthru_ClientTest.php
├── .travis.yml
├── phpunit.xml.dist
├── MIT-LICENSE
├── CHANGELOG.md
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | *.swp
2 | composer.lock
3 | phpunit.xml
4 | vendor/
5 |
6 |
--------------------------------------------------------------------------------
/examples/_autoload.php:
--------------------------------------------------------------------------------
1 | getEmail("praj@sailthru.com");
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | dist: trusty
2 | language: php
3 | php:
4 | - 5.4
5 | - 5.5
6 | - 5.6
7 | - 7.0
8 | - 7.1
9 | - hhvm
10 |
11 | env: COVERAGE=0
12 |
13 | matrix:
14 | include:
15 | - php: 5.6
16 | env: COVERAGE=1
17 |
18 | before_script:
19 | - if [[ "$COVERAGE" -eq 0 ]]; then composer install; else composer require satooshi/php-coveralls --dev; fi
20 |
21 | script:
22 | - if [[ "$COVERAGE" -eq 0 ]]; then vendor/bin/phpunit; else mkdir -p build/logs; vendor/bin/phpunit --coverage-clover=build/logs/clover.xml; fi
23 |
24 | after_success:
25 | - if [[ "$COVERAGE" -gt 0 ]]; then vendor/bin/coveralls; fi
26 |
--------------------------------------------------------------------------------
/phpunit.xml.dist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
14 |
15 |
16 | ./tests
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/MIT-LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2016 Sailthru, Inc., http://www.sailthru.com/
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining
4 | a copy of this software and associated documentation files (the
5 | "Software"), to deal in the Software without restriction, including
6 | without limitation the rights to use, copy, modify, merge, publish,
7 | distribute, sublicense, and/or sell copies of the Software, and to
8 | permit persons to whom the Software is furnished to do so, subject to
9 | the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be
12 | included in all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/tests/Sailthru_UtilTest.php:
--------------------------------------------------------------------------------
1 | params = array(
7 | 'item1' => 'value1',
8 | 'item2' => 'value2',
9 | 'item3' => array('value3', 'value4'),
10 | 'item4' => false,
11 | 'item5' => true
12 | );
13 | }
14 |
15 | public function testExtractParamValues() {
16 | $expected = array('value1', 'value2', 'value3', 'value4', 0, 1);
17 | $actual = array();
18 | Sailthru_Util::extractParamValues($this->params, $actual);
19 | $this->assertEquals(array_values($expected), $actual);
20 | }
21 |
22 | public function testGetSignatureString() {
23 | $expected_arr = array('value1', 'value2', 'value3', 'value4', 0, 1);
24 | $secret = "ABCXYZ";
25 | $expected_str = $secret;
26 | sort($expected_arr, SORT_STRING);
27 | foreach ($expected_arr as $val) {
28 | $expected_str .= $val;
29 | }
30 | $actual_signature_str = Sailthru_Util::getSignatureString($this->params, $secret);
31 | $this->assertEquals($expected_str, $actual_signature_str);
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## 1.2.1 (May 11th, 2016)
2 | - Fix typo, make tests pass
3 |
4 | ## 1.2.0 (May 4th, 2016)
5 | - Added getLastRateLimitInfo() call
6 |
7 | ## 1.1.0 (July 16, 2014)
8 | - Bump Version number for packagist to pick up
9 | - Removed contact import API call
10 | - Added stats_send call
11 | - Updated cancelSend()
12 | - Added Preview and Trigger API calls
13 | - Removed createNewUser() call
14 | - Removed setHorizon() call
15 | - Added Event call
16 | - Added options to pushContent()
17 | ## 1.09 (October 31, 2011)
18 | - Purchase API call
19 |
20 | ## 1.08 (September 07, 2011)
21 | - Added getBlasts() for querying blasts meta-data
22 | - Update job methods: processUpdateJob(), processUpdateJobFromUrl(), processUpdateJobFromFile() and processUpdateJobFromEmails()
23 | - Fixed bug for purchase API request
24 |
25 | ## 1.07 (June 02, 2011)
26 | - Preserve data type when sending to the server, All data are sent in json encoded format
27 | - Job API Call with file uploading support
28 | - Template Revisions
29 |
30 | ## 1.06 (May 14, 2011)
31 | - Added Hard bounce postback call
32 | - Added delete template API call
33 | - Added getLastResponseInfo()
34 | - Bug Fix: When boolean False is used for any parameter values, generated signature hash gets invalidated
--------------------------------------------------------------------------------
/examples/user.php:
--------------------------------------------------------------------------------
1 |
2 | require('_autoload.php');
3 |
4 | $api_key = "SAILTHRU-API-KEY";
5 | $api_secret = "SAILTHRU-API-SECRET";
6 |
7 | $client = new Sailthru_Client($api_key, $api_secret);
8 | try {
9 | // update existing user by Sailthru ID
10 | $response = $client->saveUser("4e2879472d7acd6d97144f9e", array(
11 | 'keys' => array(
12 | 'email' => 'praj@sailthru.com',
13 | 'twitter' => 'infynyxx',
14 | 'fb' => 726310296
15 | ),
16 | 'lists' => array(
17 | 'list-1' => 1,
18 | 'list-2' => 1,
19 | 'list-3' => 0
20 | )
21 | ));
22 |
23 | //update existing user by email or create new user using email address
24 | $response = $client->saveUser('praj@sailthru.com', array(
25 | 'key' => 'email',
26 | 'lists' => array(
27 | 'list-1' => 0 // optout from list-1
28 | )
29 | ));
30 |
31 | // get user by Sailthru ID
32 | $fields = array(
33 | 'keys' => 1,
34 | 'vars' => 1,
35 | 'activity' => 1
36 | );
37 | $response = $client->getUseBySid("4e2879472d7acd6d97144f9e", $fields);
38 |
39 | // get user by Custom key
40 | $response = $client->getUserByKey("praj@sailthru.com", 'email', $fields);
41 |
42 | // get last rate limit info
43 | $rate_limit_info = $client->getLastRateLimitInfo("user", "GET");
44 |
45 | } catch (Sail_Client_Exception $e) {
46 | // deal with exception
47 | }
48 |
--------------------------------------------------------------------------------
/sailthru/Sailthru_Util.php:
--------------------------------------------------------------------------------
1 | $v) {
44 | if (is_array($v) || is_object($v)) {
45 | self::extractParamValues($v, $values);
46 | } else {
47 | if (is_bool($v)) {
48 | //if a value is set as false, invalid hash will generate
49 | //https://github.com/sailthru/sailthru-php5-client/issues/4
50 | $v = intval($v);
51 | }
52 | $values[] = $v;
53 | }
54 | }
55 | }
56 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | sailthru-php5-client
2 | ====================
3 |
4 | [](https://travis-ci.org/sailthru/sailthru-php5-client)
5 | [](https://coveralls.io/github/sailthru/sailthru-php5-client?branch=master)
6 |
7 | For installation instructions, documentation, and examples please visit:
8 | [http://getstarted.sailthru.com/new-for-developers-overview/api-client-library/php5](http://getstarted.sailthru.com/new-for-developers-overview/api-client-library/php5)
9 |
10 | A simple client library to remotely access the `Sailthru REST API` as per [http://getstarted.sailthru.com/developers/api](http://getstarted.sailthru.com/developers/api)
11 |
12 | By default, it will make request in `JSON` format.
13 |
14 | ## Optional parameters for connection/read timeout settings
15 |
16 | Increase timeout from 10 (default) to 30 seconds.
17 |
18 | $client = new Sailthru_Client($this->api_key, $this->secret, $this->api_url, array('timeout' => 30000, 'connect_timeout' => 30000));
19 |
20 | ## API Rate Limiting
21 |
22 | Here is an example how to check rate limiting and throttle API calls based on that. For more information about Rate Limiting, see [Sailthru Documentation](https://getstarted.sailthru.com/new-for-developers-overview/api/api-technical-details/#Rate_Limiting)
23 |
24 |
25 | ```php
26 | // get last rate limit info
27 | $rate_limit_info = $sailthru_client->getLastRateLimitInfo("user", "POST");
28 |
29 | // getRateLimitInfo returns null if given endpoint/method wasn't triggered previously
30 | if ($rate_limit_info) {
31 | $limit = $rate_limit_info['limit'];
32 | $remaining = $rate_limit_info['remaining'];
33 | $reset_timestamp = $rate_limit_info['reset'];
34 |
35 | // throttle api calls based on last rate limit info
36 | if ($remaining <= 0) {
37 | $seconds_till_reset = $reset_timestamp - time();
38 |
39 | // sleep or perform other business logic before next user api call
40 | sleep($seconds_till_reset);
41 | }
42 | }
43 | ```
44 |
45 | ## Tests
46 |
47 | You can run the tests locally with:
48 |
49 | ```shell
50 | vendor/bin/phpunit
51 | ```
52 |
53 |
54 |
--------------------------------------------------------------------------------
/tests/Sailthru_ClientTest.php:
--------------------------------------------------------------------------------
1 | api_key, $this->api_secret, $this->api_url);
13 | $this->assertEquals(10000, $sailthru_client->getTimeout());
14 | $this->assertEquals(10000, $sailthru_client->getConnectTimeout());
15 | }
16 |
17 | public function testCustomTimeoutParameter() {
18 | $sailthru_client = new Sailthru_Client($this->api_key, $this->api_secret, $this->api_url,
19 | array('timeout' => 1, 'connect_timeout' => 2));
20 | $this->assertEquals(1, $sailthru_client->getTimeout());
21 | $this->assertEquals(2, $sailthru_client->getConnectTimeout());
22 | }
23 |
24 | public function testSendWhenTemplateNameIsInvalid() {
25 | $template_name = 'invalid_template';
26 | $email = 'praj@sailthru.com';
27 | $json_response = json_encode(array('error' => 14, 'errormsg' => 'Unknown template: ' . $template_name));
28 | $mock = $this->getMock('Sailthru_Client', array('send'), array($this->api_key, $this->api_secret, $this->api_url));
29 | $mock->expects($this->once())
30 | ->method('send')
31 | ->will($this->returnValue($json_response));
32 | $this->assertEquals($json_response, $mock->send($template_name, $email));
33 | }
34 |
35 | public function testSendWhenTemplateIsValid() {
36 | $template_name = 'my_template';
37 | $email = 'praj@sailthru.com';
38 | $json_response = json_encode(array('email' => $email, 'send_id' => 'some_unique_id', 'template' => $template_name, 'status' => 'unknown'));
39 | $mock = $this->getMock('Sailthru_Client', array('send'), array($this->api_key, $this->api_secret, $this->api_url));
40 | $mock->expects($this->once())
41 | ->method('send')
42 | ->will($this->returnvalue($json_response));
43 | $this->assertEquals($json_response, $mock->send($template_name, $email));
44 | }
45 |
46 | public function testApiPostWithValidJsonResponse() {
47 | $mock = $this->getMock('Sailthru_Client', array('apiPost'), array($this->api_key, $this->api_secret, $this->api_url));
48 | $json_response = array(
49 | 'email' => 'praj@infynyxx.com',
50 | 'profile_id' => '4f284c28a3a627b6389bfb4c',
51 | 'verified' => 0,
52 | 'vars' => array(
53 | 'name' => 'Prajwal Tuladhar'
54 | )
55 | );
56 | $mock->expects($this->once())
57 | ->method('apiPost')
58 | ->will($this->returnValue($json_response));
59 | $this->assertTrue(is_array($mock->apiPost('email', $json_response)));
60 | }
61 |
62 |
63 | /**
64 | * @expectedException Sailthru_Client_Exception
65 | */
66 | public function testApiPostWithInvalidJsonResponse() {
67 | $mock = $this->getMock('Sailthru_Client', array('apiPost'), array($this->api_key, $this->api_secret, $this->api_url));
68 | $mock->expects($this->once())
69 | ->method('apiPost')
70 | ->will($this->throwException(new Sailthru_Client_Exception()));
71 | $response = $mock->apiPost('email', array('email' => 'praj@infynyxx.com'));
72 | $this->assertTrue(is_array($response)); // this will never be called
73 | }
74 |
75 | public function testPrepareJsonPayload() {
76 | $this->sailthru_client = new Sailthru_Client($this->api_key, $this->api_secret, $this->api_url);
77 | $method = new ReflectionMethod('Sailthru_Client', 'prepareJsonPayload');
78 | $method->setAccessible(true);
79 | $json_payload_without_binary_data = array(
80 | 'email' => 'praj@infynyxx.com',
81 | 'vars' => array(
82 | 'name' => 'Prajwal Tuladhar'
83 | ),
84 | 'action' => 'user'
85 | );
86 | $invoked = $method->invoke($this->sailthru_client, $json_payload_without_binary_data);
87 | $this->assertEquals($invoked['api_key'], $this->api_key);
88 | $this->assertTrue(isset($invoked['sig']));
89 | }
90 |
91 | public function testPrepareJsonPayloadWithBinaryData() {
92 | $this->sailthru_client = new Sailthru_Client($this->api_key, $this->api_secret, $this->api_url);
93 | $method = new ReflectionMethod('Sailthru_Client', 'prepareJsonPayload');
94 | $method->setAccessible(true);
95 | $json_payload = array(
96 | 'email' => 'praj@infynyxx.com',
97 | 'vars' => array(
98 | 'name' => 'Prajwal Tuladhar'
99 | ),
100 | 'action' => 'user'
101 | );
102 | $binary_data_param = array('file' => '/tmp/file.txt');
103 | $invoked = $method->invoke($this->sailthru_client, $json_payload, $binary_data_param);
104 | $this->assertEquals($invoked['api_key'], $this->api_key);
105 | $this->assertEquals($invoked['file'], $binary_data_param['file']);
106 | }
107 |
108 | public function testParseRateLimitHeaders() {
109 | $sailthru_client = new Sailthru_Client($this->api_key, $this->api_secret, $this->api_url);
110 | $method = new ReflectionMethod("Sailthru_Client", "parseRateLimitHeaders");
111 | $method->setAccessible(true);
112 | $headers = <<invoke($sailthru_client, $headers);
124 | $expected = ['limit' => 40, 'remaining' => 3, "reset" => 1459190520];
125 | $this->assertEquals($expected, $parsed_rate_limit);
126 | }
127 | }
128 |
--------------------------------------------------------------------------------
/sailthru/Sailthru_Client.php:
--------------------------------------------------------------------------------
1 | Sailthru_Client::DEFAULT_READ_TIMEOUT, 'connect_timeout' => Sailthru_Client::DEFAULT_CONNECT_TIMEOUT ];
69 |
70 | /**
71 | * Instantiate a new client; constructor optionally takes overrides for api_uri and whether
72 | * to share the version of PHP that is being used.
73 | *
74 | * @param string $api_key
75 | * @param string $secret
76 | * @param string $api_uri
77 | * @param array $options - optional parameters for connect/read timeout
78 | */
79 | public function __construct($api_key, $secret, $api_uri = false, $options = null) {
80 | $this->api_key = $api_key;
81 | $this->secret = $secret;
82 | if ($api_uri !== false) {
83 | $this->api_uri = $api_uri;
84 | }
85 |
86 | $this->http_request_type = function_exists('curl_init') ? 'httpRequestCurl' : 'httpRequestWithoutCurl';
87 |
88 | if (isset($options)) {
89 | $this->options['timeout'] = isset($options['timeout']) ? (int) $options['timeout'] : Sailthru_Client::DEFAULT_READ_TIMEOUT;
90 | $this->options['connect_timeout'] =
91 | isset($options['connect_timeout']) ? (int) $options['connect_timeout'] : Sailthru_Client::DEFAULT_CONNECT_TIMEOUT;
92 | }
93 | }
94 |
95 | public function getConnectTimeout() {
96 | return $this->options['connect_timeout'];
97 | }
98 |
99 | public function getTimeout() {
100 | return $this->options['timeout'];
101 | }
102 |
103 | public function setHttpHeaders(array $headers) {
104 | $this->httpHeaders = array_merge($this->httpHeaders, $headers);
105 | return true;
106 | }
107 |
108 | /**
109 | * Remotely send an email template to a single email address.
110 | *
111 | * If you pass the $schedule_time parameter, the send will be scheduled for a future time.
112 | *
113 | * Options:
114 | * replyto: override Reply-To header
115 | * test: send as test email (subject line will be marked, will not count towards stats)
116 | *
117 | * @param string $template
118 | * @param string $email
119 | * @param array $vars
120 | * @param array $options
121 | * @param string $schedule_time
122 | * @link http://docs.sailthru.com/api/send
123 | * @return array API result
124 | */
125 | public function send($template, $email, $vars = [ ], $options = [ ], $schedule_time = null) {
126 | $post = [ ];
127 | $post['template'] = $template;
128 | $post['email'] = $email;
129 | $post['vars'] = $vars;
130 | $post['options'] = $options;
131 | if ($schedule_time) {
132 | $post['schedule_time'] = $schedule_time;
133 | }
134 | $result = $this->apiPost('send', $post);
135 | return $result;
136 | }
137 |
138 | /**
139 | * Remotely send an email template to multiple email addresses.
140 | *
141 | * Use the evars parameter to set replacement vars for a particular email address.
142 | *
143 | * @param string $template_name
144 | * @param array $emails
145 | * @param array $vars
146 | * @param array $evars
147 | * @param array $options
148 | * @link http://docs.sailthru.com/api/send
149 | * @return array API result
150 | */
151 | public function multisend($template_name, $emails, $vars = [ ], $evars = [ ], $options = [ ]) {
152 | $post['template'] = $template_name;
153 | $post['email'] = is_array($emails) ? implode(',', $emails) : $emails;
154 | $post['vars'] = $vars;
155 | $post['evars'] = $evars;
156 | $post['options'] = $options;
157 | $result = $this->apiPost('send', $post);
158 | return $result;
159 | }
160 |
161 | /**
162 | * Get the status of a send.
163 | *
164 | * @param string $send_id
165 | * @link http://docs.sailthru.com/api/send
166 | * @return array API result
167 | */
168 | public function getSend($send_id) {
169 | return $this->apiGet('send', [ 'send_id' => $send_id ]);
170 | }
171 |
172 | /**
173 | * Cancel a send that was scheduled for a future time.
174 | *
175 | * @param string $send_id
176 | * @link http://docs.sailthru.com/api/send
177 | * @return array API result
178 | */
179 | public function cancelSend($send_id) {
180 | return $this->apiDelete('send', [ 'send_id' => $send_id ]);
181 | }
182 |
183 | /**
184 | * Return information about an email address, including replacement vars and lists.
185 | *
186 | * @param string $email
187 | * @param array $options
188 | * @link http://docs.sailthru.com/api/email
189 | * @return array API result
190 | */
191 | public function getEmail($email, array $options = [ ]) {
192 | return $this->apiGet('email', array_merge([ 'email' => $email ], $options));
193 | }
194 |
195 | /**
196 | * Set replacement vars and/or list subscriptions for an email address.
197 | *
198 | * $lists should be an assoc array mapping list name => 1 for subscribed, 0 for unsubscribed
199 | *
200 | * @param string $email
201 | * @param array $vars
202 | * @param array $lists
203 | * @param array $templates
204 | * @param integer $verified 1 or 0
205 | * @param string $optout
206 | * @param string $send
207 | * @param array $send_vars
208 | * @link http://docs.sailthru.com/api/email
209 | * @return array API result
210 | */
211 | public function setEmail($email, $vars = [ ], $lists = [ ], $templates = [ ], $verified = 0, $optout = null, $send = null, $send_vars = [ ]) {
212 | $data = [ 'email' => $email ];
213 | if ($vars) {
214 | $data['vars'] = $vars;
215 | }
216 | if ($lists) {
217 | $data['lists'] = $lists;
218 | }
219 | if ($templates) {
220 | $data['templates'] = $templates;
221 | }
222 | $data['verified'] = (int) $verified;
223 | if ($optout !== null) {
224 | $data['optout'] = $optout;
225 | }
226 | if ($send !== null) {
227 | $data['send'] = $send;
228 | }
229 | if (!empty($send_vars)) {
230 | $data['send_vars'] = $send_vars;
231 | }
232 |
233 | return $this->apiPost('email', $data);
234 | }
235 |
236 | /**
237 | * Update / add email address
238 | *
239 | * @link http://docs.sailthru.com/api/email
240 | * @return array API result
241 | */
242 | public function setEmail2($email, array $options = [ ]) {
243 | $options['email'] = $email;
244 | return $this->apiPost('email', $options);
245 | }
246 |
247 | /**
248 | * Schedule a mass mail blast
249 | *
250 | * @param string $name the name to give to this new blast
251 | * @param string $list the mailing list name to send to
252 | * @param string $schedule_time when the blast should send. Dates in the past will be scheduled for immediate delivery. Any English textual datetime format known to PHP's strtotime function is acceptable, such as 2009-03-18 23:57:22 UTC, now (immediate delivery), +3 hours (3 hours from now), or February 14, 9:30 EST. Be sure to specify a timezone if you use an exact time.
253 | * @param string $from_name the name appearing in the "From" of the email
254 | * @param string $from_email The email address to use as the "from" – choose from any of your verified emails
255 | * @param string $subject the subject line of the email
256 | * @param string $content_html the HTML-format version of the email
257 | * @param string $content_text the text-format version of the email
258 | * @param array $options associative array
259 | * blast_id
260 | * copy_blast
261 | * copy_template
262 | * replyto
263 | * report_email
264 | * is_link_tracking
265 | * is_google_analytics
266 | * is_public
267 | * suppress_list
268 | * test_vars
269 | * email_hour_range
270 | * abtest
271 | * test_percent
272 | * data_feed_url
273 | * @link http://docs.sailthru.com/api/blast
274 | * @return array API result
275 | */
276 | public function scheduleBlast($name, $list, $schedule_time, $from_name,
277 | $from_email, $subject, $content_html, $content_text, $options = [ ]
278 | ) {
279 | $data = $options;
280 | $data['name'] = $name;
281 | $data['list'] = $list;
282 | $data['schedule_time'] = $schedule_time;
283 | $data['from_name'] = $from_name;
284 | $data['from_email'] = $from_email;
285 | $data['subject'] = $subject;
286 | $data['content_html'] = $content_html;
287 | $data['content_text'] = $content_text;
288 |
289 | return $this->apiPost('blast', $data);
290 | }
291 |
292 | /**
293 | * Schedule a mass mail from a template
294 | *
295 | * @param String $template
296 | * @param String $list
297 | * @param String $schedule_time
298 | * @param array $options
299 | * @link http://docs.sailthru.com/api/blast
300 | * @return array API result
301 | **/
302 | public function scheduleBlastFromTemplate($template, $list, $schedule_time, $options = [ ]) {
303 | $data = $options;
304 | $data['copy_template'] = $template;
305 | $data['list'] = $list;
306 | $data['schedule_time'] = $schedule_time;
307 | return $this->apiPost('blast', $data);
308 | }
309 |
310 | /**
311 | * Schedule a mass mail blast from previous blast
312 | *
313 | * @param String|Integer $blast_id
314 | * @param String $schedule_time
315 | * @param array $options
316 | * @link http://docs.sailthru.com/api/blast
317 | * @return array API result
318 | **/
319 | public function scheduleBlastFromBlast($blast_id, $schedule_time, $options = [ ]) {
320 | $data = $options;
321 | $data['copy_blast'] = $blast_id;
322 | $data['schedule_time'] = $schedule_time;
323 | return $this->apiPost('blast', $data);
324 | }
325 |
326 | /**
327 | * updates existing blast
328 | *
329 | * @param string /integer $blast_id
330 | * @param string $name
331 | * @param string $list
332 | * @param string $schedule_time
333 | * @param string $from_name
334 | * @param string $from_email
335 | * @param string $subject
336 | * @param string $content_html
337 | * @param string $content_text
338 | * @param array $options associative array
339 | * blast_id
340 | * copy_blast
341 | * copy_template
342 | * replyto
343 | * report_email
344 | * is_link_tracking
345 | * is_google_analytics
346 | * is_public
347 | * suppress_list
348 | * test_vars
349 | * email_hour_range
350 | * abtest
351 | * test_percent
352 | * data_feed_url
353 | * @link http://docs.sailthru.com/api/blast
354 | * @return array API result
355 | */
356 | public function updateBlast($blast_id, $name = null, $list = null,
357 | $schedule_time = null, $from_name = null, $from_email = null,
358 | $subject = null, $content_html = null, $content_text = null,
359 | $options = [ ]
360 | ) {
361 | $data = $options;
362 | $data['blast_id'] = $blast_id;
363 | if (!is_null($name)) {
364 | $data['name'] = $name;
365 | }
366 | if (!is_null($list)) {
367 | $data['list'] = $list;
368 | }
369 | if (!is_null($schedule_time)) {
370 | $data['schedule_time'] = $schedule_time;
371 | }
372 | if (!is_null($from_name)) {
373 | $data['from_name'] = $from_name;
374 | }
375 | if (!is_null($from_email)) {
376 | $data['from_email'] = $from_email;
377 | }
378 | if (!is_null($subject)) {
379 | $data['subject'] = $subject;
380 | }
381 | if (!is_null($content_html)) {
382 | $data['content_html'] = $content_html;
383 | }
384 | if (!is_null($content_text)) {
385 | $data['content_text'] = $content_text;
386 | }
387 |
388 | return $this->apiPost('blast', $data);
389 | }
390 |
391 | /**
392 | * Get Blast information
393 | * @param string /integer $blast_id
394 | * @link http://docs.sailthru.com/api/blast
395 | * @return array API result
396 | */
397 | public function getBlast($blast_id) {
398 | return $this->apiGet('blast', [ 'blast_id' => $blast_id ]);
399 | }
400 |
401 | /**
402 | * Get info on multiple blasts
403 | * @param array $options associative array
404 | * start_date (required)
405 | * end-date (required)
406 | * status
407 | * @link http://docs.sailthru.com/api/blast
408 | * @return array API result
409 | */
410 | public function getBlasts($options) {
411 | return $this->apiGet('blast', $options);
412 | }
413 |
414 | /**
415 | * Delete Blast
416 | * @param integer /string $blast_id
417 | * @link http://docs.sailthru.com/api/blast
418 | * @return array API result
419 | */
420 | public function deleteBlast($blast_id) {
421 | return $this->apiDelete('blast', [ 'blast_id' => $blast_id ]);
422 | }
423 |
424 | /**
425 | * Cancel a scheduled Blast
426 | * @param integer /string $blast_id
427 | * @link http://docs.sailthru.com/api/blast
428 | * @return array API result
429 | */
430 | public function cancelBlast($blast_id) {
431 | $data = [
432 | 'blast_id' => $blast_id,
433 | 'schedule_time' => ''
434 | ];
435 | return $this->apiPost('blast', $data);
436 | }
437 |
438 | /**
439 | * Fetch information about a template
440 | *
441 | * @param string $template_name
442 | * @param array $options
443 | * @return array API result
444 | * @link http://docs.sailthru.com/api/template
445 | */
446 | public function getTemplate($template_name, array $options = [ ]) {
447 | $options['template'] = $template_name;
448 | return $this->apiGet('template', $options);
449 | }
450 |
451 | /**
452 | * Fetch name of all existing templates
453 | * @link http://docs.sailthru.com/api/template
454 | * @return array API result
455 | */
456 | public function getTemplates() {
457 | return $this->apiGet('template');
458 | }
459 |
460 | public function getTemplateFromRevision($revision_id) {
461 | return $this->apiGet('template', [ 'revision' => (int) $revision_id ]);
462 | }
463 |
464 | /**
465 | * Save a template.
466 | *
467 | * @param string $template_name
468 | * @param array $template_fields
469 | * @link http://docs.sailthru.com/api/template
470 | * @return array API result
471 | */
472 | public function saveTemplate($template_name, array $template_fields = [ ]) {
473 | $data = $template_fields;
474 | $data['template'] = $template_name;
475 | return $this->apiPost('template', $data);
476 | }
477 |
478 | /**
479 | * Save a template from revision
480 | *
481 | * @param string $template_name
482 | * @param $revision_id
483 | * @return array API result
484 | * @link http://docs.sailthru.com/api/template
485 | */
486 | public function saveTemplateFromRevision($template_name, $revision_id) {
487 | $revision_id = (int) $revision_id;
488 | return $this->saveTemplate($template_name, [ 'revision' => $revision_id ]);
489 | }
490 |
491 | /**
492 | * Delete a template.
493 | *
494 | * @param string $template_name
495 | * @return array API result
496 | * @link http://docs.sailthru.com/api/template
497 | */
498 | public function deleteTemplate($template_name) {
499 | return $this->apiDelete('template', [ 'template' => $template_name ]);
500 | }
501 |
502 | /**
503 | * Fetch information about an include
504 | *
505 | * @param string $include_name
506 | * @return array API result
507 | */
508 | public function getInclude($include_name, array $options = [ ]) {
509 | $options['include'] = $include_name;
510 | return $this->apiGet('include', $options);
511 | }
512 |
513 | /**
514 | * Fetch name of all existing includes
515 | * @return array API result
516 | */
517 | public function getIncludes() {
518 | return $this->apiGet('include');
519 | }
520 |
521 | /**
522 | * Save an include
523 | *
524 | * @param string $include_name
525 | * @param array $include_fields
526 | * @return array API result
527 | */
528 | public function saveInclude($include_name, array $include_fields = [ ]) {
529 | $data = $include_fields;
530 | $data['include'] = $include_name;
531 | return $this->apiPost('include', $data);
532 | }
533 |
534 | /**
535 | * Get information about a list.
536 | *
537 | * @param string $list
538 | * @return array
539 | * @link http://docs.sailthru.com/api/list
540 | */
541 | public function getList($list) {
542 | return $this->apiGet('list', [ 'list' => $list ]);
543 | }
544 |
545 | /**
546 | * Get information about all lists
547 | * @return array
548 | * @link http://docs.sailthru.com/api/list
549 | */
550 | public function getLists() {
551 | return $this->apiGet('list', [ ]);
552 | }
553 |
554 | /**
555 | * Create a list, or update a list.
556 | *
557 | * @param string $list
558 | * @param string $list
559 | * @param string $type
560 | * @param bool $primary
561 | * @param array $query
562 | * @return array
563 | * @link http://docs.sailthru.com/api/list
564 | * @link http://docs.sailthru.com/api/query
565 | */
566 | public function saveList($list, $type = null, $primary = null, $query = [ ], $vars = []) {
567 | $data = [
568 | 'list' => $list,
569 | 'type' => $type,
570 | 'primary' => $primary ? 1 : 0,
571 | 'query' => $query,
572 | 'vars' => $vars,
573 | ];
574 | return $this->apiPost('list', $data);
575 | }
576 |
577 | /**
578 | * Deletes a list.
579 | *
580 | * @param string $list
581 | * @return array
582 | * @link http://docs.sailthru.com/api/list
583 | */
584 | public function deleteList($list) {
585 | return $this->apiDelete('list', [ 'list' => $list ]);
586 | }
587 |
588 | /**
589 | *
590 | * Push a new piece of content to Sailthru, triggering any applicable alerts.
591 | *
592 | * @param String $title
593 | * @param String $url
594 | * @param String $date
595 | * @param Mixed $tags Null for empty values, or String or arrays
596 | * @link http://docs.sailthru.com/api/content
597 | * @return array API result
598 | */
599 | public function pushContent($title, $url, $date = null, $tags = null, $vars = [ ], $options = [ ]) {
600 | $data = $options;
601 | $data['title'] = $title;
602 | $data['url'] = $url;
603 | if (!is_null($tags)) {
604 | $data['tags'] = is_array($tags) ? implode(",", $tags) : $tags;
605 | }
606 | if (!is_null($date)) {
607 | $data['date'] = $date;
608 | }
609 | if (!empty($vars)) {
610 | $data['vars'] = $vars;
611 | }
612 | return $this->apiPost('content', $data);
613 | }
614 |
615 | /**
616 | *
617 | * Retrieve a user's alert settings.
618 | *
619 | * @link http://docs.sailthru.com/api/alert
620 | * @param String $email
621 | * @return array API result
622 | */
623 | public function getAlert($email) {
624 | $data = [
625 | 'email' => $email
626 | ];
627 | return $this->apiGet('alert', $data);
628 | }
629 |
630 | /**
631 | *
632 | * Add a new alert to a user. You can add either a realtime or a summary alert (daily/weekly).
633 | * $when is only required when alert type is weekly or daily
634 | *
635 | *
636 | * array(
639 | * 'type' => array('shoes', 'shirts'),
640 | * 'min' => array('price' => 3000),
641 | * 'tags' => array('blue', 'red'),
642 | * )
643 | * );
644 | * $response = $sailthruClient->saveAlert("praj@sailthru.com", 'realtime', 'default', null, $options);
645 | * ?>
646 | *
647 | *
648 | * @link http://docs.sailthru.com/api/alert
649 | * @param String $email
650 | * @param String $type
651 | * @param String $template
652 | * @param String $when
653 | * @param array $options Associative array of additive nature
654 | * match Exact-match a custom variable match[type]=shoes
655 | * min Minimum-value variables min[price]=30000
656 | * max Maximum-value match max[price]=50000
657 | * tags Tag-match tags[]=blue
658 | * @return array API result
659 | */
660 | public function saveAlert($email, $type, $template, $when = null, $options = [ ]) {
661 | $data = $options;
662 | $data['email'] = $email;
663 | $data['type'] = $type;
664 | $data['template'] = $template;
665 | if ($type == 'weekly' || $type == 'daily') {
666 | $data['when'] = $when;
667 | }
668 | return $this->apiPost('alert', $data);
669 | }
670 |
671 | /**
672 | * Remove an alert from a user's settings.
673 | * @link http://docs.sailthru.com/api/alert
674 | * @param $email
675 | * @param $alert_id
676 | * @return array API result
677 | */
678 | public function deleteAlert($email, $alert_id) {
679 | $data = [
680 | 'email' => $email,
681 | 'alert_id' => $alert_id
682 | ];
683 | return $this->apiDelete('alert', $data);
684 | }
685 |
686 | /**
687 | * Record that a user has made a purchase, or has added items to their purchase total.
688 | * @link http://docs.sailthru.com/api/purchase
689 | * @return array API result
690 | */
691 | public function purchase($email, array $items, $incomplete = null, $message_id = null, array $options = [ ]) {
692 | $data = $options;
693 | $data['email'] = $email;
694 | $data['items'] = $items;
695 | if (!is_null($incomplete)) {
696 | $data['incomplete'] = (int) $incomplete;
697 | }
698 | if (!is_null($message_id)) {
699 | $data['message_id'] = $message_id;
700 | }
701 | return $this->apiPost('purchase', $data);
702 | }
703 |
704 | /**
705 | * Make a purchase API call with incomplete flag
706 | * @link http://docs.sailthru.com/api/purchase
707 | * @return array API result
708 | */
709 | public function purchaseIncomplete($email, array $items, $message_id, array $options = [ ]) {
710 | return $this->purchase($email, $items, 1, $message_id, $options);
711 | }
712 |
713 | /**
714 | * Retrieve information about your subscriber counts on a particular list, on a particular day.
715 | * @link http://docs.sailthru.com/api/stats
716 | * @param String $list
717 | * @param String $date
718 | * @return array API result
719 | */
720 | public function stats_list($list = null, $date = null) {
721 | $data = [ ];
722 | if (!is_null($list)) {
723 | $data['list'] = $list;
724 | }
725 |
726 | if (!is_null($date)) {
727 | $data['date'] = $date;
728 | }
729 | $data['stat'] = 'list';
730 | return $this->stats($data);
731 | }
732 |
733 | /**
734 | * Retrieve information about a particular blast or aggregated information from all of blasts over a specified date range.
735 | * @param array $data
736 | * @return array API result
737 | */
738 | public function stats_blast($blast_id = null, $start_date = null, $end_date = null, array $data = [ ]) {
739 | $data['stat'] = 'blast';
740 | if (!is_null($blast_id)) {
741 | $data['blast_id'] = $blast_id;
742 | }
743 | if (!is_null($start_date)) {
744 | $data['start_date'] = $start_date;
745 | }
746 | if (!is_null($end_date)) {
747 | $data['end_date'] = $end_date;
748 | }
749 | return $this->stats($data);
750 | }
751 |
752 | /**
753 | * Retrieve information about a particular send or aggregated information from all of templates over a specified date range.
754 | * @param array $data
755 | * @return array API result
756 | */
757 | public function stats_send($template = null, $start_date = null, $end_date = null, array $data = [ ]) {
758 | $data['stat'] = 'send';
759 |
760 | if (!is_null($template)) {
761 | $data['template'] = $template;
762 | }
763 | if (!is_null($start_date)) {
764 | $data['start_date'] = $start_date;
765 | }
766 | if (!is_null($end_date)) {
767 | $data['end_date'] = $end_date;
768 | }
769 |
770 | return $this->stats($data);
771 | }
772 |
773 | /**
774 | * Make Stats API Request
775 | * @param array $data
776 | * @return array API result
777 | */
778 | public function stats(array $data) {
779 | return $this->apiGet('stats', $data);
780 | }
781 |
782 | /**
783 | *
784 | * Returns true if the incoming request is an authenticated verify post.
785 | * @link http://docs.sailthru.com/api/postbacks
786 | * @return boolean
787 | */
788 | public function receiveVerifyPost() {
789 | $params = $_POST;
790 | foreach ([ 'action', 'email', 'send_id', 'sig' ] as $k) {
791 | if (!isset($params[$k])) {
792 | return false;
793 | }
794 | }
795 |
796 | if ($params['action'] != 'verify') {
797 | return false;
798 | }
799 | $sig = $params['sig'];
800 | unset($params['sig']);
801 | if ($sig != Sailthru_Util::getSignatureHash($params, $this->secret)) {
802 | return false;
803 | }
804 | $send = $this->getSend($params['send_id']);
805 | if (!isset($send['email'])) {
806 | return false;
807 | }
808 | if ($send['email'] != $params['email']) {
809 | return false;
810 | }
811 | return true;
812 | }
813 |
814 | /**
815 | *
816 | * Optout postbacks
817 | * @return boolean
818 | * @link http://docs.sailthru.com/api/postbacks
819 | */
820 | public function receiveOptoutPost() {
821 | $params = $_POST;
822 | foreach ([ 'action', 'email', 'sig' ] as $k) {
823 | if (!isset($params[$k])) {
824 | return false;
825 | }
826 | }
827 |
828 | if ($params['action'] != 'optout') {
829 | return false;
830 | }
831 | $sig = $params['sig'];
832 | unset($params['sig']);
833 | if ($sig != Sailthru_Util::getSignatureHash($params, $this->secret)) {
834 | return false;
835 | }
836 | return true;
837 | }
838 |
839 | /**
840 | *
841 | * Update postbacks
842 | * @return boolean
843 | * @link http://docs.sailthru.com/api/postbacks
844 | */
845 | public function receiveUpdatePost() {
846 | $params = $_POST;
847 | foreach ([ 'action', 'sid', 'sig' ] as $k) {
848 | if (!isset($params[$k])) {
849 | return false;
850 | }
851 | }
852 |
853 | if ($params['action'] != 'update') {
854 | return false;
855 | }
856 | $sig = $params['sig'];
857 | unset($params['sig']);
858 | if ($sig != Sailthru_Util::getSignatureHash($params, $this->secret)) {
859 | return false;
860 | }
861 | return true;
862 | }
863 |
864 | /**
865 | *
866 | * Hard bounce postbacks
867 | * @return boolean
868 | * @link http://docs.sailthru.com/api/postbacks
869 | */
870 | public function receiveHardBouncePost() {
871 | $params = $_POST;
872 | foreach ([ 'action', 'email', 'sig' ] as $k) {
873 | if (!isset($params[$k])) {
874 | return false;
875 | }
876 | }
877 | if ($params['action'] != 'hardbounce') {
878 | return false;
879 | }
880 | $sig = $params['sig'];
881 | unset($params['sig']);
882 | if ($sig != Sailthru_Util::getSignatureHash($params, $this->secret)) {
883 | return false;
884 | }
885 | if (isset($params['send_id'])) {
886 | $send_id = $params['send_id'];
887 | $send = $this->getSend($send_id);
888 | if (!isset($send['email'])) {
889 | return false;
890 | }
891 | } else if (isset($params['blast_id'])) {
892 | $blast_id = $params['blast_id'];
893 | $blast = $this->getBlast($blast_id);
894 | if (isset($blast['error'])) {
895 | return false;
896 | }
897 | }
898 | return true;
899 | }
900 |
901 | /**
902 | * Get status of a job
903 | * @param String $job_id
904 | * @return array
905 | */
906 | public function getJobStatus($job_id) {
907 | return $this->apiGet('job', [ 'job_id' => $job_id ]);
908 | }
909 |
910 | /**
911 | * process job api call
912 | * @param String $job
913 | * @param array $data
914 | * @param bool|String $report_email
915 | * @param bool|String $postback_url
916 | * @param array $binary_data_param
917 | * @param array $options
918 | * @return array
919 | */
920 | protected function processJob($job, array $data = [ ], $report_email = false, $postback_url = false, array $binary_data_param = [ ],
921 | array $options = [ ]) {
922 | $data['job'] = $job;
923 | if ($report_email) {
924 | $data['report_email'] = $report_email;
925 | }
926 | if ($postback_url) {
927 | $data['postback_url'] = $postback_url;
928 | }
929 | return $this->apiPost('job', $data, $binary_data_param, $options);
930 | }
931 |
932 | /**
933 | * Process import job from given email string CSV
934 | * @param String $list
935 | * @param String $emails
936 | * @param bool|String $report_email
937 | * @param bool|String $postback_url
938 | * @return array
939 | */
940 | public function processImportJob($list, $emails, $report_email = false, $postback_url = false, array $options = [ ]) {
941 | $data = [
942 | 'emails' => $emails,
943 | 'list' => $list
944 | ];
945 | return $this->processJob('import', $data, $report_email, $postback_url, [ ], $options);
946 | }
947 |
948 | /**
949 | * Process import job from given file path of a CSV or email per line file
950 | *
951 | * @param String $list
952 | * @param $file_path
953 | * @param bool|String $report_email
954 | * @param bool|String $postback_url
955 | * @param array $options
956 | * @return array
957 | */
958 | public function processImportJobFromFile($list, $file_path, $report_email = false, $postback_url = false, array $options = [ ]) {
959 | $data = [
960 | 'file' => $file_path,
961 | 'list' => $list
962 | ];
963 | return $this->processJob('import', $data, $report_email, $postback_url, [ 'file' ], $options);
964 | }
965 |
966 | /**
967 | * Process purchase import job from given file path of an email per line JSON file
968 | *
969 | * @param String $file_path
970 | * @param bool|String $report_email
971 | * @param bool|String $postback_url
972 | * @param array $options
973 | * @return array
974 | */
975 | public function processPurchaseImportJobFromFile($file_path, $report_email = false, $postback_url = false, array $options = [ ]) {
976 | $data = [
977 | 'file' => $file_path
978 | ];
979 | return $this->processJob('purchase_import', $data, $report_email, $postback_url, [ 'file' ], $options);
980 | }
981 |
982 | /**
983 | * Process a snapshot job
984 | *
985 | * @param array $query
986 | * @param bool|String $report_email
987 | * @param bool|String $postback_url
988 | * @return array
989 | */
990 | public function processSnapshotJob(array $query, $report_email = false, $postback_url = false, array $options = [ ]) {
991 | $data = [ 'query' => $query ];
992 | return $this->processJob('snaphot', $data, $report_email, $postback_url, [ ], $options);
993 | }
994 |
995 | /**
996 | * Process a export list job
997 | * @param String $list
998 | * @param bool|String $report_email
999 | * @param bool|String $postback_url
1000 | * @param array $options
1001 | * @return array
1002 | */
1003 | public function processExportListJob($list, $report_email = false, $postback_url = false, array $options = [ ]) {
1004 | $data = [ 'list' => $list ];
1005 | return $this->processJob('export_list_data', $data, $report_email, $postback_url, [ ], $options);
1006 | }
1007 |
1008 | /**
1009 | * Export blast data in CSV format
1010 | * @param integer $blast_id
1011 | * @param bool|String $report_email
1012 | * @param bool|String $postback_url
1013 | * @param array $options
1014 | * @return array
1015 | */
1016 | public function processBlastQueryJob($blast_id, $report_email = false, $postback_url = false, array $options = [ ]) {
1017 | return $this->processJob('blast_query', [ 'blast_id' => $blast_id ], $report_email, $postback_url, [ ], $options);
1018 | }
1019 |
1020 | /**
1021 | * Perform a bulk update of any number of user profiles from given context: String CSV, file, URL or query
1022 | * @param String $context
1023 | * @param $value
1024 | * @param array $update
1025 | * @param bool|String $report_email
1026 | * @param bool|String $postback_url
1027 | * @param array $file_params
1028 | * @return array
1029 | */
1030 | public function processUpdateJob($context, $value, array $update = [ ], $report_email = false, $postback_url = false, array $file_params = [ ],
1031 | array $options = [ ]) {
1032 | $data = [
1033 | $context => $value
1034 | ];
1035 | if (count($update) > 0) {
1036 | $data['update'] = $update;
1037 | }
1038 | return $this->processJob('update', $data, $report_email, $postback_url, $file_params, $options);
1039 | }
1040 |
1041 | /**
1042 | * Perform a bulk update of any number of user profiles from given URL
1043 | * @param String $url
1044 | * @param array $update
1045 | * @param bool|String $report_email
1046 | * @param bool|String $postback_url
1047 | * @param array $options
1048 | * @return array
1049 | */
1050 | public function processUpdateJobFromUrl($url, array $update = [ ], $report_email = false, $postback_url = false, array $options = [ ]) {
1051 | return $this->processUpdateJob('url', $url, $update, $report_email, $postback_url, [ ], $options);
1052 | }
1053 |
1054 | /**
1055 | * Perform a bulk update of any number of user profiles from given file
1056 | * @param $file
1057 | * @param Array $update
1058 | * @param bool|String $report_email
1059 | * @param bool|String $postback_url
1060 | * @param array $options
1061 | * @return array
1062 | * @internal param String $url
1063 | */
1064 | public function processUpdateJobFromFile($file, array $update = [ ], $report_email = false, $postback_url = false, array $options = [ ]) {
1065 | return $this->processUpdateJob('file', $file, $update, $report_email, $postback_url, [ 'file' ], $options);
1066 | }
1067 |
1068 | /**
1069 | * Perform a bulk update of any number of user profiles from a query
1070 | * @param Array $query
1071 | * @param Array $update
1072 | * @param String $report_email
1073 | * @param String $postback_url
1074 | */
1075 | public function processUpdateJobFromQuery($query, array $update = [ ], $report_email = false, $postback_url = false, array $options = [ ]) {
1076 | return $this->processUpdateJob('query', $query, $update, $report_email, $postback_url, [ ], $options);
1077 | }
1078 |
1079 | /**
1080 | * Perform a bulk update of any number of user profiles from emails CSV
1081 | * @param String $emails
1082 | * @param Array $update
1083 | * @param bool|String $report_email
1084 | * @param bool|String $postback_url
1085 | * @return array
1086 | */
1087 | public function processUpdateJobFromEmails($emails, array $update = [ ], $report_email = false, $postback_url = false, array $options = [ ]) {
1088 | return $this->processUpdateJob('emails', $emails, $update, $report_email, $postback_url, [ ], $options);
1089 | }
1090 |
1091 | /**
1092 | * Save existing user
1093 | * @param String $id
1094 | * @param array $options
1095 | * @return array
1096 | */
1097 | public function saveUser($id, array $options = [ ]) {
1098 | $data = $options;
1099 | $data['id'] = $id;
1100 | return $this->apiPost('user', $data);
1101 | }
1102 |
1103 | /**
1104 | * Get user by Sailthru ID
1105 | * @param String $id
1106 | * @return array
1107 | */
1108 | public function getUserBySid($id) {
1109 | return $this->apiGet('user', [ 'id' => $id ]);
1110 | }
1111 |
1112 | /**
1113 | * Get user by specified key
1114 | * @param String $id
1115 | * @param String $key
1116 | * @param array $fields
1117 | * @return array
1118 | */
1119 | public function getUserByKey($id, $key, array $fields = [ ]) {
1120 | $data = [
1121 | 'id' => $id,
1122 | 'key' => $key,
1123 | 'fields' => $fields
1124 | ];
1125 | return $this->apiGet('user', $data);
1126 | }
1127 |
1128 | /**
1129 | *
1130 | * Set Horizon cookie
1131 | *
1132 | * @param string $email horizon user email
1133 | * @param string $domain
1134 | * @param integer $duration
1135 | * @param boolean $secure
1136 | * @return boolean
1137 | */
1138 | public function setHorizonCookie($email, $domain = null, $duration = null, $secure = false) {
1139 | $data = $this->getUserByKey($email, 'email', [ 'keys' => 1 ]);
1140 | if (!isset($data['keys']['cookie'])) {
1141 | return false;
1142 | }
1143 | if (!$domain) {
1144 | $domain_parts = explode('.', $_SERVER['HTTP_HOST']);
1145 | $domain = $domain_parts[sizeof($domain_parts) - 2] . '.' . $domain_parts[sizeof($domain_parts) - 1];
1146 | }
1147 | if ($duration === null) {
1148 | $expire = time() + 31556926;
1149 | } else if ($duration) {
1150 | $expire = time() + $duration;
1151 | } else {
1152 | $expire = 0;
1153 | }
1154 | return setcookie('sailthru_hid', $data['keys']['cookie'], $expire, '/', $domain, $secure);
1155 | }
1156 |
1157 | /**
1158 | * Get an HTML preview of a template.
1159 | * @param $template
1160 | * @param $email
1161 | * @return array
1162 | * @link http://docs.sailthru.com/api/preview
1163 | */
1164 | public function previewTemplateWithHTML($template, $email) {
1165 | $data = [ ];
1166 | $data['template'] = $template;
1167 | $data['email'] = $email;
1168 |
1169 | $result = $this->apiPost('preview', $data);
1170 | return $result;
1171 | }
1172 |
1173 | /**
1174 | * Get an HTML preview of a blast.
1175 | * @param $blast_id
1176 | * @param $email
1177 | * @return array
1178 | * @link http://docs.sailthru.com/api/preview
1179 | */
1180 | public function previewBlastWithHTML($blast_id, $email) {
1181 | $data = [ ];
1182 | $data['blast_id'] = $blast_id;
1183 | $data['email'] = $email;
1184 |
1185 | $result = $this->apiPost('preview', $data);
1186 | return $result;
1187 | }
1188 |
1189 | /**
1190 | * Get an HTML preview of a recurring blast.
1191 | * @param $blast_repeat_id
1192 | * @param $email
1193 | * @return array
1194 | * @link http://docs.sailthru.com/api/preview
1195 | */
1196 | public function previewRecurringBlastWithHTML($blast_repeat_id, $email) {
1197 | $data = [ ];
1198 | $data['blast_repeat_id'] = $blast_repeat_id;
1199 | $data['email'] = $email;
1200 |
1201 | $result = $this->apiPost('preview', $data);
1202 | }
1203 |
1204 | /**
1205 | * Get an HTML preview of content_html.
1206 | * @param $content_html
1207 | * @param $email
1208 | * @return array
1209 | * @link http://docs.sailthru.com/api/preview
1210 | */
1211 | public function previewContentWithHTML($content_html, $email) {
1212 | $data = [ ];
1213 | $data['content_html'] = $content_html;
1214 | $data['email'] = $email;
1215 |
1216 | $result = $this->apiPost('preview', $data);
1217 | return $result;
1218 | }
1219 |
1220 | /**
1221 | * Get an email preview of a template.
1222 | * @param $template
1223 | * @param $send_email
1224 | * @return array
1225 | * @link http://docs.sailthru.com/api/preview
1226 | */
1227 | public function previewTemplateWithEmail($template, $send_email) {
1228 | $data = [ ];
1229 | $data['template'] = $template;
1230 | $data['send_email'] = $send_email;
1231 |
1232 | $result = $this->apiPost('preview', $data);
1233 | return $result;
1234 | }
1235 |
1236 | /**
1237 | * Get an email preview of a blast.
1238 | * @param $blast_id
1239 | * @param $send_email
1240 | * @return array
1241 | * @link http://docs.sailthru.com/api/preview
1242 | */
1243 | public function previewBlastWithEmail($blast_id, $send_email) {
1244 | $data = [ ];
1245 | $data['blast_id'] = $blast_id;
1246 | $data['send_email'] = $send_email;
1247 |
1248 | $result = $this->apiPost('preview', $data);
1249 | return $result;
1250 | }
1251 |
1252 | /**
1253 | * Get an email preview of a recurring blast.
1254 | * @param $blast_repeat_id
1255 | * @param $send_email
1256 | * @return array
1257 | * @link http://docs.sailthru.com/api/preview
1258 | */
1259 | public function previewRecurringBlastWithEmail($blast_repeat_id, $send_email) {
1260 | $data = [ ];
1261 | $data['blast_repeat_id'] = $blast_repeat_id;
1262 | $data['send_email'] = $send_email;
1263 |
1264 | $result = $this->apiPost('preview', $data);
1265 | return $result;
1266 | }
1267 |
1268 | /**
1269 | * Get an email preview of content_html.
1270 | * @param $content_html
1271 | * @param $send_email
1272 | * @return array
1273 | * @link http://docs.sailthru.com/api/preview
1274 | */
1275 | public function previewContentWithEmail($content_html, $send_email) {
1276 | $data = [ ];
1277 | $data['content_html'] = $content_html;
1278 | $data['send_email'] = $send_email;
1279 |
1280 | $result = $this->apiPost('preview', $data);
1281 | return $result;
1282 | }
1283 |
1284 | /**
1285 | * Get Triggers
1286 | * @return array
1287 | * @link http://docs.sailthru.com/api/trigger
1288 | */
1289 | public function getTriggers() {
1290 | $result = $this->apiGet('trigger');
1291 | return $result;
1292 | }
1293 |
1294 | /**
1295 | * Get information on a trigger
1296 | * @param string $template
1297 | * @param string $trigger_id
1298 | * @return array
1299 | * @link http://docs.sailthru.com/api/trigger
1300 | */
1301 | public function getTriggerByTemplate($template, $trigger_id = null) {
1302 | $data = [ ];
1303 | $data['template'] = $template;
1304 | if (!is_null($trigger_id)) {
1305 | $data['trigger_id'] = $trigger_id;
1306 | }
1307 |
1308 | $result = $this->apiGet('trigger', $data);
1309 | return $result;
1310 | }
1311 |
1312 | /**
1313 | * Get information on a trigger
1314 | * @param string $event
1315 | * @return array
1316 | * @link http://docs.sailthru.com/api/trigger
1317 | */
1318 | public function getTriggerByEvent($event) {
1319 | $data = [ ];
1320 | $data['event'] = $event;
1321 |
1322 | $result = $this->apiGet('trigger', $data);
1323 | return $result;
1324 | }
1325 |
1326 | /**
1327 | * Get information on a trigger
1328 | * @param string $trigger_id
1329 | * @return array
1330 | * @link http://docs.sailthru.com/api/trigger
1331 | */
1332 | public function getTriggerById($trigger_id) {
1333 | $data = [ ];
1334 | $data['trigger_id'] = $trigger_id;
1335 |
1336 | $result = $this->apiGet('trigger', $data);
1337 | return $result;
1338 | }
1339 |
1340 | /**
1341 | * Create a trigger for templates
1342 | * @param string $template
1343 | * @param integer $time
1344 | * @param string $time_unit
1345 | * @param string $event
1346 | * @param string $zephyr
1347 | * @return array
1348 | * @link http://docs.sailthru.com/api/trigger
1349 | */
1350 | public function postTrigger($template, $time, $time_unit, $event, $zephyr) {
1351 | $data = [ ];
1352 | $data['template'] = $template;
1353 | $data['time'] = $time;
1354 | $data['time_unit'] = $time_unit;
1355 | $data['event'] = $event;
1356 | $data['zephyr'] = $zephyr;
1357 |
1358 | $result = $this->apiPost('trigger', $data);
1359 | return $result;
1360 | }
1361 |
1362 | /**
1363 | * Create a trigger for events
1364 | * @param integer $time
1365 | * @param string $time_unit
1366 | * @param string $event
1367 | * @param string $zephyr
1368 | * @return array
1369 | * @link http://docs.sailthru.com/api/trigger
1370 | */
1371 | public function postEventTrigger($event, $time, $time_unit, $zephyr) {
1372 | $data = [ ];
1373 | $data['time'] = $time;
1374 | $data['time_unit'] = $time_unit;
1375 | $data['event'] = $event;
1376 | $data['zephyr'] = $zephyr;
1377 |
1378 | $result = $this->apiPost('trigger', $data);
1379 | return $result;
1380 | }
1381 |
1382 | /**
1383 | * Notify Sailthru of an event
1384 | * @param string $id
1385 | * @param string $event
1386 | * @param array $options
1387 | * @return array
1388 | * @link http://docs.sailthru.com/api/event
1389 | */
1390 | public function postEvent($id, $event, $options = [ ]) {
1391 | $data = $options;
1392 | $data['id'] = $id;
1393 | $data['event'] = $event;
1394 |
1395 | $result = $this->apiPost('event', $data);
1396 | return $result;
1397 | }
1398 |
1399 | /**
1400 | * Perform an HTTP request using the curl extension
1401 | *
1402 | * @param string $action
1403 | * @param array $data
1404 | * @param string $method
1405 | * @param array $options
1406 | * @return string
1407 | * @throws Sailthru_Client_Exception
1408 | */
1409 | protected function httpRequestCurl($action, array $data, $method = 'POST', $options = [ ]) {
1410 | $url = $this->api_uri . "/" . $action;
1411 | $ch = curl_init();
1412 | $options = array_merge($this->options, $options);
1413 | if ($method == 'POST') {
1414 | curl_setopt($ch, CURLOPT_POST, true);
1415 | if ($this->fileUpload === true) {
1416 | curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
1417 | $this->fileUpload = false;
1418 | } else {
1419 | curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data, '', '&'));
1420 | }
1421 | } else {
1422 | $url .= '?' . http_build_query($data, '', '&');
1423 | if ($method != 'GET') {
1424 | curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
1425 | }
1426 | }
1427 | curl_setopt($ch, CURLOPT_URL, $url);
1428 | curl_setopt($ch, CURLOPT_HEADER, true);
1429 | curl_setopt($ch, CURLOPT_ENCODING, 'gzip');
1430 | curl_setopt($ch, CURLOPT_TIMEOUT_MS, $options['timeout']);
1431 | curl_setopt($ch, CURLOPT_CONNECTTIMEOUT_MS, $options['connect_timeout']);
1432 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
1433 |
1434 | curl_setopt($ch, CURLOPT_HTTPHEADER, $this->httpHeaders);
1435 | $response = curl_exec($ch);
1436 | $this->lastResponseInfo = curl_getinfo($ch);
1437 | curl_close($ch);
1438 |
1439 | if (!$response) {
1440 | throw new Sailthru_Client_Exception(
1441 | "Bad response received from $url",
1442 | Sailthru_Client_Exception::CODE_RESPONSE_EMPTY
1443 | );
1444 | }
1445 |
1446 | // parse headers and body
1447 | $parts = explode("\r\n\r\nHTTP/", $response);
1448 | $parts = (count($parts) > 1 ? 'HTTP/' : '') . array_pop($parts); // deal with HTTP/1.1 100 Continue before other headers
1449 | list($headers, $body) = explode("\r\n\r\n", $parts, 2);
1450 | $this->lastRateLimitInfo[$action][$method] = self::parseRateLimitHeaders($headers);
1451 |
1452 | return $body;
1453 | }
1454 |
1455 | /**
1456 | * Adapted from: http://netevil.org/blog/2006/nov/http-post-from-php-without-curl
1457 | *
1458 | * @param string $action
1459 | * @param array $data
1460 | * @param string $method
1461 | * @param array $options
1462 | * @return string
1463 | * @throws Sailthru_Client_Exception
1464 | */
1465 | protected function httpRequestWithoutCurl($action, $data, $method = 'POST', $options = [ ]) {
1466 | if ($this->fileUpload === true) {
1467 | $this->fileUpload = false;
1468 | throw new Sailthru_Client_Exception(
1469 | 'cURL extension is required for the request with file upload',
1470 | Sailthru_Client_Exception::CODE_GENERAL
1471 | );
1472 | }
1473 |
1474 | $url = $this->api_uri . "/" . $action;
1475 | $params = [ 'http' => [ 'method' => $method, 'ignore_errors' => true ] ];
1476 | if ($method == 'POST') {
1477 | $params['http']['content'] = is_array($data) ? http_build_query($data, '', '&') : $data;
1478 | } else {
1479 | $url .= '?' . http_build_query($data, '', '&');
1480 | }
1481 | $params['http']['header'] = "User-Agent: {$this->user_agent_string}\nContent-Type: application/x-www-form-urlencoded";
1482 | $ctx = stream_context_create($params);
1483 | $fp = @fopen($url, 'rb', false, $ctx);
1484 | if (!$fp) {
1485 | throw new Sailthru_Client_Exception(
1486 | "Unable to open stream: $url",
1487 | Sailthru_Client_Exception::CODE_GENERAL
1488 | );
1489 | }
1490 | $response = @stream_get_contents($fp);
1491 | if ($response === false) {
1492 | throw new Sailthru_Client_Exception(
1493 | "No response received from stream: $url",
1494 | Sailthru_Client_Exception::CODE_RESPONSE_EMPTY
1495 | );
1496 | }
1497 | return $response;
1498 | }
1499 |
1500 | /**
1501 | * Perform an HTTP request, checking for curl extension support
1502 | *
1503 | * @param $action
1504 | * @param array $data
1505 | * @param string $method
1506 | * @param array $options
1507 | * @return string
1508 | * @throws Sailthru_Client_Exception
1509 | */
1510 | protected function httpRequest($action, $data, $method = 'POST', $options = [ ]) {
1511 | $response = $this->{$this->http_request_type}($action, $data, $method, $options);
1512 | $json = json_decode($response, true);
1513 | if ($json === NULL) {
1514 | throw new Sailthru_Client_Exception(
1515 | "Response: {$response} is not a valid JSON",
1516 | Sailthru_Client_Exception::CODE_RESPONSE_INVALID
1517 | );
1518 | }
1519 | if (!empty($json['error'])) {
1520 | throw new Sailthru_Client_Exception($json['errormsg'], $json['error']);
1521 | }
1522 |
1523 | return $json;
1524 | }
1525 |
1526 | /**
1527 | * Perform an API POST (or other) request, using the shared-secret auth hash.
1528 | * if binary_data_param is set, its appends '@' so that cURL can make binary POST request
1529 | *
1530 | * @param string $action
1531 | * @param array $data
1532 | * @param array $binary_data_param
1533 | * @param array $options
1534 | * @return array
1535 | */
1536 | public function apiPost($action, $data, array $binary_data_param = [ ], $options = [ ]) {
1537 | $binary_data = [ ];
1538 | if (!empty ($binary_data_param)) {
1539 | foreach ($binary_data_param as $param) {
1540 | if (isset($data[$param]) && file_exists($data[$param])) {
1541 | $binary_data[$param] = version_compare(PHP_VERSION, '5.5.0') >= 0 && class_exists('CURLFile')
1542 | ? new CURLFile($data[$param])
1543 | : "@{$data[$param]}";
1544 | unset($data[$param]);
1545 | $this->fileUpload = true;
1546 | }
1547 | }
1548 | }
1549 | $payload = $this->prepareJsonPayload($data, $binary_data);
1550 | return $this->httpRequest($action, $payload, 'POST', $options);
1551 | }
1552 |
1553 | /**
1554 | * Perform an API GET request, using the shared-secret auth hash.
1555 | *
1556 | * @param string $action
1557 | * @param array $data
1558 | * @return array
1559 | */
1560 | public function apiGet($action, $data = [ ], $method = 'GET', $options = [ ]) {
1561 | return $this->httpRequest($action, $this->prepareJsonPayload($data), $method, $options);
1562 | }
1563 |
1564 | /**
1565 | * Perform an API DELETE request, using the shared-secret auth hash.
1566 | *
1567 | * @param string $action
1568 | * @param array $data
1569 | * @return array
1570 | */
1571 | public function apiDelete($action, $data, $options = [ ]) {
1572 | return $this->apiGet($action, $data, 'DELETE', $options);
1573 | }
1574 |
1575 | /**
1576 | * get information from last server response when used with cURL
1577 | * returns associative array as per http://us.php.net/curl_getinfo
1578 | * @return array or null
1579 | */
1580 | public function getLastResponseInfo() {
1581 | return $this->lastResponseInfo;
1582 | }
1583 |
1584 | /**
1585 | * Prepare JSON payload
1586 | */
1587 | protected function prepareJsonPayload(array $data, array $binary_data = [ ]) {
1588 | $payload = [
1589 | 'api_key' => $this->api_key,
1590 | 'format' => 'json',
1591 | 'json' => json_encode($data)
1592 | ];
1593 | $payload['sig'] = Sailthru_Util::getSignatureHash($payload, $this->secret);
1594 | if (!empty($binary_data)) {
1595 | $payload = array_merge($payload, $binary_data);
1596 | }
1597 | return $payload;
1598 | }
1599 |
1600 | /**
1601 | * get the rate limit information for the very last call with given action and method
1602 | * @param string $action
1603 | * @param string $method GET, POST or DELETE
1604 | * @return array or null
1605 | */
1606 | public function getLastRateLimitInfo($action, $method) {
1607 | $rate_limit_info = $this->lastRateLimitInfo;
1608 | $method = strtoupper($method);
1609 | return (isset($rate_limit_info[$action]) && isset($rate_limit_info[$action][$method])) ?
1610 | $rate_limit_info[$action][$method] : null;
1611 | }
1612 |
1613 | /**
1614 | * parse rate limit headers from http response
1615 | * @param string $headers
1616 | * @return array|null
1617 | */
1618 | private function parseRateLimitHeaders($headers) {
1619 | if ($headers === null) {
1620 | return null;
1621 | }
1622 |
1623 | $header_lines = explode("\n", $headers);
1624 | $rate_limit_headers = [ ];
1625 | foreach ($header_lines as $hl) {
1626 | if (strpos($hl, "X-Rate-Limit-Limit") !== FALSE && !isset($rate_limit_headers['limit'])) {
1627 | list($header_name, $header_value) = explode(":", $hl, 2);
1628 | $rate_limit_headers['limit'] = intval($header_value);
1629 | } else if (strpos($hl, "X-Rate-Limit-Remaining") !== FALSE && !isset($rate_limit_headers['remaining'])) {
1630 | list($header_name, $header_value) = explode(":", $hl, 2);
1631 | $rate_limit_headers['remaining'] = intval($header_value);
1632 | } else if (strpos($hl, "X-Rate-Limit-Reset") !== FALSE && !isset($rate_limit_headers['reset'])) {
1633 | list($header_name, $header_value) = explode(":", $hl, 2);
1634 | $rate_limit_headers['reset'] = intval($header_value);
1635 | }
1636 |
1637 | if (count($rate_limit_headers) === 3) {
1638 | return $rate_limit_headers;
1639 | }
1640 | }
1641 |
1642 | return null;
1643 | }
1644 | }
1645 |
--------------------------------------------------------------------------------