PHP Reference Application

The following code provides a working demonstration of a sample client application utilizing the TubeMogul Upload API. It is written for PHP 5.2.x or higher.

NOTE: This app uses the Partner Auth method for authenticating, but it can be adjusted to use the Standard Auth method as well.

The contents of each file shown below should be saved into the same directory. Then, be sure to read the instruction comments at the start of the upload-api-test.php file about creating a upload-api-test-config.php config file.

The application can be run by executing the following command at the command line:
    php upload-api-test.php


upload-api-test.php


#!/usr/bin/php
<?php

/*
 * ----------------------------------------------
 * TubeMogul Upload API PHP Reference Application
 * ----------------------------------------------
 *
 * Create a file named upload-api-test-config.php with the following
 * entries, filled in to match the values you receive from TubeMogul:
 *
 *     $apiUrl = 'http://api-upload.tubemogul.com/index.php';
 *     $partnerID = '';
 *     $secretKey = '';
 *     $userToken = '';
 *
 * Provide info about a test video to upload:
 *
 *     $title = '';
 *     $tags = '';
 *     $description = '';
 *     $videoFile = ''; // file path
 *
 * To test stats, if you have an upload already with stats:
 *     $existingUploadId = 0;
 */

require_once 'class.TubeMogulApi.php';
require_once 'class.TubeMogulUploadApi.php';
require_once 'upload-api-test-config.php';

$version = '1.0.0';
$api = new TubeMogulUploadApi($apiUrl, $partnerID, $secretKey,
        $userToken);

//////////////////////////////////////////////////////
// listCategories

$result = $api->listCategories();
echoResult($result);
if (!$result['success']) {
    exit(2);
}
$xml = new SimpleXMLElement($result['data']);
$categories = array();
foreach ($xml->categories->category as $category) {
    $category = $category->attributes()->value . '';
    if ((strlen($category) == 0) || (!ctype_digit($category))) {
        exit(2);
    }
    $categories[] = $category;
}
$category = $categories[rand(0, count($categories) - 1)];
echoMessage("Selected Category:\t" . $category);

//////////////////////////////////////////////////////
// listAvailableSites

$result = $api->listAvailableSites();
echoResult($result);
if (!$result['success']) {
    exit(2);
}
$xml = new SimpleXMLElement($result['data']);
$siteIds = array();
foreach ($xml->sites->site as $site) {
    $siteId = $site->siteid . '';
    if ((strlen($siteId) == 0) || (!ctype_digit($siteId))) {
        exit(2);
    }
    $siteIds[] = $siteId;
}
$siteId = $siteIds[rand(0, count($siteIds) - 1)];
echoMessage("Selected Site ID:\t" . $siteId);

//////////////////////////////////////////////////////
// uploadVideo

// add a random suffix just for testing:
$title .= ' (' . time() . '-' . rand() . ')';
$params = array('title' => $title, 'tags' => $tags, 'description' =>
        $description, 'category' => $category, 'file' => $videoFile);
echoMessage('Upload STARTING at ' . date('Y-m-d H:i:s', time()));
$result = $api->uploadVideo($params);
echoMessage('Upload FINISHED at ' . date('Y-m-d H:i:s', time()));
echoResult($result);
if (!$result['success']) {
    exit(2);
}
$xml = new SimpleXMLElement($result['data']);
$newUploadId = $xml->uploadid . '';
echoMessage("New Upload ID:\t" . $newUploadId);

//////////////////////////////////////////////////////
// listUploads

$params = array('page' => 1, perPage => '10');
$result = $api->listUploads($params);
echoResult($result);
if (!$result['success']) {
    exit(2);
}
$xml = new SimpleXMLElement($result['data']);
$uploadsCount = $xml->uploads['count'];
echoMessage("Total Uploads:\t" . $uploadsCount);
if ($newUploadId != $xml->uploads->upload[0]->uploadid) {
    echoMessage("Did not find new Upload ID:\t" . $newUploadId);
    exit(2);
}
echoMessage("Found new Upload ID:\t" . $newUploadId);

//////////////////////////////////////////////////////
// launchVideo

$params = array('uploadid' => $newUploadId, 'title' => $title, 'tags' =>
        $tags, 'description' => $description, 'category' => $category,
        'siteid' => $siteId);
