Permalink
Browse files

added PubNub PHP Rackspace compatible API which uses CURL rather than…

… Stream Contexts: fix provided by Thiago Vaz Dias
  • Loading branch information...
1 parent feec06a commit 5bf894f84470286028ec35f19df9ba099ed2286d @stephenlb stephenlb committed Nov 3, 2011
Showing with 487 additions and 0 deletions.
  1. +247 −0 php-rackspace/Pubnub.php
  2. +83 −0 php-rackspace/README
  3. +157 −0 php-rackspace/unit-test.php
View
247 php-rackspace/Pubnub.php
@@ -0,0 +1,247 @@
+<?php
+
+/**
+ * PubNub 3.0 Real-time Push Cloud API
+ *
+ * @author Stephen Blum
+ * @package Pubnub
+ */
+class Pubnub {
+ private $ORIGIN = 'pubsub.pubnub.com';
+ private $LIMIT = 1800;
+ private $PUBLISH_KEY = 'demo';
+ private $SUBSCRIBE_KEY = 'demo';
+ private $SECRET_KEY = false;
+ private $SSL = false;
+
+ /**
+ * Pubnub
+ *
+ * Init the Pubnub Client API
+ *
+ * @param string $publish_key required key to send messages.
+ * @param string $subscribe_key required key to receive messages.
+ * @param string $secret_key optional key to sign messages.
+ * @param string $origin optional setting for cloud origin.
+ * @param boolean $ssl required for 2048 bit encrypted messages.
+ */
+ function Pubnub(
+ $publish_key = 'demo',
+ $subscribe_key = 'demo',
+ $secret_key = false,
+ $ssl = false,
+ $origin = false
+ ) {
+ $this->PUBLISH_KEY = $publish_key;
+ $this->SUBSCRIBE_KEY = $subscribe_key;
+ $this->SECRET_KEY = $secret_key;
+ $this->SSL = $ssl;
+
+ if ($origin) $this->ORIGIN = $origin;
+
+ if ($ssl) $this->ORIGIN = 'https://' . $this->ORIGIN;
+ else $this->ORIGIN = 'http://' . $this->ORIGIN;
+ }
+
+ /**
+ * Publish
+ *
+ * Send a message to a channel.
+ *
+ * @param array $args with channel and message.
+ * @return array success information.
+ */
+ function publish($args) {
+ ## Fail if bad input.
+ if (!($args['channel'] && $args['message'])) {
+ echo('Missing Channel or Message');
+ return false;
+ }
+
+ ## Capture User Input
+ $channel = $args['channel'];
+ $message = json_encode($args['message']);
+
+ ## Generate String to Sign
+ $string_to_sign = implode( '/', array(
+ $this->PUBLISH_KEY,
+ $this->SUBSCRIBE_KEY,
+ $this->SECRET_KEY,
+ $channel,
+ $message
+ ) );
+
+ ## Sign Message
+ $signature = $this->SECRET_KEY ? md5($string_to_sign) : '0';
+
+ ## Fail if message too long.
+ if (strlen($message) > $this->LIMIT) {
+ echo('Message TOO LONG (' . $this->LIMIT . ' LIMIT)');
+ return array( 0, 'Message Too Long.' );
+ }
+
+ ## Send Message
+ return $this->_request(array(
+ 'publish',
+ $this->PUBLISH_KEY,
+ $this->SUBSCRIBE_KEY,
+ $signature,
+ $channel,
+ '0',
+ $message
+ ));
+ }
+
+ /**
+ * Subscribe
+ *
+ * This is BLOCKING.
+ * Listen for a message on a channel.
+ *
+ * @param array $args with channel and message.
+ * @return mixed false on fail, array on success.
+ */
+ function subscribe($args) {
+ ## Capture User Input
+ $channel = $args['channel'];
+ $callback = $args['callback'];
+ $timetoken = isset($args['timetoken']) ? $args['timetoken'] : '0';
+
+ ## Fail if missing channel
+ if (!$channel) {
+ echo("Missing Channel.\n");
+ return false;
+ }
+
+ ## Fail if missing callback
+ if (!$callback) {
+ echo("Missing Callback.\n");
+ return false;
+ }
+
+ ## Begin Recusive Subscribe
+ try {
+ ## Wait for Message
+ $response = $this->_request(array(
+ 'subscribe',
+ $this->SUBSCRIBE_KEY,
+ $channel,
+ '0',
+ $timetoken
+ ));
+
+ $messages = $response[0];
+ $args['timetoken'] = $response[1];
+
+ ## If it was a timeout
+ if (!count($messages)) {
+ return $this->subscribe($args);
+ }
+
+ ## Run user Callback and Reconnect if user permits.
+ foreach ($messages as $message) {
+ if (!$callback($message)) return;
+ }
+
+ ## Keep Listening.
+ return $this->subscribe($args);
+ }
+ catch (Exception $error) {
+ sleep(1);
+ return $this->subscribe($args);
+ }
+ }
+
+ /**
+ * History
+ *
+ * Load history from a channel.
+ *
+ * @param array $args with 'channel' and 'limit'.
+ * @return mixed false on fail, array on success.
+ */
+ function history($args) {
+ ## Capture User Input
+ $limit = +$args['limit'] ? +$args['limit'] : 10;
+ $channel = $args['channel'];
+
+ ## Fail if bad input.
+ if (!$channel) {
+ echo('Missing Channel');
+ return false;
+ }
+
+ ## Get History
+ return $this->_request(array(
+ 'history',
+ $this->SUBSCRIBE_KEY,
+ $channel,
+ '0',
+ $limit
+ ));
+ }
+
+ /**
+ * Time
+ *
+ * Timestamp from PubNub Cloud.
+ *
+ * @return int timestamp.
+ */
+ function time() {
+ ## Get History
+ $response = $this->_request(array(
+ 'time',
+ '0'
+ ));
+
+ return $response[0];
+ }
+
+ /**
+ * Request URL
+ *
+ * @param array $request of url directories.
+ * @return array from JSON response.
+ */
+ private function _request($request) {
+ $request = array_map( 'Pubnub::_encode', $request );
+ array_unshift( $request, $this->ORIGIN );
+
+ $url = implode( '/', $request );
+ $ch = curl_init($url);
+
+ curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
+ $result = curl_exec($ch);
+ curl_close($ch);
+
+ return json_decode( $result, true );
+ }
+
+ /**
+ * Encode
+ *
+ * @param string $part of url directories.
+ * @return string encoded string.
+ */
+ private static function _encode($part) {
+ return implode( '', array_map(
+ 'Pubnub::_encode_char', str_split($part)
+ ) );
+ }
+
+ /**
+ * Encode Char
+ *
+ * @param string $char val.
+ * @return string encoded char.
+ */
+ private static function _encode_char($char) {
+ if (strpos( ' ~`!@#$%^&*()+=[]\\{}|;\':",./<>?', $char ) === false)
+ return $char;
+ return rawurlencode($char);
+ }
+}
+
+
+?>
View
83 php-rackspace/README
@@ -0,0 +1,83 @@
+## ----------------------------------------------------
+##
+## YOU MUST HAVE A PUBNUB ACCOUNT TO USE THE API.
+## http://www.pubnub.com/account
+##
+## ----------------------------------------------------
+
+## ----------------------------------------------------
+## PubNub 3.0 Real-time Cloud Push API - PHP Rackspace
+## ----------------------------------------------------
+##
+## This version of PHP provides Rackspace Support
+## using CURL rather than PHP Stream Contexts.
+##
+## ----------------------------------------------------
+## www.pubnub.com - PubNub Real-time Push Service in the Cloud.
+## http://www.pubnub.com/blog/php-push-api-walkthrough
+##
+## PubNub is a Massively Scalable Real-time Service for Web and Mobile Games.
+## This is a cloud-based service for broadcasting Real-time messages
+## to thousands of web and mobile clients simultaneously.
+
+## ------------
+## PHP Push API
+## ------------
+$pubnub = new Pubnub(
+ "demo", ## PUBLISH_KEY
+ "demo", ## SUBSCRIBE_KEY
+ "", ## SECRET_KEY
+ false ## SSL_ON?
+ false ## CUSTOM ORIGIN
+);
+
+## ----------------------
+## Send Message (PUBLISH)
+## ----------------------
+$info = $pubnub->publish(array(
+ 'channel' => 'hello_world', ## REQUIRED Channel to Send
+ 'message' => 'Hey World!' ## REQUIRED Message String/Array
+));
+var_dump($info);
+
+## --------------------------
+## Request Messages (HISTORY)
+## --------------------------
+$messages = $pubnub->history(array(
+ 'channel' => 'hello_world', ## REQUIRED Channel to Send
+ 'limit' => 100 ## OPTIONAL Limit Number of Messages
+));
+var_dump($messages); ## Prints array of messages.
+
+## --------------------------
+## Request Server Time (TIME)
+## --------------------------
+$timestamp = $pubnub->time();
+var_dump($timestamp); ## Prints integer timestamp.
+
+## ----------------------------------
+## PHP 5.2.0. THIS WILL BLOCK!!!
+## Receive Message (SUBSCRIBE)
+## THIS WILL BLOCK. PHP 5.2.0
+## ----------------------------------
+$pubnub->subscribe(array(
+ 'channel' => 'hello_world', ## REQUIRED Channel to Listen
+ 'callback' => create_function( ## REQUIRED PHP 5.2.0 Method
+ '$message',
+ 'var_dump($message); return true;'
+ )
+));
+
+
+## ----------------------------------
+## PHP 5.3.0 ONLY. THIS WILL BLOCK!!!
+## Receive Message (SUBSCRIBE)
+## THIS WILL BLOCK. PHP 5.3.0 ONLY!!!
+## ----------------------------------
+$pubnub->subscribe(array(
+ 'channel' => 'hello_world', ## REQUIRED Channel to Listen
+ 'callback' => function($message) { ## REQUIRED Callback With Response
+ var_dump($message); ## Print Message
+ return true; ## Keep listening (return false to stop)
+ }
+));
View
157 php-rackspace/unit-test.php
@@ -0,0 +1,157 @@
+<?php
+
+require_once('Pubnub.php');
+
+## ---------------------------------------------------------------------------
+## USAGE:
+## ---------------------------------------------------------------------------
+#
+# php ./unit-test.php
+# php ./unit-test.php [PUB-KEY] [SUB-KEY] [SECRET-KEY] [USE SSL]
+#
+
+
+## Capture Publish and Subscribe Keys from Command Line
+$publish_key = isset($argv[1]) ? $argv[1] : 'demo';
+$subscribe_key = isset($argv[2]) ? $argv[2] : 'demo';
+$secret_key = isset($argv[3]) ? $argv[3] : false;
+$ssl_on = isset($argv[4]);
+
+## ---------------------------------------------------------------------------
+## Create Pubnub Object
+## ---------------------------------------------------------------------------
+$pubnub = new Pubnub( $publish_key, $subscribe_key, $secret_key, $ssl_on );
+
+## ---------------------------------------------------------------------------
+## Generate Random Channel Name
+## ---------------------------------------------------------------------------
+$channel = 'unit-test-' . rand( 0, 100000000 ) . rand( 0, 100000000 );
+
+
+## ---------------------------------------------------------------------------
+## Get History Part 1
+## ---------------------------------------------------------------------------
+$history = $pubnub->history(array(
+ 'channel' => $channel,
+ 'limit' => 1
+));
+test( count($history), 0, 'Initial Empty History' );
+
+
+## ---------------------------------------------------------------------------
+## PUBLISH
+## ---------------------------------------------------------------------------
+$pubish_success = $pubnub->publish(array(
+ 'channel' => $channel,
+ 'message' => 'Hi. (顶顅Ȓ)'
+));
+test( $pubish_success[0], 1, 'Publish First Message' );
+
+
+## ---------------------------------------------------------------------------
+## Get History Part 2
+## ---------------------------------------------------------------------------
+$history = $pubnub->history(array(
+ 'channel' => $channel,
+ 'limit' => 1
+));
+test( count($history), 1, 'History With 1 Item' );
+test( $history[0], 'Hi. (顶顅Ȓ)', 'History Message Text == "Hi. (顶顅Ȓ)"' );
+
+
+## ---------------------------------------------------------------------------
+## PUBLISH 2
+## ---------------------------------------------------------------------------
+$pubish_success = $pubnub->publish(array(
+ 'channel' => $channel,
+ 'message' => 'Hi Again.'
+));
+test( $pubish_success[0], 1, 'Publish Second Message' );
+
+
+## ---------------------------------------------------------------------------
+## Get History Part 3
+## ---------------------------------------------------------------------------
+$history = $pubnub->history(array(
+ 'channel' => $channel,
+ 'limit' => 1
+));
+test( count($history), 1, 'History With 2 Items Limit 1' );
+test( $history[0], 'Hi Again.', 'History Message is Text == "Hi Again."' );
+
+$history = $pubnub->history(array(
+ 'channel' => $channel,
+ 'limit' => 2
+));
+test( count($history), 2, 'History With 2 Item Limit 2' );
+test( $history[0], 'Hi. (顶顅Ȓ)', 'History Message Text == "Hi. (顶顅Ȓ)"' );
+test( $history[1], 'Hi Again.', 'History Message is Text == "Hi Again."' );
+
+## ---------------------------------------------------------------------------
+## Test Timestamp API
+## ---------------------------------------------------------------------------
+$timestamp = $pubnub->time();
+test( $timestamp, true, 'Timestamp API Test: ' . $timestamp );
+
+
+## ---------------------------------------------------------------------------
+## PUBLISH Special Characters
+## ---------------------------------------------------------------------------
+$craziness = 'crazy -> ~!@#$%^&*()_+`-=\\][{}\'";:,./<>?顶頴ģŃՃ';
+$pubish_success = $pubnub->publish(array(
+ 'channel' => $craziness,
+ 'message' => $craziness
+));
+test( $pubish_success[0], 1, 'Publish Crazy Channel/Message' );
+
+$history = $pubnub->history(array(
+ 'channel' => $craziness,
+ 'limit' => 1
+));
+test( count($history), 1, 'History With 3 Items Limit 1' );
+test( $history[0], $craziness, 'History Message is Crazy' );
+
+
+## ---------------------------------------------------------------------------
+## Test Subscribe
+## ---------------------------------------------------------------------------
+$message = 1234;
+
+## Generate String to Sign
+$string_to_sign = implode( '/', array(
+ $publish_key,
+ $subscribe_key,
+ $secret_key,
+ $channel,
+ $message
+) );
+$signature = $secret_key ? md5($string_to_sign) : '0';
+$pubsub_url_test = "http://pubsub.pubnub.com/publish/" .
+ $publish_key . "/" .
+ $subscribe_key . "/" .
+ $signature . "/" .
+ $channel . "/0/" . $message;
+
+echo("\nHIT THIS URL to CONTINUE -> $pubsub_url_test");
+echo("\n\nHit CTRL+C to finish.");
+echo("\nYou may continue reloading the URL to keep testing.\n\n");
+$pubnub->subscribe(array(
+ 'channel' => $channel,
+ 'callback' => function($message) {
+ test( $message, 1234, 'Subscribe: ' . $message );
+ return true;
+ }
+));
+
+
+
+## ---------------------------------------------------------------------------
+## Unit Test Function
+## ---------------------------------------------------------------------------
+function test( $val1, $val2, $name ) {
+ if ($val1 == $val2) echo('PASS: ');
+ else echo('FAIL: ');
+ echo("$name\n");
+}
+?>
+

0 comments on commit 5bf894f

Please sign in to comment.