<?php
/**
 * TextMarks PHP API Client Library. v2.48a.
 * ---------------------------------------------------------------------------
 *
 * TextMarks provides a text-messaging platform you can integrate into
 * your own applications to send and receive text messages to individual
 * users or groups of users.
 *
 * For full online documentation, visit:
 *   http://www.textmarks.com/dev/docs/api/
 *   http://www.textmarks.com/dev/
 *   http://www.textmarks.com/
 *
 * The XML-RPC HTTP API that this library integrates with is NOT REQUIRED.
 * You can do all kinds of wonderful things without this API and without
 * writing any code at all.  However if you wish to automate and integrate
 * TextMarks more deeply into your applications, this API may be useful.
 *
 * This optional PHP client library provides one way to integrate with
 * the platform's XML-RPC HTTP API from your PHP applications.
 *
 * This library requires:
 *  - PHP 5.1 or greater.
 *  - libCURL (normally included with PHP).
 *  - SimpleXMLEelement (normally included with PHP).
 *
 * ---------------------------------------------------------------------------
 * @author Dan Kamins [d k a m i n s A.T t e x t m a r k s D.O.T c o m]
 * @package tmAPIClient
 * ---------------------------------------------------------------------------
 * Copyright (c) 2008, TextMarks Inc. All rights reserved.
 * ---------------------------------------------------------------------------
 *
 * THIS PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
 * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
 * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
 *
 * RECIPIENT IS SOLELY RESPONSIBLE FOR DETERMINING THE APPROPRIATENESS
 * OF USING AND DISTRIBUTING THE PROGRAM AND ASSUMES ALL RISKS ASSOCIATED
 * WITH ITS EXERCISE OF RIGHTS UNDER THIS AGREEMENT, INCLUDING BUT NOT
 * LIMITED TO THE RISKS AND COSTS OF PROGRAM ERRORS, COMPLIANCE WITH
 * APPLICABLE LAWS, DAMAGE TO OR LOSS OF DATA, PROGRAMS OR EQUIPMENT,
 * AND UNAVAILABILITY OR INTERRUPTION OF OPERATIONS.
 *
 * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR
 * DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
 * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 */
/** */



// ---------------------------------------------------------------------------



/**
 * Exception subclass used by TextMarksAPIClient.
 */
class TextMarksAPIClientException extends Exception
{
}

/**
 * Exception subclass used by TextMarksAPIClient for transport-level errors.
 */
class TextMarksAPIClientTransportException extends TextMarksAPIClientException
{
}



// ---------------------------------------------------------------------------



/**
 * Abstract TextMarksAPIClient, subclassed by API packages.
 */
abstract class TextMarksAPIClient
{
    const 
API_URL_BASE      'http://dev1.api.textmarks.com/';

    
// -----------------------------------------------------------------------

    /**
     * Create TextMarksAPIClient around indicated authentication info.
     *
     * @param string  $sApiKey   API Key ( register at http://www.textmarks.com/dev/api/reg/ )
     * @param string  $sAuthUser Phone# or TextMarks username to authenticate to API with.
     * @param string  $sAuthPass TextMarks Password associated with sAuthUser.
     */
    
public function __construct$sApiKey$sAuthUser$sAuthPass )
    {
        
$this->m_sApiKey    $sApiKey;
        
$this->m_sAuthUser  $sAuthUser;
        
$this->m_sAuthPass  $sAuthPass;
    }

    
/**
     * Execute HTTP request (post params to API endpoint) and return string response.
     *
     * @param string              $sUrl      URL to request by POST.
     * @param map(string,string)  $mssParams Params to POST.
     * @return string Response (usually XML).
     * @throws TextMarksAPIClientTransportException on error.
     */
    