$result = $api->launchVideo($params);
echoResult($result);
if (!$result['success']) {
    exit(2);
}
echoMessage("Launched Upload ID " . $newUploadId . " to Site ID " .
        $siteId . ".");

//////////////////////////////////////////////////////
// getVideoStatus

$params = array('uploadid' => $newUploadId);
$result = $api->getVideoStatus($params);
echoResult($result);
if (!$result['success']) {
    exit(2);
}
$xml = new SimpleXMLElement($result['data']);
if ($siteId != $xml->sites->site[0]->siteid) {
    echoMessage("Did not find status for Upload ID " . $newUploadId .
            " on newly launched Site ID " . $siteId . ".");
    exit(2);
}
echoMessage("Found status " . $xml->sites->site[0]->status . " (" .
        $xml->sites->site[0]->message . ") for Upload ID " .
        $newUploadId . " on newly launched Site ID " . $siteId . ".");

//////////////////////////////////////////////////////
// getVideoStatus

if ($existingUploadId == 0) {
    echoMessage("Test completed successfully without existing upload ID tests.");
    exit(0);
}

$params = array('uploadid' => $existingUploadId);
$result = $api->getVideoStatus($params);
echoResult($result);
if (!$result['success']) {
    exit(2);
}
$xml = new SimpleXMLElement($result['data']);
$sitesCount = $xml->sites['count'];
if (empty($sitesCount)) {
    echoMessage("Did not find any statuses for existing Upload ID " .
            $existingUploadId . ".");
    exit(2);
}
echoMessage("Found " . $sitesCount .
        " statuses for existing Upload ID " . $existingUploadId . ".");

//////////////////////////////////////////////////////
// listUploadVideoStats

$params = array('uploadid' => $existingUploadId);
$result = $api->listUploadVideoStats($params);
echoResult($result);
if (!$result['success']) {
    exit(2);
}
$xml = new SimpleXMLElement($result['data']);
$sitesCount = count($xml->video->site);
if (empty($sitesCount)) {
    echoMessage("Did not find any stats for existing Upload ID " .
            $existingUploadId . ".");
    exit(2);
}
echoMessage("Found stats on " . $sitesCount .
        " sites for existing Upload ID " . $existingUploadId . ".");

echoMessage("Test completed successfully with existing upload ID tests.");

//////////////////////////////////////////////////////
// Local Script Functions:

function echoResult($result) {
    $message = "METHOD:\t" . $result['method'] . " (Time: " .
            $result['info']['total_time'] . ")\t" .
            ($result['success'] ? 'SUCCESS' : 'ERROR') . "\n\n";
    $message .= "URL:\t\t" . $result['url'] . "\n";
    $message .= "POST DATA:\t" . ((is_array($result['postdata'])) ?
            print_r($result['postdata'], true) . "\n" :
            $result['postdata'] . "\n\n");
    $message .= print_r($result['info'], true) . "\n";
    if (isset($result['exception'])) {
        $message .= "EXCEPTION:\n" .
                $result['exception']->__toString() . "\n\n";
    }
    $message .= "RESPONSE: (Length: " . strlen($result['data']) .
            ")\n" . $result['data'];
    echoMessage($message);
}

function echoMessage($message) {
    echo $message . "\n\n\n";
}

?>



class.TubeMogulUploadApi.php


<?php

class TubeMogulUploadApi extends TubeMogulApi {

    private $version = '1.0.0';
    private $userToken;

    /**
     * Constructor for an instance of the TubeMogul API.
     *
     * @param apiUrl  URL to the TubeMogul API.
     *         Typically: http://api-upload.tubemogul.com/index.php
     * @param partnerID  Your TubeMogul partner ID provided by
     *         TubeMogul.
     * @param secretKey  Your TubeMogul partner secret key provided by
     *         TubeMogul.
     * @param userToken  The user token for the TubeMogul API user on
     *         whose behalf you are using the API.
     */
    public function __construct($apiUrl, $partnerID, $secretKey,
            $userToken) {
        $this->apiUrl = $apiUrl;
        $this->partnerID = $partnerID;
        $this->secretKey = $secretKey;
        $this->userToken = $userToken;
    }

