diff --git a/composer.json b/composer.json index 97d54d8..c698b11 100644 --- a/composer.json +++ b/composer.json @@ -2,31 +2,19 @@ "name": "adt/smartemailing", "type": "library", "description": "Easy way to interact with SmartEmailing API from PHP", - "keywords": ["nextras", "appsdevteam", "nette", "smartemailing"], "license": ["MIT"], "authors": [ { - "name": "Adam Stepanek", - "email": "adam@appsdevteam.com", - "homepage": "http://appsdevteam.com" - }, - { - "name": "Tomas Kudelka", - "email": "tomas@appsdevteam.com", - "homepage": "http://appsdevteam.com" + "name": "Apps Dev Team", + "email": "hello@appsdevteam.com", + "homepage": "https://www.appsdevteam.com" } ], "require": { - "nette/application": "~2.2", - "nette/component-model": "~2.2", - "nette/utils": "~2.2", - "nextras/latte-macros": "~1.1.0" - }, - "extra": { - "branch-alias": { - "dev-master": "2.1-dev" - } + "guzzlehttp/guzzle": "^6.3", + "nette/utils": "^2.2" }, + "minimum-stability": "stable", "autoload": { "psr-4": { "ADT\\": "src/" } } diff --git a/src/SmartEmailing.php b/src/SmartEmailing.php index 6fb973a..7fb78b2 100644 --- a/src/SmartEmailing.php +++ b/src/SmartEmailing.php @@ -2,255 +2,279 @@ namespace ADT; +use GuzzleHttp\Client; +use GuzzleHttp\Exception\ClientException; +use Nette\Utils\Json; + /** - * SmartEmailing API v2 + * SmartEmailing API v3 * http://docs.smartemailing.apiary.io/ */ -class SmartEmailing extends \Nette\Object +class SmartEmailing { - - protected $url = 'https://app.smartemailing.cz/api/v2'; + const NODE_PING = 'ping'; + const NODE_CHECK_CREDENTIALS = 'check-credentials'; + const NODE_CONTACTLISTS = 'contactlists'; + const NODE_CUSTOMFIELDS = 'customfields'; + const NODE_CUSTOMFIELDS_OPTIONS = 'customfield-options'; + const NODE_CONTACT_CUSTOMFIELDS = 'contact-customfields'; + const NODE_CHANGE_EMAILADDRESS = 'change-emailaddress'; + const NODE_CONTACT_FORGET = 'contacts/forget'; + const NODE_CONTACTS = 'contacts'; + const NODE_IMPORT = 'import'; + const NODE_PURPOSES = 'purposes'; + const NODE_PURPOSE_CONNECTIONS = 'purpose-connections'; + + const METHOD_GET = 'GET'; + const METHOD_POST = 'POST'; + const METHOD_PUT = 'PUT'; + const METHOD_DELETE = 'DELETE'; + + protected $url = 'https://app.smartemailing.cz/api/v3'; protected $username; protected $token; + /** + * SmartEmailing constructor. + * + * @param string $username + * @param string $token + */ public function __construct($username, $token) { $this->username = $username; $this->token = $token; } - public function contactInsert($email, $contactlists = array(), $properties = array(), $customfields = array()) { - return $this->contactUpdate($email, $contactlists, $properties, $customfields); - } - - - public function contactUpdate($email, $contactlists = array(), $properties = array(), $customfields = array()) { - $details = []; - - $details['emailaddress'] = $email; - - foreach ($properties as $key => $val) { - $details[$key] = $val; - } - - $details['customfields'] = $customfields; - - $contactlistsData = []; - foreach ($contactlists as $id => $status) { - $data = []; + /** + * Aliveness test + * + * @return array + * @throws SmartEmailingException + */ + public function ping() + { + return $this->call(self::METHOD_GET, self::NODE_PING); + } - $data['id'] = $id; - $data['status'] = $status; - $contactlistsData[] = $data; - } + /** + * Login test + * + * @return array + * @throws SmartEmailingException + */ + public function checkCredentials() + { + return $this->call(self::METHOD_GET, self::NODE_CHECK_CREDENTIALS); + } - $details['contactliststatuses'] = $contactlistsData; + /** + * @param string $name + * @param string $senderName + * @param string $senderEmail email + * @param string $replyTo email + * @param string|null $publicName + * @throws SmartEmailingException + */ + public function createContactlist($name, $senderName, $senderEmail, $replyTo, $publicName = NULL) + { $data = [ - 'username' => $this->username, - 'usertoken' => $this->token, - 'requesttype' => 'Contacts', - 'requestmethod' => 'createupdate', - 'details' => $details, + 'name' => $name, + 'sendername' => $senderName, + 'senderemail' => $senderEmail, + 'replyto' => $replyTo, ]; - - $response = $this->callSmartemailingApiWithCurl($data); - - return $response; + if (is_string($publicName)) { + $data['publicname'] = $publicName; + } + return $this->call(self::METHOD_POST, self::NODE_CONTACTLISTS, $data); } /** - * get Smartemailing contact by email address - * - * @param String $email - * - * @return \SimpleXMLElement + * @return array + * @throws SmartEmailingException */ - public function getOneByEmail($email) { - $data = [ - 'username' => $this->username, - 'usertoken' => $this->token, - 'requesttype' => 'Contacts', - 'requestmethod' => 'getOne', - 'details' => [ - 'emailaddress' => $email, - ], - ]; + public function getContactlists() + { + return $this->call(self::METHOD_GET, self::NODE_CONTACTLISTS); + } - $response = $this->callSmartemailingApiWithCurl($data); - return $response; + /** + * @param $id + * @return array + * @throws SmartEmailingException + */ + public function getContactlist($id) + { + return $this->call(self::METHOD_GET, self::NODE_CONTACTLISTS . "/" . $id); } - /** - * get Smartemailing contact by ID - * - * @param int $id - * - * @return [ty\SimpleXMLElement + * @param $id + * @param string|null $name + * @param string|null $senderName + * @param string|null $senderEmail + * @param string|null $replyTo + * @param string|null $publicName + * @return array + * @throws SmartEmailingException */ - public function contactGetOneByID($id) { - $data = [ - 'username' => $this->username, - 'usertoken' => $this->token, - 'requesttype' => 'Contacts', - 'requestmethod' => 'getOne', - 'details' => [ - 'id' => $id, - ], - ]; + public function updateContactlist($id, $name = NULL, $senderName = NULL, $senderEmail = NULL, $replyTo = NULL, $publicName = NULL) + { + $data = []; + if ($name !== NULL) $data['name'] = $name; + if ($senderName !== NULL) $data['sendername'] = $senderName; + if ($senderEmail !== NULL) $data['senderemail'] = $senderEmail; + if ($replyTo !== NULL) $data['replyto'] = $replyTo; + if ($publicName !== NULL) $data['publicname'] = $publicName; + if ($publicName !== NULL) $data['publicname'] = $publicName; + + return $this->call(self::METHOD_PUT, self::NODE_CONTACTLISTS . "/" . $id, $data); + } - $response = $this->callSmartemailingApiWithCurl($data); - return $response; + /** + * @param string $from + * @param string $to + * @return array + * @throws SmartEmailingException + */ + public function changeContactEmail($from, $to) + { + return $this->call(self::METHOD_POST, self::NODE_CHANGE_EMAILADDRESS, [ + 'from' => $from, + 'to' => $to, + ]); } /** - * delete Smartemailing contact by email address + * Deletes contact and anonymizes all his leftover data. This action cannot be undone. + * This is GDPR complaint method to secure contact's right to be forgotten. * - * @param String $email - * - * @return \SimpleXMLElement + * @param $id + * @return array + * @throws SmartEmailingException */ - public function contactDeleteByEmail($email) { - $data = [ - 'username' => $this->username, - 'usertoken' => $this->token, - 'requesttype' => 'Contacts', - 'requestmethod' => 'delete', - 'details' => [ - 'emailaddress' => $email, - ], - ]; - - $response = $this->callSmartemailingApiWithCurl($data); - - return $response; + public function deleteContact($id) + { + return $this->call(self::METHOD_DELETE, self::NODE_CONTACT_FORGET . "/" . $id); } /** - * return all unsubscribed contacts from all lists of useraccount - * - * @return \SimpleXMLElement + * @return array + * @throws SmartEmailingException */ - public function getAllUnsubscribedContacts() { - $data = [ - 'username' => $this->username, - 'usertoken' => $this->token, - 'requesttype' => 'Contacts', - 'requestmethod' => 'getAllUnsubscribed', - 'details' => [], - ]; + public function getContacts() + { + return $this->call(self::METHOD_GET, self::NODE_CONTACTS); + } - $response = $this->callSmartemailingApiWithCurl($data); - return $response; + /** + * @return array + * @throws SmartEmailingException + */ + public function getContact($id) + { + return $this->call(self::METHOD_GET, self::NODE_CONTACTS . "/" . $id); } /** - * batch insertion of contacts - * - * @param Array $contacts [pepa@seznam.cz' => ['name' => 'Pepa', 'surname' => 'Novak', 'lists' => [...]], novak@seznam.cz => ... ] + * https://app.smartemailing.cz/docs/api/v3/index.html#api-Import-Import_contacts * - * 'lists' => ['id' => 6676, 'status' => 'confirmed', 'added' => '2016-08-21 21:59:35'] - * - * @return \SimpleXMLElement + * @param $email + * @param array|NULL $contactLists + * @param array|NULL $properties + * @param array|NULL $customFields + * @param array|NULL $purposes + * @param array|NULL $settings */ - public function multipleContactsInsert($contacts) { - $dateTime = new \DateTime(); - - $contactsArray = []; + public function importContact($email, array $contactLists = NULL, array $properties = NULL, array $customFields = NULL, array $purposes = NULL, array $settings = NULL) + { + $contact = [ + 'emailaddress' => $email, + ]; - foreach ($contacts as $email => $cData) { + if (is_array($contactLists)) { + $contact['contactlists'] = []; + foreach ($contactLists as $id => $status) { + $contact['contactlists'][] = [ + 'id' => $id, + 'status' => $status, + ]; + } + } - $contactData = [ - 'emailaddress' => $email, - 'name' => $cData['name'], - 'surname' => $cData['surname'], - 'email' => $email, - 'contactliststatuses' => $cData['lists'], - ]; + if (is_array($properties)) { + foreach ($properties as $name => $value) { + $contact[$name] = $value; + } + } - $contactsArray[] = $contactData; + if (is_array($customFields)) { + $contact['customfields'] = $customFields; } + if (is_array($purposes)) { + $contact['purposes'] = $purposes; + } $data = [ - 'username' => $this->username, - 'usertoken' => $this->token, - 'requesttype' => 'Contacts', - 'requestmethod' => 'createupdateBatch', - 'details' => $contactsArray, + 'data' => [ + $contact, + ], ]; - $response = $this->callSmartemailingApiWithCurl($data); + if (is_array($settings)) { + $data['settings'] = $settings; + } - return $response; + return $this->call(self::METHOD_POST, self::NODE_IMPORT, $data); } - /** - * convert array to xml + * connect to Smartemailing API v3 + * + * @param string $method + * @param string $node + * @param array|null $data + * @param array|null $query + * @return array + * @throws SmartEmailingException */ - protected function arrayToXml($array, &$xml) { - foreach($array as $key => $value) { - if (is_array($value)) { - - if (!is_numeric($key)) { - $subnode = $xml->addChild("$key"); - $this->arrayToXml($value, $subnode); - - } else { - $subnode = $xml->addChild('item'); - $this->arrayToXml($value, $subnode); - } - - } else { - $xml->addChild("$key", htmlspecialchars("$value")); - } + protected function call($method, $node, $data = NULL, $query = NULL) + { + $options = [ + 'auth' => [$this->username, $this->token], + ]; + if (is_array($data)) { + $options['json'] = $data; + } + if (is_array($query)) { + $options['query'] = $query; } - } - - - /** - * creating simple xml - */ - protected function createSimpleXml($array, $rootElementName) { - $xml = new \SimpleXMLElement('<' . $rootElementName . '>'); - - $this->arrayToXml($array, $xml); - - return $xml->asXML(); - } - - - protected function callSmartemailingApiWithCurl($data) { - $ch = curl_init(); - - curl_setopt($ch, CURLOPT_URL, $this->url); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); - curl_setopt($ch, CURLOPT_HEADER, FALSE); - curl_setopt($ch, CURLOPT_POST, TRUE); - - $postFields = $this->createSimpleXml($data, 'xmlrequest'); - - curl_setopt($ch, CURLOPT_POSTFIELDS, $postFields); - curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/xml')); - $response = curl_exec($ch); + $client = new Client(); - curl_close($ch); + try { + $response = $client->request($method, $this->url . "/" . $node, $options); + } catch (ClientException $e) { + $response = $e->getResponse(); + $body = Json::decode((string) $response->getBody(), Json::FORCE_ARRAY); + throw new SmartEmailingException($body['message'], $response->getStatusCode()); + } - return new \SimpleXMLElement($response); + return Json::decode((string) $response->getBody(), Json::FORCE_ARRAY); } diff --git a/src/SmartEmailingException.php b/src/SmartEmailingException.php new file mode 100644 index 0000000..9e1a432 --- /dev/null +++ b/src/SmartEmailingException.php @@ -0,0 +1,8 @@ +