summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Inman <james@jamesinman.co.uk>2012-09-07 14:35:45 +0100
committerJames Inman <james@jamesinman.co.uk>2012-09-07 14:35:45 +0100
commit00a4ce5d12076348e1e56179cceb2411731ceb0d (patch)
tree193ce28fbaeca952b75a5d22adcd7986b11687f4
parent770ec8df748b1c8237714d1e65bfb5a09795c22f (diff)
downloadclockwork-php-00a4ce5d12076348e1e56179cceb2411731ceb0d.zip
clockwork-php-00a4ce5d12076348e1e56179cceb2411731ceb0d.tar.gz
clockwork-php-00a4ce5d12076348e1e56179cceb2411731ceb0d.tar.bz2
Updating for getBalance(), WordPress updates.
-rwxr-xr-x[-rw-r--r--]class-Clockwork.php61
-rwxr-xr-x[-rw-r--r--]class-ClockworkException.php1
-rwxr-xr-xwordpress/class-WordPressClockwork.php448
-rw-r--r--wordpress/class-WordPressClockworkHTTP.php168
-rwxr-xr-xwordpress/class-clockwork-plugin.php326
5 files changed, 824 insertions, 180 deletions
diff --git a/class-Clockwork.php b/class-Clockwork.php
index 68aec9e..2824a08 100644..100755
--- a/class-Clockwork.php
+++ b/class-Clockwork.php
@@ -23,31 +23,37 @@ class Clockwork {
/*
* Version of this class
+ * @author Martin Steel
*/
const VERSION = '1.1.0';
/**
* All Clockwork API calls start with BASE_URL
+ * @author Martin Steel
*/
const API_BASE_URL = 'api.clockworksms.com/xml/';
/**
* string to append to API_BASE_URL to check authentication
+ * @author Martin Steel
*/
const API_AUTH_METHOD = 'authenticate';
/**
* string to append to API_BASE_URL for sending SMS
+ * @author Martin Steel
*/
const API_SMS_METHOD = 'sms';
/**
* string to append to API_BASE_URL for checking message credit
+ * @author Martin Steel
*/
const API_CREDIT_METHOD = 'credit';
/**
* string to append to API_BASE_URL for checking account balance
+ * @author Martin Steel
*/
const API_BALANCE_METHOD = 'balance';
@@ -55,6 +61,7 @@ class Clockwork {
* Clockwork API Key
*
* @var string
+ * @author Martin Steel
*/
public $key;
@@ -64,6 +71,7 @@ class Clockwork {
* If this is not set, SSL will be used where PHP supports it
*
* @var bool
+ * @author Martin Steel
*/
public $ssl;
@@ -71,6 +79,7 @@ class Clockwork {
* Proxy server hostname (Optional)
*
* @var string
+ * @author Martin Steel
*/
public $proxy_host;
@@ -78,6 +87,7 @@ class Clockwork {
* Proxy server port (Optional)
*
* @var integer
+ * @author Martin Steel
*/
public $proxy_port;
@@ -85,6 +95,7 @@ class Clockwork {
* From address used on text messages
*
* @var string (11 characters or 12 numbers)
+ * @author Martin Steel
*/
public $from;
@@ -92,6 +103,7 @@ class Clockwork {
* Allow long SMS messages (Cost up to 3 credits)
*
* @var bool
+ * @author Martin Steel
*/
public $long;
@@ -99,6 +111,7 @@ class Clockwork {
* Truncate message text if it is too long
*
* @var bool
+ * @author Martin Steel
*/
public $truncate;
@@ -106,6 +119,7 @@ class Clockwork {
* Enables various logging of messages when true.
*
* @var bool
+ * @author Martin Steel
*/
public $log;
@@ -116,6 +130,7 @@ class Clockwork {
* 'error' - Return an error (Messasge is not sent)
* 'remove' - Remove the invalid character(s)
* 'replace' - Replace invalid characters where possible, remove others
+ * @author Martin Steel
*/
public $invalid_char_action;
@@ -124,6 +139,7 @@ class Clockwork {
*
* @param string key Your Clockwork API Key
* @param array options Optional parameters for sending SMS
+ * @author Martin Steel
*/
public function __construct($key, array $options = array()) {
if (empty($key)) {
@@ -146,6 +162,7 @@ class Clockwork {
* Send some text messages
*
*
+ * @author Martin Steel
*/
public function send(array $sms) {
if (!is_array($sms)) {
@@ -297,6 +314,7 @@ class Clockwork {
*
* @return integer SMS credits remaining
* @deprecated Use checkBalance() instead
+ * @author Martin Steel
*/
public function checkCredit() {
// Create XML doc for request
@@ -344,6 +362,7 @@ class Clockwork {
* Check your account balance
*
* @return array Array of account balance:
+ * @author Martin Steel
*/
public function checkBalance() {
// Create XML doc for request
@@ -352,14 +371,14 @@ class Clockwork {
$req_doc->appendChild($root);
$root->appendChild($req_doc->createElement('Key', $this->key));
$req_xml = $req_doc->saveXML();
-
+
// POST XML to Clockwork
$resp_xml = $this->postToClockwork(self::API_BALANCE_METHOD, $req_xml);
// Create XML doc for response
$resp_doc = new DOMDocument();
$resp_doc->loadXML($resp_xml);
-
+
// Parse the response to find balance value
$balance = null;
$err_no = null;
@@ -368,7 +387,7 @@ class Clockwork {
foreach ($resp_doc->documentElement->childNodes as $doc_child) {
switch ($doc_child->nodeName) {
case "Balance":
- $balance = floatval($doc_child->nodeValue);
+ $balance = number_format(floatval($doc_child->nodeValue), 2);
break;
case "Currency":
foreach ($doc_child->childNodes as $resp_node) {
@@ -404,6 +423,7 @@ class Clockwork {
* Check whether the API Key is valid
*
* @return bool True indicates a valid key
+ * @author Martin Steel
*/
public function checkKey() {
// Create XML doc for request
@@ -454,17 +474,21 @@ class Clockwork {
* @param string data Content of HTTP POST
*
* @return string Response from Clockwork
+ * @author Martin Steel
*/
protected function postToClockwork($method, $data) {
-
if ($this->log) {
$this->logXML("API $method Request XML", $data);
}
-
- $ssl = isset($this->ssl) ? $this->ssl : $this->sslSupport();
+
+ if( isset( $this->ssl ) ) {
+ $ssl = $this->ssl;
+ } else {
+ $ssl = $this->sslSupport();
+ }
$url = $ssl ? 'https://' : 'http://';
- $url.= self::API_BASE_URL . $method;
+ $url .= self::API_BASE_URL . $method;
$response = $this->xmlPost($url, $data);
@@ -483,6 +507,7 @@ class Clockwork {
* @param string url URL to send to
* @param string data Data to POST
* @return string Response returned by server
+ * @author Martin Steel
*/
protected function xmlPost($url, $data) {
if(extension_loaded('curl')) {
@@ -551,8 +576,9 @@ class Clockwork {
* any requests.
*
* @return bool True if SSL is supported
+ * @author Martin Steel
*/
- private function sslSupport() {
+ protected function sslSupport() {
$ssl = false;
// See if PHP is compiled with cURL
if (extension_loaded('curl')) {
@@ -571,6 +597,7 @@ class Clockwork {
* @param string xml An XML formatted string
*
* @return void
+ * @author Martin Steel
*/
protected function logXML($log_msg, $xml) {
// Tidy if possible
@@ -590,14 +617,26 @@ class Clockwork {
error_log("Clockwork $log_msg: $xml");
}
- /*
+ /**
* Check if an array is associative
*
* @param array $array Array to check
- * @return bool
+ * @return bool
+ * @author Martin Steel
*/
- function is_assoc($array) {
+ protected function is_assoc($array) {
return (bool)count(array_filter(array_keys($array), 'is_string'));
}
+
+ /**
+ * Check if a number is a valid MSISDN
+ *
+ * @param string $val Value to check
+ * @return bool True if valid MSISDN
+ * @author James Inman
+ */
+ public static function is_valid_msisdn($val) {
+ return preg_match( '/^[1-9][0-9]{10,14}$/', $val );
+ }
}
diff --git a/class-ClockworkException.php b/class-ClockworkException.php
index 0b1c8bf..bf8d63e 100644..100755
--- a/class-ClockworkException.php
+++ b/class-ClockworkException.php
@@ -25,4 +25,3 @@ class ClockworkException extends Exception {
parent::__construct( $message, $code );
}
}
-
diff --git a/wordpress/class-WordPressClockwork.php b/wordpress/class-WordPressClockwork.php
new file mode 100755
index 0000000..764e42d
--- /dev/null
+++ b/wordpress/class-WordPressClockwork.php
@@ -0,0 +1,448 @@
+<?php
+/**
+* WordPress Clockwork class
+*
+* Extends the Clockwor wrapper class to use the
+* WordPress HTTP API for HTTP calls, attempts to work
+* round the differences in PHP versions, such as SSL
+* & curl support
+*
+* @package Clockwork
+* @subpackage WordPressClockwork
+* @since 1.0
+*/
+
+class WordPressClockwork extends Clockwork {
+
+ /**
+ * Options key for Clockwork plugins
+ */
+ const OPTIONS_KEY = 'clockwork_options';
+
+ /**
+ * SSL options key for Clockwork plugins
+ */
+ const SSL_OPTIONS_KEY = 'clockwork_ssl_options';
+
+ /**
+ * String to append to API_BASE_URL for getting a new key
+ */
+ const API_GET_KEY_METHOD = 'get_key';
+
+ /**
+ * Mapping of country dialing codes to ISO codes
+ */
+ public static $country_codes = array(
+ 'AC' => '247',
+ 'AD' => '376',
+ 'AE' => '971',
+ 'AF' => '93',
+ 'AG' => '1268',
+ 'AI' => '1264',
+ 'AL' => '355',
+ 'AM' => '374',
+ 'AO' => '244',
+ 'AQ' => '672',
+ 'AR' => '54',
+ 'AS' => '1684',
+ 'AT' => '43',
+ 'AU' => '61',
+ 'AW' => '297',
+ 'AX' => '358',
+ 'AZ' => '994',
+ 'BA' => '387',
+ 'BB' => '1246',
+ 'BD' => '880',
+ 'BE' => '32',
+ 'BF' => '226',
+ 'BG' => '359',
+ 'BH' => '973',
+ 'BI' => '257',
+ 'BJ' => '229',
+ 'BL' => '590',
+ 'BM' => '1441',
+ 'BN' => '673',
+ 'BO' => '591',
+ 'BQ' => '599',
+ 'BR' => '55',
+ 'BS' => '1242',
+ 'BT' => '975',
+ 'BW' => '267',
+ 'BY' => '375',
+ 'BZ' => '501',
+ 'CA' => '1',
+ 'CC' => '61',
+ 'CD' => '243',
+ 'CF' => '236',
+ 'CG' => '242',
+ 'CH' => '41',
+ 'CI' => '225',
+ 'CK' => '682',
+ 'CL' => '56',
+ 'CM' => '237',
+ 'CN' => '86',
+ 'CO' => '57',
+ 'CR' => '506',
+ 'CU' => '53',
+ 'CV' => '238',
+ 'CW' => '599',
+ 'CX' => '61',
+ 'CY' => '357',
+ 'CZ' => '420',
+ 'DE' => '49',
+ 'DJ' => '253',
+ 'DK' => '45',
+ 'DM' => '1767',
+ 'DO' => '1809',
+ 'DO' => '1829',
+ 'DO' => '1849',
+ 'DZ' => '213',
+ 'EC' => '593',
+ 'EE' => '372',
+ 'EG' => '20',
+ 'EH' => '212',
+ 'ER' => '291',
+ 'ES' => '34',
+ 'ET' => '251',
+ 'EU' => '388',
+ 'FI' => '358',
+ 'FJ' => '679',
+ 'FK' => '500',
+ 'FM' => '691',
+ 'FO' => '298',
+ 'FR' => '33',
+ 'GA' => '241',
+ 'GB' => '44',
+ 'GD' => '1473',
+ 'GE' => '995',
+ 'GF' => '594',
+ 'GG' => '44',
+ 'GH' => '233',
+ 'GI' => '350',
+ 'GL' => '299',
+ 'GM' => '220',
+ 'GN' => '224',
+ 'GP' => '590',
+ 'GQ' => '240',
+ 'GR' => '30',
+ 'GT' => '502',
+ 'GU' => '1671',
+ 'GW' => '245',
+ 'GY' => '592',
+ 'HK' => '852',
+ 'HN' => '504',
+ 'HR' => '385',
+ 'HT' => '509',
+ 'HU' => '36',
+ 'ID' => '62',
+ 'IE' => '353',
+ 'IL' => '972',
+ 'IM' => '44',
+ 'IN' => '91',
+ 'IO' => '246',
+ 'IQ' => '964',
+ 'IR' => '98',
+ 'IS' => '354',
+ 'IT' => '39',
+ 'JE' => '44',
+ 'JM' => '1876',
+ 'JO' => '962',
+ 'JP' => '81',
+ 'KE' => '254',
+ 'KG' => '996',
+ 'KH' => '855',
+ 'KI' => '686',
+ 'KM' => '269',
+ 'KN' => '1869',
+ 'KP' => '850',
+ 'KR' => '82',
+ 'KW' => '965',
+ 'KY' => '1345',
+ 'KZ' => '7',
+ 'LA' => '856',
+ 'LB' => '961',
+ 'LC' => '1758',
+ 'LI' => '423',
+ 'LK' => '94',
+ 'LR' => '231',
+ 'LS' => '266',
+ 'LT' => '370',
+ 'LU' => '352',
+ 'LV' => '371',
+ 'LY' => '218',
+ 'MA' => '212',
+ 'MC' => '377',
+ 'MD' => '373',
+ 'ME' => '382',
+ 'MF' => '590',
+ 'MG' => '261',
+ 'MH' => '692',
+ 'MK' => '389',
+ 'ML' => '223',
+ 'MM' => '95',
+ 'MN' => '976',
+ 'MO' => '853',
+ 'MP' => '1670',
+ 'MQ' => '596',
+ 'MR' => '222',
+ 'MS' => '1664',
+ 'MT' => '356',
+ 'MU' => '230',
+ 'MV' => '960',
+ 'MW' => '265',
+ 'MX' => '52',
+ 'MY' => '60',
+ 'MZ' => '258',
+ 'NA' => '264',
+ 'NC' => '687',
+ 'NE' => '227',
+ 'NF' => '672',
+ 'NG' => '234',
+ 'NI' => '505',
+ 'NL' => '31',
+ 'NO' => '47',
+ 'NP' => '977',
+ 'NR' => '674',
+ 'NU' => '683',
+ 'NZ' => '64',
+ 'OM' => '968',
+ 'PA' => '507',
+ 'PE' => '51',
+ 'PF' => '689',
+ 'PG' => '675',
+ 'PH' => '63',
+ 'PK' => '92',
+ 'PL' => '48',
+ 'PM' => '508',
+ 'PR' => '1787',
+ 'PR' => '1939',
+ 'PS' => '970',
+ 'PT' => '351',
+ 'PW' => '680',
+ 'PY' => '595',
+ 'QA' => '974',
+ 'QN' => '374',
+ 'QS' => '252',
+ 'QY' => '90',
+ 'RE' => '262',
+ 'RO' => '40',
+ 'RS' => '381',
+ 'RU' => '7',
+ 'RW' => '250',
+ 'SA' => '966',
+ 'SB' => '677',
+ 'SC' => '248',
+ 'SD' => '249',
+ 'SE' => '46',
+ 'SG' => '65',
+ 'SH' => '290',
+ 'SI' => '386',
+ 'SJ' => '47',
+ 'SK' => '421',
+ 'SL' => '232',
+ 'SM' => '378',
+ 'SN' => '221',
+ 'SO' => '252',
+ 'SR' => '597',
+ 'SS' => '211',
+ 'ST' => '239',
+ 'SV' => '503',
+ 'SX' => '1721',
+ 'SY' => '963',
+ 'SZ' => '268',
+ 'TA' => '290',
+ 'TC' => '1649',
+ 'TD' => '235',
+ 'TG' => '228',
+ 'TH' => '66',
+ 'TJ' => '992',
+ 'TK' => '690',
+ 'TL' => '670',
+ 'TM' => '993',
+ 'TN' => '216',
+ 'TO' => '676',
+ 'TR' => '90',
+ 'TT' => '1868',
+ 'TV' => '688',
+ 'TW' => '886',
+ 'TZ' => '255',
+ 'UA' => '380',
+ 'UG' => '256',
+ 'UK' => '44',
+ 'US' => '1',
+ 'UY' => '598',
+ 'UZ' => '998',
+ 'VA' => '379',
+ 'VA' => '39',
+ 'VC' => '1784',
+ 'VE' => '58',
+ 'VG' => '1284',
+ 'VI' => '1340',
+ 'VN' => '84',
+ 'VU' => '678',
+ 'WF' => '681',
+ 'WS' => '685',
+ 'XC' => '991',
+ 'XD' => '888',
+ 'XG' => '881',
+ 'XL' => '883',
+ 'XN' => '857',
+ 'XN' => '858',
+ 'XN' => '870',
+ 'XP' => '878',
+ 'XR' => '979',
+ 'XS' => '808',
+ 'XT' => '800',
+ 'XV' => '882',
+ 'YE' => '967',
+ 'YT' => '262',
+ 'ZA' => '27',
+ 'ZM' => '260',
+ 'ZW' => '263',
+ );
+
+ /**
+ * Legacy username
+ *
+ * @var string
+ */
+ private $username;
+
+ /**
+ * Legacy password
+ *
+ * @var string
+ */
+ public $password;
+
+ /**
+ * Create a new instance of the Clockwork wrapper
+ *
+ * Also supports passing a username and a password as first and second parameter, but ONLY when
+ * used in WordPressClockwork for the purposes of converting to an API key.
+ *
+ * @param string key Your Clockwork API Key
+ * @param array options Optional parameters for sending SMS
+ * @author James Inman
+ */
+ public function __construct( $arg1, $arg2 = array() ) {
+ if( !isset( $arg2 ) || is_array( $arg2 ) ) {
+ parent::__construct( $arg1, $arg2 );
+ } else {
+ $this->username = $arg1;
+ $this->password = $arg2;
+ }
+ }
+
+ public function createAPIKey( $name = 'WordPress API Key' ) {
+ // Create XML doc for request
+ $req_doc = new DOMDocument( '1.0', 'UTF-8' );
+ $root = $req_doc->createElement( 'GetKey' );
+ $req_doc->appendChild( $root );
+ $root->appendChild( $req_doc->createElement( 'Username', $this->username ) );
+ $root->appendChild( $req_doc->createElement( 'Password', $this->password ) );
+ $root->appendChild( $req_doc->createElement( 'Name', $name ) );
+ $req_xml = $req_doc->saveXML();
+ // POST XML to Clockwork
+ $resp_xml = $this->postToClockwork( self::API_GET_KEY_METHOD, $req_xml );
+
+ // Create XML doc for response
+ $resp_doc = new DOMDocument();
+ $resp_doc->loadXML( $resp_xml );
+
+ // Parse the response to find credit value
+ $key = null;
+ $err_no = null;
+ $err_desc = null;
+
+ foreach( $resp_doc->documentElement->childNodes as $doc_child ) {
+ switch( $doc_child->nodeName ) {
+ case "Key":
+ $key = $doc_child->nodeValue;
+ break;
+ case "ErrNo":
+ $err_no = $doc_child->nodeValue;
+ break;
+ case "ErrDesc":
+ $err_desc = $doc_child->nodeValue;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if( isset( $err_no ) ) {
+ throw new ClockworkException( $err_desc, $err_no );
+ }
+
+ $this->key = $key;
+ return $key;
+ }
+
+ /**
+ * Check if the WordPress HTTP API can support SSL
+ *
+ * @returns bool True if SSL is supported
+ */
+ public function sslSupport() {
+ return wp_http_supports( array( 'ssl' ) );
+ }
+
+ /**
+ * Make an HTTP POST using the WordPress HTTP API.
+ *
+ * @param string url URL to send to
+ * @param string data Data to POST
+ * @return string Response returned by server
+ */
+ protected function xmlPost( $url, $data ) {
+ $args = array(
+ 'body' => $data,
+ 'headers' => array( 'Content-Type' => 'text/xml' ),
+ 'timeout' => 10, // Seconds
+ );
+
+ // Check whether WordPress should veryify the SSL certificate
+ if( stristr( $url, 'https://' ) ) {
+ $args['sslverify'] = $this->sslVerify( $url );
+ }
+
+ $result = wp_remote_post( $url, $args );
+ if( is_wp_error( $result ) ) {
+ error_log( "POST failed: " . $result->get_error_message() );
+ throw new ClockworkException( "HTTP Call failed - Error: " . $result->get_error_message() );
+ }
+ return $result[ 'body' ];
+ }
+
+ /**
+ * Verify SSL conectivity to the remote host
+ *
+ * If the request fails store a flag so that we
+ * don't need to do the check again
+ */
+ private function sslVerify($url) {
+ $opt = get_option( self::SSL_OPTIONS_KEY );
+ if( !$opt ) {
+ $opt = array();
+ }
+
+ if( !array_key_exists( 'sslverify', $opt ) ) {
+ $args = array(
+ 'timeout' => 10 // Seconds
+ );
+
+ $result = wp_remote_post( $url, $args );
+
+ if( is_wp_error( $result ) ) {
+ $opt['sslverify'] = false;
+ } else {
+ $opt['sslverify'] = true;
+ }
+
+ update_option( self::SSL_OPTIONS_KEY, $opt );
+ }
+ return $opt['sslverify'];
+ }
+
+}
diff --git a/wordpress/class-WordPressClockworkHTTP.php b/wordpress/class-WordPressClockworkHTTP.php
deleted file mode 100644
index 06e039e..0000000
--- a/wordpress/class-WordPressClockworkHTTP.php
+++ /dev/null
@@ -1,168 +0,0 @@
-<?php
-/**
-* WordPress Clockwork class
-*
-* Extends the Clockwork wrapper class to use the
-* WordPress HTTP API for HTTP calls, attempts to work
-* round the differences in PHP versions, such as SSL
-* and curl support.
-*
-* @package Clockwork
-* @subpackage WordPressClockwork
-* @since 1.0
-*/
-
-class WordPressClockwork extends Clockwork {
-
- /**
- * Options key for Clockwork plugins
- */
- const OPTIONS_KEY = 'clockwork_options';
-
- /**
- * String to append to API_BASE_URL for getting a new key
- */
- const API_GET_KEY_METHOD = 'get_key';
-
- /**
- * Legacy username
- *
- * @var string
- */
- private $username;
-
- /**
- * Legacy password
- *
- * @var string
- */
- public $password;
-
- /**
- * Create a new instance of the Clockwork wrapper
- *
- * Also supports passing a username and a password as first and second parameter, but ONLY when
- * used in WordPressClockwork for the purposes of converting to an API key.
- *
- * @param string key Your Clockwork API Key
- * @param array options Optional parameters for sending SMS
- * @author James Inman
- */
- public function __construct( $arg1, $arg2 = array() ) {
- if( !isset( $arg2 ) || is_array( $arg2 ) ) {
- parent::__construct( $arg1, $arg2 );
- } else {
- $this->username = $arg1;
- $this->password = $arg2;
- }
- }
-
- public function createAPIKey( $name = 'WordPress API Key' ) {
- // Create XML doc for request
- $req_doc = new DOMDocument( '1.0', 'UTF-8' );
- $root = $req_doc->createElement( 'GetKey' );
- $req_doc->appendChild( $root );
- $root->appendChild( $req_doc->createElement( 'Username', $this->username ) );
- $root->appendChild( $req_doc->createElement( 'Password', $this->password ) );
- $root->appendChild( $req_doc->createElement( 'Name', $name ) );
- $req_xml = $req_doc->saveXML();
-
- // POST XML to Clockwork
- $resp_xml = $this->postToClockwork( self::API_GET_KEY_METHOD, $req_xml );
-
- // Create XML doc for response
- $resp_doc = new DOMDocument();
- $resp_doc->loadXML( $resp_xml );
-
- // Parse the response to find credit value
- $key = null;
- $err_no = null;
- $err_desc = null;
-
- foreach( $resp_doc->documentElement->childNodes as $doc_child ) {
- switch( $doc_child->nodeName ) {
- case "Key":
- $key = $doc_child->nodeValue;
- break;
- case "ErrNo":
- $err_no = $doc_child->nodeValue;
- break;
- case "ErrDesc":
- $err_desc = $doc_child->nodeValue;
- break;
- default:
- break;
- }
- }
-
- if( isset( $err_no ) ) {
- throw new ClockworkException( $err_desc, $err_no );
- }
-
- $this->key = $key;
- return $key;
- }
-
- /**
- * Check if the WordPress HTTP API can support SSL
- *
- * @returns bool True if SSL is supported
- */
- public function sslSupport() {
- return wp_http_supports( array( 'ssl' ) );
- }
-
- /**
- * Make an HTTP POST using the WordPress HTTP API.
- *
- * @param string url URL to send to
- * @param string data Data to POST
- * @return string Response returned by server
- */
- protected function xmlPost( $url, $data ) {
- $args = array(
- 'body' => $data,
- 'headers' => array( 'Content-Type' => 'text/xml' ),
- 'timeout' => 10, // Seconds
- );
-
- // Check whether WordPress should veryify the SSL certificate
- if( stristr( $url, 'https://' ) ) {
- $args['sslverify'] = $this->sslVerify( $url );
- }
-
- $result = wp_remote_post( $url, $args );
- if( is_wp_error( $result ) ) {
- error_log( "POST failed: " . $result->get_error_message() );
- throw new ClockworkException( "HTTP Call failed - Error: " . $result->get_error_message() );
- }
- return $result[ 'body' ];
- }
-
- /**
- * Verify SSL conectivity to the remote host
- *
- * If the request fails store a flag so that we
- * don't need to do the check again
- */
- private function sslVerify($url) {
- $opt = get_option( self::OPTIONS_KEY );
- if( !$opt ) {
- $opt = array();
- }
- if( !array_key_exists( 'sslverify', $opt ) ) {
- $args = array(
- 'timeout' => 10, // Seconds
- );
- $result = wp_remote_post( $url, $args );
- if( is_wp_error( $result ) ) {
- $opt['sslverify'] = false;
- } else {
- $opt['sslverify'] = true;
- }
- update_option( self::OPTIONS_KEY, $opt );
- }
- return $opt['sslverify'];
- }
-
-} \ No newline at end of file
diff --git a/wordpress/class-clockwork-plugin.php b/wordpress/class-clockwork-plugin.php
new file mode 100755
index 0000000..aa879b8
--- /dev/null
+++ b/wordpress/class-clockwork-plugin.php
@@ -0,0 +1,326 @@
+<?php
+/* Copyright 2012, Mediaburst Limited.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+// Require the Clockwork API
+if( !class_exists('Clockwork') ) {
+ require_once( 'clockwork/class-Clockwork.php' );
+}
+if( !class_exists('WordPressClockwork') ) {
+ require_once( 'clockwork/class-WordPressClockwork.php' );
+}
+
+/**
+ * Base class for Clockwork plugins
+ *
+ * @package Clockwork
+ * @author James Inman
+ */
+abstract class Clockwork_Plugin {
+
+ /**
+ * Version of the Clockwork Wordpress wrapper
+ */
+ const VERSION = '1.0.0';
+ /**
+ * URL to signup for a new Clockwork account
+ */
+ const SIGNUP_URL = 'http://www.clockworksms.com/platforms/wordpress/?utm_source=wpadmin&utm_medium=plugin&utm_campaign=wp-clockwork';
+ /**
+ * URL to top up message credit
+ */
+ const BUY_URL = 'https://app.clockworksms.com/purchase/?utm_source=wpadmin&utm_medium=plugin&utm_campaign=wp-clockwork';
+ /**
+ * URL for support
+ */
+ const SUPPORT_URL = 'http://www.clockworksms.com/support/?utm_source=wpadmin&utm_medium=plugin&utm_campaign=wp-clockwork';
+
+ /**
+ * @param $callback Callback function for the plugin's menu item
+ *
+ * @author James Inman
+ */
+ public $plugin_callback = null;
+
+ /**
+ * Instance of WordPressClockwork
+ *
+ * @var WordPressClockwork
+ * @author James Inman
+ */
+ protected $clockwork = null;
+
+ /**
+ * Setup admin panel menu, notices and settings
+ *
+ * @author James Inman
+ */
+ public function __construct() {
+ // If Clockwork API key isn't set, convert existing username and password into API key
+ $this->convert_existing_username_and_password();
+
+ // Setup clockwork
+ try {
+ $options = get_option( 'clockwork_options' );
+ if( is_array( $options ) && isset( $options['api_key'] ) ) {
+ $this->clockwork = new WordPressClockwork( $options['api_key'] );
+ }
+ } catch( Exception $e ) {
+ }
+
+ add_action( 'admin_head', array( $this, 'setup_admin_head' ) );
+ add_action( 'admin_menu', array( $this, 'setup_admin_navigation' ) );
+ add_action( 'admin_notices', array( $this, 'setup_admin_message' ) );
+ add_action( 'admin_bar_menu', array( $this, 'setup_admin_bar' ), 999 );
+ add_action( 'admin_init', array( $this, 'setup_admin_init' ) );
+
+ $this->plugin_callback = array( $this, 'main' );
+ }
+
+ /**
+ * Return the username and password from the plugin's existing options
+ *
+ * @return array Array of 'username' and 'password'
+ * @author James Inman
+ */
+ abstract public function get_existing_username_and_password();
+
+ /**
+ * Setup HTML for the admin <head>
+ *
+ * @return void
+ * @author James Inman
+ */
+ abstract public function setup_admin_head();
+
+ /**
+ * Convert existing username and password to a new API key
+ *
+ * @return void
+ * @author James Inman
+ */
+ public function convert_existing_username_and_password() {
+ $options = get_option( 'clockwork_options' );
+ if( !is_array( $options ) || !isset( $options['api_key'] ) ) {
+ $existing_details = $this->get_existing_username_and_password();
+
+ if( is_array( $existing_details ) && isset( $existing_details['username'] ) && isset( $existing_details['password'] ) ) {
+ try {
+ // We have a username and password, now go and convert them
+ $this->clockwork = new WordPressClockwork( $existing_details['username'], $existing_details['password'] );
+ $key = $this->clockwork->createAPIKey( 'WordPress - ' . home_url() );
+ // Set the Clockwork API key to be the newly created key
+ update_option( 'clockwork_options', array( 'api_key' => $key ) );
+ } catch( ClockworkException $e ) {
+ return;
+ }
+ }
+ }
+ }
+
+ /**
+ * Tell the user to update their Clockwork options on every admin panel page if they haven't already
+ *
+ * @return void
+ * @author James Inman
+ */
+ public function setup_admin_message() {
+ // Don't bother showing the "You need to set your Clockwork options" message if it's that form we're viewing
+ if( !isset( $this->clockwork ) && ( get_current_screen()->base != 'toplevel_page_clockwork_options' ) ) {
+ $this->show_admin_message('You need to set your <a href="/wp-admin/admin.php?page=clockwork_options">Clockwork options</a> before you can use ' . $this->plugin_name . '.');
+ }
+ }
+
+ /**
+ * Add the Clockwork balance to the admin bar
+ *
+ * @return void
+ * @author James Inman
+ */
+ public function setup_admin_bar() {
+ global $wp_admin_bar;
+ if ( !is_super_admin() || !is_admin_bar_showing() ) {
+ return;
+ }
+ // Display a low credit notification if there's no credit
+ try {
+ if( !isset( $this->clockwork ) ) {
+ $options = get_option( 'clockwork_options' );
+
+ $clockwork = new WordPressClockwork( $options['api_key'] );
+ }
+ $balance = $this->clockwork->checkBalance();
+ if( $balance <= 0 ) {
+ $balance_string = '£0. Top up now!';
+ } else {
+ $balance_string = $balance['symbol'] . $balance['balance'];
+ }
+ // Add a node to the Admin bar
+ $wp_admin_bar->add_node( array(
+ 'id' => 'clockwork_balance',
+ 'title' => 'Clockwork: ' . $balance_string,
+ 'href' => self::BUY_URL )
+ );
+ } catch( Exception $e ) {
+ // Don't kill the entire admin panel because we can't get the balance
+ }
+ }
+
+ /**
+ * Setup admin navigation: callback for 'admin_menu'
+ *
+ * @return void
+ * @author James Inman
+ */
+ public function setup_admin_navigation() {
+ global $menu;
+
+ $menu_exists = false;
+ foreach( $menu as $k => $item ) {
+ if( $item[0] == "Clockwork SMS" ) {
+ $menu_exists = true;
+ break;
+ }
+ }
+
+ // Setup global Clockwork options
+ if( !$menu_exists ) {
+ add_menu_page( __( 'Clockwork SMS', $this->language_string ), __( 'Clockwork SMS', $this->language_string ), 'manage_options', 'clockwork_options', array( $this, 'clockwork_options' ), plugins_url( 'images/logo_16px_16px.png', dirname( __FILE__ ) ) );
+ add_submenu_page( 'clockwork_options', __( 'Clockwork Options', $this->language_string ), __( 'Clockwork Options', $this->language_string ), 'manage_options', 'clockwork_options', array( $this, 'clockwork_options' ) );
+ }
+
+ // Setup options for this plugin
+ add_submenu_page( 'clockwork_options', __( $this->plugin_name, $this->language_string ), __( $this->plugin_name, $this->language_string ), 'manage_options', $this->plugin_callback[1], $this->plugin_callback );
+ }
+
+ /**
+ * Register global Clockwork settings for API keys
+ *
+ * @return void
+ * @author James Inman
+ */
+ public function setup_admin_init() {
+ register_setting( 'clockwork_options', 'clockwork_options', array( $this, 'clockwork_options_validate' ) );
+ add_settings_section( 'clockwork_options', 'API Key', array( $this, 'settings_api_key_text' ), 'clockwork_options' );
+ add_settings_field( 'clockwork_api_key', 'Your API Key', array( $this, 'settings_api_key_input' ), 'clockwork_options', 'clockwork_options' );
+ }
+
+ /**
+ * Introductory text for the API keys part of the form
+ *
+ * @return void
+ * @author James Inman
+ */
+ public function settings_api_key_text() {
+ echo '<p>You need an API key to use the Clockwork plugins.</p>';
+ }
+
+ /**
+ * Input box for the API key
+ *
+ * @return void
+ * @author James Inman
+ */
+ public function settings_api_key_input() {
+ try {
+ if( !isset( $this->clockwork ) ) {
+ $options = get_option( 'clockwork_options' );
+ $this->clockwork = new WordPressClockwork( $options['api_key'] );
+ }
+
+ echo "<input id='clockwork_api_key' name='clockwork_options[api_key]' size='40' type='text' value='{$this->clockwork->key}' />";
+
+ // Show balance
+ $balance = $this->clockwork->checkBalance();
+ if( $balance ) {
+ echo '<p><strong>Balance:</strong> ' . $balance['symbol'] . $balance['balance'] . '&nbsp;&nbsp;&nbsp;<a href="' . self::BUY_URL . '" class="button">Buy More</a></p>';
+ } else { // We can't get the credits for some reason
+ echo '<p><a href="' . self::BUY_URL . '" class="button">Buy More Credit</a></p>';
+ }
+
+ } catch( ClockworkException $e ) {
+ echo "<input id='clockwork_api_key' name='clockwork_options[api_key]' size='40' type='text' value='' />";
+ echo '<p><a href="' . self::SIGNUP_URL . '" class="button">Get An API Key</a></p>';
+ }
+ }
+
+ /**
+ * Validation for the API key
+ *
+ * @return void
+ * @author James Inman
+ */
+ public function clockwork_options_validate( $val ) {
+ try {
+ $key = trim( $val['api_key'] );
+ if( $key ) {
+ $clockwork = new WordPressClockwork( $key );
+ $clockwork->checkKey();
+ $this->clockwork = $clockwork;
+ add_settings_error( 'clockwork_options', 'clockwork_options', 'Your settings were saved! You can now start using Clockwork SMS.', 'updated' );
+ } else {
+ $key = '';
+ add_settings_error( 'clockwork_options', 'clockwork_options', 'You cannot enter a blank API key.', 'error' );
+ }
+ } catch( ClockworkException $ex ) {
+ add_settings_error( 'clockwork_options', 'clockwork_options', 'Your API key was incorrect. Please enter it again.', 'error' );
+ }
+ return $val;
+ }
+
+ /**
+ * Render the main Clockwork options page
+ *
+ * @return void
+ * @author James Inman
+ */
+ public function clockwork_options() {
+ $this->render_template( 'clockwork-options' );
+ }
+
+ /**
+ * Show a message at the top of the administration panel
+ *
+ * @param string $message Error message to show (can include HTML)
+ * @param bool $errormsg True to display as a red 'error message'
+ * @return void
+ * @author James Inman
+ */
+ protected function show_admin_message( $message, $errormsg = false ) {
+ if( $errormsg ) {
+ echo '<div id="message" class="error">';
+ } else {
+ echo '<div id="message" class="updated fade">';
+ }
+
+ echo "<p><strong>$message</strong></p></div>";
+ }
+
+ /**
+ * Render a template file from the templates directory
+ *
+ * @param string $name Path to template file, excluding .php extension
+ * @param array $data Array of data to include in template
+ * @return void
+ * @author James Inman
+ */
+ protected function render_template( $name, $data = array() ) {
+ extract( $data );
+ include( WP_PLUGIN_DIR . '/' . rtrim( basename( dirname( dirname( __FILE__ ) ) ), '/' ) . '/templates/' . $name . '.php' );
+ }
+
+}