    /**
     * No parameters are required for this call.
     */
    public function listCategories() {
        $method = 'listCategories';
        $postString = $this->getBasePostString($method);
        $postString = $this->getAuthorizedPostString($postString);
        $result = $this->submitRequest($postString, $method);
        return $result;
    }

    /**
     * No parameters are required for this call.
     */
    public function listAvailableSites() {
        $method = 'listAvailableSites';
        $postString = $this->getBasePostString($method);
        $postString = $this->getAuthorizedPostString($postString);
        $result = $this->submitRequest($postString, $method);
        return $result;
    }

    /**
     * This call conveniently calls the whichHost and uploadVideo API
     * methods in one step.
     *
     * The params array should contain the following keys/values:
     *
     * title (string) - Required
     *         The title of the video.
     * tags (comma-delimited string) - Required
     *         The tags of the video.
     * description (string) - Required
     *         The description of the video. (3000 character limit.)
     * category (integer) - Required
     *         The category ID of the video. The available values are
     *         returned by listCategories.
     * file (binary file) - Required
     *         The file.
     */
    public function uploadVideo($params) {
        $whichHostResult = $this->_whichHost();
        if (!$whichHostResult['success']) {
            return $whichHostResult;
        }
        $xml = new SimpleXMLElement($whichHostResult['data']);
        $uploadHost = $xml->host . '';
        $token = $xml->token . '';
        if ((empty($uploadHost)) || (empty($token))) {
            $whichHostResult['success'] = false;
            return $whichHostResult;
        }
        $params['token'] = $token;
        $uploadVideoResult = $this->_uploadVideo($params, $uploadHost);
        return $uploadVideoResult;
    }

    /**
     * NOTE: This method is not required to be used if you use
     * uploadVideo() instead.
     *
     * No parameters are required for this call.
     */
    public function _whichHost() {
        $method = 'whichHost';
        $postString = $this->getBasePostString($method);
        $postString = $this->getAuthorizedPostString($postString);
        $result = $this->submitRequest($postString, $method);
        return $result;
    }

    /**
     * NOTE: This method is not required to be used if you use
     * uploadVideo() instead.
     *
     * The params array should contain the following keys/values:
     *
     * title (string) - Required
     *         The title of the video.
     * tags (comma-delimited string) - Required
     *         The tags of the video.
     * description (string) - Required
     *         The description of the video. (3000 character limit.)
     * category (integer) - Required
     *         The category ID of the video. The available values are
     *         returned by listCategories.
     * token (string) - Required
     *         This value is obtained by calling whichHost.
     * file (binary file) - Required
     *         The file.
     */
    public function _uploadVideo($params, $uploadHost) {
        $method = 'uploadVideo';
        $postArray = $this->getBasePostArray($method);
        $postArray = array_merge($params, $postArray);
        $hashInput = $this->userToken . $method . $this->partnerID .
                time() . $params['title'] . basename($params['file']);
        $hash = $this->getAuthorizationHash($hashInput);
        $postArray['hash'] = $hash;
        // send binary file contents:
        $postArray['file'] = '@' . $postArray['file'];
        $timeout = 120 * 60;
        $uploadUrl = 'http://' . $uploadHost . '/index.php';
        $result = $this->submitRequest($postArray, $method, $timeout,
                $uploadUrl);
        return $result;
    }

    /**
     * The params array should contain the following keys/values:
     *
     * page (integer) - Optional, default is 1
     *         The desired page of results to return.
     * perPage (integer) - Optional, default is 100
     *         Number of items to show per page of results.
     */
    public function listUploads($params = array()) {
        $method = 'listUploads';
        $postArray = $this->getBasePostArray($method);
        $postArray = array_merge($params, $postArray);
        $postString = $this->convertPostArrayToString($postArray);
        $postString = $this->getAuthorizedPostString($postString);
        $result = $this->submitRequest($postString, $method);
        return $result;
    }

