├── .gitignore ├── README.md ├── bootstrap.php ├── composer.json ├── phpunit.xml ├── src ├── Exception.php ├── Exception │ ├── CurlException.php │ ├── DomainException.php │ ├── ForbiddenCustomFieldNameException.php │ ├── InvalidEmailException.php │ ├── InvalidURLException.php │ ├── LogicException.php │ ├── RuntimeException.php │ └── UnexpectedValueException.php ├── Model │ ├── Campaign.php │ ├── EmailBody.php │ └── Sender.php ├── Response │ └── SubscriptionStatus.php ├── Sendy.php └── autoload.php └── tests ├── SendyPHP └── Response │ └── SubscriptionStatusTest.php └── TestBootstrap.php /.gitignore: -------------------------------------------------------------------------------- 1 | composer.lock 2 | .idea/ 3 | vendor -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PHP sendy client 2 | PHP interface for Sendy api ([http://sendy.co/](http://sendy.co/?ref=q5mRD "Sendy - Send newsletters, 100x cheaper via Amazon SES")) with full support Sendy API ([http://sendy.co/api](http://sendy.co/api?ref=q5mRD "Sendy - API documentation")) 3 | 4 | # Installation 5 | ## Using composer 6 | Simply add new require jiririedl/php-sendy to your composer.json. 7 | ```json 8 | "require": { 9 | "jiririedl/php-sendy" : ">=1.0.0" 10 | } 11 | ``` 12 | and update in console 13 | ```sh 14 | composer update 15 | ``` 16 | ## Using autoload (alternative dirty way) 17 | If you don't use Composer (for some reasons) you can download and include library bootstrap into your project manually. 18 | This wil add spl_autoload for SendyPHP namespace. 19 | ```php 20 | $phpSendyPath = ''; // here you can fill something like 'vendor/SendyPHP' 21 | require_once($phpSendyPath.'/bootstrap.php'); 22 | ``` 23 | ## Using autoload method (alternative dirty dirty way) 24 | If you have your own solution of class autoloading, there is prepared autload function in /src/autoload.php. 25 | Calling ```\SendyPHP\autoload($className)``` includes requested class from SendyPHP namespace or returns FALSE 26 | 27 | # Usage 28 | Create instance of \SendyPHP\Sendy with URL of your Sendy installation and API key. 29 | Your API key is located in sendy - login as Admin and go to "Settings" (/settings) - your key is located in right side under topic "Your API key" beware of white spaces! 30 | ```php 31 | $sendy = new \SendyPHP\Sendy('http://mysendyinstalation.mydomain','myAPIKey'); 32 | ``` 33 | Some request doesn't need API key for work (f.e. subscribe() or unsubscribe()) so setting api key is optional. 34 | You can also set api key by using setApiKey() method or redefine sendy URL by setURL(). 35 | 36 | ## Methods 37 | 38 | ### Sendy API Requests 39 | All requests uses curl library for calling Sendy API. 40 | If you have installed library by using Composer, curl was checked automatically, 41 | otherwise you can check this in your phpinfo, or just try to call some method from curl (http://php.net/manual/en/ref.curl.php). 42 | 43 | #### Subscribe 44 | This method adds a new subscriber to a list. 45 | You can also use this method to update an existing subscriber. 46 | ```php 47 | bool subscribe($listID, $email, $name = NULL, array $customFields = array(), &$statusMessage = NULL) 48 | ``` 49 | ##### Parameters 50 | * $listID - the list id you want to subscribe a user to. This encrypted & hashed id can be found under View all lists section named ID 51 | * $email - user's email 52 | * $name - optional -user's name is optional 53 | * $customFields - optional - associative array of custom fields and their values f.e. array('salutation'=>'Mr.','userLevel'=>'VIP+') 54 | * $statusMessage - optional - here will be returned status message f.e. if you get FALSE again, and again, here you can find why 55 | 56 | ##### Example 57 | ```php 58 | try{ 59 | $sendy = new \SendyPHP\Sendy('http://mysendyinstalation.mydomain','myAPIKey'); 60 | 61 | $statusMessage = ''; 62 | $status = $sendy->subscribe('myHashedListID','newsubscribers@email.com','John Doe',$statusMessage); 63 | 64 | if($status) 65 | echo "Yeah! New subscriber successfully added"; 66 | else 67 | echo "Ops! Sendy API responds a problem with adding subscriber - Sendy PHP message :".$statusMessage; 68 | 69 | }catch (\SendyPHP\Exception $e) 70 | { 71 | echo "Ops! An exception raised: ".$e; 72 | } 73 | ``` 74 | ##### Exceptions 75 | All exceptions are extended from \SendyPHP\Exception so you can easily catch just this parent class 76 | * \SendyPHP\Exception\InvalidEmailException is thrown if email address is not valid 77 | * \SendyPHP\Exception\DomainException is thrown if $listID is empty 78 | * \SendyPHP\Exception\CurlException is thrown if cURL library could not handle your request 79 | 80 | ##### Return values 81 | Returns TRUE on success or FALSE on failure. 82 | 83 | #### UnSubscribe 84 | This method unsubscribes a user from a list. 85 | ```php 86 | bool unsubscribe($listID, $email,&$statusMessage = NULL) 87 | ``` 88 | ##### Parameters 89 | * $listID - the list id you want to unsubscribe a user from. This encrypted & hashed id can be found under View all lists section named ID 90 | * $email - user's email 91 | * $statusMessage - optional - here will be returned status message f.e. if you get FALSE again, and again, here you can find why 92 | 93 | ##### Example 94 | ```php 95 | try{ 96 | $sendy = new \SendyPHP\Sendy('http://mysendyinstalation.mydomain','myAPIKey'); 97 | 98 | $statusMessage = ''; 99 | $status = $sendy->unsubscribe('myHashedListID','newsubscribers@email.com',$statusMessage); 100 | 101 | if($status) 102 | echo "Subscriber successfully removed from list"; 103 | else 104 | echo "Ops! Sendy API responds a problem with unsubscribing - Sendy PHP message :".$statusMessage; 105 | 106 | }catch (\SendyPHP\Exception $e) 107 | { 108 | echo "Ops! An exception raised: ".$e; 109 | } 110 | ``` 111 | ##### Exceptions 112 | All exceptions are extended from \SendyPHP\Exception so you can easily catch just this parent class 113 | * \SendyPHP\Exception\InvalidEmailException is thrown if email address is not valid 114 | * \SendyPHP\Exception\DomainException is thrown if $listID is empty 115 | * \SendyPHP\Exception\CurlException is thrown if cURL library could not handle your request 116 | 117 | ##### Return values 118 | Returns TRUE on success or FALSE on failure. 119 | 120 | #### Delete 121 | This method deletes a subscriber off a list (only supported in Sendy version 2.1.1.4 and above). 122 | ```php 123 | bool delete($listID, $email,&$statusMessage = NULL) 124 | ``` 125 | ##### Parameters 126 | * $listID - the list id you want to delete a user from. This encrypted & hashed id can be found under View all lists section named ID 127 | * $email - user's email 128 | * $statusMessage - optional - here will be returned status message f.e. if you get FALSE again, and again, here you can find why 129 | 130 | ##### Example 131 | ```php 132 | try{ 133 | $sendy = new \SendyPHP\Sendy('http://mysendyinstalation.mydomain','myAPIKey'); 134 | 135 | $statusMessage = ''; 136 | $status = $sendy->delete('myHashedListID','newsubscribers@email.com',$statusMessage); 137 | 138 | if($status) 139 | echo "Subscriber successfully deleted from list"; 140 | else 141 | echo "Ops! Sendy API responds a problem with deleting - Sendy PHP message :".$statusMessage; 142 | 143 | }catch (\SendyPHP\Exception $e) 144 | { 145 | echo "Ops! An exception raised: ".$e; 146 | } 147 | ``` 148 | ##### Exceptions 149 | All exceptions are extended from \SendyPHP\Exception so you can easily catch just this parent class 150 | * \SendyPHP\Exception\InvalidEmailException is thrown if email address is not valid 151 | * \SendyPHP\Exception\DomainException is thrown if $listID is empty 152 | * \SendyPHP\Exception\CurlException is thrown if cURL library could not handle your request 153 | 154 | ##### Return values 155 | Returns TRUE on success or FALSE on failure. 156 | 157 | #### Get active subscriber count 158 | This method gets the total active subscriber count. 159 | ```php 160 | number|false getActiveSubscriberCount($listID, &$statusMessage = NULL) 161 | ``` 162 | ##### Parameters 163 | * $listID - the list id you want to subscribe a user to. This encrypted & hashed id can be found under View all lists section named ID 164 | * $statusMessage - optional - here will be returned status message f.e. if you get FALSE again, and again, here you can find why 165 | 166 | ##### Example 167 | ```php 168 | try{ 169 | $sendy = new \SendyPHP\Sendy('http://mysendyinstalation.mydomain','myAPIKey'); 170 | 171 | $statusMessage = ''; 172 | $subscribersCount = $sendy->getActiveSubscriberCount('myHashedListID',$statusMessage); 173 | 174 | if($subscribersCount!==false) 175 | echo "In this list is $subscribersCount active subscribers"; 176 | else 177 | echo "Ops! Sendy API responds a problem with getting active subscribers count - Sendy PHP message :".$statusMessage; 178 | 179 | }catch (\SendyPHP\Exception $e) 180 | { 181 | echo "Ops! An exception raised: ".$e; 182 | } 183 | ``` 184 | ##### Exceptions 185 | All exceptions are extended from \SendyPHP\Exception so you can easily catch just this parent class 186 | * \SendyPHP\Exception\DomainException is thrown if $listID is empty 187 | * \SendyPHP\Exception\CurlException is thrown if cURL library could not handle your request 188 | 189 | ##### Return values 190 | Returns number of active subscribers or FALSE on failure. 191 | 192 | #### Get subscribtion status 193 | This method gets the current status of a subscriber (eg. subscribed, unsubscribed, bounced, complained). 194 | ```php 195 | \SendyPHP\Response\SubscriptionStatus getSubscriptionStatus($listID, $email) 196 | ``` 197 | ##### Parameters 198 | * $listID - the list id you want to subscribe a user to. This encrypted & hashed id can be found under View all lists section named ID 199 | * $email - user's email 200 | 201 | ##### Example 202 | ```php 203 | try{ 204 | $sendy = new \SendyPHP\Sendy('http://mysendyinstalation.mydomain','myAPIKey'); 205 | 206 | $subscriptionStatus = $sendy->getSubscriptionStatus('myHashedListID','mysubscribers@email.com'); 207 | 208 | if($subscriptionStatus->success()) 209 | { 210 | switch(true) 211 | { 212 | case $subscriptionStatus->isSubscribed(): 213 | echo "Subscribed"; 214 | break; 215 | case $subscriptionStatus->isUnSubscribed(): 216 | echo "Unsubscribed"; 217 | break; 218 | case $subscriptionStatus->isComplained(): 219 | echo "Complained"; 220 | break; 221 | case $subscriptionStatus->isUnconfirmed(): 222 | echo "Unconfirmed"; 223 | break; 224 | case $subscriptionStatus->isHardBounced(): 225 | echo "Hard Bounced"; 226 | break; 227 | case $subscriptionStatus->isSoftBounced(): 228 | echo "Soft bounced"; 229 | break; 230 | } 231 | } 232 | else 233 | echo "Ops! Sendy API responds a problem with getting subscribtion status - Sendy PHP message :".$subscriptionStatus->getRawResponse(); 234 | 235 | }catch (\SendyPHP\Exception $e) 236 | { 237 | echo "Ops! An exception raised: ".$e; 238 | } 239 | ``` 240 | ##### Exceptions 241 | All exceptions are extended from \SendyPHP\Exception so you can easily catch just this parent class 242 | * \SendyPHP\Exception\DomainException is thrown if $listID is empty 243 | * \SendyPHP\Exception\InvalidEmailException is thrown if email address is not valid 244 | * \SendyPHP\Exception\CurlException is thrown if cURL library could not handle your request 245 | 246 | ##### Return values 247 | \SendyPHP\Response\SubscriptionStatus 248 | returned object has many of usable methods (see phpdoc) f.e. by calling success() are you able to check if API returns some subscribers status. 249 | 250 | #### Create campaign 251 | Creates draft of campaign 252 | ```php 253 | bool createCampaign($brandID, Model\Campaign $campaign, &$statusMessage = NULL) 254 | ``` 255 | ##### Parameters 256 | * $brandID - Brand IDs can be found under 'Brands' page named ID 257 | * $campaign <\SendyPHP\Model\Campaign> - configured campaign 258 | * $statusMessage - optional - here will be returned status message f.e. if you get FALSE again, and again, here you can find why 259 | 260 | ##### Example 261 | ```php 262 | try{ 263 | $sender = new \SendyPHP\Model\Sender('From name','from-adrress@mydomain.com','reply-address@mydomain.com'); 264 | $emailBody = new \SendyPHP\Model\EmailBody('

HTML body of my newsletter

', 'Plaintext body of my newsletter'); 265 | $campaign = new \SendyPHP\Model\Campaign($sender,'My first great newsletter!',$emailBody); 266 | $brandID = 1; // here fill your brand ID 267 | 268 | $sendy = new \SendyPHP\Sendy('http://mysendyinstalation.mydomain','myAPIKey'); 269 | 270 | $statusMessage = ''; 271 | $status = $sendy->createCampaign($brandID,$campaign,$statusMessage); 272 | 273 | if($status) 274 | { 275 | echo "Campaign successfully created"; 276 | } 277 | else 278 | echo "Ops! Sendy API responds a problem with creating campaign - Sendy PHP message :".$statusMessage; 279 | 280 | }catch (\SendyPHP\Exception $e) 281 | { 282 | echo "Ops! An exception raised: ".$e; 283 | } 284 | ``` 285 | ##### Exceptions 286 | All exceptions are extended from \SendyPHP\Exception so you can easily catch just this parent class 287 | * \SendyPHP\Exception\CurlException is thrown if cURL library could not handle your request 288 | 289 | ##### Return values 290 | Returns TRUE on success or FALSE on failure. 291 | 292 | #### Send campaign 293 | Creates draft and automatically sends campaign 294 | ```php 295 | bool sendCampaign(array $listIDs, Model\Campaign $campaign, &$statusMessage = NULL) 296 | ``` 297 | ##### Parameters 298 | * $listIDs - The encrypted & hashed ids can be found under View all lists section named ID. 299 | * $campaign <\SendyPHP\Model\Campaign> - configured campaign 300 | * $statusMessage - optional - here will be returned status message f.e. if you get FALSE again, and again, here you can find why 301 | 302 | ##### Example 303 | ```php 304 | try{ 305 | $sender = new \SendyPHP\Model\Sender('From name','from-adrress@mydomain.com','reply-address@mydomain.com'); 306 | $emailBody = new \SendyPHP\Model\EmailBody('

HTML body of my newsletter

', 'Plaintext body of my newsletter'); 307 | $campaign = new \SendyPHP\Model\Campaign($sender,'My first great newsletter!',$emailBody); 308 | $listIDs = array(1); // here fill your list IDs 309 | 310 | $sendy = new \SendyPHP\Sendy('http://mysendyinstalation.mydomain','myAPIKey'); 311 | 312 | $statusMessage = ''; 313 | $status = $sendy->sendCampaign($listIDs,$campaign,$statusMessage); 314 | 315 | if($status) 316 | { 317 | echo "Campaign successfully created and now sending"; 318 | } 319 | else 320 | echo "Ops! Sendy API responds a problem with creating and sending campaign - Sendy PHP message :".$statusMessage; 321 | 322 | }catch (\SendyPHP\Exception $e) 323 | { 324 | echo "Ops! An exception raised: ".$e; 325 | } 326 | ``` 327 | ##### Exceptions 328 | All exceptions are extended from \SendyPHP\Exception so you can easily catch just this parent class 329 | * \SendyPHP\Exception\CurlException is thrown if cURL library could not handle your request 330 | * \SendyPHP\Exception\DomainException is thrown if $listIDs array is empty 331 | 332 | ##### Return values 333 | Returns TRUE on success or FALSE on failure. 334 | 335 | ### Other methods 336 | #### Set cURL option 337 | Sets cURL option 338 | You can set cURL options f.e. CURLOPT_SSL_VERIFYPEER or CURLOPT_SSL_VERIFYHOST 339 | some parameters (\CURLOPT_RETURNTRANSFER, \CURLOPT_POST, \CURLOPT_POSTFIELDS) are used, if you try to set one of these exception is thrown. 340 | See http://php.net/manual/en/function.curl-setopt.php for more informations. 341 | ```php 342 | void setCurlOption($option, $value) 343 | ``` 344 | ##### Parameters 345 | * $option - use \CURLOPT_* constant 346 | * $value mixed 347 | 348 | ##### Exceptions 349 | \SendyPHP\Exception\UnexpectedValueException is thrown if you try to set one of predefined options (\CURLOPT_RETURNTRANSFER, \CURLOPT_POST and \CURLOPT_POSTFIELDS). 350 | 351 | #### Clear cURL option 352 | Sets cURL option 353 | Clears user defined cURL options 354 | ```php 355 | void clearCurlOptions() 356 | ``` 357 | 358 | #### Set URL 359 | Sets sendy installation URL 360 | Clears user defined cURL options 361 | ```php 362 | void setURL($URL) 363 | ``` 364 | ##### Exceptions 365 | \SendyPHP\Exception\InvalidURLException is thrown if URL is invalid. 366 | 367 | #### Set API key 368 | Sets api key 369 | ```php 370 | void setApiKey($apiKey) 371 | ``` 372 | ##### Parameters 373 | * $apiKey - sendy API key - your API key is available in sendy Settings 374 | 375 | ##### Exceptions 376 | \SendyPHP\Exception\DomainException is thrown if API key is not string. 377 | -------------------------------------------------------------------------------- /bootstrap.php: -------------------------------------------------------------------------------- 1 | =1.0.0" to your composer.json for obtaining last stable release 11 | * @link https://getcomposer.org/doc/00-intro.md#declaring-dependencies 12 | * @link https://packagist.org/packages/jiririedl/php-sendy 13 | * 14 | * @author Jiri Riedl 15 | * @package SendyPHP 16 | */ 17 | 18 | require_once(__DIR__.DIRECTORY_SEPARATOR.'src'.DIRECTORY_SEPARATOR.'autoload.php'); 19 | 20 | \spl_autoload_register('\\SendyPHP\\autoload'); -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jiririedl/php-sendy", 3 | "description": "PHP class for using sendy API", 4 | "keywords": ["sendy","api","php"], 5 | "homepage": "https://github.com/jiririedl/php-sendy", 6 | "license": "MIT", 7 | "authors": [ 8 | { 9 | "name": "Jiri Riedl", 10 | "email": "riedl@dcommunity.org", 11 | "homepage": "http://www.riedl.in", 12 | "role": "Local genius" 13 | } 14 | ], 15 | "require": { 16 | "php": ">=5.3.0", 17 | "lib-curl": "*" 18 | }, 19 | "autoload": { 20 | "psr-4": {"SendyPHP\\": "src/"} 21 | } 22 | } -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | tests 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/Exception.php: -------------------------------------------------------------------------------- 1 | _buildMessage($message),$code,$previous); 23 | } 24 | /** 25 | * Builds Exception message text 26 | * 27 | * @param string $message 28 | * @param resource|null $resource 29 | * @return string 30 | */ 31 | protected function _buildMessage($message, $resource = NULL) 32 | { 33 | $message = 'cURL '.$message; 34 | if(!is_null($resource)) 35 | { 36 | $message.= ' cURL error: ['.curl_errno($resource).'] '.curl_error($resource); 37 | } 38 | return $message; 39 | } 40 | } -------------------------------------------------------------------------------- /src/Exception/DomainException.php: -------------------------------------------------------------------------------- 1 | _buildMessage($customFieldName), $code, $previous); 22 | } 23 | /** 24 | * Builds Exception message text 25 | * 26 | * @param mixed $customFieldName 27 | * @return string 28 | */ 29 | protected function _buildMessage($customFieldName) 30 | { 31 | $message = 'Forbidden custom field name detected '; 32 | if(is_string($customFieldName)) 33 | $message.= ' - [.'.$customFieldName.'.] - this field name is reserved.'; 34 | else 35 | $message.= ' - '.gettype($customFieldName).' given ['.var_export($customFieldName,1).'], string expected.'; 36 | return $message; 37 | } 38 | } -------------------------------------------------------------------------------- /src/Exception/InvalidEmailException.php: -------------------------------------------------------------------------------- 1 | _buildMessage($email), $code, $previous); 22 | } 23 | /** 24 | * Builds Exception message text 25 | * 26 | * @param mixed $email 27 | * @return string 28 | */ 29 | protected function _buildMessage($email) 30 | { 31 | $message = 'Valid e-mail address expected '; 32 | if(is_string($email)) 33 | $message.= ' - invalid e-mail given [.'.$email.'.]'; 34 | else 35 | $message.= ' - '.gettype($email).' given ['.var_export($email,1).']'; 36 | return $message; 37 | } 38 | } -------------------------------------------------------------------------------- /src/Exception/InvalidURLException.php: -------------------------------------------------------------------------------- 1 | _buildMessage($URL), $code, $previous); 22 | } 23 | /** 24 | * Builds Exception message text 25 | * 26 | * @param mixed $URL 27 | * @return string 28 | */ 29 | protected function _buildMessage($URL) 30 | { 31 | $message = 'Valid URL expected '; 32 | if(is_string($URL)) 33 | $message.= ' - invalid URL given [.'.$URL.'.]'; 34 | else 35 | $message.= ' - '.gettype($URL).' given ['.var_export($URL,1).']'; 36 | return $message; 37 | } 38 | } -------------------------------------------------------------------------------- /src/Exception/LogicException.php: -------------------------------------------------------------------------------- 1 | 7 | * @package SendyPHP 8 | */ 9 | class Campaign 10 | { 11 | /** 12 | * Sender settings 13 | * @var Sender 14 | */ 15 | protected $_sender = NULL; 16 | /** 17 | * Email subject 18 | * @var string 19 | */ 20 | protected $_subject = NULL; 21 | /** 22 | * Email body 23 | * @var EmailBody 24 | */ 25 | protected $_emailBody = NULL; 26 | 27 | /** 28 | * Sendy campaign settings 29 | * 30 | * @param Sender $sender Sender settings 31 | * @param string|null $subject email subject 32 | * @param EmailBody $emailBody Email body variants 33 | * 34 | * @throws \SendyPHP\Exception\DomainException 35 | */ 36 | public function __construct(Sender $sender = NULL, $subject = NULL, EmailBody $emailBody = NULL) 37 | { 38 | if(!is_null($sender)) 39 | $this->setSenderSettings($sender); 40 | 41 | if(!is_null($subject)) 42 | $this->setSubject($subject); 43 | 44 | if(!is_null($emailBody)) 45 | $this->setEmailBodyVariants($emailBody); 46 | } 47 | /** 48 | * Sets e-mail body 49 | * 50 | * @param string $html 51 | * @param string|null $plainText 52 | * @throws \SendyPHP\Exception\DomainException 53 | */ 54 | public function setEmailBody($html, $plainText = NULL) 55 | { 56 | $this->setEmailBodyVariants(new EmailBody($html,$plainText)); 57 | } 58 | /** 59 | * Sets e-mail body variants 60 | * 61 | * @param EmailBody $emailBody 62 | */ 63 | public function setEmailBodyVariants(EmailBody $emailBody) 64 | { 65 | $this->_emailBody = $emailBody; 66 | } 67 | /** 68 | * Returns e-mail body 69 | * 70 | * @return EmailBody 71 | */ 72 | public function getEmailBody() 73 | { 74 | return $this->_emailBody; 75 | } 76 | /** 77 | * Sets sender settings 78 | * 79 | * @param string $fromName 'From name' of your campaign 80 | * @param string $fromAddress 'From email' of your campaign 81 | * @param string $replyAddress 'Reply to' of your campaign 82 | * @throws \SendyPHP\Exception\DomainException 83 | */ 84 | public function setSender($fromName, $fromAddress, $replyAddress) 85 | { 86 | $this->setSenderSettings(new Sender($fromName, $fromAddress, $replyAddress)); 87 | } 88 | /** 89 | * Sets sender settings 90 | * 91 | * @param Sender $sender 92 | */ 93 | public function setSenderSettings(Sender $sender) 94 | { 95 | $this->_sender = $sender; 96 | } 97 | /** 98 | * Returns Sender settings 99 | * 100 | * @return Sender 101 | */ 102 | public function getSender() 103 | { 104 | return $this->_sender; 105 | } 106 | /** 107 | * Sets e-mail subject 108 | * 109 | * @param string $subject 110 | * @throws \SendyPHP\Exception\DomainException 111 | */ 112 | public function setSubject($subject) 113 | { 114 | if(strlen($subject) == 0) 115 | throw new \SendyPHP\Exception\DomainException('Email subject can not be empty'); 116 | 117 | $this->_subject = $subject; 118 | } 119 | /** 120 | * Returns e-mail subject 121 | * 122 | * @return string 123 | */ 124 | public function getSubject() 125 | { 126 | return $this->_subject; 127 | } 128 | } -------------------------------------------------------------------------------- /src/Model/EmailBody.php: -------------------------------------------------------------------------------- 1 | 7 | * @package SendyPHP 8 | */ 9 | class EmailBody 10 | { 11 | /** 12 | * HTML email code 13 | * @var string 14 | */ 15 | protected $_html = NULL; 16 | /** 17 | * Plain text version of e-mail 18 | * @var string|null 19 | */ 20 | protected $_plainText = NULL; 21 | 22 | /** 23 | * Email body 24 | * 25 | * @param string $html the 'HTML version' of your e-mail 26 | * @param string|null $plainText the 'Plain text version' of your e-mail (optional) 27 | * 28 | * @throws \SendyPHP\Exception\DomainException 29 | */ 30 | public function __construct($html, $plainText = NULL) 31 | { 32 | $this->setHtml($html); 33 | 34 | if(!is_null($plainText)) 35 | $this->setPlainText($plainText); 36 | } 37 | /** 38 | * Sets HTML email code 39 | * 40 | * @param string $html 41 | * @throws \SendyPHP\Exception\DomainException 42 | */ 43 | public function setHtml($html) 44 | { 45 | if(strlen($html) == 0) 46 | throw new \SendyPHP\Exception\DomainException('HTML email code can not be empty'); 47 | 48 | $this->_html = $html; 49 | } 50 | /** 51 | * Returns HTML email code 52 | * 53 | * @return string 54 | */ 55 | public function getHtml() 56 | { 57 | return $this->_html; 58 | } 59 | /** 60 | * Sets plain text version of e-mail 61 | * 62 | * @param string $plainText 63 | * @throws \SendyPHP\Exception\DomainException 64 | */ 65 | public function setPlainText($plainText) 66 | { 67 | if(strlen($plainText) == 0) 68 | throw new \SendyPHP\Exception\DomainException('Plain text version of e-mai can not be empty - you can disable plaintext version by calling removePlainText().'); 69 | 70 | $this->_plainText = $plainText; 71 | } 72 | /** 73 | * Remove plaintext version 74 | */ 75 | public function removePlainText() 76 | { 77 | $this->_plainText = NULL; 78 | } 79 | /** 80 | * Returns plain text version of e-mail 81 | * 82 | * NULL is returned, if no plain text version is set 83 | * 84 | * @return null|string 85 | */ 86 | public function getPlainText() 87 | { 88 | return $this->_plainText; 89 | } 90 | 91 | } -------------------------------------------------------------------------------- /src/Model/Sender.php: -------------------------------------------------------------------------------- 1 | 8 | * @package SendyPHP 9 | */ 10 | class Sender 11 | { 12 | /** 13 | * "From name" of your campaign 14 | * @var string 15 | */ 16 | protected $_name = NULL; 17 | /** 18 | * "From email" of your campaign 19 | * @var string 20 | */ 21 | protected $_address = NULL; 22 | /** 23 | * "Reply to" of your campaign 24 | * @var string 25 | */ 26 | protected $_replyAddress = NULL; 27 | 28 | /** 29 | * Sender settings 30 | * 31 | * @param string $fromName 'From name' of your campaign 32 | * @param string $fromAddress 'From email' of your campaign 33 | * @param string $replyAddress 'Reply to' of your campaign 34 | * @throws \SendyPHP\Exception\DomainException 35 | * @throws \SendyPHP\Exception\InvalidEmailException 36 | */ 37 | public function __construct($fromName, $fromAddress, $replyAddress) 38 | { 39 | $this->setName($fromName); 40 | $this->setAddress($fromAddress); 41 | $this->setReplyAddress($replyAddress); 42 | } 43 | /** 44 | * Sets "From" e-mail address 45 | * 46 | * @param string $address 47 | * @throws \SendyPHP\Exception\InvalidEmailException 48 | * @uses \SendyPHP\Sendy::isEmailValid() 49 | */ 50 | public function setAddress($address) 51 | { 52 | if(!Sendy::isEmailValid($address)) 53 | throw new \SendyPHP\Exception\InvalidEmailException($address); 54 | 55 | $this->_address = $address; 56 | } 57 | /** 58 | * Returns "From" e-mail address 59 | * @return string 60 | */ 61 | public function getAddress() 62 | { 63 | return $this->_address; 64 | } 65 | /** 66 | * Sets From name 67 | * 68 | * @param string $name 69 | * @throws \SendyPHP\Exception\DomainException 70 | */ 71 | public function setName($name) 72 | { 73 | if(strlen($name) == 0) 74 | throw new \SendyPHP\Exception\DomainException('From name have to longer than zero'); 75 | 76 | $this->_name = $name; 77 | } 78 | /** 79 | * Returns From name 80 | * 81 | * @return string 82 | */ 83 | public function getName() 84 | { 85 | return $this->_name; 86 | } 87 | /** 88 | * Sets reply e-mail address 89 | * 90 | * @param string $replyAddress 91 | * @throws \SendyPHP\Exception\InvalidEmailException 92 | * @uses \SendyPHP\Sendy::isEmailValid() 93 | */ 94 | public function setReplyAddress($replyAddress) 95 | { 96 | if(!Sendy::isEmailValid($replyAddress)) 97 | throw new \SendyPHP\Exception\InvalidEmailException($replyAddress); 98 | 99 | $this->_replyAddress = $replyAddress; 100 | } 101 | /** 102 | * Returns reply e-mail address 103 | * 104 | * @return string 105 | */ 106 | public function getReplyAddress() 107 | { 108 | return $this->_replyAddress; 109 | } 110 | } -------------------------------------------------------------------------------- /src/Response/SubscriptionStatus.php: -------------------------------------------------------------------------------- 1 | 9 | * @package SendyPHP 10 | */ 11 | class SubscriptionStatus 12 | { 13 | /** 14 | * Subscribed text response from API 15 | * @link http://sendy.co/api 16 | */ 17 | const RESPONSE_SUBSCRIBED = 'Subscribed'; 18 | /** 19 | * Unsubscribed text response from API 20 | * @link http://sendy.co/api 21 | */ 22 | const RESPONSE_UNSUBSCRIBED = 'Unsubscribed'; 23 | /** 24 | * Unconfirmed text response from API 25 | * @link http://sendy.co/api 26 | */ 27 | const RESPONSE_UNCONFIRMED = 'Unconfirmed'; 28 | /** 29 | * Bounced text response from API - this usually means hard bounces 30 | * @link http://sendy.co/api 31 | */ 32 | const RESPONSE_BOUNCED = 'Bounced'; 33 | /** 34 | * Soft bounced text response from API 35 | * @link http://sendy.co/api 36 | */ 37 | const RESPONSE_SOFT_BOUNCED = 'Soft bounced'; 38 | /** 39 | * Complained text response from API 40 | * @link http://sendy.co/api 41 | */ 42 | const RESPONSE_COMPLAINED = 'Complained'; 43 | 44 | /** 45 | * RAW sendy response 46 | * @var string 47 | */ 48 | protected $_rawResponse = NULL; 49 | 50 | /** 51 | * Subscription status 52 | * 53 | * @param string $rawResponse 54 | */ 55 | public function __construct($rawResponse) 56 | { 57 | $this->_rawResponse = $rawResponse; 58 | } 59 | /** 60 | * Returns TRUE if user is subscribed 61 | * 62 | * @return bool 63 | */ 64 | public function isSubscribed() 65 | { 66 | return ($this->getRawResponse() == self::RESPONSE_SUBSCRIBED); 67 | } 68 | /** 69 | * Returns true if user is unsubscribed 70 | * 71 | * @return bool 72 | */ 73 | public function isUnSubscribed() 74 | { 75 | return ($this->getRawResponse() == self::RESPONSE_UNSUBSCRIBED); 76 | } 77 | /** 78 | * Returns true if user is unconfirmed 79 | * 80 | * @return bool 81 | */ 82 | public function isUnconfirmed() 83 | { 84 | return ($this->getRawResponse() == self::RESPONSE_UNCONFIRMED); 85 | } 86 | /** 87 | * Returns true if user is bounced 88 | * 89 | * The email is rejected by the recipient's ISP or rejected by Amazon SES because the email address is on the Amazon SES suppression list. 90 | * For ISP bounces, Amazon SES reports only hard bounces and soft bounces that will no longer be retried by Amazon SES. 91 | * In these cases, your recipient did not receive your email message, and Amazon SES will not try to resend it. 92 | * Bounce notifications are available through email and Amazon SNS. 93 | * You are notified of out-of-the-office (OOTO) messages through the same method as bounces, although they don't count toward your bounce statistics. 94 | * 95 | * You can also call isHardBounced() or isSoftBounced() 96 | * 97 | * @see http://docs.aws.amazon.com/ses/latest/DeveloperGuide/notifications.html 98 | * @return bool 99 | */ 100 | public function isBounced() 101 | { 102 | return ($this->isSoftBounced() || $this->isHardBounced()); 103 | } 104 | /** 105 | * Returns TRUE if user id hard bounced 106 | * 107 | * A hard bounce indicates a persistent delivery failure (e.g., mailbox does not exist). 108 | * In other words, your recipient did not receive your email message, and your server will not try to resend it. 109 | * 110 | * @return bool 111 | */ 112 | public function isHardBounced() 113 | { 114 | return ($this->getRawResponse() == self::RESPONSE_BOUNCED); 115 | } 116 | /** 117 | * Returns true if user is soft bounced 118 | * 119 | * Unlike a hard bounce, a soft bounce is not a permanent failure or rejection (e.g., mailbox full). 120 | * Many email systems (including Amazon SES) will automatically try to resend a message that has generated a soft bounce over a period of time until the message either delivers or the system will no longer retry the delivery and in turn generates a hard bounce. 121 | * 122 | * @return bool 123 | */ 124 | public function isSoftBounced() 125 | { 126 | return ($this->getRawResponse() == self::RESPONSE_SOFT_BOUNCED); 127 | } 128 | /** 129 | * Returns true if user is complained 130 | * 131 | * The email is accepted by the ISP and delivered to the recipient, but the recipient does not want the email and clicks a button such as "Mark as spam." 132 | * If Amazon SES has a feedback loop set up with the ISP, Amazon SES will send you a complaint notification. 133 | * Complaint notifications are available through email and Amazon SNS. 134 | * 135 | * @return bool 136 | */ 137 | public function isComplained() 138 | { 139 | return ($this->getRawResponse() == self::RESPONSE_COMPLAINED); 140 | } 141 | /** 142 | * Returns TRUE if request successfully obtains status 143 | * 144 | * if FALSE you can get error message by calling getRawResponse() 145 | * @return bool 146 | */ 147 | public function success() 148 | { 149 | return ($this->isSubscribed() || $this->isUnSubscribed() || $this->isUnconfirmed() || $this->isBounced() || $this->isSoftBounced() || $this->isComplained()); 150 | } 151 | /** 152 | * Returns TRUE if request obtaining status failed 153 | * 154 | * If TRUE you can get error message by calling getRawMessage() 155 | * @return bool 156 | */ 157 | public function failed() 158 | { 159 | return !$this->success(); 160 | } 161 | /** 162 | * Returns raw response (plaintext api response) 163 | * 164 | * @see http://sendy.co/api section "subscription status":"response" 165 | * @return string 166 | */ 167 | public function getRawResponse() 168 | { 169 | return $this->_rawResponse; 170 | } 171 | } -------------------------------------------------------------------------------- /src/Sendy.php: -------------------------------------------------------------------------------- 1 | 7 | * @package SendyPHP 8 | */ 9 | class Sendy 10 | { 11 | /** 12 | * Subscribe API URI 13 | */ 14 | CONST URI_SUBSCRIBE = 'subscribe'; 15 | /** 16 | * Unsubscribe API URI 17 | */ 18 | CONST URI_UNSUBSCRIBE = 'unsubscribe'; 19 | /** 20 | * Delete subscriber API URL 21 | */ 22 | CONST URI_DELETE_SUBSCRIBER = 'api/subscribers/delete.php'; 23 | /** 24 | * Subscribtion status API URI 25 | */ 26 | CONST URI_SUBSCRIPTION_STATUS = 'api/subscribers/subscription-status.php'; 27 | /** 28 | * Active subscibers API URI 29 | */ 30 | CONST URI_ACTIVE_SUBSCRIBER_COUNT = 'api/subscribers/active-subscriber-count.php'; 31 | /** 32 | * Create campaign API URI 33 | */ 34 | CONST URI_CAMPAIGN = 'api/campaigns/create.php'; 35 | /** 36 | * Sendy installation URL 37 | * @var string|NULL 38 | */ 39 | protected $_URL = NULL; 40 | /** 41 | * Api key 42 | * @var string|null 43 | */ 44 | protected $_apiKey = NULL; 45 | /** 46 | * Additional cUrL options 47 | * @var array 48 | */ 49 | protected $_cURLOption = array(); 50 | 51 | /** 52 | * PHP interface for Sendy api 53 | * 54 | * @param string $URL sendy installation URL 55 | * @param string|null $apiKey your API key is available in sendy Settings - api key is required almost for all requests 56 | * @throws Exception\InvalidURLException 57 | * @throws Exception\DomainException 58 | */ 59 | public function __construct($URL, $apiKey = NULL) 60 | { 61 | $this->setURL($URL); 62 | 63 | if(!is_null($apiKey)) 64 | $this->setApiKey($apiKey); 65 | } 66 | /** 67 | * This method adds a new subscriber to a list. 68 | * 69 | * You can also use this method to update an existing subscriber. 70 | * On another note, you can also embed a subscribe form on your website using Sendy's subscribe form HTML code. 71 | * Visit View all lists, select your desired list then click 'Subscribe form' at the top of the page. 72 | * 73 | * @param string $listID the list id you want to subscribe a user to. This encrypted & hashed id can be found under View all lists section named ID 74 | * @param string $email user's email 75 | * @param string|null $name user's name is optional 76 | * @param array $customFields associative array of custom fields and their values f.e. array('salutation'=>'Mr.','userLevel'=>'VIP+') 77 | * @param string|null $statusMessage optional - here will be returned status message f.e. if you get FALSE again, and again, here you can find why 78 | * @throws \SendyPHP\Exception [\SendyPHP\Exception\InvalidEmailException|\SendyPHP\Exception\DomainException|\SendyPHP\Exception\CurlException] 79 | * @return bool 80 | */ 81 | public function subscribe($listID, $email, $name = NULL, array $customFields = array(), &$statusMessage = NULL) 82 | { 83 | if(strlen($listID) == 0) 84 | throw new Exception\DomainException('List ID can not be empty'); 85 | if(!self::isEmailValid($email)) 86 | throw new Exception\InvalidEmailException($email); 87 | 88 | $request = array( 'api_key'=>$this->_getApiKey(), 89 | 'email'=>$email, 90 | 'list'=>$listID, 91 | 'boolean' => 'true'); 92 | if(!is_null($name)) 93 | $request['name'] = $name; 94 | 95 | foreach ($customFields as $fieldName=>$value) 96 | { 97 | if(array_key_exists($fieldName,$request)) 98 | throw new Exception\ForbiddenCustomFieldNameException($fieldName); 99 | else 100 | $request[$fieldName] = $value; 101 | } 102 | 103 | $response = $this->_callSendy(self::URI_SUBSCRIBE,$request); 104 | if(!in_array($response,array(true,'true','1'))) 105 | { 106 | $statusMessage = $response; 107 | return false; 108 | } 109 | else 110 | { 111 | $statusMessage = 'Success'; 112 | return true; 113 | } 114 | } 115 | /** 116 | * This method unsubscribes a user from a list. 117 | * 118 | * @param string $listID the list id you want to unsubscribe a user from. This encrypted & hashed id can be found under View all lists section named ID 119 | * @param string $email user's email 120 | * @param string|null $statusMessage optional - here will be returned status message f.e. if you get FALSE again, and again, here you can find why 121 | * @throws \SendyPHP\Exception [\SendyPHP\Exception\InvalidEmailException|\SendyPHP\Exception\DomainException|\SendyPHP\Exception\CurlException] 122 | * @return bool 123 | */ 124 | public function unsubscribe($listID, $email,&$statusMessage = NULL) 125 | { 126 | if(strlen($listID) == 0) 127 | throw new Exception\DomainException('List ID can not be empty'); 128 | if(!self::isEmailValid($email)) 129 | throw new Exception\InvalidEmailException($email); 130 | 131 | $request = array( 'api_key'=>$this->_getApiKey(), 132 | 'email'=>$email, 133 | 'list'=>$listID, 134 | 'boolean' => 'true'); 135 | 136 | $response = $this->_callSendy(self::URI_UNSUBSCRIBE,$request); 137 | if(!in_array($response,array(true,'true','1'))) 138 | { 139 | $statusMessage = $response; 140 | return false; 141 | } 142 | else 143 | { 144 | $statusMessage = 'Success'; 145 | return true; 146 | } 147 | } 148 | 149 | /** 150 | * This method deletes a user from a list. 151 | * 152 | * @param string $listID the list id you want to delete a user from. This encrypted & hashed id can be found under View all lists section named ID 153 | * @param string $email user's email 154 | * @param string|null $statusMessage optional - here will be returned status message f.e. if you get FALSE again, and again, here you can find why 155 | * @throws \SendyPHP\Exception [\SendyPHP\Exception\InvalidEmailException|\SendyPHP\Exception\DomainException|\SendyPHP\Exception\CurlException] 156 | * @return bool 157 | */ 158 | public function delete($listID, $email,&$statusMessage = NULL) 159 | { 160 | if(strlen($listID) == 0) 161 | throw new Exception\DomainException('List ID can not be empty'); 162 | if(!self::isEmailValid($email)) 163 | throw new Exception\InvalidEmailException($email); 164 | 165 | $request = array( 'api_key'=>$this->_getApiKey(), 166 | 'email'=>$email, 167 | 'list_id'=>$listID); 168 | 169 | $response = $this->_callSendy(self::URI_DELETE_SUBSCRIBER,$request); 170 | if(!in_array($response,array(true,'true','1'))) 171 | { 172 | $statusMessage = $response; 173 | return false; 174 | } 175 | else 176 | { 177 | $statusMessage = 'Success'; 178 | return true; 179 | } 180 | } 181 | /** 182 | * This method gets the current status of a subscriber (eg. subscribed, unsubscribed, bounced, complained). 183 | * 184 | * @param string $listID 185 | * @param string $email 186 | * @throws \SendyPHP\Exception [\SendyPHP\Exception\DomainException|\SendyPHP\Exception\InvalidEmailException|\SendyPHP\Exception\CurlException] 187 | * @return \SendyPHP\Response\SubscriptionStatus 188 | */ 189 | public function getSubscriptionStatus($listID, $email) 190 | { 191 | if(strlen($listID) == 0) 192 | throw new Exception\DomainException('List ID can not be empty'); 193 | if(!self::isEmailValid($email)) 194 | throw new Exception\InvalidEmailException($email); 195 | 196 | $request = array( 'api_key'=>$this->_getApiKey(), 197 | 'list_id'=>$listID, 198 | 'email' => $email); 199 | 200 | $response = $this->_callSendy(self::URI_SUBSCRIPTION_STATUS,$request); 201 | return new Response\SubscriptionStatus($response); 202 | } 203 | /** 204 | * This method gets the total active subscriber count. 205 | * 206 | * @param string $listID the id of the list you want to get the active subscriber count. This encrypted id can be found under View all lists section named ID 207 | * @param string|null $statusMessage optional - here will be returned status message f.e. if you get FALSE again, and again, here you can find why 208 | * @throws \SendyPHP\Exception [\SendyPHP\Exception\DomainException|\SendyPHP\Exception\CurlException] 209 | * @return number|false 210 | */ 211 | public function getActiveSubscriberCount($listID, &$statusMessage = NULL) 212 | { 213 | if(strlen($listID) == 0) 214 | throw new Exception\DomainException('List ID can not be empty'); 215 | 216 | $request = array( 'api_key'=>$this->_getApiKey(), 217 | 'list_id'=>$listID); 218 | 219 | $response = $this->_callSendy(self::URI_ACTIVE_SUBSCRIBER_COUNT,$request); 220 | 221 | if(!is_numeric($response)) 222 | { 223 | $statusMessage = $response; 224 | return false; 225 | } 226 | else 227 | { 228 | $statusMessage = 'Success'; 229 | return intval($response); 230 | } 231 | } 232 | /** 233 | * Creates draft of campaign 234 | * 235 | * @param string $brandID Brand IDs can be found under 'Brands' page named ID 236 | * @param Model\Campaign $campaign configured campaign 237 | * @param string|NULL $statusMessage optional - here will be returned status message f.e. if you get FALSE again, and again, here you can find why 238 | * @throws \SendyPHP\Exception [\SendyPHP\Exception\CurlException] 239 | * @return bool 240 | */ 241 | public function createCampaign($brandID, Model\Campaign $campaign, &$statusMessage = NULL) 242 | { 243 | $request = array( 'api_key'=>$this->_getApiKey(), 244 | 'from_name'=>$campaign->getSender()->getName(), 245 | 'from_email'=>$campaign->getSender()->getAddress(), 246 | 'reply_to'=>$campaign->getSender()->getReplyAddress(), 247 | 'subject'=>$campaign->getSubject(), 248 | 'html_text'=>$campaign->getEmailBody()->getHtml(), 249 | 'brand_id'=>$brandID, 250 | 'send_campaign'=>0); 251 | 252 | $plainText = $campaign->getEmailBody()->getPlainText(); 253 | if(!is_null($plainText)) 254 | $request['plain_text'] = $plainText; 255 | 256 | $response = $this->_callSendy(self::URI_CAMPAIGN,$request); 257 | $statusMessage = $response; 258 | if($response == 'Campaign created') 259 | return true; 260 | else 261 | return false; 262 | } 263 | /** 264 | * Creates draft and automatically sends campaign 265 | * 266 | * @param array $listIDs The encrypted & hashed ids can be found under View all lists section named ID. 267 | * @param Model\Campaign $campaign configured campaign 268 | * @param string|NULL $statusMessage optional - here will be returned status message f.e. if you get FALSE again, and again, here you can find why 269 | * @throws \SendyPHP\Exception [\SendyPHP\Exception\CurlException|\SendyPHP\Exception\DomainException] 270 | * @return bool 271 | */ 272 | public function sendCampaign(array $listIDs, Model\Campaign $campaign, &$statusMessage = NULL) 273 | { 274 | if(count($listIDs) == 0) 275 | throw new Exception\DomainException('List IDs can not be empty'); 276 | 277 | $request = array( 'api_key'=>$this->_getApiKey(), 278 | 'from_name'=>$campaign->getSender()->getName(), 279 | 'from_email'=>$campaign->getSender()->getAddress(), 280 | 'reply_to'=>$campaign->getSender()->getReplyAddress(), 281 | 'subject'=>$campaign->getSubject(), 282 | 'html_text'=>$campaign->getEmailBody()->getHtml(), 283 | 'list_ids'=>implode(',',$listIDs), 284 | 'send_campaign'=>1); 285 | 286 | $plainText = $campaign->getEmailBody()->getPlainText(); 287 | if(!is_null($plainText)) 288 | $request['plain_text'] = $plainText; 289 | 290 | $response = $this->_callSendy(self::URI_CAMPAIGN,$request); 291 | $statusMessage = $response; 292 | if($response == 'Campaign created and now sending') 293 | return true; 294 | else 295 | return false; 296 | } 297 | /** 298 | * Sets sendy installation URL 299 | * 300 | * @param string $URL 301 | * @throws \SendyPHP\Exception\InvalidURLException 302 | */ 303 | public function setURL($URL) 304 | { 305 | if(!self::isURLValid($URL)) 306 | throw new Exception\InvalidURLException($URL); 307 | 308 | $this->_URL = $URL; 309 | } 310 | /** 311 | * Sets api key 312 | * 313 | * your API key is available in sendy Settings 314 | * 315 | * @param string $apiKey 316 | * @throws \SendyPHP\Exception\DomainException 317 | */ 318 | public function setApiKey($apiKey) 319 | { 320 | if(!is_string($apiKey)) 321 | throw new Exception\DomainException('Api key have to be string '.gettype($apiKey).' given'); 322 | 323 | $this->_apiKey = $apiKey; 324 | } 325 | /** 326 | * Sets cURL option 327 | * 328 | * You can set cURL options f.e. CURLOPT_SSL_VERIFYPEER or CURLOPT_SSL_VERIFYHOST 329 | * some parameters (\CURLOPT_RETURNTRANSFER,\CURLOPT_POST,\CURLOPT_POSTFIELDS) are used, if you try to set one of these exception is thrown 330 | * 331 | * @param number $option use \CURLOPT_* constant 332 | * @param mixed $value 333 | * @throws \SendyPHP\Exception\UnexpectedValueException 334 | * @see http://php.net/manual/en/function.curl-setopt.php 335 | */ 336 | public function setCurlOption($option, $value) 337 | { 338 | // reserved options check 339 | if(in_array($option,array(\CURLOPT_RETURNTRANSFER,\CURLOPT_POST,\CURLOPT_POSTFIELDS))) 340 | throw new Exception\UnexpectedValueException('cURL option ['.$option.'] is reserved and can not be changed'); 341 | 342 | $this->_cURLOption[$option] = $value; 343 | } 344 | /** 345 | * Clears user defined cURL options 346 | */ 347 | public function clearCurlOptions() 348 | { 349 | $this->_cURLOption = array(); 350 | } 351 | /** 352 | * Checks URL validity 353 | * 354 | * returns TRUE if given URL is valid 355 | * 356 | * @param mixed $url 357 | * @return bool 358 | */ 359 | public static function isURLValid($url) 360 | { 361 | return (filter_var($url,\FILTER_VALIDATE_URL)!==false); 362 | } 363 | /** 364 | * Checks Email validity 365 | * 366 | * returns TRUE if given e-mail address is valid 367 | * 368 | * @param mixed $email 369 | * @return bool 370 | */ 371 | public static function isEmailValid($email) 372 | { 373 | return (filter_var($email,\FILTER_VALIDATE_EMAIL)!==false); 374 | } 375 | /** 376 | * Returns URL 377 | * 378 | * if no no URL is defined throws an exception 379 | * 380 | * @throws Exception\UnexpectedValueException 381 | * @return string 382 | */ 383 | protected function _getURL() 384 | { 385 | if(is_null($this->_URL)) 386 | throw new Exception\UnexpectedValueException('There is no Sendy URL defined - use setURL() first'); 387 | 388 | return $this->_URL; 389 | } 390 | /** 391 | * Returns API key 392 | * 393 | * @return string 394 | * @throws Exception\UnexpectedValueException 395 | */ 396 | protected function _getApiKey() 397 | { 398 | if(is_null($this->_apiKey)) 399 | throw new Exception\UnexpectedValueException('There is no Sendy Api Key defined - use setAPIKey() first'); 400 | 401 | return $this->_apiKey; 402 | } 403 | /** 404 | * Returns user specified cURL options 405 | * 406 | * @return array 407 | */ 408 | protected function _getCurlOptions() 409 | { 410 | return $this->_cURLOption; 411 | } 412 | /** 413 | * Call sendy api 414 | * 415 | * @param string $URI 416 | * @param array $params 417 | * @throws Exception\CurlException 418 | * @return string 419 | */ 420 | protected function _callSendy($URI, array $params) 421 | { 422 | $url = $this->_getURL() .'/'. $URI; 423 | $resource = curl_init($url); 424 | 425 | if($resource === false) 426 | throw new Exception\CurlException('initialization failed. URL: '.$url); 427 | 428 | $postData = http_build_query($params); 429 | 430 | $curlOptions = $this->_getCurlOptions(); 431 | 432 | $curlOptions[\CURLOPT_RETURNTRANSFER] = 1; 433 | $curlOptions[\CURLOPT_POST] = 1; 434 | $curlOptions[\CURLOPT_POSTFIELDS] = $postData; 435 | 436 | foreach($curlOptions as $option=>$value) 437 | { 438 | if(!curl_setopt($resource, $option, $value)) 439 | throw new Exception\CurlException('option setting failed. Option: ['.$option.'] , value ['.$value.'])',$resource); 440 | } 441 | 442 | $result = curl_exec($resource); 443 | if($result === false) 444 | throw new Exception\CurlException('exec failed',$resource); 445 | 446 | curl_close($resource); 447 | 448 | return $result; 449 | } 450 | } 451 | -------------------------------------------------------------------------------- /src/autoload.php: -------------------------------------------------------------------------------- 1 | assertTrue($response->success()); 20 | $this->assertFalse($response->failed()); 21 | } 22 | /** 23 | * @test 24 | * @dataProvider failedResponseProvider 25 | * @param string $rawResponse 26 | */ 27 | public function testFailed($rawResponse) 28 | { 29 | $response = new \SendyPHP\Response\SubscriptionStatus($rawResponse); 30 | $this->assertFalse($response->success()); 31 | $this->assertTrue($response->failed()); 32 | } 33 | /** 34 | * @test 35 | */ 36 | public function testSubscribed() 37 | { 38 | $response = new \SendyPHP\Response\SubscriptionStatus('Subscribed'); 39 | $this->assertTrue($response->success()); 40 | $this->assertFalse($response->failed()); 41 | $this->assertTrue($response->isSubscribed()); 42 | $this->assertFalse($response->isBounced()); 43 | $this->assertFalse($response->isSoftBounced()); 44 | $this->assertFalse($response->isHardBounced()); 45 | $this->assertFalse($response->isUnconfirmed()); 46 | $this->assertFalse($response->isUnSubscribed()); 47 | $this->assertFalse($response->isComplained()); 48 | } 49 | /** 50 | * @test 51 | */ 52 | public function testUnSubscribed() 53 | { 54 | $response = new \SendyPHP\Response\SubscriptionStatus('Unsubscribed'); 55 | $this->assertTrue($response->success()); 56 | $this->assertFalse($response->failed()); 57 | $this->assertFalse($response->isSubscribed()); 58 | $this->assertFalse($response->isBounced()); 59 | $this->assertFalse($response->isSoftBounced()); 60 | $this->assertFalse($response->isHardBounced()); 61 | $this->assertFalse($response->isUnconfirmed()); 62 | $this->assertTrue($response->isUnSubscribed()); 63 | $this->assertFalse($response->isComplained()); 64 | } 65 | /** 66 | * @test 67 | */ 68 | public function testUnconfirmed() 69 | { 70 | $response = new \SendyPHP\Response\SubscriptionStatus('Unconfirmed'); 71 | $this->assertTrue($response->success()); 72 | $this->assertFalse($response->failed()); 73 | $this->assertFalse($response->isSubscribed()); 74 | $this->assertFalse($response->isBounced()); 75 | $this->assertFalse($response->isSoftBounced()); 76 | $this->assertFalse($response->isHardBounced()); 77 | $this->assertTrue($response->isUnconfirmed()); 78 | $this->assertFalse($response->isUnSubscribed()); 79 | $this->assertFalse($response->isComplained()); 80 | } 81 | /** 82 | * @test 83 | */ 84 | public function testBounced() 85 | { 86 | $response = new \SendyPHP\Response\SubscriptionStatus('Bounced'); 87 | $this->assertTrue($response->success()); 88 | $this->assertFalse($response->failed()); 89 | $this->assertFalse($response->isSubscribed()); 90 | $this->assertTrue($response->isBounced()); 91 | $this->assertFalse($response->isSoftBounced()); 92 | $this->assertTrue($response->isHardBounced()); 93 | $this->assertFalse($response->isUnconfirmed()); 94 | $this->assertFalse($response->isUnSubscribed()); 95 | $this->assertFalse($response->isComplained()); 96 | } 97 | /** 98 | * @test 99 | */ 100 | public function testSoftBounced() 101 | { 102 | $response = new \SendyPHP\Response\SubscriptionStatus('Soft bounced'); 103 | $this->assertTrue($response->success()); 104 | $this->assertFalse($response->failed()); 105 | $this->assertFalse($response->isSubscribed()); 106 | $this->assertTrue($response->isBounced()); 107 | $this->assertTrue($response->isSoftBounced()); 108 | $this->assertFalse($response->isHardBounced()); 109 | $this->assertFalse($response->isUnconfirmed()); 110 | $this->assertFalse($response->isUnSubscribed()); 111 | $this->assertFalse($response->isComplained()); 112 | } 113 | /** 114 | * @test 115 | */ 116 | public function testComplained() 117 | { 118 | $response = new \SendyPHP\Response\SubscriptionStatus('Complained'); 119 | $this->assertTrue($response->success()); 120 | $this->assertFalse($response->failed()); 121 | $this->assertFalse($response->isSubscribed()); 122 | $this->assertFalse($response->isBounced()); 123 | $this->assertFalse($response->isSoftBounced()); 124 | $this->assertFalse($response->isHardBounced()); 125 | $this->assertFalse($response->isUnconfirmed()); 126 | $this->assertFalse($response->isUnSubscribed()); 127 | $this->assertTrue($response->isComplained()); 128 | } 129 | /** 130 | * @test 131 | * @dataProvider badResponseProvider 132 | * @param mixed $response 133 | */ 134 | public function testBadResponse($response) 135 | { 136 | $response = new \SendyPHP\Response\SubscriptionStatus($response); 137 | $this->assertFalse($response->success()); 138 | $this->assertTrue($response->failed()); 139 | $this->assertFalse($response->isSubscribed()); 140 | $this->assertFalse($response->isBounced()); 141 | $this->assertFalse($response->isSoftBounced()); 142 | $this->assertFalse($response->isHardBounced()); 143 | $this->assertFalse($response->isUnconfirmed()); 144 | $this->assertFalse($response->isUnSubscribed()); 145 | $this->assertFalse($response->isComplained()); 146 | } 147 | /** 148 | * Dataprovider for success responses 149 | * 150 | * Includes all success responses from documentation 151 | * @link http://sendy.co/api section ["Subscription status" > "Response" > "Error"] 152 | * @return array 153 | */ 154 | public static function successResponseProvider() 155 | { 156 | return array(array('Subscribed'),array('Unsubscribed'),array('Unconfirmed'),array('Bounced'),array('Soft bounced'),array('Complained')); 157 | } 158 | /** 159 | * Dataprovider for error responses 160 | * 161 | * Includes all error responses from documentation 162 | * @link http://sendy.co/api section ["Subscription status" > "Response" > "Error"] 163 | * @return array 164 | */ 165 | public static function failedResponseProvider() 166 | { 167 | return array(array('No data passed'),array('API key not passed'),array('Email not passed'),array('List ID not passed'),array('Email does not exist in list')); 168 | } 169 | /** 170 | * Dataprovider for bad responses 171 | * 172 | * @return array 173 | */ 174 | public static function badResponseProvider() 175 | { 176 | return array(array(NULL),array(''),array(-1),array(1)); 177 | } 178 | } 179 | -------------------------------------------------------------------------------- /tests/TestBootstrap.php: -------------------------------------------------------------------------------- 1 |