PageRenderTime 55ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 1ms

/sailthru/Sailthru_Client.php

http://github.com/sailthru/sailthru-php5-client
PHP | 1644 lines | 765 code | 133 blank | 746 comment | 104 complexity | f9f31d3674d85d155521d7402a1970d7 MD5 | raw file
  1. <?php
  2. /**
  3. *
  4. * Makes HTTP Request to Sailthru API server
  5. * Response from server depends on the format being queried
  6. * if 'json' format is requested, client will recieve JSON object and 'php' is requested, client will recieve PHP array
  7. * XML format is also available but not has not been tested thoroughly
  8. *
  9. */
  10. class Sailthru_Client {
  11. /**
  12. *
  13. * Sailthru API Key
  14. * @var string
  15. */
  16. protected $api_key;
  17. /**
  18. *
  19. * Sailthru Secret
  20. * @var string
  21. */
  22. protected $secret;
  23. /**
  24. *
  25. * Sailthru API URL, can be different for different users according to their settings
  26. * @var string
  27. */
  28. protected $api_uri = 'https://api.sailthru.com';
  29. /**
  30. *
  31. * cURL or non-cURL request
  32. * @var string
  33. */
  34. protected $http_request_type;
  35. /**
  36. *
  37. * User agent making request to Sailthru API server
  38. * Even, if you modify user-agent, please try to include 'PHP5' somewhere in the user-agent
  39. * @var String
  40. */
  41. protected $user_agent_string;
  42. /**
  43. * Get information regarding last response from server
  44. */
  45. private $lastResponseInfo = null;
  46. /**
  47. * Rate Limit information for last API call
  48. */
  49. private $lastRateLimitInfo = [ ];
  50. /**
  51. * File Upload Flag variable
  52. */
  53. private $fileUpload = false;
  54. private $httpHeaders = [ "User-Agent: Sailthru API PHP5 Client" ];
  55. const DEFAULT_READ_TIMEOUT = 10000;
  56. const DEFAULT_CONNECT_TIMEOUT = 10000;
  57. private $options = [ 'timeout' => Sailthru_Client::DEFAULT_READ_TIMEOUT, 'connect_timeout' => Sailthru_Client::DEFAULT_CONNECT_TIMEOUT ];
  58. /**
  59. * Instantiate a new client; constructor optionally takes overrides for api_uri and whether
  60. * to share the version of PHP that is being used.
  61. *
  62. * @param string $api_key
  63. * @param string $secret
  64. * @param string $api_uri
  65. * @param array $options - optional parameters for connect/read timeout
  66. */
  67. public function __construct($api_key, $secret, $api_uri = false, $options = null) {
  68. $this->api_key = $api_key;
  69. $this->secret = $secret;
  70. if ($api_uri !== false) {
  71. $this->api_uri = $api_uri;
  72. }
  73. $this->http_request_type = function_exists('curl_init') ? 'httpRequestCurl' : 'httpRequestWithoutCurl';
  74. if (isset($options)) {
  75. $this->options['timeout'] = isset($options['timeout']) ? (int) $options['timeout'] : Sailthru_Client::DEFAULT_READ_TIMEOUT;
  76. $this->options['connect_timeout'] =
  77. isset($options['connect_timeout']) ? (int) $options['connect_timeout'] : Sailthru_Client::DEFAULT_CONNECT_TIMEOUT;
  78. }
  79. }
  80. public function getConnectTimeout() {
  81. return $this->options['connect_timeout'];
  82. }
  83. public function getTimeout() {
  84. return $this->options['timeout'];
  85. }
  86. public function setHttpHeaders(array $headers) {
  87. $this->httpHeaders = array_merge($this->httpHeaders, $headers);
  88. return true;
  89. }
  90. /**
  91. * Remotely send an email template to a single email address.
  92. *
  93. * If you pass the $schedule_time parameter, the send will be scheduled for a future time.
  94. *
  95. * Options:
  96. * replyto: override Reply-To header
  97. * test: send as test email (subject line will be marked, will not count towards stats)
  98. *
  99. * @param string $template
  100. * @param string $email
  101. * @param array $vars
  102. * @param array $options
  103. * @param string $schedule_time
  104. * @link http://docs.sailthru.com/api/send
  105. * @return array API result
  106. */
  107. public function send($template, $email, $vars = [ ], $options = [ ], $schedule_time = null) {
  108. $post = [ ];
  109. $post['template'] = $template;
  110. $post['email'] = $email;
  111. $post['vars'] = $vars;
  112. $post['options'] = $options;
  113. if ($schedule_time) {
  114. $post['schedule_time'] = $schedule_time;
  115. }
  116. $result = $this->apiPost('send', $post);
  117. return $result;
  118. }
  119. /**
  120. * Remotely send an email template to multiple email addresses.
  121. *
  122. * Use the evars parameter to set replacement vars for a particular email address.
  123. *
  124. * @param string $template_name
  125. * @param array $emails
  126. * @param array $vars
  127. * @param array $evars
  128. * @param array $options
  129. * @link http://docs.sailthru.com/api/send
  130. * @return array API result
  131. */
  132. public function multisend($template_name, $emails, $vars = [ ], $evars = [ ], $options = [ ]) {
  133. $post['template'] = $template_name;
  134. $post['email'] = is_array($emails) ? implode(',', $emails) : $emails;
  135. $post['vars'] = $vars;
  136. $post['evars'] = $evars;
  137. $post['options'] = $options;
  138. $result = $this->apiPost('send', $post);
  139. return $result;
  140. }
  141. /**
  142. * Get the status of a send.
  143. *
  144. * @param string $send_id
  145. * @link http://docs.sailthru.com/api/send
  146. * @return array API result
  147. */
  148. public function getSend($send_id) {
  149. return $this->apiGet('send', [ 'send_id' => $send_id ]);
  150. }
  151. /**
  152. * Cancel a send that was scheduled for a future time.
  153. *
  154. * @param string $send_id
  155. * @link http://docs.sailthru.com/api/send
  156. * @return array API result
  157. */
  158. public function cancelSend($send_id) {
  159. return $this->apiDelete('send', [ 'send_id' => $send_id ]);
  160. }
  161. /**
  162. * Return information about an email address, including replacement vars and lists.
  163. *
  164. * @param string $email
  165. * @param array $options
  166. * @link http://docs.sailthru.com/api/email
  167. * @return array API result
  168. */
  169. public function getEmail($email, array $options = [ ]) {
  170. return $this->apiGet('email', array_merge([ 'email' => $email ], $options));
  171. }
  172. /**
  173. * Set replacement vars and/or list subscriptions for an email address.
  174. *
  175. * $lists should be an assoc array mapping list name => 1 for subscribed, 0 for unsubscribed
  176. *
  177. * @param string $email
  178. * @param array $vars
  179. * @param array $lists
  180. * @param array $templates
  181. * @param integer $verified 1 or 0
  182. * @param string $optout
  183. * @param string $send
  184. * @param array $send_vars
  185. * @link http://docs.sailthru.com/api/email
  186. * @return array API result
  187. */
  188. public function setEmail($email, $vars = [ ], $lists = [ ], $templates = [ ], $verified = 0, $optout = null, $send = null, $send_vars = [ ]) {
  189. $data = [ 'email' => $email ];
  190. if ($vars) {
  191. $data['vars'] = $vars;
  192. }
  193. if ($lists) {
  194. $data['lists'] = $lists;
  195. }
  196. if ($templates) {
  197. $data['templates'] = $templates;
  198. }
  199. $data['verified'] = (int) $verified;
  200. if ($optout !== null) {
  201. $data['optout'] = $optout;
  202. }
  203. if ($send !== null) {
  204. $data['send'] = $send;
  205. }
  206. if (!empty($send_vars)) {
  207. $data['send_vars'] = $send_vars;
  208. }
  209. return $this->apiPost('email', $data);
  210. }
  211. /**
  212. * Update / add email address
  213. *
  214. * @link http://docs.sailthru.com/api/email
  215. * @return array API result
  216. */
  217. public function setEmail2($email, array $options = [ ]) {
  218. $options['email'] = $email;
  219. return $this->apiPost('email', $options);
  220. }
  221. /**
  222. * Schedule a mass mail blast
  223. *
  224. * @param string $name the name to give to this new blast
  225. * @param string $list the mailing list name to send to
  226. * @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.
  227. * @param string $from_name the name appearing in the "From" of the email
  228. * @param string $from_email The email address to use as the "from" – choose from any of your verified emails
  229. * @param string $subject the subject line of the email
  230. * @param string $content_html the HTML-format version of the email
  231. * @param string $content_text the text-format version of the email
  232. * @param array $options associative array
  233. * blast_id
  234. * copy_blast
  235. * copy_template
  236. * replyto
  237. * report_email
  238. * is_link_tracking
  239. * is_google_analytics
  240. * is_public
  241. * suppress_list
  242. * test_vars
  243. * email_hour_range
  244. * abtest
  245. * test_percent
  246. * data_feed_url
  247. * @link http://docs.sailthru.com/api/blast
  248. * @return array API result
  249. */
  250. public function scheduleBlast($name, $list, $schedule_time, $from_name,
  251. $from_email, $subject, $content_html, $content_text, $options = [ ]
  252. ) {
  253. $data = $options;
  254. $data['name'] = $name;
  255. $data['list'] = $list;
  256. $data['schedule_time'] = $schedule_time;
  257. $data['from_name'] = $from_name;
  258. $data['from_email'] = $from_email;
  259. $data['subject'] = $subject;
  260. $data['content_html'] = $content_html;
  261. $data['content_text'] = $content_text;
  262. return $this->apiPost('blast', $data);
  263. }
  264. /**
  265. * Schedule a mass mail from a template
  266. *
  267. * @param String $template
  268. * @param String $list
  269. * @param String $schedule_time
  270. * @param array $options
  271. * @link http://docs.sailthru.com/api/blast
  272. * @return array API result
  273. **/
  274. public function scheduleBlastFromTemplate($template, $list, $schedule_time, $options = [ ]) {
  275. $data = $options;
  276. $data['copy_template'] = $template;
  277. $data['list'] = $list;
  278. $data['schedule_time'] = $schedule_time;
  279. return $this->apiPost('blast', $data);
  280. }
  281. /**
  282. * Schedule a mass mail blast from previous blast
  283. *
  284. * @param String|Integer $blast_id
  285. * @param String $schedule_time
  286. * @param array $options
  287. * @link http://docs.sailthru.com/api/blast
  288. * @return array API result
  289. **/
  290. public function scheduleBlastFromBlast($blast_id, $schedule_time, $options = [ ]) {
  291. $data = $options;
  292. $data['copy_blast'] = $blast_id;
  293. $data['schedule_time'] = $schedule_time;
  294. return $this->apiPost('blast', $data);
  295. }
  296. /**
  297. * updates existing blast
  298. *
  299. * @param string /integer $blast_id
  300. * @param string $name
  301. * @param string $list
  302. * @param string $schedule_time
  303. * @param string $from_name
  304. * @param string $from_email
  305. * @param string $subject
  306. * @param string $content_html
  307. * @param string $content_text
  308. * @param array $options associative array
  309. * blast_id
  310. * copy_blast
  311. * copy_template
  312. * replyto
  313. * report_email
  314. * is_link_tracking
  315. * is_google_analytics
  316. * is_public
  317. * suppress_list
  318. * test_vars
  319. * email_hour_range
  320. * abtest
  321. * test_percent
  322. * data_feed_url
  323. * @link http://docs.sailthru.com/api/blast
  324. * @return array API result
  325. */
  326. public function updateBlast($blast_id, $name = null, $list = null,
  327. $schedule_time = null, $from_name = null, $from_email = null,
  328. $subject = null, $content_html = null, $content_text = null,
  329. $options = [ ]
  330. ) {
  331. $data = $options;
  332. $data['blast_id'] = $blast_id;
  333. if (!is_null($name)) {
  334. $data['name'] = $name;
  335. }
  336. if (!is_null($list)) {
  337. $data['list'] = $list;
  338. }
  339. if (!is_null($schedule_time)) {
  340. $data['schedule_time'] = $schedule_time;
  341. }
  342. if (!is_null($from_name)) {
  343. $data['from_name'] = $from_name;
  344. }
  345. if (!is_null($from_email)) {
  346. $data['from_email'] = $from_email;
  347. }
  348. if (!is_null($subject)) {
  349. $data['subject'] = $subject;
  350. }
  351. if (!is_null($content_html)) {
  352. $data['content_html'] = $content_html;
  353. }
  354. if (!is_null($content_text)) {
  355. $data['content_text'] = $content_text;
  356. }
  357. return $this->apiPost('blast', $data);
  358. }
  359. /**
  360. * Get Blast information
  361. * @param string /integer $blast_id
  362. * @link http://docs.sailthru.com/api/blast
  363. * @return array API result
  364. */
  365. public function getBlast($blast_id) {
  366. return $this->apiGet('blast', [ 'blast_id' => $blast_id ]);
  367. }
  368. /**
  369. * Get info on multiple blasts
  370. * @param array $options associative array
  371. * start_date (required)
  372. * end-date (required)
  373. * status
  374. * @link http://docs.sailthru.com/api/blast
  375. * @return array API result
  376. */
  377. public function getBlasts($options) {
  378. return $this->apiGet('blast', $options);
  379. }
  380. /**
  381. * Delete Blast
  382. * @param integer /string $blast_id
  383. * @link http://docs.sailthru.com/api/blast
  384. * @return array API result
  385. */
  386. public function deleteBlast($blast_id) {
  387. return $this->apiDelete('blast', [ 'blast_id' => $blast_id ]);
  388. }
  389. /**
  390. * Cancel a scheduled Blast
  391. * @param integer /string $blast_id
  392. * @link http://docs.sailthru.com/api/blast
  393. * @return array API result
  394. */
  395. public function cancelBlast($blast_id) {
  396. $data = [
  397. 'blast_id' => $blast_id,
  398. 'schedule_time' => ''
  399. ];
  400. return $this->apiPost('blast', $data);
  401. }
  402. /**
  403. * Fetch information about a template
  404. *
  405. * @param string $template_name
  406. * @param array $options
  407. * @return array API result
  408. * @link http://docs.sailthru.com/api/template
  409. */
  410. public function getTemplate($template_name, array $options = [ ]) {
  411. $options['template'] = $template_name;
  412. return $this->apiGet('template', $options);
  413. }
  414. /**
  415. * Fetch name of all existing templates
  416. * @link http://docs.sailthru.com/api/template
  417. * @return array API result
  418. */
  419. public function getTemplates() {
  420. return $this->apiGet('template');
  421. }
  422. public function getTemplateFromRevision($revision_id) {
  423. return $this->apiGet('template', [ 'revision' => (int) $revision_id ]);
  424. }
  425. /**
  426. * Save a template.
  427. *
  428. * @param string $template_name
  429. * @param array $template_fields
  430. * @link http://docs.sailthru.com/api/template
  431. * @return array API result
  432. */
  433. public function saveTemplate($template_name, array $template_fields = [ ]) {
  434. $data = $template_fields;
  435. $data['template'] = $template_name;
  436. return $this->apiPost('template', $data);
  437. }
  438. /**
  439. * Save a template from revision
  440. *
  441. * @param string $template_name
  442. * @param $revision_id
  443. * @return array API result
  444. * @link http://docs.sailthru.com/api/template
  445. */
  446. public function saveTemplateFromRevision($template_name, $revision_id) {
  447. $revision_id = (int) $revision_id;
  448. return $this->saveTemplate($template_name, [ 'revision' => $revision_id ]);
  449. }
  450. /**
  451. * Delete a template.
  452. *
  453. * @param string $template_name
  454. * @return array API result
  455. * @link http://docs.sailthru.com/api/template
  456. */
  457. public function deleteTemplate($template_name) {
  458. return $this->apiDelete('template', [ 'template' => $template_name ]);
  459. }
  460. /**
  461. * Fetch information about an include
  462. *
  463. * @param string $include_name
  464. * @return array API result
  465. */
  466. public function getInclude($include_name, array $options = [ ]) {
  467. $options['include'] = $include_name;
  468. return $this->apiGet('include', $options);
  469. }
  470. /**
  471. * Fetch name of all existing includes
  472. * @return array API result
  473. */
  474. public function getIncludes() {
  475. return $this->apiGet('include');
  476. }
  477. /**
  478. * Save an include
  479. *
  480. * @param string $include_name
  481. * @param array $include_fields
  482. * @return array API result
  483. */
  484. public function saveInclude($include_name, array $include_fields = [ ]) {
  485. $data = $include_fields;
  486. $data['include'] = $include_name;
  487. return $this->apiPost('include', $data);
  488. }
  489. /**
  490. * Get information about a list.
  491. *
  492. * @param string $list
  493. * @return array
  494. * @link http://docs.sailthru.com/api/list
  495. */
  496. public function getList($list) {
  497. return $this->apiGet('list', [ 'list' => $list ]);
  498. }
  499. /**
  500. * Get information about all lists
  501. * @return array
  502. * @link http://docs.sailthru.com/api/list
  503. */
  504. public function getLists() {
  505. return $this->apiGet('list', [ ]);
  506. }
  507. /**
  508. * Create a list, or update a list.
  509. *
  510. * @param string $list
  511. * @param string $list
  512. * @param string $type
  513. * @param bool $primary
  514. * @param array $query
  515. * @return array
  516. * @link http://docs.sailthru.com/api/list
  517. * @link http://docs.sailthru.com/api/query
  518. */
  519. public function saveList($list, $type = null, $primary = null, $query = [ ], $vars = []) {
  520. $data = [
  521. 'list' => $list,
  522. 'type' => $type,
  523. 'primary' => $primary ? 1 : 0,
  524. 'query' => $query,
  525. 'vars' => $vars,
  526. ];
  527. return $this->apiPost('list', $data);
  528. }
  529. /**
  530. * Deletes a list.
  531. *
  532. * @param string $list
  533. * @return array
  534. * @link http://docs.sailthru.com/api/list
  535. */
  536. public function deleteList($list) {
  537. return $this->apiDelete('list', [ 'list' => $list ]);
  538. }
  539. /**
  540. *
  541. * Push a new piece of content to Sailthru, triggering any applicable alerts.
  542. *
  543. * @param String $title
  544. * @param String $url
  545. * @param String $date
  546. * @param Mixed $tags Null for empty values, or String or arrays
  547. * @link http://docs.sailthru.com/api/content
  548. * @return array API result
  549. */
  550. public function pushContent($title, $url, $date = null, $tags = null, $vars = [ ], $options = [ ]) {
  551. $data = $options;
  552. $data['title'] = $title;
  553. $data['url'] = $url;
  554. if (!is_null($tags)) {
  555. $data['tags'] = is_array($tags) ? implode(",", $tags) : $tags;
  556. }
  557. if (!is_null($date)) {
  558. $data['date'] = $date;
  559. }
  560. if (!empty($vars)) {
  561. $data['vars'] = $vars;
  562. }
  563. return $this->apiPost('content', $data);
  564. }
  565. /**
  566. *
  567. * Retrieve a user's alert settings.
  568. *
  569. * @link http://docs.sailthru.com/api/alert
  570. * @param String $email
  571. * @return array API result
  572. */
  573. public function getAlert($email) {
  574. $data = [
  575. 'email' => $email
  576. ];
  577. return $this->apiGet('alert', $data);
  578. }
  579. /**
  580. *
  581. * Add a new alert to a user. You can add either a realtime or a summary alert (daily/weekly).
  582. * $when is only required when alert type is weekly or daily
  583. *
  584. * <code>
  585. * <?php
  586. * $options = array(
  587. * 'match' => array(
  588. * 'type' => array('shoes', 'shirts'),
  589. * 'min' => array('price' => 3000),
  590. * 'tags' => array('blue', 'red'),
  591. * )
  592. * );
  593. * $response = $sailthruClient->saveAlert("praj@sailthru.com", 'realtime', 'default', null, $options);
  594. * ?>
  595. * </code>
  596. *
  597. * @link http://docs.sailthru.com/api/alert
  598. * @param String $email
  599. * @param String $type
  600. * @param String $template
  601. * @param String $when
  602. * @param array $options Associative array of additive nature
  603. * match Exact-match a custom variable match[type]=shoes
  604. * min Minimum-value variables min[price]=30000
  605. * max Maximum-value match max[price]=50000
  606. * tags Tag-match tags[]=blue
  607. * @return array API result
  608. */
  609. public function saveAlert($email, $type, $template, $when = null, $options = [ ]) {
  610. $data = $options;
  611. $data['email'] = $email;
  612. $data['type'] = $type;
  613. $data['template'] = $template;
  614. if ($type == 'weekly' || $type == 'daily') {
  615. $data['when'] = $when;
  616. }
  617. return $this->apiPost('alert', $data);
  618. }
  619. /**
  620. * Remove an alert from a user's settings.
  621. * @link http://docs.sailthru.com/api/alert
  622. * @param <type> $email
  623. * @param <type> $alert_id
  624. * @return array API result
  625. */
  626. public function deleteAlert($email, $alert_id) {
  627. $data = [
  628. 'email' => $email,
  629. 'alert_id' => $alert_id
  630. ];
  631. return $this->apiDelete('alert', $data);
  632. }
  633. /**
  634. * Record that a user has made a purchase, or has added items to their purchase total.
  635. * @link http://docs.sailthru.com/api/purchase
  636. * @return array API result
  637. */
  638. public function purchase($email, array $items, $incomplete = null, $message_id = null, array $options = [ ]) {
  639. $data = $options;
  640. $data['email'] = $email;
  641. $data['items'] = $items;
  642. if (!is_null($incomplete)) {
  643. $data['incomplete'] = (int) $incomplete;
  644. }
  645. if (!is_null($message_id)) {
  646. $data['message_id'] = $message_id;
  647. }
  648. return $this->apiPost('purchase', $data);
  649. }
  650. /**
  651. * Make a purchase API call with incomplete flag
  652. * @link http://docs.sailthru.com/api/purchase
  653. * @return array API result
  654. */
  655. public function purchaseIncomplete($email, array $items, $message_id, array $options = [ ]) {
  656. return $this->purchase($email, $items, 1, $message_id, $options);
  657. }
  658. /**
  659. * Retrieve information about your subscriber counts on a particular list, on a particular day.
  660. * @link http://docs.sailthru.com/api/stats
  661. * @param String $list
  662. * @param String $date
  663. * @return array API result
  664. */
  665. public function stats_list($list = null, $date = null) {
  666. $data = [ ];
  667. if (!is_null($list)) {
  668. $data['list'] = $list;
  669. }
  670. if (!is_null($date)) {
  671. $data['date'] = $date;
  672. }
  673. $data['stat'] = 'list';
  674. return $this->stats($data);
  675. }
  676. /**
  677. * Retrieve information about a particular blast or aggregated information from all of blasts over a specified date range.
  678. * @param array $data
  679. * @return array API result
  680. */
  681. public function stats_blast($blast_id = null, $start_date = null, $end_date = null, array $data = [ ]) {
  682. $data['stat'] = 'blast';
  683. if (!is_null($blast_id)) {
  684. $data['blast_id'] = $blast_id;
  685. }
  686. if (!is_null($start_date)) {
  687. $data['start_date'] = $start_date;
  688. }
  689. if (!is_null($end_date)) {
  690. $data['end_date'] = $end_date;
  691. }
  692. return $this->stats($data);
  693. }
  694. /**
  695. * Retrieve information about a particular send or aggregated information from all of templates over a specified date range.
  696. * @param array $data
  697. * @return array API result
  698. */
  699. public function stats_send($template = null, $start_date = null, $end_date = null, array $data = [ ]) {
  700. $data['stat'] = 'send';
  701. if (!is_null($template)) {
  702. $data['template'] = $template;
  703. }
  704. if (!is_null($start_date)) {
  705. $data['start_date'] = $start_date;
  706. }
  707. if (!is_null($end_date)) {
  708. $data['end_date'] = $end_date;
  709. }
  710. return $this->stats($data);
  711. }
  712. /**
  713. * Make Stats API Request
  714. * @param array $data
  715. * @return array API result
  716. */
  717. public function stats(array $data) {
  718. return $this->apiGet('stats', $data);
  719. }
  720. /**
  721. *
  722. * Returns true if the incoming request is an authenticated verify post.
  723. * @link http://docs.sailthru.com/api/postbacks
  724. * @return boolean
  725. */
  726. public function receiveVerifyPost() {
  727. $params = $_POST;
  728. foreach ([ 'action', 'email', 'send_id', 'sig' ] as $k) {
  729. if (!isset($params[$k])) {
  730. return false;
  731. }
  732. }
  733. if ($params['action'] != 'verify') {
  734. return false;
  735. }
  736. $sig = $params['sig'];
  737. unset($params['sig']);
  738. if ($sig != Sailthru_Util::getSignatureHash($params, $this->secret)) {
  739. return false;
  740. }
  741. $send = $this->getSend($params['send_id']);
  742. if (!isset($send['email'])) {
  743. return false;
  744. }
  745. if ($send['email'] != $params['email']) {
  746. return false;
  747. }
  748. return true;
  749. }
  750. /**
  751. *
  752. * Optout postbacks
  753. * @return boolean
  754. * @link http://docs.sailthru.com/api/postbacks
  755. */
  756. public function receiveOptoutPost() {
  757. $params = $_POST;
  758. foreach ([ 'action', 'email', 'sig' ] as $k) {
  759. if (!isset($params[$k])) {
  760. return false;
  761. }
  762. }
  763. if ($params['action'] != 'optout') {
  764. return false;
  765. }
  766. $sig = $params['sig'];
  767. unset($params['sig']);
  768. if ($sig != Sailthru_Util::getSignatureHash($params, $this->secret)) {
  769. return false;
  770. }
  771. return true;
  772. }
  773. /**
  774. *
  775. * Update postbacks
  776. * @return boolean
  777. * @link http://docs.sailthru.com/api/postbacks
  778. */
  779. public function receiveUpdatePost() {
  780. $params = $_POST;
  781. foreach ([ 'action', 'sid', 'sig' ] as $k) {
  782. if (!isset($params[$k])) {
  783. return false;
  784. }
  785. }
  786. if ($params['action'] != 'update') {
  787. return false;
  788. }
  789. $sig = $params['sig'];
  790. unset($params['sig']);
  791. if ($sig != Sailthru_Util::getSignatureHash($params, $this->secret)) {
  792. return false;
  793. }
  794. return true;
  795. }
  796. /**
  797. *
  798. * Hard bounce postbacks
  799. * @return boolean
  800. * @link http://docs.sailthru.com/api/postbacks
  801. */
  802. public function receiveHardBouncePost() {
  803. $params = $_POST;
  804. foreach ([ 'action', 'email', 'sig' ] as $k) {
  805. if (!isset($params[$k])) {
  806. return false;
  807. }
  808. }
  809. if ($params['action'] != 'hardbounce') {
  810. return false;
  811. }
  812. $sig = $params['sig'];
  813. unset($params['sig']);
  814. if ($sig != Sailthru_Util::getSignatureHash($params, $this->secret)) {
  815. return false;
  816. }
  817. if (isset($params['send_id'])) {
  818. $send_id = $params['send_id'];
  819. $send = $this->getSend($send_id);
  820. if (!isset($send['email'])) {
  821. return false;
  822. }
  823. } else if (isset($params['blast_id'])) {
  824. $blast_id = $params['blast_id'];
  825. $blast = $this->getBlast($blast_id);
  826. if (isset($blast['error'])) {
  827. return false;
  828. }
  829. }
  830. return true;
  831. }
  832. /**
  833. * Get status of a job
  834. * @param String $job_id
  835. * @return array
  836. */
  837. public function getJobStatus($job_id) {
  838. return $this->apiGet('job', [ 'job_id' => $job_id ]);
  839. }
  840. /**
  841. * process job api call
  842. * @param String $job
  843. * @param array $data
  844. * @param bool|String $report_email
  845. * @param bool|String $postback_url
  846. * @param array $binary_data_param
  847. * @param array $options
  848. * @return array
  849. */
  850. protected function processJob($job, array $data = [ ], $report_email = false, $postback_url = false, array $binary_data_param = [ ],
  851. array $options = [ ]) {
  852. $data['job'] = $job;
  853. if ($report_email) {
  854. $data['report_email'] = $report_email;
  855. }
  856. if ($postback_url) {
  857. $data['postback_url'] = $postback_url;
  858. }
  859. return $this->apiPost('job', $data, $binary_data_param, $options);
  860. }
  861. /**
  862. * Process import job from given email string CSV
  863. * @param String $list
  864. * @param String $emails
  865. * @param bool|String $report_email
  866. * @param bool|String $postback_url
  867. * @return array
  868. */
  869. public function processImportJob($list, $emails, $report_email = false, $postback_url = false, array $options = [ ]) {
  870. $data = [
  871. 'emails' => $emails,
  872. 'list' => $list
  873. ];
  874. return $this->processJob('import', $data, $report_email, $postback_url, [ ], $options);
  875. }
  876. /**
  877. * Process import job from given file path of a CSV or email per line file
  878. *
  879. * @param String $list
  880. * @param $file_path
  881. * @param bool|String $report_email
  882. * @param bool|String $postback_url
  883. * @param array $options
  884. * @return array
  885. */
  886. public function processImportJobFromFile($list, $file_path, $report_email = false, $postback_url = false, array $options = [ ]) {
  887. $data = [
  888. 'file' => $file_path,
  889. 'list' => $list
  890. ];
  891. return $this->processJob('import', $data, $report_email, $postback_url, [ 'file' ], $options);
  892. }
  893. /**
  894. * Process purchase import job from given file path of an email per line JSON file
  895. *
  896. * @param String $file_path
  897. * @param bool|String $report_email
  898. * @param bool|String $postback_url
  899. * @param array $options
  900. * @return array
  901. */
  902. public function processPurchaseImportJobFromFile($file_path, $report_email = false, $postback_url = false, array $options = [ ]) {
  903. $data = [
  904. 'file' => $file_path
  905. ];
  906. return $this->processJob('purchase_import', $data, $report_email, $postback_url, [ 'file' ], $options);
  907. }
  908. /**
  909. * Process a snapshot job
  910. *
  911. * @param array $query
  912. * @param bool|String $report_email
  913. * @param bool|String $postback_url
  914. * @return array
  915. */
  916. public function processSnapshotJob(array $query, $report_email = false, $postback_url = false, array $options = [ ]) {
  917. $data = [ 'query' => $query ];
  918. return $this->processJob('snaphot', $data, $report_email, $postback_url, [ ], $options);
  919. }
  920. /**
  921. * Process a export list job
  922. * @param String $list
  923. * @param bool|String $report_email
  924. * @param bool|String $postback_url
  925. * @param array $options
  926. * @return array
  927. */
  928. public function processExportListJob($list, $report_email = false, $postback_url = false, array $options = [ ]) {
  929. $data = [ 'list' => $list ];
  930. return $this->processJob('export_list_data', $data, $report_email, $postback_url, [ ], $options);
  931. }
  932. /**
  933. * Export blast data in CSV format
  934. * @param integer $blast_id
  935. * @param bool|String $report_email
  936. * @param bool|String $postback_url
  937. * @param array $options
  938. * @return array
  939. */
  940. public function processBlastQueryJob($blast_id, $report_email = false, $postback_url = false, array $options = [ ]) {
  941. return $this->processJob('blast_query', [ 'blast_id' => $blast_id ], $report_email, $postback_url, [ ], $options);
  942. }
  943. /**
  944. * Perform a bulk update of any number of user profiles from given context: String CSV, file, URL or query
  945. * @param String $context
  946. * @param $value
  947. * @param array $update
  948. * @param bool|String $report_email
  949. * @param bool|String $postback_url
  950. * @param array $file_params
  951. * @return array
  952. */
  953. public function processUpdateJob($context, $value, array $update = [ ], $report_email = false, $postback_url = false, array $file_params = [ ],
  954. array $options = [ ]) {
  955. $data = [
  956. $context => $value
  957. ];
  958. if (count($update) > 0) {
  959. $data['update'] = $update;
  960. }
  961. return $this->processJob('update', $data, $report_email, $postback_url, $file_params, $options);
  962. }
  963. /**
  964. * Perform a bulk update of any number of user profiles from given URL
  965. * @param String $url
  966. * @param array $update
  967. * @param bool|String $report_email
  968. * @param bool|String $postback_url
  969. * @param array $options
  970. * @return array
  971. */
  972. public function processUpdateJobFromUrl($url, array $update = [ ], $report_email = false, $postback_url = false, array $options = [ ]) {
  973. return $this->processUpdateJob('url', $url, $update, $report_email, $postback_url, [ ], $options);
  974. }
  975. /**
  976. * Perform a bulk update of any number of user profiles from given file
  977. * @param $file
  978. * @param Array $update
  979. * @param bool|String $report_email
  980. * @param bool|String $postback_url
  981. * @param array $options
  982. * @return array
  983. * @internal param String $url
  984. */
  985. public function processUpdateJobFromFile($file, array $update = [ ], $report_email = false, $postback_url = false, array $options = [ ]) {
  986. return $this->processUpdateJob('file', $file, $update, $report_email, $postback_url, [ 'file' ], $options);
  987. }
  988. /**
  989. * Perform a bulk update of any number of user profiles from a query
  990. * @param Array $query
  991. * @param Array $update
  992. * @param String $report_email
  993. * @param String $postback_url
  994. */
  995. public function processUpdateJobFromQuery($query, array $update = [ ], $report_email = false, $postback_url = false, array $options = [ ]) {
  996. return $this->processUpdateJob('query', $query, $update, $report_email, $postback_url, [ ], $options);
  997. }
  998. /**
  999. * Perform a bulk update of any number of user profiles from emails CSV
  1000. * @param String $emails
  1001. * @param Array $update
  1002. * @param bool|String $report_email
  1003. * @param bool|String $postback_url
  1004. * @return array
  1005. */
  1006. public function processUpdateJobFromEmails($emails, array $update = [ ], $report_email = false, $postback_url = false, array $options = [ ]) {
  1007. return $this->processUpdateJob('emails', $emails, $update, $report_email, $postback_url, [ ], $options);
  1008. }
  1009. /**
  1010. * Save existing user
  1011. * @param String $id
  1012. * @param array $options
  1013. * @return array
  1014. */
  1015. public function saveUser($id, array $options = [ ]) {
  1016. $data = $options;
  1017. $data['id'] = $id;
  1018. return $this->apiPost('user', $data);
  1019. }
  1020. /**
  1021. * Get user by Sailthru ID
  1022. * @param String $id
  1023. * @return array
  1024. */
  1025. public function getUserBySid($id) {
  1026. return $this->apiGet('user', [ 'id' => $id ]);
  1027. }
  1028. /**
  1029. * Get user by specified key
  1030. * @param String $id
  1031. * @param String $key
  1032. * @param array $fields
  1033. * @return array
  1034. */
  1035. public function getUserByKey($id, $key, array $fields = [ ]) {
  1036. $data = [
  1037. 'id' => $id,
  1038. 'key' => $key,
  1039. 'fields' => $fields
  1040. ];
  1041. return $this->apiGet('user', $data);
  1042. }
  1043. /**
  1044. *
  1045. * Set Horizon cookie
  1046. *
  1047. * @param string $email horizon user email
  1048. * @param string $domain
  1049. * @param integer $duration
  1050. * @param boolean $secure
  1051. * @return boolean
  1052. */
  1053. public function setHorizonCookie($email, $domain = null, $duration = null, $secure = false) {
  1054. $data = $this->getUserByKey($email, 'email', [ 'keys' => 1 ]);
  1055. if (!isset($data['keys']['cookie'])) {
  1056. return false;
  1057. }
  1058. if (!$domain) {
  1059. $domain_parts = explode('.', $_SERVER['HTTP_HOST']);
  1060. $domain = $domain_parts[sizeof($domain_parts) - 2] . '.' . $domain_parts[sizeof($domain_parts) - 1];
  1061. }
  1062. if ($duration === null) {
  1063. $expire = time() + 31556926;
  1064. } else if ($duration) {
  1065. $expire = time() + $duration;
  1066. } else {
  1067. $expire = 0;
  1068. }
  1069. return setcookie('sailthru_hid', $data['keys']['cookie'], $expire, '/', $domain, $secure);
  1070. }
  1071. /**
  1072. * Get an HTML preview of a template.
  1073. * @param $template
  1074. * @param $email
  1075. * @return array
  1076. * @link http://docs.sailthru.com/api/preview
  1077. */
  1078. public function previewTemplateWithHTML($template, $email) {
  1079. $data = [ ];
  1080. $data['template'] = $template;
  1081. $data['email'] = $email;
  1082. $result = $this->apiPost('preview', $data);
  1083. return $result;
  1084. }
  1085. /**
  1086. * Get an HTML preview of a blast.
  1087. * @param $blast_id
  1088. * @param $email
  1089. * @return array
  1090. * @link http://docs.sailthru.com/api/preview
  1091. */
  1092. public function previewBlastWithHTML($blast_id, $email) {
  1093. $data = [ ];
  1094. $data['blast_id'] = $blast_id;
  1095. $data['email'] = $email;
  1096. $result = $this->apiPost('preview', $data);
  1097. return $result;
  1098. }
  1099. /**
  1100. * Get an HTML preview of a recurring blast.
  1101. * @param $blast_repeat_id
  1102. * @param $email
  1103. * @return array
  1104. * @link http://docs.sailthru.com/api/preview
  1105. */
  1106. public function previewRecurringBlastWithHTML($blast_repeat_id, $email) {
  1107. $data = [ ];
  1108. $data['blast_repeat_id'] = $blast_repeat_id;
  1109. $data['email'] = $email;
  1110. $result = $this->apiPost('preview', $data);
  1111. }
  1112. /**
  1113. * Get an HTML preview of content_html.
  1114. * @param $content_html
  1115. * @param $email
  1116. * @return array
  1117. * @link http://docs.sailthru.com/api/preview
  1118. */
  1119. public function previewContentWithHTML($content_html, $email) {
  1120. $data = [ ];
  1121. $data['content_html'] = $content_html;
  1122. $data['email'] = $email;
  1123. $result = $this->apiPost('preview', $data);
  1124. return $result;
  1125. }
  1126. /**
  1127. * Get an email preview of a template.
  1128. * @param $template
  1129. * @param $send_email
  1130. * @return array
  1131. * @link http://docs.sailthru.com/api/preview
  1132. */
  1133. public function previewTemplateWithEmail($template, $send_email) {
  1134. $data = [ ];
  1135. $data['template'] = $template;
  1136. $data['send_email'] = $send_email;
  1137. $result = $this->apiPost('preview', $data);
  1138. return $result;
  1139. }
  1140. /**
  1141. * Get an email preview of a blast.
  1142. * @param $blast_id
  1143. * @param $send_email
  1144. * @return array
  1145. * @link http://docs.sailthru.com/api/preview
  1146. */
  1147. public function previewBlastWithEmail($blast_id, $send_email) {
  1148. $data = [ ];
  1149. $data['blast_id'] = $blast_id;
  1150. $data['send_email'] = $send_email;
  1151. $result = $this->apiPost('preview', $data);
  1152. return $result;
  1153. }
  1154. /**
  1155. * Get an email preview of a recurring blast.
  1156. * @param $blast_repeat_id
  1157. * @param $send_email
  1158. * @return array
  1159. * @link http://docs.sailthru.com/api/preview
  1160. */
  1161. public function previewRecurringBlastWithEmail($blast_repeat_id, $send_email) {
  1162. $data = [ ];
  1163. $data['blast_repeat_id'] = $blast_repeat_id;
  1164. $data['send_email'] = $send_email;
  1165. $result = $this->apiPost('preview', $data);
  1166. return $result;
  1167. }
  1168. /**
  1169. * Get an email preview of content_html.
  1170. * @param $content_html
  1171. * @param $send_email
  1172. * @return array
  1173. * @link http://docs.sailthru.com/api/preview
  1174. */
  1175. public function previewContentWithEmail($content_html, $send_email) {
  1176. $data = [ ];
  1177. $data['content_html'] = $content_html;
  1178. $data['send_email'] = $send_email;
  1179. $result = $this->apiPost('preview', $data);
  1180. return $result;
  1181. }
  1182. /**
  1183. * Get Triggers
  1184. * @return array
  1185. * @link http://docs.sailthru.com/api/trigger
  1186. */
  1187. public function getTriggers() {
  1188. $result = $this->apiGet('trigger');
  1189. return $result;
  1190. }
  1191. /**
  1192. * Get information on a trigger
  1193. * @param string $template
  1194. * @param string $trigger_id
  1195. * @return array
  1196. * @link http://docs.sailthru.com/api/trigger
  1197. */
  1198. public function getTriggerByTemplate($template, $trigger_id = null) {
  1199. $data = [ ];
  1200. $data['template'] = $template;
  1201. if (!is_null($trigger_id)) {
  1202. $data['trigger_id'] = $trigger_id;
  1203. }
  1204. $result = $this->apiGet('trigger', $data);
  1205. return $result;
  1206. }
  1207. /**
  1208. * Get information on a trigger
  1209. * @param string $event
  1210. * @return array
  1211. * @link http://docs.sailthru.com/api/trigger
  1212. */
  1213. public function getTriggerByEvent($event) {
  1214. $data = [ ];
  1215. $data['event'] = $event;
  1216. $result = $this->apiGet('trigger', $data);
  1217. return $result;
  1218. }
  1219. /**
  1220. * Get information on a trigger
  1221. * @param string $trigger_id
  1222. * @return array
  1223. * @link http://docs.sailthru.com/api/trigger
  1224. */
  1225. public function getTriggerById($trigger_id) {
  1226. $data = [ ];
  1227. $data['trigger_id'] = $trigger_id;
  1228. $result = $this->apiGet('trigger', $data);
  1229. return $result;
  1230. }
  1231. /**
  1232. * Create a trigger for templates
  1233. * @param string $template
  1234. * @param integer $time
  1235. * @param string $time_unit
  1236. * @param string $event
  1237. * @param string $zephyr
  1238. * @return array
  1239. * @link http://docs.sailthru.com/api/trigger
  1240. */
  1241. public function postTrigger($template, $time, $time_unit, $event, $zephyr) {
  1242. $data = [ ];
  1243. $data['template'] = $template;
  1244. $data['time'] = $time;
  1245. $data['time_unit'] = $time_unit;
  1246. $data['event'] = $event;
  1247. $data['zephyr'] = $zephyr;
  1248. $result = $this->apiPost('trigger', $data);
  1249. return $result;
  1250. }
  1251. /**
  1252. * Create a trigger for events
  1253. * @param integer $time
  1254. * @param string $time_unit
  1255. * @param string $event
  1256. * @param string $zephyr
  1257. * @return array
  1258. * @link http://docs.sailthru.com/api/trigger
  1259. */
  1260. public function postEventTrigger($event, $time, $time_unit, $zephyr) {
  1261. $data = [ ];
  1262. $data['time'] = $time;
  1263. $data['time_unit'] = $time_unit;
  1264. $data['event'] = $event;
  1265. $data['zephyr'] = $zephyr;
  1266. $result = $this->apiPost('trigger', $data);
  1267. return $result;
  1268. }
  1269. /**
  1270. * Notify Sailthru of an event
  1271. * @param string $id
  1272. * @param string $event
  1273. * @param array $options
  1274. * @return array
  1275. * @link http://docs.sailthru.com/api/event
  1276. */
  1277. public function postEvent($id, $event, $options = [ ]) {
  1278. $data = $options;
  1279. $data['id'] = $id;
  1280. $data['event'] = $event;
  1281. $result = $this->apiPost('event', $data);
  1282. return $result;
  1283. }
  1284. /**
  1285. * Perform an HTTP request using the curl extension
  1286. *
  1287. * @param string $action
  1288. * @param array $data
  1289. * @param string $method
  1290. * @param array $options
  1291. * @return string
  1292. * @throws Sailthru_Client_Exception
  1293. */
  1294. protected function httpRequestCurl($action, array $data, $method = 'POST', $options = [ ]) {
  1295. $url = $this->api_uri . "/" . $action;
  1296. $ch = curl_init();
  1297. $options = array_merge($this->options, $options);
  1298. if ($method == 'POST') {
  1299. curl_setopt($ch, CURLOPT_POST, true);
  1300. if ($this->fileUpload === true) {
  1301. curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
  1302. $this->fileUpload = false;
  1303. } else {
  1304. curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data, '', '&'));
  1305. }
  1306. } else {
  1307. $url .= '?' . http_build_query($data, '', '&');
  1308. if ($method != 'GET') {
  1309. curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
  1310. }
  1311. }
  1312. curl_setopt($ch, CURLOPT_URL, $url);
  1313. curl_setopt($ch, CURLOPT_HEADER, true);
  1314. curl_setopt($ch, CURLOPT_ENCODING, 'gzip');
  1315. curl_setopt($ch, CURLOPT_TIMEOUT_MS, $options['timeout']);
  1316. curl_setopt($ch, CURLOPT_CONNECTTIMEOUT_MS, $options['connect_timeout']);
  1317. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  1318. curl_setopt($ch, CURLOPT_HTTPHEADER, $this->httpHeaders);
  1319. $response = curl_exec($ch);
  1320. $this->lastResponseInfo = curl_getinfo($ch);
  1321. curl_close($ch);
  1322. if (!$response) {
  1323. throw new Sailthru_Client_Exception(
  1324. "Bad response received from $url",
  1325. Sailthru_Client_Exception::CODE_RESPONSE_EMPTY
  1326. );
  1327. }
  1328. // parse headers and body
  1329. $parts = explode("\r\n\r\nHTTP/", $response);
  1330. $parts = (count($parts) > 1 ? 'HTTP/' : '') . array_pop($parts); // deal with HTTP/1.1 100 Continue before other headers
  1331. list($headers, $body) = explode("\r\n\r\n", $parts, 2);
  1332. $this->lastRateLimitInfo[$action][$method] = self::parseRateLimitHeaders($headers);
  1333. return $body;
  1334. }
  1335. /**
  1336. * Adapted from: http://netevil.org/blog/2006/nov/http-post-from-php-without-curl
  1337. *
  1338. * @param string $action
  1339. * @param array $data
  1340. * @param string $method
  1341. * @param array $options
  1342. * @return string
  1343. * @throws Sailthru_Client_Exception
  1344. */
  1345. protected function httpRequestWithoutCurl($action, $data, $method = 'POST', $options = [ ]) {
  1346. if ($this->fileUpload === true) {
  1347. $this->fileUpload = false;
  1348. throw new Sailthru_Client_Exception(
  1349. 'cURL extension is required for the request with file upload',
  1350. Sailthru_Client_Exception::CODE_GENERAL
  1351. );
  1352. }
  1353. $url = $this->api_uri . "/" . $action;
  1354. $params = [ 'http' => [ 'method' => $method, 'ignore_errors' => true ] ];
  1355. if ($method == 'POST') {
  1356. $params['http']['content'] = is_array($data) ? http_build_query($data, '', '&') : $data;
  1357. } else {
  1358. $url .= '?' . http_build_query($data, '', '&');
  1359. }
  1360. $params['http']['header'] = "User-Agent: {$this->user_agent_string}\nContent-Type: application/x-www-form-urlencoded";
  1361. $ctx = stream_context_create($params);
  1362. $fp = @fopen($url, 'rb', false, $ctx);
  1363. if (!$fp) {
  1364. throw new Sailthru_Client_Exception(
  1365. "Unable to open stream: $url",
  1366. Sailthru_Client_Exception::CODE_GENERAL
  1367. );
  1368. }
  1369. $response = @stream_get_contents($fp);
  1370. if ($response === false) {
  1371. throw new Sailthru_Client_Exception(
  1372. "No response received from stream: $url",
  1373. Sailthru_Client_Exception::CODE_RESPONSE_EMPTY
  1374. );
  1375. }
  1376. return $response;
  1377. }
  1378. /**
  1379. * Perform an HTTP request, checking for curl extension support
  1380. *
  1381. * @param $action
  1382. * @param array $data
  1383. * @param string $method
  1384. * @param array $options
  1385. * @return string
  1386. * @throws Sailthru_Client_Exception
  1387. */
  1388. protected function httpRequest($action, $data, $method = 'POST', $options = [ ]) {
  1389. $response = $this->{$this->http_request_type}($action, $data, $method, $options);
  1390. $json = json_decode($response, true);
  1391. if ($json === NULL) {
  1392. throw new Sailthru_Client_Exception(
  1393. "Response: {$response} is not a valid JSON",
  1394. Sailthru_Client_Exception::CODE_RESPONSE_INVALID
  1395. );
  1396. }
  1397. if (!empty($json['error'])) {
  1398. throw new Sailthru_Client_Exception($json['errormsg'], $json['error']);
  1399. }
  1400. return $json;
  1401. }
  1402. /**
  1403. * Perform an API POST (or other) request, using the shared-secret auth hash.
  1404. * if binary_data_param is set, its appends '@' so that cURL can make binary POST request
  1405. *
  1406. * @param string $action
  1407. * @param array $data
  1408. * @param array $binary_data_param
  1409. * @param array $options
  1410. * @return array
  1411. */
  1412. public function apiPost($action, $data, array $binary_data_param = [ ], $options = [ ]) {
  1413. $binary_data = [ ];
  1414. if (!empty ($binary_data_param)) {
  1415. foreach ($binary_data_param as $param) {
  1416. if (isset($data[$param]) && file_exists($data[$param])) {
  1417. $binary_data[$param] = version_compare(PHP_VERSION, '5.5.0') >= 0 && class_exists('CURLFile')
  1418. ? new CURLFile($data[$param])
  1419. : "@{$data[$param]}";
  1420. unset($data[$param]);
  1421. $this->fileUpload = true;
  1422. }
  1423. }
  1424. }
  1425. $payload = $this->prepareJsonPayload($data, $binary_data);
  1426. return $this->httpRequest($action, $payload, 'POST', $options);
  1427. }
  1428. /**
  1429. * Perform an API GET request, using the shared-secret auth hash.
  1430. *
  1431. * @param string $action
  1432. * @param array $data
  1433. * @return array
  1434. */
  1435. public function apiGet($action, $data = [ ], $method = 'GET', $options = [ ]) {
  1436. return $this->httpRequest($action, $this->prepareJsonPayload($data), $method, $options);
  1437. }
  1438. /**
  1439. * Perform an API DELETE request, using the shared-secret auth hash.
  1440. *
  1441. * @param string $action
  1442. * @param array $data
  1443. * @return array
  1444. */
  1445. public function apiDelete($action, $data, $options = [ ]) {
  1446. return $this->apiGet($action, $data, 'DELETE', $options);
  1447. }
  1448. /**
  1449. * get information from last server response when used with cURL
  1450. * returns associative array as per http://us.php.net/curl_getinfo
  1451. * @return array or null
  1452. */
  1453. public function getLastResponseInfo() {
  1454. return $this->lastResponseInfo;
  1455. }
  1456. /**
  1457. * Prepare JSON payload
  1458. */
  1459. protected function prepareJsonPayload(array $data, array $binary_data = [ ]) {
  1460. $payload = [
  1461. 'api_key' => $this->api_key,
  1462. 'format' => 'json',
  1463. 'json' => json_encode($data)
  1464. ];
  1465. $payload['sig'] = Sailthru_Util::getSignatureHash($payload, $this->secret);
  1466. if (!empty($binary_data)) {
  1467. $payload = array_merge($payload, $binary_data);
  1468. }
  1469. return $payload;
  1470. }
  1471. /**
  1472. * get the rate limit information for the very last call with given action and method
  1473. * @param string $action
  1474. * @param string $method GET, POST or DELETE
  1475. * @return array or null
  1476. */
  1477. public function getLastRateLimitInfo($action, $method) {
  1478. $rate_limit_info = $this->lastRateLimitInfo;
  1479. $method = strtoupper($method);
  1480. return (isset($rate_limit_info[$action]) && isset($rate_limit_info[$action][$method])) ?
  1481. $rate_limit_info[$action][$method] : null;
  1482. }
  1483. /**
  1484. * parse rate limit headers from http response
  1485. * @param string $headers
  1486. * @return array|null
  1487. */
  1488. private function parseRateLimitHeaders($headers) {
  1489. if ($headers === null) {
  1490. return null;
  1491. }
  1492. $header_lines = explode("\n", $headers);
  1493. $rate_limit_headers = [ ];
  1494. foreach ($header_lines as $hl) {
  1495. if (strpos($hl, "X-Rate-Limit-Limit") !== FALSE && !isset($rate_limit_headers['limit'])) {
  1496. list($header_name, $header_value) = explode(":", $hl, 2);
  1497. $rate_limit_headers['limit'] = intval($header_value);
  1498. } else if (strpos($hl, "X-Rate-Limit-Remaining") !== FALSE && !isset($rate_limit_headers['remaining'])) {
  1499. list($header_name, $header_value) = explode(":", $hl, 2);
  1500. $rate_limit_headers['remaining'] = intval($header_value);
  1501. } else if (strpos($hl, "X-Rate-Limit-Reset") !== FALSE && !isset($rate_limit_headers['reset'])) {
  1502. list($header_name, $header_value) = explode(":", $hl, 2);
  1503. $rate_limit_headers['reset'] = intval($header_value);
  1504. }
  1505. if (count($rate_limit_headers) === 3) {
  1506. return $rate_limit_headers;
  1507. }
  1508. }
  1509. return null;
  1510. }
  1511. }