    /**
     * The params array should contain the following keys/values:
     *
     * uploadid (integer) - Required
     *         The ID of the uploaded video. This value is returned by
     *         listUploads and uploadVideo.
     * title (string) - Required
     *         The title of the video.
     * tags (comma-delimited string) - Required
     *         The tags of the video.
     * description (string) - Required
     *         The description of the video. (3000 character limit.)
     * category (integer) - Required
     *         The category ID of the video. The available values are
     *         returned by listCategories.
     * siteid (integer) - Required
     *         The ID of the video site to upload to. The available
     *         values are returned by listAvailableSites.
     */
    public function launchVideo($params) {
        $method = 'launchVideo';
        $postArray = $this->getBasePostArray($method);
        $postArray = array_merge($params, $postArray);
        $postString = $this->convertPostArrayToString($postArray);
        $postString = $this->getAuthorizedPostString($postString);
        $result = $this->submitRequest($postString, $method);
        return $result;
    }

    /**
     * The params array should contain the following keys/values:
     *
     * uploadid (integer) - Required
     *         The ID of the uploaded video. This value is returned by
     *         listUploads and uploadVideo.
     */
    public function getVideoStatus($params) {
        $method = 'getVideoStatus';
        $postArray = $this->getBasePostArray($method);
        $postArray = array_merge($params, $postArray);
        $postString = $this->convertPostArrayToString($postArray);
        $postString = $this->getAuthorizedPostString($postString);
        $result = $this->submitRequest($postString, $method);
        return $result;
    }

    /**
     * The params array should contain the following keys/values:
     *
     * uploadid (integer) - Required
     *         The ID of the uploaded video. This value is returned by
     *         listUploads and uploadVideo.
     */
    public function listUploadVideoStats($params) {
        $method = 'listUploadVideoStats';
        $postArray = $this->getBasePostArray($method);
        $postArray = array_merge($params, $postArray);
        $postString = $this->convertPostArrayToString($postArray);
        $postString = $this->getAuthorizedPostString($postString);
        $result = $this->submitRequest($postString, $method);
        return $result;
    }

    protected function getBasePostArray($method) {
        $postArray = parent::getBasePostArray($method);
        $postArray['userToken'] = $this->userToken;
        return $postArray;
    }

}

?>



class.TubeMogulApi.php


<?php

class TubeMogulApi {

    private $version = '1.0.1';
    protected $apiUrl;
    protected $partnerID;
    protected $secretKey;

    protected function getBasePostArray($method) {
        return array('date' => time() . '', 'partnerID' =>
                urlencode($this->partnerID), 'method' =>
                urlencode($method));
    }

    protected function convertPostArrayToString($postArray) {
        $postString = '';
        foreach ($postArray as $key => $value) {
            $postString .= '&' . $key . '=' . urlencode($value);
        }
        return substr($postString, 1);
    }

    protected function getBasePostString($method) {
        return $this->convertPostArrayToString(
                $this->getBasePostArray($method));
    }

    protected function getAuthorizedPostString($postString) {
        return $postString .= '&hash=' . $this->getAuthorizationHash(
                $postString);
    }

    protected function getAuthorizationHash($requestFingerprint) {
        return sha1($this->secretKey . $requestFingerprint);
    }

    protected function submitRequest($postData, $method = 'unspecified',
            $timeoutSecs = 60, $url = null) {
        if ($url == null) {
            $url = $this->apiUrl;
        }
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_HEADER, 0);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($ch, CURLOPT_TIMEOUT, $timeoutSecs);
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
        // Uncomment if you need to use a HTTP proxy:
        //curl_setopt($ch, CURLOPT_PROXYPORT, 8888);
        //curl_setopt($ch, CURLOPT_PROXY, '127.0.0.1');
        $data = curl_exec($ch);
        $info = curl_getinfo($ch);
        $info['errno'] = curl_errno($ch);
        $info['error'] = curl_error($ch);
        curl_close($ch);
        $result = array('data' => $data, 'info' => $info, 'method' =>
                $method, 'url' => $url, 'postdata' => $postData);
        return $this->checkResult($result);
    }

    protected function checkResult($result) {
        try {
            $xml = new SimpleXMLElement($result['data']);
        } catch (Exception $e) {
            $result['success'] = false;
            $result['exception'] = $e;
            return $result;
        }
        $success = ($xml->xpath("//response[@stat='ok']"));
        $result['success'] = $success;
        return $result;
    }

}

?>