protected function _makeHttpCall$sUrl$mssParams )
    {
        
// Convert param map to encoded form (to post):
        
$sPostData "";
        foreach (
$mssParams as $sK => $sV)
        {
            
$sPostData .= "&" urlencode($sK) . "=" urlencode($sV);
        }

        
// Prep curl:
        
$ch curl_init();
        
$arsHeaders = array("Content-Type: application/x-www-form-urlencoded",);
        
curl_setopt($chCURLOPT_URL$sUrl);
        
curl_setopt($chCURLOPT_HTTPHEADER$arsHeaders);
        
curl_setopt($chCURLOPT_POSTFIELDS$sPostData);
        
curl_setopt($chCURLOPT_RETURNTRANSFER1); // (response as string, not output)

        // Make request (synchronous):
        
$sResponse curl_exec($ch);

        
// Check for transport-level errors:
        
$iCurlErrNo     curl_errno($ch);
        
$iHttpRespCode  curl_getinfo($chCURLINFO_HTTP_CODE);
        if (
$iCurlErrNo != 0)
        {
            
curl_close($ch);
            throw new 
TextMarksAPIClientTransportException("TextMarksAPIClient ($sUrl) saw CURL error #$iCurlErrNo: " curl_error($ch), curl_error($ch));
        }
        if (
$iHttpRespCode != 200)
        {
            
curl_close($ch);
            throw new 
TextMarksAPIClientTransportException("TextMarksAPIClient ($sUrl) saw non-200 HTTP response #$iHttpRespCode.", -1);
        }

        
// No obvious transport-level errors. Return response:
        
return $sResponse;
    }

    
/**
     * Execute API call and return XML response.
     *
     * The API Key and auth params are automatically added.
     *
     * @param string              $sMethodName     URL to request by POST.
     * @param map(string,string)  $mssParams       Params for method.
     * @return SimpleXMLElement representing XML response.
     * @throws Exception on error.
     */
    
protected function _callApi$sPackageName$sMethodName$mssParams )
    {
        
// Prep:
        
$mssParamsFull $mssParams// (copy array to keep original clean)
        
$mssParamsFull['apik']      = $this->m_sApiKey;
        
$mssParamsFull['auth_user'] = $this->m_sAuthUser;
        
$mssParamsFull['auth_pass'] = $this->m_sAuthPass;
        
$sUrl self::API_URL_BASE $sPackageName '/' $sMethodName '/';

        
// Make actual HTTP call:
        
$sResp $this->_makeHttpCall$sUrl$mssParamsFull );

        
// Parse and return XML of response:
        
$xml = new SimpleXMLElement($sResp);
        return 
$xml;
    }

    
// -----------------------------------------------------------------------

    
protected $m_sApiKey;
    protected 
$m_sAuthUser;
    protected 
$m_sAuthPass;
}



// ---------------------------------------------------------------------------


/**
 * API Client for "Messaging" package.
 * See:
 *   http://www.textmarks.com/dev/docs/api/
 */
class TextMarksAPIClient_Messaging        extends TextMarksAPIClient
{
    
/**
     * Broadcast an alert to a TextMark's subscribers.
     * See:
     *   http://www.textmarks.com/dev/docs/api/ref/Messaging/postAlert/
     *
     * @param string $sTextMark   Keyword to broadcast alert on.
     * @param string $sMessage    Message to send.
     * @throws Exception on error.
     */
    
public function postAlert$sTextMark$sMessage )
    {
        
// Call API:
        
$xmlResp $this->_callApi('Messaging''postAlert', array(
            
'tm'     => $sTextMark,
            
'msg'    => $sMessage,
            ));

        
// Check API response code:
        
$iResCode = (int) $xmlResp->TMHead->ResCode;
        
$sResMsg  $xmlResp->TMHead->ResMsg;
        if (
$iResCode != 0)
        {
            throw new 
TextMarksAPIClientException("TextMarksAPIClient_Messaging.postAlert got API error #$iResCode: $sResMsg"$iResCode);
        }
    }

    
/**
     * Send a text message to a single TextMark subscriber.
     * See:
     *   http://www.textmarks.com/dev/docs/api/ref/Messaging/sendText/
     *
     * @param string $sTextMark   Keyword the message is associated with.
     * @param string $sTo         Phone#/username to send to (must be $sTextMark subscriber).
     * @param string $sMessage    Message to send.
     * @throws Exception on error.
     */
    
