You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@shindig.apache.org by ch...@apache.org on 2009/05/10 21:29:38 UTC

svn commit: r773390 - in /incubator/shindig/trunk/php: src/social/converters/ src/social/model/ src/social/sample/ src/social/service/ src/social/spi/ test/social/

Author: chabotc
Date: Sun May 10 19:29:37 2009
New Revision: 773390

URL: http://svn.apache.org/viewvc?rev=773390&view=rev
Log:
Message api change for spec 0.9 patch by Jinhui Du

Added:
    incubator/shindig/trunk/php/src/social/model/MessageCollection.php
    incubator/shindig/trunk/php/src/social/service/HandlerPreconditions.php
    incubator/shindig/trunk/php/test/social/ActivityRestTest.php
    incubator/shindig/trunk/php/test/social/AppDataRestTest.php
    incubator/shindig/trunk/php/test/social/MessageRestTest.php
    incubator/shindig/trunk/php/test/social/RestBase.php
Modified:
    incubator/shindig/trunk/php/src/social/converters/InputBasicXmlConverter.php
    incubator/shindig/trunk/php/src/social/model/Message.php
    incubator/shindig/trunk/php/src/social/sample/JsonDbOpensocialService.php
    incubator/shindig/trunk/php/src/social/service/MessagesHandler.php
    incubator/shindig/trunk/php/src/social/service/RequestItem.php
    incubator/shindig/trunk/php/src/social/service/RestRequestItem.php
    incubator/shindig/trunk/php/src/social/spi/CollectionOptions.php
    incubator/shindig/trunk/php/src/social/spi/MessagesService.php
    incubator/shindig/trunk/php/test/social/JsonDbOpensocialServiceTest.php
    incubator/shindig/trunk/php/test/social/MessageTest.php

