You are here

function CMBase::makeCall in Campaign Monitor 5.2

Same name and namespace in other branches
  1. 6.3 lib/CMBase.php \CMBase::makeCall()
  2. 6.2 lib/CMBase.php \CMBase::makeCall()

* The direct way to make an API call. This allows developers to include new API * methods that might not yet have a wrapper method as part of the package. * *

Parameters

string $action The API call.: * @param array $options An associative array of values to send as part of the request. * @return array The parsed XML of the request.

22 calls to CMBase::makeCall()
CampaignMonitor::campaignCreate in lib/CMBase.php
*
CampaignMonitor::campaignGeneric in lib/CMBase.php
* A generic wrapper to feed Campaign.* calls. * *
CampaignMonitor::campaignSend in lib/CMBase.php
*
CampaignMonitor::clientCreate in lib/CMBase.php
*
CampaignMonitor::clientGeneric in lib/CMBase.php

... See full list

File

lib/CMBase.php, line 121

Class

CMBase

Code

function makeCall($action = '', $options = array()) {

  // NEW [2008-06-24]: switch to soap automatically for these calls
  $old_method = $this->method;
  if ($action == 'Subscriber.AddWithCustomFields' || $action == 'Subscriber.AddAndResubscribeWithCustomFields' || $action == 'Campaign.Create') {
    $this->method = 'soap';
  }
  if (!$action) {
    return null;
  }
  $url = $this->url;

  // DONE: like facebook's client, allow for get/post through the file wrappers
  // if curl isn't available. (or maybe have curl-emulating functions defined
  // at the bottom of this script.)

  //$ch = curl_init();
  if (!isset($options['header'])) {
    $options['header'] = array();
  }
  $options['header'][] = 'User-Agent: CMBase URL Handler 1.5';
  $postdata = '';
  $method = 'GET';
  if ($this->method == 'soap') {
    $options['header'][] = 'Content-Type: text/xml; charset=utf-8';
    $options['header'][] = 'SOAPAction: "' . $this->soapAction . $action . '"';
    $postdata = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
    $postdata .= "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"";
    $postdata .= " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"";
    $postdata .= " xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n";
    $postdata .= "<soap:Body>\n";
    $postdata .= "\t<{$action} xmlns=\"{$this->soapAction}\">\n";
    $postdata .= "\t\t<ApiKey>{$this->api}</ApiKey>\n";
    if (isset($options['params'])) {
      $postdata .= array2xml($options['params'], "\t\t");
    }
    $postdata .= "\t</{$action}>\n";
    $postdata .= "</soap:Body>\n";
    $postdata .= "</soap:Envelope>";
    $method = 'POST';

    //curl_setopt( $ch, CURLOPT_POST, 1 );

    //curl_setopt( $ch, CURLOPT_POSTFIELDS, $postdata );
  }
  else {
    $postdata = "ApiKey={$this->api}";
    $url .= "/{$action}";

    // NOTE: since this is GET, the assumption is that params is a set of simple key-value pairs.
    if (isset($options['params'])) {
      foreach ($options['params'] as $k => $v) {
        $postdata .= '&' . $k . '=' . rawurlencode(utf8_encode($v));
      }
    }
    if ($this->method == 'get') {
      $url .= '?' . $postdata;
      $postdata = '';
    }
    else {
      $options['header'][] = 'Content-Type: application/x-www-form-urlencoded';
      $method = 'POST';

      //curl_setopt( $ch, CURLOPT_POST, 1 );

      //curl_setopt( $ch, CURLOPT_POSTFIELDS, $postdata );
    }
  }
  $res = '';

  // WARNING: using fopen() does not recognize stream contexts in PHP 4.x, so
  // my guess is using fopen() in PHP 4.x implies that POST is not supported
  // (otherwise, how do you tell fopen() to use POST?). tried fsockopen(), but
  // response time was terrible. if someone has more experience with working
  // directly with streams, please troubleshoot that.
  // NOTE: fsockopen() needs a small timeout to force the socket to close.
  // it's defined in SOCKET_TIMEOUT.
  // preferred method is curl, only if it exists and $this->curl is true.
  if ($this->curl && $this->curlExists) {
    $ch = curl_init();
    if ($this->method != 'get') {
      curl_setopt($ch, CURLOPT_POST, 1);
      curl_setopt($ch, CURLOPT_POSTFIELDS, $postdata);
    }
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $options['header']);
    curl_setopt($ch, CURLOPT_HEADER, $this->show_response_headers);

    // except for the response, all other information will be stored when debugging is on.
    $res = curl_exec($ch);
    if ($this->debug_level) {
      $this->debug_url = $url;
      $this->debug_request = $postdata;
      $this->debug_info = curl_getinfo($ch);
      $this->debug_info['headers_sent'] = $options['header'];
    }
    $this->debug_response = $res;
    curl_close($ch);
  }
  else {

    // 'header' is actually the entire HTTP payload. as such, you need
    // Content-Length header, otherwise you'll get errors returned/emitted.
    $postLen = strlen($postdata);
    $ctx = array(
      'method' => $method,
      'header' => implode("\n", $options['header']) . "\nContent-Length: " . $postLen . "\n\n" . $postdata,
    );
    if ($this->debug_level) {
      $this->debug_url = $url;
      $this->debug_request = $postdata;
      $this->debug_info['overview'] = 'Used stream_context_create()/fopen() to make request. Content length=' . $postLen;
      $this->debug_info['headers_sent'] = $options['header'];

      //$this->debug_info['complete_content'] = $ctx;
    }
    $pv = PHPVER;

    // the preferred non-cURL way if user is using PHP 5.x
    if ($pv[0] == '5') {
      $context = stream_context_create(array(
        'http' => $ctx,
      ));
      $fp = fopen($url, 'r', false, $context);
      ob_start();
      fpassthru($fp);
      fclose($fp);
      $res = ob_get_clean();
    }
    else {

      // this should work with PHP 4, but it seems to take forever to get data back this way
      // NOTE: setting the default_socket_timeout seems to alleviate this issue [finally].
      list($protocol, $url) = explode('//', $url, 2);
      list($domain, $path) = explode('/', $url, 2);
      $fp = fsockopen($domain, 80, $tvar, $tvar2, SOCKET_TIMEOUT);
      if ($fp) {
        $payload = "{$method} /{$path} HTTP/1.1\n" . "Host: {$domain}\n" . $ctx['header'];
        fwrite($fp, $payload);

        // even with the socket timeout set, using fgets() isn't playing nice, but
        // fpassthru() seems to be doing the right thing.
        ob_start();
        fpassthru($fp);
        list($headers, $res) = explode("\r\n\r\n", ob_get_clean(), 2);
        if ($this->debug_level) {
          $this->debug_info['headers_received'] = $headers;
        }
        fclose($fp);
      }
      elseif ($this->debug_level) {
        $this->debug_info['overview'] .= "\nOpening {$domain}/{$path} failed!";
      }
    }
  }

  //$this->method = $old_method;
  if ($res) {
    if ($this->method == 'soap') {
      $tmp = xml2array($res, '/soap:Envelope/soap:Body');
      if (!is_array($tmp)) {
        return $tmp;
      }
      else {
        return $tmp[$action . 'Response'][$action . 'Result'];
      }
    }
    else {
      return xml2array($res);
    }
  }
  else {
    return null;
  }
}