public function sendText$sTextMark$sTo$sMessage )
    {
        
// Call API:
        
$xmlResp $this->_callApi('Messaging''sendText', array(
            
'tm'     => $sTextMark,
            
'to'     => $sTo,
            
'msg'    => $sMessage,
            ));

        
// Check API response code:
        
$iResCode = (int) $xmlResp->TMHead->ResCode;
        
$sResMsg  $xmlResp->TMHead->ResMsg;
        if (
$iResCode != 0)
        {
            throw new 
TextMarksAPIClientException("TextMarksAPIClient_Messaging.sendText got API error #$iResCode: $sResMsg"$iResCode);
        }
    }

    
/**
     * Attempt to subscribe phone# to TextMark.
     * See:
     *   http://www.textmarks.com/dev/docs/api/ref/Messaging/subscribe/
     *
     * @param string $sTextMark   Keyword to subscribe to.
     * @param string $sPhone      Phone# to subscribe.
     * @throws Exception on error.
     */
    
public function subscribe$sTextMark$sPhone )
    {
        
// Call API:
        
$xmlResp $this->_callApi('Messaging''subscribe', array(
            
'tm'     => $sTextMark,
            
'phone'  => $sPhone,
            ));

        
// Check API response code:
        
$iResCode = (int) $xmlResp->TMHead->ResCode;
        
$sResMsg  $xmlResp->TMHead->ResMsg;
        if (
$iResCode != 0)
        {
            throw new 
TextMarksAPIClientException("TextMarksAPIClient_Messaging.subscribe got API error #$iResCode: $sResMsg"$iResCode);
        }
    }
}



// ---------------------------------------------------------------------------


/**
 * Example code to demonstrate how you might call the API.
 */
function exampleTextMarksUsage()
{
    try
    {
        
// Try to subscribe a user to a TextMark:
        
$sMyApiKey        'MyAPIKEY_12345678';
        
$sMyTextMarksUser 'mytmuser'// (or my TextMarks phone#)
        
$sMyTextMarksPass 'mytmp@$$word';
        
$sKeyword         'MYKEYWORD';
        
$sPhone           '4155551212';
        
$tmapi = new TextMarksAPIClient_Messaging($sMyApiKey$sMyTextMarksUser$sMyTextMarksPass);
        
$tmapi->subscribe($sKeyword$sPhone);
        echo 
"<h2>Success! Subscription pending.</h2>";

        
// Try to post an alert to a TextMark:
        
$sMyApiKey        'MyAPIKEY_12345678';
        
$sMyTextMarksUser 'mytmuser'// (or my TextMarks phone#)
        
$sMyTextMarksPass 'mytmp@$$word';
        
$sKeyword         'MYKEYWORD';
        
$sMessage         "This is an alert sent from the PHP API Client. Did it work?";
        
$tmapi = new TextMarksAPIClient_Messaging($sMyApiKey$sMyTextMarksUser$sMyTextMarksPass);
        
$tmapi->postAlert($sKeyword$sMessage);
        echo 
"<h2>Success! Alert sent.</h2>";

        
// Try to send a message to a user:
        
$sMyApiKey        'MyAPIKEY_12345678';
        
$sMyTextMarksUser 'mytmuser'// (or my TextMarks phone#)
        
$sMyTextMarksPass 'mytmp@$$word';
        
$sKeyword         'MYKEYWORD';
        
$sMessage         "This is a message sent from the PHP API Client. Did it work?";
        
$sTo              "415-555-1212";
        
$tmapi = new TextMarksAPIClient_Messaging($sMyApiKey$sMyTextMarksUser$sMyTextMarksPass);
        
$tmapi->sendText($sKeyword$sTo$sMessage);
        echo 
"<h2>Success! Alert sent.</h2>";
    }
    catch (
Exception $e)
    {
        echo 
"Whoops... Exception caught: " $e;
    }
}

?>