Modified: incubator/shindig/trunk/php/src/social/converters/InputBasicXmlConverter.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/social/converters/InputBasicXmlConverter.php?rev=773390&r1=773389&r2=773390&view=diff
==============================================================================
--- incubator/shindig/trunk/php/src/social/converters/InputBasicXmlConverter.php (original)
+++ incubator/shindig/trunk/php/src/social/converters/InputBasicXmlConverter.php Sun May 10 19:29:37 2009
@@ -58,22 +58,78 @@
   }
 
   public static function convertMessages($requestParam, $xml, $content) {
+    // As only message handler has the context to know whether it's a message or a message
+    // collection request. All the fields for both the Message and the MessageCollection
+    // classes are converted here. Message handler has the responsibility to validate the
+    // params.
     $message = array();
-    if (! isset($xml->title) || ! isset($content)) {
-      throw new Exception("Invalid message structure");
+    if (isset($xml->id)) {
+      $message['id'] = trim($xml->id);
     }
-    $message['id'] = isset($xml->id) ? trim($xml->id) : null;
-    $message['title'] = trim($xml->title);
-    $message['body'] = trim($content);
-    // retrieve recipients by looking at the osapi name space
-    $xml = self::loadString($requestParam, "http://opensocial.org/2008/opensocialapi");
-    if (! isset($xml->recipient)) {
-      throw new Exception("Invalid message structure");
-    }
-    $message['recipients'] = array();
-    foreach ($xml->recipient as $recipient) {
-      $message['recipients'][] = trim($recipient);
+    if (isset($xml->title)) {
+      $message['title'] = trim($xml->title);
     }
+    if (!empty($content)) {
+      $message['body'] = trim($content);
+    }
+    if (isset($xml->bodyId)) {
+      $meesage['bodyId'] = trim($xml->bodyId);
+    }
+    if (isset($xml->titleId)) {
+      $message['titleId'] = trim($xml->titleId);
+    }
+    if (isset($xml->appUrl)) {
+      $message['appUrl'] = trim($xml->appUrl);
+    }
+    if (isset($xml->status)) {
+      $message['status'] = trim($xml->status);
+    }
+    if (isset($xml->timeSent)) {
+      $message['timeSent'] = trim($xml->timeSent);
+    }
+    if (isset($xml->type)) {
+      $message['type'] = trim($xml->type);
+    }
+    if (isset($xml->updated)) {
+      $message['updated'] = trim($xml->updated);
+    }
+    if (isset($xml->senderId)) {
+      $message['senderId'] = trim($xml->senderId);
+    }
+    if (isset($xml->appUrl)) {
+      $message['appUrl'] = trim($xml->appUrl);
+    }
+    if (isset($xml->collectionIds)) {
+      $message['collectionIds'] = array();
+      foreach ($xml->collectionIds as $collectionId) {
+        $message['collectionIds'][] = trim($collectionId);
+      }
+    }
+    
+    // Tries to retrieve recipients by looking at the osapi name space first then
+    // the default namespace.
+    $recipientXml = self::loadString($requestParam, "http://opensocial.org/2008/opensocialapi");
+    if (empty($recipientXml) || !isset($recipientXml->recipient)) {
+      $recipientXml = $xml;
+    }
+    
+    if (isset($recipientXml->recipient)) {
+      $message['recipients'] = array();
+      foreach ($recipientXml->recipient as $recipient) {
+        $message['recipients'][] = trim($recipient);
+      }
+    }
+    
+    // TODO: Parses the inReplyTo, replies and urls fields.
+    
+    // MessageCollection specified fiedls.
+    if (isset($xml->total)) {
+      $message['total'] = trim($xml->total);
+    }
+    if (isset($xml->unread)) {
+      $message['unread'] = trim($xml->unread);
+    }
+    
     return $message;
   }
 }

Modified: incubator/shindig/trunk/php/src/social/model/Message.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/social/model/Message.php?rev=773390&r1=773389&r2=773390&view=diff
==============================================================================
--- incubator/shindig/trunk/php/src/social/model/Message.php (original)
+++ incubator/shindig/trunk/php/src/social/model/Message.php Sun May 10 19:29:37 2009
@@ -19,25 +19,40 @@
  */
 
 /**
- *
- * Base interface for all message objects.
- *
  * see
- * http://www.opensocial.org/Technical-Resources/opensocial-spec-v081/opensocial-reference#opensocial.Message
+ * http://opensocial-resources.googlecode.com/svn/spec/draft/OpenSocial-Specification.xml#opensocial.Message.Field
  */
 class Message {
-  public $body;
-  public $title;
-  public $type;
+  private $appUrl;
+  private $body;
+  private $bodyId;
+  private $collectionIds = array();
+  private $id;
+  private $inReplyTo;
+  private $recipients = array();
+  private $replies = array();
+  private $senderId;
+  private $status;
+  private $timeSent;
+  private $title;
+  private $titleId;
+  private $type;
+  private $updated;
+  private $urls = array();
+
+  public static $DEFAULT_FIELDS = array('appUrl', 'body', 'bodyId', 'collectionIds', 'id', 'inReplyTo', 'recipients', 'replies', 'senderId', 'status', 'timeSent', 'title', 'titleId', 'type', 'updated', 'urls');
+
   public $types = array(
-	    /* An email */
-	    'EMAIL',
-	    /* A short private message */
-	    'NOTIFICATION',
-	    /* A message to a specific user that can be seen only by that user */
-	    'PRIVATE_MESSAGE',
-	    /* A message to a specific user that can be seen by more than that user */
-	    'PUBLIC_MESSAGE');
+      /* An email */
+      'EMAIL',
+      /* A short private message */
+      'NOTIFICATION',
+      /* A message to a specific user that can be seen only by that user */
+      'PRIVATE_MESSAGE',
+      /* A message to a specific user that can be seen by more than that user */
+      'PUBLIC_MESSAGE');
+
+  public $statuses = array('NEW', 'READ', 'DELETED');
 
   public function __construct($initBody, $initTitle, $initType) {
     $this->setBody($initBody);
@@ -45,57 +60,140 @@
     $this->setType($initType);
   }
 
-  /**
-   * Gets the main text of the message.
-   * @return the main text of the message
-   */
+  public function getAppUrl() {
+    return $this->appUrl;
+  }
+
+  public function setAppUrl($url) {
+    $this->url = $url;
+  }
+
   public function getBody() {
     return $this->body;
   }
 
-  /**
-   * Sets the main text of the message.
-   * HTML attributes are allowed and are sanitized by the container
-   * @param newBody the main text of the message
-   */
-  public function setBody($newBody) {
-    $this->body = $newBody;
+  public function setBody($body) {
+    $this->body = $body;
+  }
+
+  public function getBodyId() {
+    return $this->bodyId;
+  }
+
+  public function setBodyId($bodyId) {
+    $this->bodyId = $bodyId;
+  }
+
+  public function getCollectionIds() {
+    return $this->collectionIds;
+  }
+
+  public function setCollectionIds($collectionIds) {
+    $this->$collectionIds = $collectionIds;
+  }
+
+  public function getId() {
+    return $this->id;
+  }
+
+  public function setId($id) {
+    $this->id = $id;
+  }
+
+  public function getInReplyTo() {
+    return $this->inReplyTo;
+  }
+
+  public function setInReplyTo($inReplyTo) {
+    $this->inReplyTo = $inReplyTo;
+  }
+
+  public function getRecipients() {
+    return $this->recipients;
+  }
+
+  public function setRecipients($recipients) {
+    $this->recipients = $recipients;
+  }
+
+  public function getReplies() {
+    return $this->replies;
+  }
+
+  public function setReplies($replies) {
+    $this->replies = $replies;
+  }
+
+  public function getStatus() {
+    return $this->status;
+  }
+
+  public function setStatus($status) {
+    $this->status = $status;
+  }
+
+  public function getSenderId() {
+    return $this->senderId;
+  }
+
+  public function setSenderId($senderId) {
+    $this->senderId = $senderId;
+  }
+
+  public function getTimeSent() {
+    return $this->timeSent;
+  }
+
+  public function setTimeSent($timeSent) {
+    $this->timeSent = $timeSent;
   }
 
-  /**
-   * Gets the title of the message
-   * @return the title of the message
-   */
   public function getTitle() {
     return $this->title;
   }
 
-  /**
-   * Sets the title of the message
-   * HTML attributes are allowed and are sanitized by the container.
-   * @param newTitle the title of the message
-   */
-  public function setTitle($newTitle) {
-    $this->title = $newTitle;
+  public function setTitle($title) {
+    $this->title = $title;
+  }
+
+  public function getTitleId() {
+    return $this->titleId;
+  }
+
+  public function setTitleId($titleId) {
+    $this->titleId = $titleId;
   }
 
-  /**
-   * Gets the type of the message, as specified by opensocial.Message.Type
-   * @return the type of message (enum Message.Type)
-   */
   public function getType() {
     return $this->type;
   }
 
+  public function setType($type) {
+    $this->type = $type;
+  }
+
+  public function getUpdated() {
+    return $this->updated;
+  }
+
+  public function setUpdated($updated) {
+    $this->updated = $updated;
+  }
+
+  /**
+   * Gets the URLs related to the message
+   * @return the URLs related to the person, their webpages, or feeds
+   */
+  public function getUrls() {
+    return $this->urls;
+  }
+
   /**
-   * Sets the type of the message, as specified by opensocial.Message.Type
-   * @param newType the type of message (enum Message.Type)
+   * Sets the URLs related to the message
+   * @param urls the URLs related to the person, their webpages, or feeds
    */
-  public function setType($newType) {
-    if (! in_array($newType, $this->types)) {
-      throw new Exception('Invalid message type');
-    }
-    $this->type = $newType;
+  public function setUrls($urls) {
+    $this->urls = $urls;
   }
 
   /**

Added: incubator/shindig/trunk/php/src/social/model/MessageCollection.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/social/model/MessageCollection.php?rev=773390&view=auto
==============================================================================
--- incubator/shindig/trunk/php/src/social/model/MessageCollection.php (added)
+++ incubator/shindig/trunk/php/src/social/model/MessageCollection.php Sun May 10 19:29:37 2009
@@ -0,0 +1,95 @@
+<?php
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ * see
+ * http://opensocial-resources.googlecode.com/svn/spec/draft/OpenSocial-Specification.xml#opensocial.MessageCollection.Field
+ *
+ */
+class MessageCollection {
+  // Indicates the collection of all messages sent to the user
+  public static $INBOX = "@inbox";
+  // Indicates the collection of all messages sent by the user
+  // and used as a special endpoint for posting outbound messages.
+  public static $OUTBOX = "@outbox";
+
+  private $id;
+  private $title;
+  private $total;
+  private $unread;
+  private $updated;
+  private $urls = array();
+
+  public static $DEFAULT_FIELDS = array('id', 'title', 'total', 'unread', 'updated', 'urls');
+
+  public function __construct($id, $title) {
+    $this->setId($id);
+    $this->setTitle($title);
+  }
+
+  public function getId() {
+    return $this->id;
+  }
+
+  public function setId($id) {
+    $this->id = $id;
+  }
+
+  public function getTitle() {
+    return $this->title;
+  }
+
+  public function setTitle($title) {
+    $this->title = $title;
+  }
+
+  public function getTotal() {
+    return $this->total;
+  }
+
+  public function setTotal($total) {
+    $this->total = $total;
+  }
+
+  public function getUnread() {
+    return $this->unread;
+  }
+
+  public function setUnread($unread) {
+    $this->unread = $unread;
+  }
+
+  public function getUpdated() {
+    return $this->updated;
+  }
+
+  public function setUpdated($updated) {
+    $this->updated = $updated;
+  }
+
+  public function getUrls() {
+    return $this->urls;
+  }
+
+  public function setUrls($urls) {
+    $this->urls = $urls;
+  }
+}
+

Modified: incubator/shindig/trunk/php/src/social/sample/JsonDbOpensocialService.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/social/sample/JsonDbOpensocialService.php?rev=773390&r1=773389&r2=773390&view=diff
==============================================================================
--- incubator/shindig/trunk/php/src/social/sample/JsonDbOpensocialService.php (original)
+++ incubator/shindig/trunk/php/src/social/sample/JsonDbOpensocialService.php Sun May 10 19:29:37 2009
@@ -39,6 +39,11 @@
   private static $ACTIVITIES_TABLE = "activities";
 
   /**
+   * db["messages"] : Map<Person.Id, MessageCollection>
+   */
+  private static $MESSAGES_TABLE = "messages";
+
+  /**
    * db["data"] -> Map<Person.Id, Map<String, String>>
    */
   private static $DATA_TABLE = "data";
@@ -59,6 +64,8 @@
 
   private $allActivities = null;
 
+  private $allMessageCollections = null;
+
   private $jsonDbFileName = 'ShindigDb.json';
 
   public function getDb() {
@@ -129,6 +136,16 @@
     return $this->allActivities;
   }
 
+  private function getAllMessageCollections() {
+    $db = $this->getDb();
+    $messagesTable = $db[self::$MESSAGES_TABLE];
+    foreach ($messagesTable as $key => $value) {
+      $this->allMessageCollections[$key] = $value;
+    }
+    $db[self::$MESSAGES_TABLE] = $this->allMessageCollections;
+    return $this->allMessageCollections;
+  }
+
   private function getPeopleWithApp($appId) {
     $peopleWithApp = array();
     $db = $this->getDb();
@@ -205,7 +222,7 @@
 
     try {
       $people = $this->filterResults($people, $options);
-    } catch(Exception $e) {
+    } catch (Exception $e) {
       $people['filtered'] = 'false';
     }
 
@@ -216,9 +233,9 @@
     return $collection;
   }
 
-  private function filterResults($peopleById, $options) {
+  private function filterResults($results, $options) {
     if (! $options->getFilterBy()) {
-      return $peopleById; // no filtering specified
+      return $results; // no filtering specified
     }
     $filterBy = $options->getFilterBy();
     $op = $options->getFilterOperation();
@@ -228,7 +245,7 @@
     $value = $options->getFilterValue();
     $filteredResults = array();
     $numFilteredResults = 0;
-    foreach ($peopleById as $id => $person) {
+    foreach ($results as $id => $person) {
       if ($this->passesFilter($person, $filterBy, $op, $value)) {
         $filteredResults[$id] = $person;
         $numFilteredResults ++;
@@ -237,15 +254,15 @@
     return $filteredResults;
   }
 
-  private function passesFilter($person, $filterBy, $op, $value) {
-    $fieldValue = $person[$filterBy];
+  private function passesFilter($entity, $filterBy, $op, $value) {
+    $fieldValue = $entity[$filterBy];
     if (! $fieldValue || (is_array($fieldValue) && ! count($fieldValue))) {
       return false; // person is missing the field being filtered for
     }
     if ($op == CollectionOptions::FILTER_OP_PRESENT) {
       return true; // person has a non-empty value for the requested field
     }
-    if (!$value) {
+    if (! $value) {
       return false; // can't do an equals/startswith/contains filter on an empty filter value
     }
     // grab string value for comparison
@@ -314,14 +331,14 @@
   }
 
   public function deletePersonData($userId, GroupId $groupId, $appId, $fields, SecurityToken $token) {
-  	$db = $this->getDb();
-  	$allData = $this->getAllData();
-  	if ($fields == null || $fields[0] == '*') {
+    $db = $this->getDb();
+    $allData = $this->getAllData();
+    if ($fields == null || $fields[0] == '*') {
       $allData[$userId->getUserId($token)] = null;
       $db[self::$DATA_TABLE] = $allData;
       $this->saveDb($db);
       return null;
-  	}
+    }
     foreach ($fields as $key => $present) {
       if (! $this->isValidKey($key)) {
         throw new SocialSpiException("The person app data key had invalid characters", ResponseError::$BAD_REQUEST);
@@ -406,10 +423,8 @@
   }
 
   /*
-	*
-	* to check the activity against filter
-	*
-	*/
+   * to check the activity against filter
+   */
   private function passesStringFilter($fieldValue, $filterOp, $filterValue) {
     switch ($filterOp) {
       case CollectionOptions::FILTER_OP_EQUALS:
@@ -428,6 +443,10 @@
     $activitiesTable = $this->getAllActivities();
     $activity['appId'] = $token->getAppId();
     try {
+      if (! isset($activitiesTable[$userId->getUserId($token)])) {
+        $activitiesTable[$userId->getUserId($token)] = array();
+      }
+      $activity['id'] = count($activitiesTable[$userId->getUserId($token)]) + 1;
       array_push($activitiesTable[$userId->getUserId($token)], $activity);
       $db[self::$ACTIVITIES_TABLE] = $activitiesTable;
       $this->saveDb($db);
@@ -438,13 +457,228 @@
   }
 
   public function deleteActivities($userId, $groupId, $appId, $activityIds, SecurityToken $token) {
-    throw new SocialSpiException("Not implemented", ResponseError::$NOT_IMPLEMENTED);
+    $db = $this->getDb();
+    $activitiesTable = $this->getAllActivities();
+    if (! isset($activitiesTable[$userId->getUserId($token)])) {
+      throw new SocialSpiException("Activity not found.", ResponseError::$BAD_REQUEST);
+    }
+    $newActivities = array();
+    foreach ($activitiesTable[$userId->getUserId($token)] as $activity) {
+      $found = false;
+      foreach ($activityIds as $id) {
+        if ($activity['id'] == $id) {
+          $found = true;
+        }
+      }
+      if (! $found) {
+        array_push($newActivities, $activity);
+      }
+    }
+    if (count($newActivities) == count($activitiesTable[$userId->getUserId($token)])) {
+      throw new SocialSpiException("Activities not found.", ResponseError::$BAD_REQUEST);
+    }
+    $activitiesTable[$userId->getUserId($token)] = $newActivities;
+    $db[self::$ACTIVITIES_TABLE] = $activitiesTable;
+    $this->saveDb($db);
   }
 
-  public function createMessage($userId, $appId, $message, $optionalMessageId, SecurityToken $token) {
+  public function createMessage($userId, $msgCollId, $message, $token) {
+    $db = $this->getDb();
+    $messagesTable = $this->getAllMessageCollections();
+    if (! isset($messagesTable[$userId->getUserId($token)]) || ! isset($messagesTable[$userId->getUserId($token)][$msgCollId])) {
+      throw new SocialSpiException("Message collection not found.", ResponseError::$BAD_REQUEST);
+    }
+    $msgColl = $messagesTable[$userId->getUserId($token)][$msgCollId];
+    if (! isset($msgColl['messages'])) {
+      $msgColl['messages'] = array();
+    }
+    $message['id'] = count($msgColl['messages']) + 1;
+    $msgColl['messages'][$message['id']] = $message;
+    if (isset($msgColl['total'])) {
+      ++ $msgColl['total'];
+    } else {
+      $msgColl['total'] = 1;
+    }
+    if (isset($msgColl['unread'])) {
+      ++ $msgColl['unread'];
+    } else {
+      $msgColl['unread'] = 1;
+    }
+    $messagesTable[$userId->getUserId($token)][$msgCollId] = $msgColl;
+    $db[self::$MESSAGES_TABLE] = $messagesTable;
+    $this->saveDb($db);
+  }
+
+  public function updateMessage($userId, $msgCollId, $message, $token) {
     throw new SocialSpiException("Not implemented", ResponseError::$NOT_IMPLEMENTED);
   }
 
+  public function deleteMessages($userId, $msgCollId, $messageIds, $token) {
+    $db = $this->getDb();
+    $messagesTable = $this->getAllMessageCollections();
+    if (! isset($messagesTable[$userId->getUserId($token)]) || ! isset($messagesTable[$userId->getUserId($token)][$msgCollId])) {
+      throw new SocialSpiException("Message collection not found.", ResponseError::$BAD_REQUEST);
+    }
+    $msgColl = $messagesTable[$userId->getUserId($token)][$msgCollId];
+    foreach ($messageIds as $id) {
+      if (! isset($msgColl['messages']) || ! isset($msgColl['messages'][$id])) {
+        throw new SocialSpiException("Message not found.", ResponseError::$BAD_REQUEST);
+      }
+    }
+    foreach ($messageIds as $id) {
+      unset($msgColl['messages'][$id]);
+    }
+    if (isset($msgColl['total'])) {
+      $msgColl['total'] -= count($messageIds);
+    }
+    $messagesTable[$userId->getUserId($token)][$msgCollId] = $msgColl;
+    $db[self::$MESSAGES_TABLE] = $messagesTable;
+    $this->saveDb($db);
+  }
+
+  public function getMessages($userId, $msgCollId, $fields, $msgIds, $options, $token) {
+    $collections = $this->getAllMessageCollections();
+    $results = array();
+    // TODO: Handles @inbox and @outbox.
+    if (isset($collections[$userId->getUserId($token)]) && isset($collections[$userId->getUserId($token)][$msgCollId])) {
+      $msgColl = $collections[$userId->getUserId($token)][$msgCollId];
+      if (! isset($msgColl['messages'])) {
+        $msgColl['messages'] = array();
+      }
+      if (empty($msgIds)) {
+        $results = $msgColl['messages'];
+      } else {
+        foreach ($msgColl['messages'] as $message) {
+          if (in_array($message['id'], $msgIds)) {
+            $results[] = $message;
+          }
+        }
+      }
+      if ($options) {
+        $results = $this->filterResults($results, $options);
+      }
+      if ($fields) {
+        $results = self::adjustFields($results, $fields);
+      }
+      return self::paginateResults($results, $options);
+    } else {
+      throw new SocialSpiException("Message collections not found", ResponseError::$NOT_FOUND);
+    }
+  }
+
+  public function createMessageCollection($userId, $msgCollection, $token) {
+    $db = $this->getDb();
+    $messagesTable = $this->getAllMessageCollections();
+    try {
+      if (! isset($messagesTable[$userId->getUserId($token)])) {
+        $messagesTable[$userId->getUserId($token)] = array();
+      } else if (isset($messagesTable[$userId->getUserId($token)][$msgCollection['id']])) {
+        throw new SocialSpiException("Message collection already exists.", ResponseError::$BAD_REQUEST);
+      }
+      $msgCollection['total'] = 0;
+      $msgCollection['unread'] = 0;
+      $msgCollection['updated'] = time();
+      $messagesTable[$userId->getUserId($token)][$msgCollection['id']] = $msgCollection;
+      $db[self::$MESSAGES_TABLE] = $messagesTable;
+      $this->saveDb($db);
+    } catch (Exception $e) {
+      throw new SocialSpiException("Message collection can't be created: " . $e->getMessage(), ResponseError::$INTERNAL_ERROR);
+    }
+  }
+
+  public function updateMessageCollection($userId, $msgCollection, $token) {
+    $db = $this->getDb();
+    $messagesTable = $this->getAllMessageCollections();
+    if (! isset($messagesTable[$userId->getUserId($token)]) || ! isset($messagesTable[$userId->getUserId($token)][$msgCollection['id']])) {
+      throw new SocialSpiException("Message collection not found.", ResponseError::$BAD_REQUEST);
+    }
+    // The total number of messages in the collection shouldn't be updated.
+    $msgCollection['total'] = $messagesTable[$userId->getUserId($token)][$msgCollection['id']]['total'];
+    $msgCollection['updated'] = time();
+    $messagesTable[$userId->getUserId($token)][$msgCollection['id']] = $msgCollection;
+    $db[self::$MESSAGES_TABLE] = $messagesTable;
+    $this->saveDb($db);
+  }
+
+  public function deleteMessageCollection($userId, $msgCollId, $token) {
+    $db = $this->getDb();
+    $messagesTable = $this->getAllMessageCollections();
+    try {
+      if (! isset($messagesTable[$userId->getUserId($token)]) || ! isset($messagesTable[$userId->getUserId($token)][$msgCollId])) {
+        throw new SocialSpiException("Message collection not found.", ResponseError::$NOT_FOUND);
+      } else {
+        unset($messagesTable[$userId->getUserId($token)][$msgCollId]);
+      }
+      $db[self::$MESSAGES_TABLE] = $messagesTable;
+      $this->saveDb($db);
+    } catch (Exception $e) {
+      throw new SocialSpiException("Message collection can't be created: " . $e->getMessage(), ResponseError::$INTERNAL_ERROR);
+    }
+  }
+
+  public function getMessageCollections($userId, $fields, $options, $token) {
+    $all = $this->getAllMessageCollections();
+    $results = array();
+    if (isset($all[$userId->getUserId($token)])) {
+      $results = $all[$userId->getUserId($token)];
+    } else {
+      return RestfulCollection::createFromEntry(array());
+    }
+    if ($options) {
+      $results = $this->filterResults($results, $options);
+    }
+    if (empty($results)) {
+      throw new SocialSpiException("Message collections not found", ResponseError::$NOT_FOUND);
+    }
+    foreach ($results as $id => $messageCollection) {
+      if (! isset($results[$id]["id"])) {
+        $results[$id]["id"] = $id;
+      }
+      $results[$id]["total"] = isset($results[$id]["messages"]) ? count($results[$id]["messages"]) : 0;
+      $results[$id]["unread"] = $results[$id]["total"];
+    }
+    if ($fields) {
+      $results = self::adjustFields($results, $fields);
+    }
+    return self::paginateResults($results, $options);
+  }
+
+  /**
+   * Paginates the results set according to the critera specified by the options.
+   */
+  private static function paginateResults($results, $options) {
+    if (! $options) {
+      return RestfulCollection::createFromEntry($results);
+    } else {
+      $startIndex = $options->getStartIndex();
+      $count = $options->getCount();
+      $totalResults = count($results);
+      // NOTE: Assumes the index is 0 based.
+      $results = array_slice($results, $startIndex, $count);
+      $ret = new RestfulCollection($results, $startIndex, $totalResults);
+      $ret->setItemsPerPage($count);
+      return $ret;
+    }
+  }
+
+  /**
+   * Removes the unnecessary fields by sets the requested fiedls only.
+   */
+  private static function adjustFields($results, $fields) {
+    if (empty($fields) || empty($results) || in_array('@all', $fields)) {
+      return $results;
+    }
+    $newResults = array();
+    foreach ($results as $entity) {
+      $newEntity = array();
+      foreach ($fields as $field) {
+        $newEntity[$field] = isset($entity[$field]) ? $entity[$field] : null;
+      }
+      $newResults[] = $newEntity;
+    }
+    return $newResults;
+  }
+
   /**
    * Determines whether the input is a valid key.
    *

Added: incubator/shindig/trunk/php/src/social/service/HandlerPreconditions.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/social/service/HandlerPreconditions.php?rev=773390&view=auto
==============================================================================
--- incubator/shindig/trunk/php/src/social/service/HandlerPreconditions.php (added)
+++ incubator/shindig/trunk/php/src/social/service/HandlerPreconditions.php Sun May 10 19:29:37 2009
@@ -0,0 +1,59 @@
+<?php
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ * Preconditions for handlers.
+ */
+class HandlerPreconditions {
+
+  private function __construct() {}
+
+  public static function requireNotEmpty($item, $message) {
+    if (empty($item)) {
+      throw new InvalidArgumentException($message);
+    }
+  }
+
+  public static function requireEmpty($item, $message) {
+    if (! empty($item)) {
+      throw new InvalidArgumentException($message);
+    }
+  }
+
+  public static function requireSingular($item, $message) {
+    self::requireNotEmpty($item, $message);
+    if (count($item) != 1) {
+      throw new InvalidArgumentException($message);
+    }
+  }
+
+  public static function requirePlural($item, $message) {
+    self::requireNotEmpty($item, $message);
+    if (count($item) <= 1) {
+      throw new InvalidArgumentException($message);
+    }
+  }
+
+  public static function requireCondition($cond, $message) {
+    if (! $cond) {
+      throw new InvalidArgumentException($message);
+    }
+  }
+}

Modified: incubator/shindig/trunk/php/src/social/service/MessagesHandler.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/social/service/MessagesHandler.php?rev=773390&r1=773389&r2=773390&view=diff
==============================================================================
--- incubator/shindig/trunk/php/src/social/service/MessagesHandler.php (original)
+++ incubator/shindig/trunk/php/src/social/service/MessagesHandler.php Sun May 10 19:29:37 2009
@@ -19,8 +19,8 @@
  */
 
 class MessagesHandler extends DataRequestHandler {
-  
-  private static $MESSAGES_PATH = "/messages/userId/outbox/msgId";
+
+  private static $MESSAGES_PATH = "/messages/{userId}/msgCollId/{messageId}";
   private $service;
 
   public function __construct() {
@@ -28,30 +28,113 @@
     $this->service = new $service();
   }
 
+  /**
+   * Deletes the message collection or the messages.
+   */
   public function handleDelete(RequestItem $requestItem) {
-    throw new SocialSpiException("You can't delete messages", ResponseError::$NOT_IMPLEMENTED);
+    $requestItem->applyUrlTemplate(self::$MESSAGES_PATH);
+
+    $userIds = $requestItem->getUsers();
+    HandlerPreconditions::requireSingular($userIds, "UserId can only be singular.");
+    $msgCollId = $requestItem->getParameter("msgCollId");
+    HandlerPreconditions::requireNotEmpty($msgCollId, "A message collection is required");
+
+    $token = $requestItem->getToken();
+    $messageIds = $requestItem->getListParameter("messageId");
+    if (empty($messageIds)) {
+      $this->service->deleteMessageCollection($userIds[0], $msgCollId, $token);
+    } else {
+      $this->service->deleteMessages($userIds[0], $msgCollId, $messageIds, $token);
+    }
   }
 
+  /**
+   * Returns a list of message collections or messages.
+   * Examples:
+   * /messages/john.doe
+   * /messages/john.doe/notification
+   * /messages/john.doe/notification/1,2,3
+   */
   public function handleGet(RequestItem $requestItem) {
-    throw new SocialSpiException("You can't retrieve messages", ResponseError::$NOT_IMPLEMENTED);
+    $requestItem->applyUrlTemplate(self::$MESSAGES_PATH);
+
+    $userIds = $requestItem->getUsers();
+    HandlerPreconditions::requireSingular($userIds, "UserId is not singular.");
+
+    $options = new CollectionOptions($requestItem);
+    $msgCollId = $requestItem->getParameter("msgCollId");
+
+    $token = $requestItem->getToken();
+    if (empty($msgCollId)) {
+      // Gets the message collections.
+      return $this->service->getMessageCollections($userIds[0], $requestItem->getFields(MessageCollection::$DEFAULT_FIELDS), $options, $token);
+    }
+
+    $messageIds = $requestItem->getListParameter("messageId");
+    if (empty($messageIds)) {
+      $messageIds = array();
+    }
+    return $this->service->getMessages($userIds[0], $msgCollId, $requestItem->getFields(Message::$DEFAULT_FIELDS), $messageIds, $options, $token);
   }
 
   /**
-   * /messages/{groupId}/outbox/{msgId}
-   * /messages/{groupId}/outbox
-   *
-   * @param RequestItem $requestItem
-   * @return responseItem
+   * Creates a new message collection or message.
+   * Exapmples:
+   * /messages/john.doe
+   * /messages/john.doe/notification
    */
   public function handlePost(RequestItem $requestItem) {
     $requestItem->applyUrlTemplate(self::$MESSAGES_PATH);
+
     $userIds = $requestItem->getUsers();
-    $message = $requestItem->getParameter('message');
-    $optionalMessageId = $requestItem->getParameter('msgId');
-    return $this->service->createMessage($userIds[0], $requestItem->getAppId(), $message, $optionalMessageId, $requestItem->getToken());
+    HandlerPreconditions::requireSingular($userIds, "UserId is not singular.");
+
+    $msgCollId = $requestItem->getParameter("msgCollId");
+    if (empty($msgCollId)) {
+      // Creates a message collection.
+      $messageCollection = $requestItem->getParameter("entity");
+      HandlerPreconditions::requireNotEmpty($messageCollection, "Can't parse message collection.");
+      return $this->service->createMessageCollection($userIds[0], $messageCollection, $requestItem->getToken());
+    } else {
+      // Creates a message.
+      $messageIds = $requestItem->getListParameter("messageId");
+      HandlerPreconditions::requireEmpty($messageIds, "messageId cannot be specified in create method.");
+      $message = $requestItem->getParameter("entity");
+      HandlerPreconditions::requireNotEmpty($message, "Can't parse message.");
+      HandlerPreconditions::requireEmpty($messageIds, "messageId cannot be specified in create method.");
+
+      // Message fields validation.
+      HandlerPreconditions::requireCondition(! ($message['title'] === null && $message['body'] === null), "title and/or body should be specified.");
+      HandlerPreconditions::requireNotEmpty($message['recipients'], "Field recipients is required.");
+
+      return $this->service->createMessage($userIds[0], $msgCollId, $message, $requestItem->getToken());
+    }
   }
 
+  /**
+   * Updates a message or a message collection.
+   */
   public function handlePut(RequestItem $requestItem) {
-    $this->handlePost($requestItem);
+    $requestItem->applyUrlTemplate(self::$MESSAGES_PATH);
+
+    $userIds = $requestItem->getUsers();
+    HandlerPreconditions::requireSingular("UserId is not singular.");
+
+    $msgCollId = $requestItem->getParameter("msgCollId");
+    HandlerPreconditions::requireNotEmpty($msgCollId, "msgCollId is required.");
+
+    $messageIds = $requestItem->getListParameter("messageId");
+    if (empty($messageIds)) {
+      // Updates message collection. NOTE: "message" is used here to represent message collection.
+      $messageCollection = $requestItem->getParameter("message");
+      HandlerPreconditions::requireNotEmpty($messageCollection, "Can't parse message collection.");
+      return $this->service->updateMessageCollection($userIds[0], $messageCollection, $requestItem->getToken());
+    } else {
+      // Updates a message.
+      HandlerPreconditions::requireSingular("UserId is not singular.");
+      $message = $requestItem->getParameter("message");
+      HandlerPreconditions::requireNotEmpty($message, "Can't parse message.");
+      return $this->service->updateMessage($userIds[0], $msgCollId, $message, $requestItem->getToken());
+    }
   }
 }

Modified: incubator/shindig/trunk/php/src/social/service/RequestItem.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/social/service/RequestItem.php?rev=773390&r1=773389&r2=773390&view=diff
==============================================================================
--- incubator/shindig/trunk/php/src/social/service/RequestItem.php (original)
+++ incubator/shindig/trunk/php/src/social/service/RequestItem.php Sun May 10 19:29:37 2009
@@ -22,41 +22,41 @@
  * Abstract base type for social API requests.
  */
 abstract class RequestItem {
-  
+
   // Common OpenSocial API fields
   public static $APP_ID = "appId";
-  
+
   public static $USER_ID = "userId";
-  
+
   public static $GROUP_ID = "groupId";
-  
+
   public static $START_INDEX = "startIndex";
-  
+
   public static $COUNT = "count";
-  
+
   public static $SORT_BY = "sortBy";
   public static $SORT_ORDER = "sortOrder";
-  
+
   public static $FILTER_BY = "filterBy";
   public static $FILTER_OPERATION = "filterOp";
   public static $FILTER_VALUE = "filterValue";
-  
+
   public static $FIELDS = "fields";
-  
+
   // Opensocial defaults
   public static $DEFAULT_START_INDEX = 0;
-  
+
   public static $DEFAULT_COUNT = 20;
-  
+
   public static $APP_SUBSTITUTION_TOKEN = "@app";
-  
+
   /**
    * @var SecurityToken
    */
   protected $token;
-  
+
   protected $operation;
-  
+
   protected $service;
 
   public function __construct($service, $operation, SecurityToken $token) {

Modified: incubator/shindig/trunk/php/src/social/service/RestRequestItem.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/social/service/RestRequestItem.php?rev=773390&r1=773389&r2=773390&view=diff
==============================================================================
--- incubator/shindig/trunk/php/src/social/service/RestRequestItem.php (original)
+++ incubator/shindig/trunk/php/src/social/service/RestRequestItem.php Sun May 10 19:29:37 2009
@@ -79,7 +79,8 @@
         break;
       case DataServiceServlet::$MESSAGE_ROUTE:
         $data = $this->inputConverter->convertMessages($this->postData);
-        $this->params['message'] = $data;
+        // 'entity' may be a message or a message collection.
+        $this->params['entity'] = $data;
         break;
       case DataServiceServlet::$INVALIDATE_ROUTE:
         $this->params = json_decode($this->postData, true);

Modified: incubator/shindig/trunk/php/src/social/spi/CollectionOptions.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/social/spi/CollectionOptions.php?rev=773390&r1=773389&r2=773390&view=diff
==============================================================================
--- incubator/shindig/trunk/php/src/social/spi/CollectionOptions.php (original)
+++ incubator/shindig/trunk/php/src/social/spi/CollectionOptions.php Sun May 10 19:29:37 2009
@@ -26,32 +26,41 @@
   private $sortOrder;
   const SORT_ORDER_ASCENDING = 'ascending';
   const SORT_ORDER_DESCENDING = 'descending';
-  
+
   private $filterBy;
   private $filterOp;
   private $filterValue;
-  
+
   const FILTER_OP_EQUALS = 'equals';
   const FILTER_OP_CONTAINS = 'contains';
   const FILTER_OP_STARTSWITH = 'startswith';
   const FILTER_OP_PRESENT = 'present';
-  
+
   const TOP_FRIENDS_SORT = "topFriends";
   const TOP_FRIENDS_FILTER = "topFriends";
   const HAS_APP_FILTER = "hasApp";
-  
+
   private $updatedSince;
-  
+
   private $networkDistance;
-  
+
   private $startIndex;
   private $count;
 
-  public function __construct() {
-    // set default values, per spec
-    $this->startIndex = 0;
-    $this->count = 0;
-    $this->sortOrder = CollectionOptions::SORT_ORDER_ASCENDING;
+  public function __construct($requestItem = NULL) {
+    if (empty($requestItem)) {
+      $this->startIndex = 0;
+      $this->count = 0;
+      $this->sortOrder = CollectionOptions::SORT_ORDER_ASCENDING;
+    } else {
+      $this->setSortBy($requestItem->getSortBy());
+      $this->setSortOrder($requestItem->getSortOrder());
+      $this->setFilterBy($requestItem->getFilterBy());
+      $this->setFilterOperation($requestItem->getFilterOperation());
+      $this->setFilterValue($requestItem->getFilterValue());
+      $this->setStartIndex($requestItem->getStartIndex());
+      $this->setCount($requestItem->getCount());
+    }
   }
 
   public function getSortBy() {

Modified: incubator/shindig/trunk/php/src/social/spi/MessagesService.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/social/spi/MessagesService.php?rev=773390&r1=773389&r2=773390&view=diff
==============================================================================
--- incubator/shindig/trunk/php/src/social/spi/MessagesService.php (original)
+++ incubator/shindig/trunk/php/src/social/spi/MessagesService.php Sun May 10 19:29:37 2009
@@ -20,21 +20,82 @@
 
 interface MessagesService {
 
-  /**  
-   * Send a message to the chosen recipients.
-   * $userId - the sender
-   * $appId - the application Id
-   * $message - an array containing the following fields:
-   *  [id] => {msgid}
-   *  [title] => You have an invitation from Joe
-   *  [body] => Click <a href="http://app.example.org/invites/{msgid}">here</a> to review your invitation.
-   *  [recipients] => Array
-   *      (
-   *          [0] => UserId1
-   *          [1] => UserId2
-   *      )
-   * $optionalMessageId - if the REST action was a PUT containing an message id this is filled in
-   * $token - the security token
+  /**
+   * Creates a new message collection for the given arguments.
+   * NOTE: It'd better not to use 0 or "0" as message collection id
+   * to prevent pertential problems.
+   * @param userId  The userId to create the message collection for
+   * @param msgCollection A message collection that is to be created
+   * @param token  A security token for this request
    */
-  public function createMessage($userId, $appId, $message, $optionalMessageId, SecurityToken $token);
+  public function createMessageCollection($userId, $msgCollection, $token);
+
+  /**
+   * Updates a message collection for the given arguments
+   * @param userId  The userId to update the message collection for
+   * @param msgCollection Data for the message collection to be updated
+   * @param token  A security token for this request
+   */
+  public function updateMessageCollection($userId, $msgCollection, $token);
+
+  /**
+   * Deletes a message collection for the given arguments
+   * @param userId  The userId to create the message collection for
+   * @param msgCollId The message collection id to be deleted
+   * @param token  A security token for this request
+   */
+  public function deleteMessageCollection($userId, $msgCollId, $token);
+
+  /**
+   * Returns a list of message collections corresponding to the given user
+   * @param userId   The User to fetch for
+   * @param fields   The fields that the returned message collections contain.
+   * @param options  Filter criteria, pagination, etc.
+   * @param token    Given security token for this request
+   * @return a collection of message collections.
+   */
+  public function getMessageCollections($userId, $fields, $options, $token);
+
+  /**
+   * Posts a message to the user's specified message collection and sends the
+   * message to the set of recipients specified in the message.
+   * @param userId      The user posting the message.
+   * @param msgCollId   The message collection Id to post to
+   * @param message     The message to post
+   * @param token       A valid security token
+   */
+  public function createMessage($userId, $msgCollId, $message, $token);
+
+  /**
+   * Updates a specific message with new data
+   * @param userId      The User to modify for
+   * @param msgCollId   The Message Collection ID to update from
+   * @param message     The message details to modify
+   * @param token       Given Security Token for this request
+   */
+  public function updateMessage($userId, $msgCollId, $message, $token);
+
+  /**
+   * Deletes a set of messages for a given user/message collection
+   * @param userId      The User to delete for
+   * @param msgCollId   The Message Collection ID to delete from
+   * @param messageIds  List of IDs to delete
+   * @param token       Given Security Token for this request
+   */
+  public function deleteMessages($userId, $msgCollId, $messageIds, $token);
+
+  /**
+   * Returns a collection of messages that correspond to the passed in criteria.
+   * The container implementation can get appId from the token and translate
+   * the appId to appUrl in the response.
+   * @param userId     The user id to fetch for
+   * @param msgCollId  A message collection id. Supports @inbox and @outbox defined in MessageCollection class.
+   * @param fields     The fields to fetch for the messages
+   * @param msgIds     An explicit set of message ids to fetch. Empty means all the messages that fulfills the given criterias.
+   * @param options    Options to control the fetch.
+   * @param token      Given security token for this request
+   * @return a collection of messages
+   */
+  public function getMessages($userId, $msgCollId, $fields, $msgIds, $options, $token);
+
 }

Added: incubator/shindig/trunk/php/test/social/ActivityRestTest.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/test/social/ActivityRestTest.php?rev=773390&view=auto
==============================================================================
--- incubator/shindig/trunk/php/test/social/ActivityRestTest.php (added)
+++ incubator/shindig/trunk/php/test/social/ActivityRestTest.php Sun May 10 19:29:37 2009
@@ -0,0 +1,94 @@
+<?php
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+require_once 'RestBase.php';
+
+class ActivityRestTest extends RestBase {
+
+  private function verifyLifeCycle($postData, $postDataFormat, $randomTitle) {
+    $url = '/activities/1/@self';
+    $ret = $this->curlRest($url, $postData, $postDataFormat);
+    $this->assertTrue(empty($ret), "Create activity failed. Response: $ret");
+    
+    // Verifyies data was written correctly
+    $ret = $this->curlRest($url . '?count=20', '', 'application/json', 'GET');
+    $retDecoded = json_decode($ret, true);
+    $this->assertTrue($ret != $retDecoded && $ret != null, "Invalid json string in return: $ret");
+    // Sees if we can find our just created activity
+    $activityId = null;
+    foreach ($retDecoded['entry'] as $entry) {
+      if ($entry['title'] == $randomTitle) {
+        $activityId = $entry['id'];
+        break;
+      }
+    }
+    $this->assertNotNull($activityId, "Couldn't find created activity.");
+    $ret = $this->curlRest($url . "/@app/$activityId", '', 'application/json', 'DELETE');
+    $this->assertTrue(empty($ret), "Delete activity failed. Repsonse: $ret");
+  }
+  
+  public function testLifeCycleInJson() {
+    $randomTitle = "[" . rand(0, 2048) . "] test activity";
+    $postData = '{
+      "id" : "http://example.org/activities/example.org:87ead8dead6beef/self/af3778",
+      "title" : "' . $randomTitle . '",
+      "updated" : "2008-02-20T23:35:37.266Z",
+      "body" : "Some details for some activity",
+      "bodyId" : "383777272",
+      "url" : "http://api.example.org/activity/feeds/.../af3778",
+      "userId" : "example.org:34KJDCSKJN2HHF0DW20394"
+    }';
+    $this->verifyLifeCycle($postData, 'application/json', $randomTitle);
+  }
+  
+  public function testLifeCycleInAtom() {
+    $randomTitle = "[" . rand(0, 2048) . "] test activity";
+    $postData = '<entry xmlns="http://www.w3.org/2005/Atom">
+        <category term="status"/>
+        <id>http://example.org/activities/example.org:87ead8dead6beef/self/af3778</id>
+        <title>' . $randomTitle . '</title>
+        <summary>Some details for some activity</summary>
+        <updated>2008-02-20T23:35:37.266Z</updated>
+        <link rel="self" type="application/atom+xml" href="http://api.example.org/activity/feeds/.../af3778"/>
+        <author><uri>urn:guid:example.org:34KJDCSKJN2HHF0DW20394</uri></author>
+        <content>
+          <activity xmlns="http://ns.opensocial.org/2008/opensocial">
+            <bodyId>383777272</bodyId>
+          </activity>
+        </content>
+      </entry>';
+    $this->verifyLifeCycle($postData, 'application/atom+xml', $randomTitle);
+  }
+  
+  public function testLifeCycleInXml() {
+    $randomTitle = "[" . rand(0, 2048) . "] test activity";
+    $postData = '<activity xmlns="http://ns.opensocial.org/2008/opensocial">
+      <id>http://example.org/activities/example.org:87ead8dead6beef/self/af3778</id>
+      <title>' . $randomTitle . '</title>
+      <updated>2008-02-20T23:35:37.266Z</updated>
+      <body>Some details for some activity</body>
+      <bodyId>383777272</bodyId>
+      <url>http://api.example.org/activity/feeds/.../af3778</url>
+      <userId>example.org:34KJDCSKJN2HHF0DW20394</userId>
+      </activity>';
+    $this->verifyLifeCycle($postData, 'application/xml', $randomTitle);
+  }
+}
+

Added: incubator/shindig/trunk/php/test/social/AppDataRestTest.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/test/social/AppDataRestTest.php?rev=773390&view=auto
==============================================================================
--- incubator/shindig/trunk/php/test/social/AppDataRestTest.php (added)
+++ incubator/shindig/trunk/php/test/social/AppDataRestTest.php Sun May 10 19:29:37 2009
@@ -0,0 +1,126 @@
+<?php
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+require_once 'RestBase.php';
+
+class AppDataRestTest extends RestBase {
+  
+  public function testAppDataLifeCycleInJson() {
+    $postData = '{
+      "pokes" : 4,
+      "last_poke" : "2008-06-13T18:30:02Z"
+    }';
+    // Creates the app data.
+    $ret = $this->curlRest('/appdata/1/@self/1', $postData, 'application/json');
+    $this->assertTrue(empty($ret), "Create app data failed. $ret.");
+    // Verifies data was written correctly
+    $ret = $this->curlRest('/appdata/1/@self/1?fields=pokes,last_poke', '', 'application/json', 'GET');
+    $retDecoded = json_decode($ret, true);
+    $this->assertTrue($ret != $retDecoded && $ret != null, "Invalid json string in return: $ret.");
+    $this->assertTrue(isset($retDecoded['entry']) && isset($retDecoded['entry'][1])
+        && isset($retDecoded['entry'][1]['last_poke']) && isset($retDecoded['entry'][1]['pokes'])
+        && $retDecoded['entry'][1]['last_poke'] == '2008-06-13T18:30:02Z'
+        && $retDecoded['entry'][1]['pokes'] == '4', "Unexpected return value: $ret.");
+    // Deletes the app data.
+    $ret = $this->curlRest('/appdata/1/@self/1?fields=pokes,last_poke', '', 'application/json', 'DELETE');
+    $this->assertTrue(empty($ret), "Delete app data failed. $ret");       
+  }
+  
+  public function testAppDataLifeCycleInXml() {
+    $postData = '<appdata xmlns="http://ns.opensocial.org/2008/opensocial">
+        <entry>
+          <key>pokes</key>
+          <value>1</value>
+        </entry>
+        <entry>
+          <key>last_poke</key>
+          <value>2008-02-13T18:30:02Z</value>
+        </entry>
+      </appdata>';
+    // Creates or update the app data.
+    $ret = $this->curlRest('/appdata/1/@self/1', $postData, 'application/xml');
+    $this->assertTrue(empty($ret), "Create app data failed. $ret");
+    
+    // Verifies data was written correctly.
+    $ret = $this->curlRest('/appdata/1/@self/1?fields=pokes,last_poke', '', 'application/json', 'GET');
+    $retDecoded = json_decode($ret, true);
+    $this->assertTrue($ret != $retDecoded && $ret != null, "Invalid json string in return: $ret.");
+    $this->assertTrue(isset($retDecoded['entry']) && isset($retDecoded['entry'][1])
+        && isset($retDecoded['entry'][1]['last_poke']) && isset($retDecoded['entry'][1]['pokes'])
+        && $retDecoded['entry'][1]['last_poke'] == '2008-02-13T18:30:02Z'
+        && $retDecoded['entry'][1]['pokes'] == '1', "Unexpected return value: $ret.");
+        
+    // Updates the app data.
+    $updateData = '<appdata xmlns="http://ns.opensocial.org/2008/opensocial">
+        <entry>
+          <key>pokes</key>
+          <value>100</value>
+        </entry>
+        <entry>
+          <key>last_poke</key>
+          <value>2009-02-13T18:30:02Z</value>
+        </entry>
+      </appdata>';
+    $ret = $this->curlRest('/appdata/1/@self/1', $updateData, 'application/xml');
+    $this->assertTrue(empty($ret), "Update app data failed. $ret");
+    
+    // Verifies data was written correctly.
+    $ret = $this->curlRest('/appdata/1/@self/1?fields=pokes,last_poke', '', 'application/json', 'GET');
+    $retDecoded = json_decode($ret, true);
+    $this->assertTrue($ret != $retDecoded && $ret != null, "Invalid json string in return: $ret.");
+    $this->assertTrue(isset($retDecoded['entry']) && isset($retDecoded['entry'][1])
+        && isset($retDecoded['entry'][1]['last_poke']) && isset($retDecoded['entry'][1]['pokes'])
+        && $retDecoded['entry'][1]['last_poke'] == '2009-02-13T18:30:02Z'
+        && $retDecoded['entry'][1]['pokes'] == '100', "Unexpected return value: $ret.");
+    
+    // Deletes the app data.
+    $ret = $this->curlRest('/appdata/1/@self/1?fields=pokes,last_poke', '', 'application/json', 'DELETE');
+    $this->assertTrue(empty($ret), "Delete app data failed. $ret");        
+  }
+  
+  public function testAppDataLifeCycleInAtom() {
+    $postData = '<entry xmlns="http://www.w3.org/2005/Atom">
+      <content type="text/xml">
+        <appdata xmlns="http://opensocial.org/2008/opensocial">  
+            <pokes>2</pokes>
+            <last_poke>2003-12-14T18:30:02Z</last_poke>
+          </appdata>
+      </content>
+      <title/>
+      <updated>2003-12-14T18:30:02Z</updated>
+      <author><url>urn:guid:example.org:34KJDCSKJN2HHF0DW20394</url></author>
+      <id>urn:guid:example.org:34KJDCSKJN2HHF0DW20394</id>
+    </entry>';
+    // Creates the app data.
+    $ret = $this->curlRest('/appdata/1/@self/1', $postData, 'application/atom+xml');
+    $this->assertTrue(empty($ret), "Create app data failed. $ret");
+    // Verifies data was written correctly
+    $ret = $this->curlRest('/appdata/1/@self/1?fields=pokes,last_poke', '', 'application/json', 'GET');
+    $retDecoded = json_decode($ret, true);
+    $this->assertTrue($ret != $retDecoded && $ret != null, "Invalid json string in return: $ret.");
+    $this->assertTrue(isset($retDecoded['entry']) && isset($retDecoded['entry'][1])
+        && isset($retDecoded['entry'][1]['last_poke']) && isset($retDecoded['entry'][1]['pokes'])
+        && $retDecoded['entry'][1]['last_poke'] == '2003-12-14T18:30:02Z'
+        && $retDecoded['entry'][1]['pokes'] == '2', "Unexpected return value: $ret\n");
+    // Deletes the app data.
+    $ret = $this->curlRest('/appdata/1/@self/1?fields=pokes,last_poke', '', 'application/json', 'DELETE');
+    $this->assertTrue(empty($ret), "Delete app data failed. $ret");       
+  }
+}

Modified: incubator/shindig/trunk/php/test/social/JsonDbOpensocialServiceTest.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/test/social/JsonDbOpensocialServiceTest.php?rev=773390&r1=773389&r2=773390&view=diff
==============================================================================
--- incubator/shindig/trunk/php/test/social/JsonDbOpensocialServiceTest.php (original)
+++ incubator/shindig/trunk/php/test/social/JsonDbOpensocialServiceTest.php Sun May 10 19:29:37 2009
@@ -53,13 +53,13 @@
    * Tests JsonDbOpensocialService->getActivities() with paging.
    */
   public function testGetActivities() {
-  	$token = BasicSecurityToken::createFromValues('jane.doe', 'jane.doe', 1, 1, 1, 1, 'default');
-  	$userId = new UserId('owner', null);
-  	$userIds = array($userId);
-  	$groupId = new GroupId('self', null);
-  	$startIndex = 1;
-  	$count = 1;
-  	
+    $token = BasicSecurityToken::createFromValues('jane.doe', 'jane.doe', 1, 1, 1, 1, 'default');
+    $userId = new UserId('owner', null);
+    $userIds = array($userId);
+    $groupId = new GroupId('self', null);
+    $startIndex = 1;
+    $count = 1;
+    
     $ret = $this->service->getActivities($userIds, $groupId, 1, null, null, null, null, $startIndex, $count, null, 1, $token);
     $this->assertEquals($startIndex, $ret->startIndex);
     $this->assertEquals($count, count($ret->entry));
@@ -68,5 +68,133 @@
     $this->assertEquals('Jane says George likes yoda!', $ret->entry[0]['title']);
     $this->assertEquals('or is it you?', $ret->entry[0]['body']);
   }
+  
+  public function testActivityLifeCycle() {
+    $token = BasicSecurityToken::createFromValues('jane.doe', 'jane.doe', 1, 1, 1, 1, 'default');
+    $userId = new UserId('owner', null);
+    $userIds = array($userId);
+    $groupId = new GroupId('self', null);
+    $title = 'activity life cycle unit test title';
+    $activity = array('id' => '1', 'userId' => 'userId', 'title' => $title);
+    $ret = $this->service->getActivities($userIds, $groupId, 1, null, null, null, null, 0, 4, null, 1, $token);
+    $this->assertEquals(2, count($ret->entry));
+    
+    $this->service->createActivity($userId, $groupId, $token->getAppId(), null, $activity, $token);
+    $ret = $this->service->getActivities($userIds, $groupId, 1, null, null, null, null, 0, 4, null, 1, $token);
+    $this->assertEquals(3, count($ret->entry));
+    $id = null;
+    foreach ($ret->entry as $entity) {
+      if ($entity['title'] == $title) {
+        $id = $entity['id'];
+      }
+    }
+    $this->assertNotNull($id);
+    
+    $this->service->deleteActivities($userId, $groupId, $token->getAppId(), array($id), $token);
+    
+    $ret = $this->service->getActivities($userIds, $groupId, 1, null, null, null, null, 0, 4, null, 1, $token);
+    $this->assertEquals(2, count($ret->entry));
+  }
 
+  public function testMessageLifeCycle() {
+    $token = BasicSecurityToken::createFromValues('john.doe', 'canonical', 1, 1, 1, 1, 'default');
+    $userId = new UserId('viewer', null);
+    $body = 'message unit test body';
+    $title = 'message unit test title';
+    $message = array('id' => '1', 'body' => $body, 'title' => $title, 'type' => 'NOTIFICATION');
+    $ret = $this->service->getMessages($userId, 'notification', null, null, null, $token);
+    $this->assertEquals(3, count($ret->entry));
+    
+    $this->service->createMessage($userId, 'notification', $message, $token);
+    $ret = $this->service->getMessages($userId, 'notification', null, null, null, $token);
+    $this->assertEquals(4, count($ret->entry));
+    
+    $fetchedMessage = null;
+    foreach ($ret->entry as $message) {
+      if ($message['title'] == $title) {
+        $fetchedMessage = $message;
+      }
+    }
+    $this->assertEquals($body, $fetchedMessage['body']);
+    
+    $this->service->deleteMessages($userId, 'notification', array($fetchedMessage['id']), $token);
+    $ret = $this->service->getMessages($userId, 'notification', null, null, null, $token);
+    $this->assertEquals(3, count($ret->entry));
+  }
+  
+  public function testGetMessages() {
+    $token = BasicSecurityToken::createFromValues('canonical', 'canonical', 1, 1, 1, 1, 'default');
+    $userId = new UserId('viewer', null);
+    $options = new CollectionOptions();
+    $options->setCount(2);
+    $options->setStartIndex(1);
+    $ret = $this->service->getMessages($userId, 'notification', Message::$DEFAULT_FIELDS, array('1', '2', '3'), $options, $token);
+    
+    $this->assertEquals(2, count($ret->entry));
+    $this->assertEquals('2', $ret->entry[0]['id']);
+    $this->assertEquals('notification', $ret->entry[0]['type']);
+    $this->assertEquals('play checkers', $ret->entry[0]['title']);
+    
+    $this->assertEquals('3', $ret->entry[1]['id']);
+    
+    $this->assertEquals('you won!', $ret->entry[1]['title']);
+  }
+  
+  public function testMessageCollectionLifeCycle() {
+    // NOTE: If this method failes after the creation of the market collection.
+    // There will be a market collection in the cached json file /tmp/ShindigDb.json
+    // that prevents the test from passing. Change the test case and remove that
+    // file then run again.
+    $token = BasicSecurityToken::createFromValues('john.doe', 'john.doe', 1, 1, 1, 1, 'default');
+    $title = 'created for message collection unit test';
+    $userId = new UserId('owner', null);
+    $msgColl = array('id' => '1', 'title' => $title);
+    $this->service->createMessageCollection($userId, $msgColl, $token);
+    
+    $msgColls = $this->service->getMessageCollections($userId, null, null, $token)->entry;
+    $this->assertEquals(4, count($msgColls));
+    $fetchedMsgColl = null;
+    foreach ($msgColls as $coll) {
+      if ($coll['title'] == $title) {
+        $fetchedMsgColl = $coll;
+      }
+    }
+    $this->assertNotNull($fetchedMsgColl);
+    
+    $newTitle = 'new title for unit test';
+    $msgColl['title'] = $newTitle;
+    $msgColl['id'] = $fetchedMsgColl['id'];
+    $this->service->updateMessageCollection($userId, $msgColl, $token);
+    
+    $msgColls = $this->service->getMessageCollections($userId, null, null, $token)->entry;
+    $this->assertEquals(4, count($msgColls));
+    foreach ($msgColls as $coll) {
+      if ($coll['id'] == $fetchedMsgColl['id']) {
+        $fetchedMsgColl = $coll;
+      }
+    }
+    $this->assertEquals($newTitle, $fetchedMsgColl['title']);
+    
+    $this->service->deleteMessageCollection($userId, $fetchedMsgColl['id'], $token);
+    $msgColls = $this->service->getMessageCollections($userId, null, null, $token)->entry;
+    $this->assertEquals(3, count($msgColls));    
+  }
+  
+  public function testGetMessageCollections() {
+    $token = BasicSecurityToken::createFromValues('john.doe', 'john.doe', 1, 1, 1, 1, 'default');
+    $userId = new UserId('owner', null);
+    $ret = $this->service->getMessageCollections($userId, MessageCollection::$DEFAULT_FIELDS, null, $token);
+    $this->assertEquals('Notifications', $ret->entry[0]['title']);
+    $this->assertEquals('notification', $ret->entry[0]['id']);
+    $this->assertEquals(2, $ret->entry[0]['total']);
+    
+    $this->assertEquals('Inbox', $ret->entry[1]['title']);
+    $this->assertEquals('privateMessage', $ret->entry[1]['id']);
+    $this->assertEquals(0, $ret->entry[1]['total']);
+    
+    $this->assertEquals('Inbox', $ret->entry[2]['title']);
+    $this->assertEquals('publicMessage', $ret->entry[2]['id']);
+    $this->assertEquals(0, $ret->entry[2]['total']);
+  }
+  
 }

Added: incubator/shindig/trunk/php/test/social/MessageRestTest.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/test/social/MessageRestTest.php?rev=773390&view=auto
==============================================================================
--- incubator/shindig/trunk/php/test/social/MessageRestTest.php (added)
+++ incubator/shindig/trunk/php/test/social/MessageRestTest.php Sun May 10 19:29:37 2009
@@ -0,0 +1,134 @@
+<?php
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+require_once 'RestBase.php';
+
+class MessageRestTest extends RestBase {
+	
+  private function getMessages($url) {
+    $ret = $this->curlRest($url, '', 'application/json', 'GET');
+    $retDecoded = json_decode($ret, true);
+    $this->assertTrue($ret != $retDecoded && $ret != null, "Invalid json response: $retDecoded");
+    return $retDecoded['entry'];
+  }
+  
+  private function verifyLifeCycle($postData, $postDataFormat, $randomTitle) {
+    $url = '/messages/1/notification';
+    
+    $cnt = count($this->getMessages($url));
+    
+    // Creates the message.
+    $ret = $this->curlRest($url, $postData, $postDataFormat, 'POST');
+    $this->assertTrue(empty($ret), "Create message failed. Response: $ret");
+    
+    // Gets the message.
+    $messages = $this->getMessages($url);
+    $this->assertEquals($cnt + 1, count($messages), "Size of the messages is not right.");
+    $fetchedMessage = null;
+    foreach ($messages as $m) {
+      if ($m['title'] == $randomTitle) {
+        $fetchedMessage = $m;
+      }
+    }
+    $this->assertNotNull($fetchedMessage, "Couldn't find the created message with title $randomTitle");
+    
+    // Deletes the message.
+    $ret = $this->curlRest($url . '/' . urlencode($fetchedMessage['id']), '', 'application/json', 'DELETE');
+    $this->assertTrue(empty($ret), "Delete the created message failed. Response: $ret");
+    
+    $messages = $this->getMessages($url, $randomTitle);
+    $this->assertEquals($cnt, count($messages), "Size of the messages is not right after deletion.");
+  }
+  
+  public function testLifeCycleInJson() {
+    $randomTitle = "[" . rand(0, 2048) . "] message test title.";
+    $postData = '{
+      "id" : "msgid",
+      "recipients" : [1, 2, 3],
+      "title" : "' . $randomTitle . '",
+      "titleId" : "541141091700",
+      "body" : "Short message from Joe to some friends",
+      "bodyId" : "5491155811231",
+      "type" : "privateMessage",
+      "status" : "unread"
+    }';
+    $this->verifyLifeCycle($postData, 'application/json', $randomTitle);
+  }
+
+  public function testLifeCycleInXml() {
+    $randomTitle = "[" . rand(0, 2048) . "] message test title.";
+    $postData = '<message xmlns="http://ns.opensocial.org/2008/opensocial">
+      <recipient>1</recipient>
+      <recipient>2</recipient>
+      <recipient>3</recipient>
+      <title>' . $randomTitle . '</title>
+      <id>msgid</id>
+      <body>Click <a href="http://app.example.org/invites/{msgid}">here</a> to review your invitation.</body>
+    </message>';
+    $this->verifyLifeCycle($postData, 'application/xml', $randomTitle);
+  }
+  
+  public function testLifeCycleInAtom() {
+    $randomTitle = "[" . rand(0, 2048) . "] message test title.";
+    $postData = '<entry xmlns="http://www.w3.org/2005/Atom"
+             xmlns:osapi="http://opensocial.org/2008/opensocialapi">
+      <osapi:recipient>1</osapi:recipient>
+      <osapi:recipient>2</osapi:recipient>
+      <osapi:recipient>3</osapi:recipient>
+      <title>' . $randomTitle . '</title>
+      <id>{msgid}</id>
+      <link rel="alternate" href="http://app.example.org/invites/{msgid}"/>
+      <content>Click <a href="http://app.example.org/invites/{msgid}">here</a> to review your invitation.</content>
+    </entry>';
+    $this->verifyLifeCycle($postData, 'application/atom+xml', $randomTitle);
+  }
+  
+  public function testMessageCollectionLifeCycle() {
+    $url = '/messages/1';
+    $randomTitle = "[" . rand(0, 2048) . "] message collection test title.";
+    
+    $ret = $this->curlRest($url, '', 'application/json', 'GET');
+    $retDecoded = json_decode($ret, true);
+    $this->assertTrue($ret != $retDecoded && $ret != null, "Invalid json response: $retDecoded");
+    $cnt = count($retDecoded['entry']);
+    
+    $id = 'msgCollId';
+    
+    $postData = '{
+      "id" : "' . $id . '",
+      "title" : "' . $randomTitle . '"
+    }';
+    $ret = $this->curlRest($url, $postData, 'application/json', 'POST');
+    $this->assertTrue(empty($ret), "Create message collection failed. Response: $ret");
+
+    $ret = $this->curlRest($url, '', 'application/json', 'GET');
+    $retDecoded = json_decode($ret, true);
+    $this->assertTrue($ret != $retDecoded && $ret != null, "Invalid json response: $retDecoded");
+    $this->assertEquals($cnt + 1, count($retDecoded['entry']), "Wrong size of the collections. $ret");
+    
+    $ret = $this->curlRest($url . "/$id", '', 'application/json', 'DELETE');
+    
+    $ret = $this->curlRest($url, '', 'application/json', 'GET');
+    $retDecoded = json_decode($ret, true);
+    $this->assertTrue($ret != $retDecoded && $ret != null, "Invalid json response: $retDecoded");
+    $this->assertEquals($cnt, count($retDecoded['entry']), "Wrong size of the collections. $ret");
+  }
+}
+

Modified: incubator/shindig/trunk/php/test/social/MessageTest.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/test/social/MessageTest.php?rev=773390&r1=773389&r2=773390&view=diff
==============================================================================
--- incubator/shindig/trunk/php/test/social/MessageTest.php (original)
+++ incubator/shindig/trunk/php/test/social/MessageTest.php Sun May 10 19:29:37 2009
@@ -77,7 +77,7 @@
    */
   public function testSetBody() {
     $this->Message->setBody('body');
-    $this->assertEquals('body', $this->Message->body);
+    $this->assertEquals('body', $this->Message->getBody());
   }
 
   /**
@@ -85,7 +85,7 @@
    */
   public function testSetTitle() {
     $this->Message->setTitle('title');
-    $this->assertEquals('title', $this->Message->title);
+    $this->assertEquals('title', $this->Message->getTitle());
   }
 
   /**
@@ -93,6 +93,6 @@
    */
   public function testSetType() {
     $this->Message->setType('EMAIL');
-    $this->assertEquals('EMAIL', $this->Message->type);
+    $this->assertEquals('EMAIL', $this->Message->getType());
   }
 }

Added: incubator/shindig/trunk/php/test/social/RestBase.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/test/social/RestBase.php?rev=773390&view=auto
==============================================================================
--- incubator/shindig/trunk/php/test/social/RestBase.php (added)
+++ incubator/shindig/trunk/php/test/social/RestBase.php Sun May 10 19:29:37 2009
@@ -0,0 +1,70 @@
+<?php
+
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ * Base class for the REST api integration tests.
+ */
+class RestBase extends PHPUnit_Framework_TestCase {
+  
+  /* Modify this if you want to test in a different social graph then partuza. The security token
+   * only works if ALLOW_PLAINTEXT_TOKEN is set to true in the file shindig/php/config/containerphp
+   * The format of the plain text token is owner:viewer:appId:domain:appUrl:moduleId:containerId
+   */
+  private $securityToken = '1:1:1:partuza:test.com:1:0';
+  // The server to test against. You may need to add shindig to 127.0.0.1 mapping in /etc/hosts.
+  private $restUrl = 'http://shindig/social/rest';
+  
+  protected function curlRest($url, $postData, $contentType, $method = 'POST') {
+    $ch = curl_init();
+    if (substr($url, 0, 1) != '/') {
+      $url = '/' . $url;
+    }
+    $sep = strpos($url, '?') !== false ? '&' : '?';
+    curl_setopt($ch, CURLOPT_URL, $this->restUrl . $url . $sep . 'st=' . $this->securityToken);
+    curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-Type: $contentType"));
+    curl_setopt($ch, CURLOPT_HEADER, 0);
+    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
+    curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
+    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+    $ret = curl_exec($ch);
+    curl_close($ch);
+    return $ret;
+  }
+
+  protected function getSecurityToken() {
+    return $this->securityToken;
+  }
+  
+  protected function setSecurityToken($token) {
+    $this->securityToken = $token;
+  }
+  
+  protected function getRestUrl() {
+    return $this->restUrl;
+  }
+  
+  protected function setRestUrl($url) {
+    $this->restUrl = $url; 
+  }
+}
+
+
+