Merge branch 'develop'
diff --git a/.travis.yml b/.travis.yml
index 68b4dfe..9a6ff78 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -2,7 +2,6 @@
php:
- 5.5
- 5.4
- - 5.3
before_script:
- pear channel-discover pear.phing.info
- pear install phing/phing
diff --git a/README.md b/README.md
index 2ff11b9..aaeb7ea 100644
--- a/README.md
+++ b/README.md
@@ -8,11 +8,12 @@
Prerequisites
=============
-* PHP 5.3+ (http://php.net/)
+* PHP 5.4+ (http://php.net/)
* PHP: cURL (http://php.net/manual/en/book.curl.php)
* Phing (http://www.phing.info/)
* ApiGen (http://apigen.org/)
+Note: This SDK only supports Prediction IO version 0.8 or higher.
Support
=======
@@ -45,7 +46,7 @@
{
"require": {
- "predictionio/predictionio": "~0.6.0"
+ "predictionio/predictionio": "~0.8.0"
}
}
@@ -62,25 +63,6 @@
require_once("vendor/autoload.php");
-By Building Phar
-----------------
-
-1. Assuming you are cloning to your home directory:
-
- cd ~
- git clone git://github.com/PredictionIO/PredictionIO-PHP-SDK.git
-
-2. Build the Phar:
-
- cd ~/PredictionIO-PHP-SDK
- phing
-
-3. Once the build finishes you will get a Phar in `build/artifacts`, and a set of API documentation.
- Assuming you have copied the Phar to your current working directory, to use the client, simply
-
- require_once("predictionio.phar");
-
-
Supported Commands
==================
@@ -94,39 +76,30 @@
This package is a web service client based on Guzzle.
A few quick examples are shown below.
-For a full user guide on how to take advantage of all Guzzle features, please refer to http://guzzlephp.org.
-Specifically, http://guzzlephp.org/tour/using_services.html#using-client-objects describes how to use a web service client.
-
-Many REST request commands support optional arguments.
-They can be supplied to these commands by the `set` method.
-
-
-Instantiate PredictionIO API Client
+Instantiate PredictionIO API Event Client
-----------------------------------
```PHP
-use PredictionIO\PredictionIOClient;
-$client = PredictionIOClient::factory(array("appkey" => "<your app key>"));
+use predictionio\EventClient;
+$app_id = 8;
+$client = new EventClient($app_id, 'http://localhost:7070');
```
-
-Import a User Record from Your App
-----------------------------------
+Set a User Record from Your App
+-------------------------------
```PHP
// assume you have a user with user ID 5
-$command = $client->getCommand('create_user', array('pio_uid' => 5));
-$response = $client->execute($command);
+$response = $client->setUser(5);
```
-Import an Item Record from Your App
------------------------------------
+Set an Item Record from Your App
+---------------------------------
```PHP
// assume you have a book with ID 'bookId1' and we assign 1 as the type ID for book
-$command = $client->getCommand('create_item', array('pio_iid' => 'bookId1', 'pio_itypes' => 1));
-$response = $client->execute($command);
+$response = $client->setItem('bookId1', array('pio_itypes' => 1));
```
@@ -135,55 +108,19 @@
```PHP
// assume this user has viewed this book item
-$client->identify('5');
-$client->execute($client->getCommand('record_action_on_item', array('pio_action' => 'view', 'pio_iid' => 'bookId1')));
+$client->recordUserActionOnItem('view', 5, 'bookId1');
```
-Retrieving Top N Recommendations for a User
--------------------------------------------
+Retrieving Prediction Result
+----------------------------
```PHP
-try {
- // assume you have created an itemrec engine named 'engine1'
- // we try to get top 10 recommendations for a user (user ID 5)
- $client->identify('5');
- $command = $client->getCommand('itemrec_get_top_n', array('pio_engine' => 'engine1', 'pio_n' => 10));
- $rec = $client->execute($command);
- print_r($rec);
-} catch (Exception $e) {
- echo 'Caught exception: ', $e->getMessage(), "\n";
-}
-```
+// assume you have created an itemrank engine on localhost:8000
+// we try to get ranking of 5 items (item IDs: 1, 2, 3, 4, 5) for a user (user ID 7)
+$engineClient = new EngineClient('http://localhost:8000');
+$response = $engineClient->sendQuery(array('uid'=>7, 'iids'=>array(1,2,3,4,5)));
-Retrieving Top N Similar Items for an Item
-------------------------------------------
-
-```PHP
-try {
- // assume you have created an itemsim engine named 'engine2'
- // we try to get top 10 similar items for an item (item ID 6)
- $command = $client->getCommand('itemsim_get_top_n', array('pio_iid' => '6', 'pio_engine' => 'engine2', 'pio_n' => 10));
- $rec = $client->execute($command);
- print_r($rec);
-} catch (Exception $e) {
- echo 'Caught exception: ', $e->getMessage(), "\n";
-}
-```
-
-
-Retrieving Ranking of Items for a User
---------------------------------------
-
-```PHP
-try {
- // assume you have created an itemrank engine named 'engine3'
- // we try to get ranking of 5 items (item IDs: 1, 2, 3, 4, 5) for a user (user ID 7)
- $command = $client->getCommand('itemrank_get_ranked', array('pio_uid' => '7', 'pio_iids' => '1,2,3,4,5', 'pio_engine' => 'engine3'));
- $rec = $client->execute($command);
- print_r($rec);
-} catch (Exception $e) {
- echo 'Caught exception: ', $e->getMessage(), "\n";
-}
+print_r($rec);
```
diff --git a/build.xml b/build.xml
index d959425..4355efe 100644
--- a/build.xml
+++ b/build.xml
@@ -1,18 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
-<project name="predictionio" default="package">
+<project name="predictionio" default="install-dependencies">
- <property name="dir.output" value="${project.basedir}/build/artifacts" />
-
- <target name="clean">
- <delete dir="${dir.output}" />
- </target>
-
- <target name="prepare" depends="clean">
- <mkdir dir="${dir.output}" />
- </target>
-
- <target name="install-dependencies" depends="prepare">
+ <target name="install-dependencies">
<if>
<available file="composer.phar" />
<then>
@@ -35,24 +25,7 @@
<exec command="php composer.phar update --dev" passthru="true" />
</target>
- <target name="package" depends="install-dependencies" description="Create a PHAR with an autoloader">
- <pharpackage
- destfile="${dir.output}/predictionio.phar"
- basedir="."
- stub="phar-stub.php">
- <fileset dir=".">
- <include name="src/**/*.php" />
- <include name="src/**/*.json" />
- <include name="vendor/symfony/class-loader/Symfony/Component/ClassLoader/UniversalClassLoader.php" />
- <include name="vendor/symfony/event-dispatcher/**/*.php" />
- <include name="vendor/guzzle/guzzle/src/Guzzle/**/*.php" />
- <include name="vendor/guzzle/guzzle/src/Guzzle/Http/Resources/cacert.pem" />
- <include name="vendor/guzzle/guzzle/src/Guzzle/Http/Resources/cacert.pem.md5" />
- </fileset>
- <metadata>
- <element name="author" value="PredictionIO" />
- </metadata>
- </pharpackage>
+ <target name="apigen">
<exec command="apigen -s src -d docs --title 'PredictionIO API PHP Client'" passthru="true" />
</target>
diff --git a/composer.json b/composer.json
index fd4343b..13dfce7 100644
--- a/composer.json
+++ b/composer.json
@@ -21,15 +21,15 @@
}
],
"require": {
- "php": ">=5.3.2",
- "guzzle/guzzle": "~3.8.0"
+ "php": ">=5.4.0",
+ "guzzlehttp/guzzle": "~4.0"
},
"require-dev": {
"symfony/class-loader": "*"
},
"autoload": {
"psr-0": {
- "PredictionIO": "src/"
+ "predictionio": "src/"
}
}
}
diff --git a/examples/ItemrankImport.php b/examples/ItemrankImport.php
new file mode 100644
index 0000000..f9dea16
--- /dev/null
+++ b/examples/ItemrankImport.php
@@ -0,0 +1,33 @@
+<?php
+require_once("vendor/autoload.php");
+
+use predictionio\EventClient;
+
+// check Event Server status
+$client = new EventClient(88);
+$response=$client->getStatus();
+echo($response);
+
+// set user - generate 10 users
+for ($u=1; $u<=10; $u++) {
+ $response=$client->setUser($u, array('age'=>20+$u, 'gender'=>'M'));
+ print_r($response);
+}
+
+// set item - generate 50 items
+for ($i=1; $i<=50; $i++) {
+ $response=$client->setItem($i, array('pio_itypes'=>array('1')));
+ print_r($response);
+}
+
+// record event - each user randomly views 10 items
+for ($u=1; $u<=10; $u++) {
+ for ($count=0; $count<10; $count++) {
+ $i = rand(1,50);
+ $response=$client->recordUserActionOnItem('view', $u, $i);
+ print_r($response);
+ }
+}
+
+
+?>
diff --git a/examples/ItemrankQuery.php b/examples/ItemrankQuery.php
new file mode 100644
index 0000000..2d06346
--- /dev/null
+++ b/examples/ItemrankQuery.php
@@ -0,0 +1,16 @@
+<?php
+require_once("vendor/autoload.php");
+
+use predictionio\EngineClient;
+
+$client = new EngineClient();
+$response=$client->getStatus();
+//echo $response;
+
+// Rank item 1 to 5 for each user
+for ($i=1; $i<=10; $i++) {
+ $response=$client->sendQuery(array('uid'=>$i, 'iids'=>array(1,2,3,4,5)));
+ print_r($response);
+}
+
+?>
diff --git a/examples/SampleEvent.php b/examples/SampleEvent.php
new file mode 100644
index 0000000..65138e0
--- /dev/null
+++ b/examples/SampleEvent.php
@@ -0,0 +1,68 @@
+<?php
+require_once("vendor/autoload.php");
+
+use predictionio\EventClient;
+use predictionio\PredictionIOAPIError;
+
+try {
+ // check Event Server status
+ $client = new EventClient(25);
+ $response=$client->getStatus();
+ echo($response);
+
+ // set user with event time
+ $response=$client->setUser(9, array('age'=>10),
+ '2014-01-01T10:20:30.400+08:00');
+ print_r($response);
+
+ // set user
+ $response=$client->setUser(8, array('age'=>20, 'gender'=>'M'));
+ print_r($response);
+
+ // unset user
+ $response=$client->unsetUser(8, array('age'=>20));
+ print_r($response);
+
+ // delete user
+ $response=$client->deleteUser(9);
+ print_r($response);
+
+ // set item with event time
+ $response=$client->setItem(3, array('pio_itypes'=>array('1')),
+ '2013-12-20T05:15:25.350+08:00');
+ print_r($response);
+
+ // set item
+ $response=$client->setItem(2, array('pio_itypes'=>array('1')));
+ print_r($response);
+
+ // unset item
+ $response=$client->unsetItem(2, array('pio_itypes'=>array('1')));
+ print_r($response);
+
+ // delete item
+ $response=$client->deleteItem(3, '2000-01-01T01:01:01.001+01:00');
+ print_r($response);
+
+ // record user action on item
+ $response=$client->recordUserActionOnItem('view', 8, 2);
+ print_r($response);
+
+ // create event
+ $response=$client->createEvent(array(
+ 'appId' => 25,
+ 'event' => 'my_event',
+ 'entityType' => 'pio_user',
+ 'entityId' => '8',
+ 'properties' => array('prop1'=>1, 'prop2'=>2),
+ ));
+ print_r($response);
+
+ // get event
+ $response=$client->getEvent('event_id_goes_here');
+ print_r($response);
+
+} catch (PredictionIOAPIError $e) {
+ echo $e->getMessage();
+}
+?>
diff --git a/examples/SampleImport.php b/examples/SampleImport.php
deleted file mode 100644
index 83c9adf..0000000
--- a/examples/SampleImport.php
+++ /dev/null
@@ -1,44 +0,0 @@
-<?php
-
-require_once("../build/artifacts/predictionio.phar");
-
-use PredictionIO\PredictionIOClient;
-
-if (!isset($argv[1]) || !isset($argv[2])) {
- print "Usage: $argv[0] <appkey> <data file>\n";
- exit(1);
-}
-
-$appkey = $argv[1];
-$input = $argv[2];
-
-if (!file_exists($input)) {
- print "$input not found!\n";
- exit(1);
-}
-
-if (!is_readable($input)) {
- print "$input cannot be read!\n";
- exit(1);
-}
-
-// Instantiate a client
-$client = PredictionIOClient::factory(array("appkey" => $appkey));
-
-// Scan sample data file and import ratings
-$handle = fopen($input, "r");
-while (!feof($handle)) {
- $line = fgets($handle);
- $tuple = explode("\t", $line);
- if (count($tuple) == 3) {
- try {
- $client->identify($tuple[0]);
- $client->execute($client->getCommand("record_action_on_item", array("pio_action" => "rate", "pio_iid" => $tuple[1], "pio_rate" => intval($tuple[2]))));
- } catch (Guzzle\Http\Exception\ClientErrorResponseException $e) {
- print $e->getResponse()->getBody()."\n\n";
- }
- }
-}
-fclose($handle);
-
-?>
diff --git a/examples/SampleTasks.php b/examples/SampleTasks.php
deleted file mode 100644
index c5f7218..0000000
--- a/examples/SampleTasks.php
+++ /dev/null
@@ -1,71 +0,0 @@
-<?php
-
-require_once("../build/artifacts/predictionio.phar");
-
-use PredictionIO\PredictionIOClient;
-
-if (!isset($argv[1])) {
- print "Usage: $argv[0] <appkey>\n";
- exit(1);
-}
-
-$appkey = $argv[1];
-
-// Instantiate a client
-$client = PredictionIOClient::factory(array("appkey" => $appkey));
-
-try {
- // Create, get and delete a user
- print "Create, get and delete a user:\n";
-
- $uid = "foobar";
-
- $command = $client->getCommand('create_user', array('pio_uid' => $uid));
- $command->setInactive("true");
- $command->set("gender", "F");
- $response =$client->execute($command);
- print_r($response);
-
- $command = $client->getCommand('get_user', array('pio_uid' => $uid));
- $response = $client->execute($command);
- print_r($response);
-
- $command = $client->getCommand('delete_user', array('pio_uid' => $uid));
- $response =$client->execute($command);
- print_r($response);
-
- print "\n";
-
- // Create, get and delete an item
- print "Create, get and delete an item:\n";
-
- $iid = "barbaz";
-
- $command = $client->getCommand('create_item', array('pio_iid' => $iid));
- $command->setItypes(array("dead", "beef"));
- $command->setPrice(9.99);
- $command->set("weight", "10");
- $response = $client->execute($command);
- print_r($response);
-
- $command = $client->getCommand('get_item', array('pio_iid' => $iid));
- $response = $client->execute($command);
- print_r($response);
-
- $command = $client->getCommand('delete_item', array('pio_iid' => $iid));
- $response = $client->execute($command);
- print_r($response);
-
- print "\n";
-
- // Retrieving Top N Recommendations for a User
- print "Get top 10 recommendations for a user:\n";
-
- $client->identify("1");
- $response = $client->execute($client->getCommand("itemrec_get_top_n", array("pio_engine" => "movies", "pio_n" => 10)));
- print_r($response);
-} catch (Guzzle\Http\Exception\ClientErrorResponseException $e) {
- print $e->getResponse()->getBody()."\n\n";
-}
-
-?>
diff --git a/examples/sample1.txt b/examples/sample1.txt
deleted file mode 100644
index a466652..0000000
--- a/examples/sample1.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-1 3 5
-1 2 3
-1 4 5
-2 1 2
-2 3 4
-3 4 1
diff --git a/phar-stub.php b/phar-stub.php
deleted file mode 100644
index 950d682..0000000
--- a/phar-stub.php
+++ /dev/null
@@ -1,13 +0,0 @@
-<?php
-
-Phar::mapPhar('predictionio.phar');
-
-require_once 'phar://predictionio.phar/vendor/symfony/class-loader/Symfony/Component/ClassLoader/UniversalClassLoader.php';
-
-$classLoader = new Symfony\Component\ClassLoader\UniversalClassLoader();
-$classLoader->registerNamespaces(array('PredictionIO' => 'phar://predictionio.phar/src',
- 'Symfony\\Component\\EventDispatcher' => 'phar://predictionio.phar/vendor/symfony/event-dispatcher',
- 'Guzzle' => 'phar://predictionio.phar/vendor/guzzle/guzzle/src'));
-$classLoader->register();
-
-__HALT_COMPILER();
\ No newline at end of file
diff --git a/src/PredictionIO/Command/CreateItem.php b/src/PredictionIO/Command/CreateItem.php
deleted file mode 100644
index ab02c35..0000000
--- a/src/PredictionIO/Command/CreateItem.php
+++ /dev/null
@@ -1,147 +0,0 @@
-<?php
-
-namespace PredictionIO\Command;
-
-use Guzzle\Http\Message\RequestInterface;
-use Guzzle\Service\Command\AbstractCommand;
-
-/**
- * Create Item Information
- *
- * Create or re-create an information record for a item. Re-creation will remove all data of the current record.
- *
- * To supply custom item information, simply pass it in during command creation,
- * or use the "set" method inherited from Guzzle\Common\Collection.
- * <code>
- * $command = $client->getCommand('create_item', array('pio_iid' => 'foobar', 'custom1' => 'baz'));
- * $command->set('custom2', '0xdeadbeef');
- * </code>
- *
- * @guzzle iid type="string" required="true"
- * @guzzle itypes type="string" required="true"
- * @guzzle startT type="string"
- * @guzzle endT type="string"
- * @guzzle price type="float"
- * @guzzle profit type="float"
- * @guzzle latlng type="string"
- * @guzzle inactive type="boolean"
- */
-class CreateItem extends AbstractCommand
-{
- /**
- * Set the "iid" parameter for the current command
- *
- * @param string $iid Item ID
- *
- * @return CreateItem
- */
- public function setIid($iid)
- {
- return $this->set("pio_iid", $iid);
- }
-
- /**
- * Set the "itypes" parameter for the current command
- *
- * $itypes can be supplied as an array of strings, or a "," delimited list of strings.
- *
- * @param array|string $itypes Item types
- *
- * @return CreateItem
- */
- public function setItypes($itypes)
- {
- if (is_array($itypes)) {
- return $this->set("pio_itypes", implode(",", $itypes));
- }
-
- return $this->set("pio_itypes", $itypes);
- }
-
- /**
- * Set the "startT" parameter for the current command
- *
- * @param string $startT Start time
- *
- * @return CreateItem
- */
- public function setStartT($startT)
- {
- return $this->set("pio_startT", $startT);
- }
-
- /**
- * Set the "endT" parameter for the current command
- *
- * @param string $endT End time
- *
- * @return CreateItem
- */
- public function setEndT($endT)
- {
- return $this->set("pio_endT", $endT);
- }
-
- /**
- * Set the "price" parameter for the current command
- *
- * @param float $price Price
- *
- * @return CreateItem
- */
- public function setPrice($price)
- {
- return $this->set("pio_price", $price);
- }
-
- /**
- * Set the "profit" parameter for the current command
- *
- * @param float $profit Profit
- *
- * @return CreateItem
- */
- public function setProfit($profit)
- {
- return $this->set("pio_profit", $profit);
- }
-
- /**
- * Set the "latlng" parameter for the current command
- *
- * In "latitude,longitude" format, e.g. "20.17,114.08"
- *
- * @param string $lat Latitude
- * @param string $lng Longitude
- *
- * @return CreateItem
- */
- public function setLatlng($lat, $lng = null)
- {
- if (null === $lng) {
- return $this->set("pio_latlng", $lat);
- }
-
- return $this->set("pio_latlng", sprintf("%s,%s", $lat, $lng));
- }
-
- /**
- * Set the "inactive" parameter for the current command
- *
- * @param string $inactive Inactive flag (use "true" or "false" string)
- *
- * @return CreateItem
- */
- public function setInactive($inactive)
- {
- return $this->set("pio_inactive", $inactive);
- }
-
- /**
- * Create the request object that will carry out the command. Used internally by Guzzle.
- */
- protected function build()
- {
- $this->request = $this->client->createRequest(RequestInterface::POST, 'items', null, $this->getAll());
- }
-}
diff --git a/src/PredictionIO/Command/CreateUser.php b/src/PredictionIO/Command/CreateUser.php
deleted file mode 100644
index 0a3c380..0000000
--- a/src/PredictionIO/Command/CreateUser.php
+++ /dev/null
@@ -1,76 +0,0 @@
-<?php
-
-namespace PredictionIO\Command;
-
-use Guzzle\Http\Message\RequestInterface;
-use Guzzle\Service\Command\AbstractCommand;
-
-/**
- * Create User Information
- *
- * Create or re-create an information record for a user. Re-creation will remove all data of the current record.
- *
- * To supply custom user information, simply pass it in during command creation,
- * or use the "set" method inherited from Guzzle\Common\Collection.
- * <code>
- * $command = $client->getCommand('create_user', array('pio_uid' => 'foobar', 'custom1' => 'baz'));
- * $command->set('custom2', '0xdeadbeef');
- * </code>
- *
- * @guzzle uid type="string" required="true"
- * @guzzle latlng type="string"
- * @guzzle inactive type="boolean"
- */
-class CreateUser extends AbstractCommand
-{
- /**
- * Set the "uid" parameter for the current command
- *
- * @param string $uid User ID
- *
- * @return CreateUser
- */
- public function setUid($uid)
- {
- return $this->set("pio_uid", $uid);
- }
-
- /**
- * Set the "latlng" parameter for the current command
- *
- * In "latitude,longitude" format, e.g. "20.17,114.08"
- *
- * @param string $lat Latitude
- * @param string $lng Longitude
- *
- * @return CreateUser
- */
- public function setLatlng($lat, $lng = null)
- {
- if (null === $lng) {
- return $this->set("pio_latlng", $lat);
- }
-
- return $this->set("pio_latlng", sprintf("%s,%s", $lat, $lng));
- }
-
- /**
- * Set the "inactive" parameter for the current command
- *
- * @param bool $inactive Inactive flag (use "true" or "false" string)
- *
- * @return CreateUser
- */
- public function setInactive($inactive)
- {
- return $this->set("pio_inactive", $inactive);
- }
-
- /**
- * Create the request object that will carry out the command. Used internally by Guzzle.
- */
- protected function build()
- {
- $this->request = $this->client->createRequest(RequestInterface::POST, 'users', null, $this->getAll());
- }
-}
diff --git a/src/PredictionIO/Command/DeleteItem.php b/src/PredictionIO/Command/DeleteItem.php
deleted file mode 100644
index c8df188..0000000
--- a/src/PredictionIO/Command/DeleteItem.php
+++ /dev/null
@@ -1,36 +0,0 @@
-<?php
-
-namespace PredictionIO\Command;
-
-use Guzzle\Http\Message\RequestInterface;
-use Guzzle\Service\Command\AbstractCommand;
-
-/**
- * Delete Item Information
- *
- * Delete the information record of an item.
- *
- * @guzzle iid type="string" required="true"
- */
-class DeleteItem extends AbstractCommand
-{
- /**
- * Set the "iid" parameter for the current command
- *
- * @param string $iid Item ID
- *
- * @return DeleteItem
- */
- public function setIid($iid)
- {
- return $this->set('pio_iid', $iid);
- }
-
- /**
- * Create the request object that will carry out the command. Used internally by Guzzle.
- */
- protected function build()
- {
- $this->request = $this->client->createRequest(RequestInterface::DELETE, 'items/' . $this->get('pio_iid'));
- }
-}
diff --git a/src/PredictionIO/Command/DeleteUser.php b/src/PredictionIO/Command/DeleteUser.php
deleted file mode 100644
index 4df9c1d..0000000
--- a/src/PredictionIO/Command/DeleteUser.php
+++ /dev/null
@@ -1,36 +0,0 @@
-<?php
-
-namespace PredictionIO\Command;
-
-use Guzzle\Http\Message\RequestInterface;
-use Guzzle\Service\Command\AbstractCommand;
-
-/**
- * Delete User Information
- *
- * Delete the information record of a user.
- *
- * @guzzle uid type="string" required="true"
- */
-class DeleteUser extends AbstractCommand
-{
- /**
- * Set the "uid" parameter for the current command
- *
- * @param string $uid User ID
- *
- * @return DeleteUser
- */
- public function setUid($uid)
- {
- return $this->set('pio_uid', $uid);
- }
-
- /**
- * Create the request object that will carry out the command. Used internally by Guzzle.
- */
- protected function build()
- {
- $this->request = $this->client->createRequest(RequestInterface::DELETE, 'users/' . $this->get('pio_uid'));
- }
-}
diff --git a/src/PredictionIO/Command/GetItem.php b/src/PredictionIO/Command/GetItem.php
deleted file mode 100644
index 368c595..0000000
--- a/src/PredictionIO/Command/GetItem.php
+++ /dev/null
@@ -1,37 +0,0 @@
-<?php
-
-namespace PredictionIO\Command;
-
-use Guzzle\Http\Message\RequestInterface;
-use Guzzle\Service\Command\AbstractCommand;
-
-/**
- * Retrieve Item Information
- *
- * Get the information record of an item.
- * If startT/endT exists, it will be returned in UNIX UTC timestamp (milliseconds) format.
- *
- * @guzzle iid type="string" required="true"
- */
-class GetItem extends AbstractCommand
-{
- /**
- * Set the "iid" parameter for the current command
- *
- * @param string $iid Item ID
- *
- * @return GetItem
- */
- public function setIid($iid)
- {
- return $this->set('pio_iid', $iid);
- }
-
- /**
- * Create the request object that will carry out the command. Used internally by Guzzle.
- */
- protected function build()
- {
- $this->request = $this->client->createRequest(RequestInterface::GET, 'items/' . $this->get('pio_iid'));
- }
-}
diff --git a/src/PredictionIO/Command/GetUser.php b/src/PredictionIO/Command/GetUser.php
deleted file mode 100644
index 0a1a0c4..0000000
--- a/src/PredictionIO/Command/GetUser.php
+++ /dev/null
@@ -1,36 +0,0 @@
-<?php
-
-namespace PredictionIO\Command;
-
-use Guzzle\Http\Message\RequestInterface;
-use Guzzle\Service\Command\AbstractCommand;
-
-/**
- * Retrieve User Information
- *
- * Get the information record of a user.
- *
- * @guzzle uid type="string" required="true"
- */
-class GetUser extends AbstractCommand
-{
- /**
- * Set the "uid" parameter for the current command
- *
- * @param string $uid User ID
- *
- * @return GetUser
- */
- public function setUid($uid)
- {
- return $this->set('pio_uid', $uid);
- }
-
- /**
- * Create the request object that will carry out the command. Used internally by Guzzle.
- */
- protected function build()
- {
- $this->request = $this->client->createRequest(RequestInterface::GET, 'users/' . $this->get('pio_uid'));
- }
-}
diff --git a/src/PredictionIO/Command/ItemrankGetRanked.php b/src/PredictionIO/Command/ItemrankGetRanked.php
deleted file mode 100644
index 317c41d..0000000
--- a/src/PredictionIO/Command/ItemrankGetRanked.php
+++ /dev/null
@@ -1,55 +0,0 @@
-<?php
-
-namespace PredictionIO\Command;
-
-use Guzzle\Http\Message\RequestInterface;
-use Guzzle\Service\Command\AbstractCommand;
-
-/**
- * ItemRank Engine Get Items Ranking for a User
- *
- * Retrieve ranking of items for this specific user.
- *
- * @guzzle engine type="string" required="true"
- * @guzzle iids type="string" required="true"
- */
-class ItemrankGetRanked extends AbstractCommand
-{
- /**
- * Set the "engine" parameter for the current command
- *
- * @param string $engine Engine Name
- *
- * @return ItemrankGetRanked
- */
- public function setEngine($engine)
- {
- return $this->set('pio_engine', $engine);
- }
-
- /**
- * Set the "iids" parameter for the current command
- *
- * @param string $iids Comma-separated list of Item IDs
- *
- * @return ItemrankGetRanked
- */
- public function setIids($iids)
- {
- return $this->set('pio_iids', $iids);
- }
-
- /**
- * Create the request object that will carry out the command. Used internally by Guzzle.
- */
- protected function build()
- {
- $this->set('pio_uid', $this->client->getIdentity());
- $this->request = $this->client->createRequest(
- RequestInterface::GET,
- 'engines/itemrank/' . $this->get('pio_engine') . '/ranked',
- null,
- $this->getAll()
- );
- }
-}
diff --git a/src/PredictionIO/Command/ItemrecGetTopN.php b/src/PredictionIO/Command/ItemrecGetTopN.php
deleted file mode 100644
index a319483..0000000
--- a/src/PredictionIO/Command/ItemrecGetTopN.php
+++ /dev/null
@@ -1,120 +0,0 @@
-<?php
-
-namespace PredictionIO\Command;
-
-use Guzzle\Http\Message\RequestInterface;
-use Guzzle\Service\Command\AbstractCommand;
-
-/**
- * ItemRec Engine Get Top N Recommendations for a User
- *
- * Retrieve top N recommended items for this specific user.
- *
- * @guzzle engine type="string" required="true"
- * @guzzle n type="integer" required="true"
- * @guzzle itypes type="string"
- * @guzzle latlng type="string"
- * @guzzle within type="float"
- * @guzzle unit type="enum:km,mi"
- */
-class ItemrecGetTopN extends AbstractCommand
-{
- /**
- * Set the "engine" parameter for the current command
- *
- * @param string $engine Engine Name
- *
- * @return ItemrecGetTopN
- */
- public function setEngine($engine)
- {
- return $this->set('pio_engine', $engine);
- }
-
- /**
- * Set the "n" parameter for the current command
- *
- * @param integer $n N
- *
- * @return ItemrecGetTopN
- */
- public function setN($n)
- {
- return $this->set('pio_n', $n);
- }
-
- /**
- * Set the "itypes" parameter for the current command
- *
- * $itypes can be supplied as an array of integers, or a "," delimited list of integers.
- *
- * @param array|string $itypes Item types
- *
- * @return ItemrecGetTopN
- */
- public function setItypes($itypes)
- {
- if (is_array($itypes)) {
- return $this->set('pio_itypes', implode(',', $itypes));
- } else {
- return $this->set('pio_itypes', $itypes);
- }
- }
-
- /**
- * Set the "latlng" parameter for the current command
- *
- * In "latitude,longitude" format, e.g. "20.17,114.08"
- *
- * @param string $lat Latitude
- * @param string $lng Longitude
- *
- * @return ItemrecGetTopN
- */
- public function setLatlng($lat,$lng=null)
- {
- if ($lng === null) {
- return $this->set("pio_latlng", $lat);
- } else {
- return $this->set("pio_latlng", sprintf("%s,%s", $lat, $lng));
- }
- }
-
- /**
- * Set the "within" parameter for the current command
- *
- * @param float $within Radius
- *
- * @return ItemrecGetTopN
- */
- public function setWithin($within)
- {
- return $this->set('pio_within', $within);
- }
-
- /**
- * Set the "unit" parameter for the current command
- *
- * @param string $unit Unit of radius
- *
- * @return ItemrecGetTopN
- */
- public function setUnit($unit)
- {
- return $this->set('pio_unit', $unit);
- }
-
- /**
- * Create the request object that will carry out the command. Used internally by Guzzle.
- */
- protected function build()
- {
- $this->set('pio_uid', $this->client->getIdentity());
- $this->request = $this->client->createRequest(
- RequestInterface::GET,
- 'engines/itemrec/' . $this->get('pio_engine') . '/topn',
- null,
- $this->getAll()
- );
- }
-}
diff --git a/src/PredictionIO/Command/ItemsimGetTopN.php b/src/PredictionIO/Command/ItemsimGetTopN.php
deleted file mode 100644
index 217f810..0000000
--- a/src/PredictionIO/Command/ItemsimGetTopN.php
+++ /dev/null
@@ -1,132 +0,0 @@
-<?php
-
-namespace PredictionIO\Command;
-
-use Guzzle\Http\Message\RequestInterface;
-use Guzzle\Service\Command\AbstractCommand;
-
-/**
- * ItemSim Engine Get Top N Similar Items for an Item
- *
- * Retrieve top N similar items for this specific item.
- *
- * @guzzle engine type="string" required="true"
- * @guzzle iid type="string" required="true"
- * @guzzle n type="integer" required="true"
- * @guzzle itypes type="string"
- * @guzzle latlng type="string"
- * @guzzle within type="float"
- * @guzzle unit type="enum:km,mi"
- */
-class ItemsimGetTopN extends AbstractCommand
-{
- /**
- * Set the "engine" parameter for the current command
- *
- * @param string $engine Engine Name
- *
- * @return ItemsimGetTopN
- */
- public function setEngine($engine)
- {
- return $this->set('pio_engine', $engine);
- }
-
- /**
- * Set the "iid" parameter for the current command
- *
- * @param string $iid Item ID
- *
- * @return ItemsimGetTopN
- */
- public function setIid($iid)
- {
- return $this->set('pio_iid', $iid);
- }
-
- /**
- * Set the "n" parameter for the current command
- *
- * @param integer $n N
- *
- * @return ItemsimGetTopN
- */
- public function setN($n)
- {
- return $this->set('pio_n', $n);
- }
-
- /**
- * Set the "itypes" parameter for the current command
- *
- * $itypes can be supplied as an array of integers, or a "," delimited list of integers.
- *
- * @param array|string $itypes Item types
- *
- * @return ItemsimGetTopN
- */
- public function setItypes($itypes)
- {
- if (is_array($itypes)) {
- return $this->set('pio_itypes', implode(',', $itypes));
- }
-
- return $this->set('pio_itypes', $itypes);
- }
-
- /**
- * Set the "latlng" parameter for the current command
- *
- * In "latitude,longitude" format, e.g. "20.17,114.08"
- *
- * @param string $lat Latitude
- * @param string $lng Longitude
- *
- * @return ItemsimGetTopN
- */
- public function setLatlng($lat,$lng=null)
- {
- if ($lng === null) {
- return $this->set("pio_latlng", $lat);
- } else {
- return $this->set("pio_latlng", sprintf("%s,%s", $lat, $lng));
- }
- }
-
- /**
- * Set the "within" parameter for the current command
- *
- * @param float $within Radius
- *
- * @return ItemsimGetTopN
- */
- public function setWithin($within)
- {
- return $this->set('pio_within', $within);
- }
-
- /**
- * Set the "unit" parameter for the current command
- *
- * @param string $unit Unit of radius
- *
- * @return ItemsimGetTopN
- */
- public function setUnit($unit)
- {
- return $this->set('pio_unit', $unit);
- }
-
- /**
- * Create the request object that will carry out the command. Used internally by Guzzle.
- */
- protected function build()
- {
- $this->request = $this->client->createRequest(
- RequestInterface::GET,
- 'engines/itemsim/' . $this->get('pio_engine') . '/topn',
- null,
- $this->getAll()
- );
- }
-}
diff --git a/src/PredictionIO/Command/RecordActionOnItem.php b/src/PredictionIO/Command/RecordActionOnItem.php
deleted file mode 100644
index 09e3d57..0000000
--- a/src/PredictionIO/Command/RecordActionOnItem.php
+++ /dev/null
@@ -1,82 +0,0 @@
-<?php
-
-namespace PredictionIO\Command;
-
-use Guzzle\Http\Message\RequestInterface;
-use Guzzle\Service\Command\AbstractCommand;
-
-/**
- * Record an action on an item by a user
- *
- * @guzzle action type="string" required="true"
- * @guzzle iid type="string" required="true"
- * @guzzle price type="float"
- * @guzzle t type="string"
- * @guzzle latlng type="string"
- */
-class RecordActionOnItem extends AbstractCommand
-{
- /**
- * Set the "action" parameter for the current command
- *
- * @param string $action Action name
- *
- * @return RecordActionOnItem
- */
- public function setAction($action)
- {
- return $this->set('pio_action', $action);
- }
-
- /**
- * Set the "iid" parameter for the current command
- *
- * @param string $iid Item ID
- *
- * @return RecordActionOnItem
- */
- public function setIid($iid)
- {
- return $this->set('pio_iid', $iid);
- }
-
- /**
- * Set the "t" parameter for the current command
- *
- * @param string $t Time
- *
- * @return RecordActionOnItem
- */
- public function setT($t)
- {
- return $this->set('pio_t', $t * 1000);
- }
-
- /**
- * Set the "latlng" parameter for the current command
- *
- * In "latitude,longitude" format, e.g. "20.17,114.08"
- *
- * @param string $lat Latitude
- * @param string $lng Longitude
- *
- * @return RecordActionOnItem
- */
- public function setLatlng($lat, $lng = null)
- {
- if (null === $lng) {
- return $this->set("pio_latlng", $lat);
- }
-
- return $this->set("pio_latlng", sprintf("%s,%s", $lat, $lng));
- }
-
- /**
- * Create the request object that will carry out the command. Used internally by Guzzle.
- */
- protected function build()
- {
- $this->set('pio_uid', $this->client->getIdentity());
- $this->request = $this->client->createRequest(RequestInterface::POST, 'actions/u2i', null, $this->getAll());
- }
-}
diff --git a/src/PredictionIO/PredictionIOClient.php b/src/PredictionIO/PredictionIOClient.php
deleted file mode 100644
index e8dd60b..0000000
--- a/src/PredictionIO/PredictionIOClient.php
+++ /dev/null
@@ -1,147 +0,0 @@
-<?php
-
-namespace PredictionIO;
-
-use Guzzle\Http\Message\RequestInterface;
-use Guzzle\Http\EntityBodyInterface;
-use Guzzle\Common\Collection;
-use Guzzle\Service\Client;
-use Guzzle\Service\Command\AbstractCommand;
-
-/**
- * PredictionIO API Client
- *
- * This package is a web service client based on Guzzle.
- * A few quick examples are shown below.
- * For a full user guide on how to take advantage of all Guzzle features, please refer to http://guzzlephp.org.
- * Specifically, http://guzzlephp.org/tour/using_services.html#using-client-objects describes
- * how to use a web service client.
- *
- * Many REST request commands support optional arguments. They can be supplied to these commands using the set method.
- *
- * <b>Instantiate PredictionIO API Client</b>
- * <code>
- * require_once("predictionio.phar");
- * use PredictionIO\PredictionIOClient;
- * $client = PredictionIOClient::factory(array("appkey" => "<your app key>"));
- * </code>
- *
- * <b>Import a User Record from Your App</b>
- * <code>
- * // (your user registration logic)
- * $uid = get_user_from_your_db();
- * $command = $client->getCommand('create_user', array('pio_uid' => $uid));
- * $response = $client->execute($command);
- * // (other work to do for the rest of the page)
- * </code>
- *
- * <b>Import a User Action (View) form Your App</b>
- * <code>
- * $client->identify('4');
- * $client->execute($client->getCommand('record_action_on_item', array('pio_action' => 'view', 'pio_iid' => '15')));
- * // (other work to do for the rest of the page)
- * </code>
- *
- * <b>Retrieving Top N Recommendations for a User</b>
- * <code>
- * $client->identify('4');
- * $client->execute($client->getCommand('itemrec_get_top_n', array('pio_engine' => 'test', 'pio_n' => 10)));
- * // (work you need to do for the page (rendering, db queries, etc))
- * </code>
- *
- * @author The PredictionIO Team (http://prediction.io)
- * @copyright 2013 TappingStone Inc.
- */
-class PredictionIOClient extends Client
-{
- private $apiuid = NULL;
-
- /**
- * Factory method to create a new PredictionIOClient
- *
- * Configuration data is an array with these keys:
- * * appkey - App key of your PredictionIO app (required)
- * * apiurl - URL of API endpoint (optional)
- *
- * @param array|Collection $config Configuration data.
- *
- * @return PredictionIOClient
- */
- public static function factory($config = array())
- {
- $default = array('apiurl' => 'http://localhost:8000');
- $required = array('appkey');
- $config = Collection::fromConfig($config, $default, $required);
-
- $client = new self($config->get('apiurl'), $config);
-
- return $client;
- }
-
- /**
- * Identify the user ID that will be used by all subsequent
- * recording of actions on items, and recommendations retrieval.
- *
- * @param string $uid User ID.
- */
- public function identify($uid)
- {
- $this->apiuid = $uid;
- }
-
- /**
- * Returns the identity (user ID) that will be used by all subsequent
- * recording of actions on items, and recommendations retrieval.
- *
- * @return string
- * @throws UnidentifiedUserException
- */
- public function getIdentity()
- {
- if (!isset($this->apiuid)) {
- throw new UnidentifiedUserException("Must call identify() before performing any user-related commands.");
- }
-
- return $this->apiuid;
- }
-
- /**
- * Create and return a new RequestInterface configured for the client.
- *
- * Used internally by the library. Do not use directly.
- *
- * @param string $method HTTP method. Default to GET.
- * @param string|array $uri Resource URI
- * @param array|Collection $headers HTTP headers
- * @param string|resource|array|EntityBodyInterface $body Entity body of request (POST/PUT) or response (GET)
- * @param array $options Array of options to apply to the request
- *
- * @return RequestInterface
- */
- public function createRequest($method = RequestInterface::GET, $uri = null, $headers = null, $body = null, array $options = array())
- {
- if (is_array($body)) {
- $body['pio_appkey'] = $this->getConfig()->get("appkey");
- } else {
- $body = array('pio_appkey' => $this->getConfig()->get("appkey"));
- }
-
- // Remove Guzzle internals to prevent them from going to the API
- unset($body[AbstractCommand::HEADERS_OPTION]);
- unset($body[AbstractCommand::ON_COMPLETE]);
- unset($body[AbstractCommand::DISABLE_VALIDATION]);
- unset($body[AbstractCommand::RESPONSE_PROCESSING]);
- unset($body[AbstractCommand::RESPONSE_BODY]);
- unset($body[AbstractCommand::HIDDEN_PARAMS]);
-
- if ($method == RequestInterface::GET || $method == RequestInterface::DELETE) {
- $request = parent::createRequest($method, $uri, $headers, null, $options);
- $request->getQuery()->replace($body);
- } else {
- $request = parent::createRequest($method, $uri, $headers, $body, $options);
- }
- $request->setPath($request->getPath() . ".json");
-
- return $request;
- }
-}
\ No newline at end of file
diff --git a/src/PredictionIO/UnidentifiedUserException.php b/src/PredictionIO/UnidentifiedUserException.php
deleted file mode 100644
index 637fda1..0000000
--- a/src/PredictionIO/UnidentifiedUserException.php
+++ /dev/null
@@ -1,11 +0,0 @@
-<?php
-
-namespace PredictionIO;
-
-/**
- * Thrown when user-related commands are called before identify() is called.
- */
-class UnidentifiedUserException extends \Exception
-{
-
-}
diff --git a/src/predictionio/BaseClient.php b/src/predictionio/BaseClient.php
new file mode 100644
index 0000000..83376de
--- /dev/null
+++ b/src/predictionio/BaseClient.php
@@ -0,0 +1,63 @@
+<?php
+
+namespace predictionio;
+
+use GuzzleHttp\Client;
+use GuzzleHttp\Exception\ClientException;
+
+/**
+ * Base client for Event and Engine client
+ *
+ */
+abstract class BaseClient {
+ private $baseUrl;
+ public $client;
+
+ /**
+ * @param string Base URL to the server
+ * @param float Timeout of the request in seconds. Use 0 to wait indefinitely
+ * @param float Number of seconds to wait while trying to connect to a server
+ */
+ public function __construct($baseUrl, $timeout, $connectTimeout) {
+ $this->baseUrl = $baseUrl;
+ $this->client = new Client([
+ 'base_url' => $this->baseUrl,
+ 'defaults' => ['timeout' => $timeout,
+ 'connect_timeout' => $connectTimeout]
+ ]);
+
+ }
+
+ /**
+ * Get the status of the Event Server or Engine Instance
+ *
+ * @return string status
+ */
+ public function getStatus() {
+ return $this->client->get('/')->getBody();
+ }
+
+ /**
+ * Send a HTTP request to the server
+ *
+ * @param string HTTP request method
+ * @param string Relative or absolute url
+ * @param string HTTP request body
+ *
+ * @return array JSON response
+ * @throws PredictionIOAPIError Request error
+ */
+ protected function sendRequest($method, $url, $body) {
+ $options = ['headers' => ['Content-Type' => 'application/json'],
+ 'body' => $body];
+ $request = $this->client->createRequest($method, $url, $options);
+
+ try {
+ $response = $this->client->send($request);
+ return $response->json();
+ } catch (ClientException $e) {
+ throw new PredictionIOAPIError($e->getMessage());
+ }
+ }
+}
+?>
diff --git a/src/predictionio/EngineClient.php b/src/predictionio/EngineClient.php
new file mode 100644
index 0000000..f45ac35
--- /dev/null
+++ b/src/predictionio/EngineClient.php
@@ -0,0 +1,37 @@
+<?php
+
+namespace predictionio;
+
+/**
+ * Client for connecting to an Engine Instance
+ *
+ */
+class EngineClient extends BaseClient {
+
+ /**
+ * @param string Base URL to the Engine Instance. Default is localhost:8000.
+ * @param float Timeout of the request in seconds. Use 0 to wait indefinitely
+ * Default is 0.
+ * @param float Number of seconds to wait while trying to connect to a server.
+ * Default is 5.
+ */
+ public function __construct($baseUrl="http://localhost:8000",
+ $timeout=0, $connectTimeout=5 ) {
+ parent::__construct($baseUrl, $timeout, $connectTimeout);
+ }
+
+ /**
+ * Send prediction query to an Engine Instance
+ *
+ * @param array Query
+ *
+ * @return array JSON response
+ *
+ * @throws PredictionIOAPIError Request error
+ */
+ public function sendQuery(array $query) {
+ return $this->sendRequest("POST", "/queries.json", json_encode($query));
+ }
+}
+
+?>
diff --git a/src/predictionio/EventClient.php b/src/predictionio/EventClient.php
new file mode 100644
index 0000000..13918f5
--- /dev/null
+++ b/src/predictionio/EventClient.php
@@ -0,0 +1,271 @@
+<?php
+
+namespace predictionio;
+use GuzzleHttp\Client;
+use \DateTime;
+
+/**
+ * Client for connecting to an Event Server
+ *
+ */
+class EventClient extends BaseClient {
+ const DATE_TIME_FORMAT = DateTime::ISO8601;
+ private $appId;
+
+ /**
+ * @param string Base URL to the Event Server. Default is localhost:7070.
+ * @param float Timeout of the request in seconds. Use 0 to wait indefinitely
+ * Default is 0.
+ * @param float Number of seconds to wait while trying to connect to a server.
+ * Default is 5.
+ */
+ public function __construct($appId, $baseUrl='http://localhost:7070',
+ $timeout=0, $connectTimeout=5 ) {
+ parent::__construct($baseUrl, $timeout, $connectTimeout);
+ $this->appId = $appId;
+ }
+
+ private function getEventTime($eventTime) {
+ $result = $eventTime;
+ if (!isset($eventTime)) {
+ $result = (new DateTime('NOW'))->format(self::DATE_TIME_FORMAT);
+ }
+
+ return $result;
+ }
+
+ /**
+ * Set a user entity
+ *
+ * @param int|string User Id
+ * @param array Properties of the user entity to set
+ * @param string Time of the event in ISO 8601 format
+ * (e.g. 2014-09-09T16:17:42.937-08:00).
+ * Default is the current time.
+ *
+ * @return string JSON response
+ *
+ * @throws PredictionIOAPIError Request error
+ */
+ public function setUser($uid, array $properties=array(), $eventTime=null) {
+ $eventTime = $this->getEventTime($eventTime);
+
+ // casting to object so that an empty array would be represented as {}
+ if (empty($properties)) $properties = (object)$properties;
+
+ $json = json_encode([
+ 'event' => '$set',
+ 'entityType' => 'pio_user',
+ 'entityId' => $uid,
+ 'appId' => $this->appId,
+ 'properties' => $properties,
+ 'eventTime' => $eventTime,
+ ]);
+
+ return $this->sendRequest('POST', '/events.json', $json);
+ }
+
+ /**
+ * Unset a user entity
+ *
+ * @param int|string User Id
+ * @param array Properties of the user entity to unset
+ * @param string Time of the event in ISO 8601 format
+ * (e.g. 2014-09-09T16:17:42.937-08:00).
+ * Default is the current time.
+ *
+ * @return string JSON response
+ *
+ * @throws PredictionIOAPIError Request error
+ */
+ public function unsetUser($uid, array $properties, $eventTime=null) {
+ $eventTime = $this->getEventTime($eventTime);
+ if (empty($properties))
+ throw new PredictionIOAPIError('Specify at least one property');
+
+ $json = json_encode([
+ 'event' => '$unset',
+ 'entityType' => 'pio_user',
+ 'entityId' => $uid,
+ 'appId' => $this->appId,
+ 'properties' => $properties,
+ 'eventTime' => $eventTime,
+ ]);
+
+ return $this->sendRequest('POST', '/events.json', $json);
+ }
+
+ /**
+ * Delete a user entity
+ *
+ * @param int|string User Id
+ * @param string Time of the event in ISO 8601 format
+ * (e.g. 2014-09-09T16:17:42.937-08:00).
+ * Default is the current time.
+ *
+ * @return string JSON response
+ *
+ * @throws PredictionIOAPIError Request error
+ */
+ public function deleteUser($uid, $eventTime=null) {
+ $eventTime = $this->getEventTime($eventTime);
+
+ $json = json_encode([
+ 'event' => '$delete',
+ 'entityType' => 'pio_user',
+ 'entityId' => $uid,
+ 'appId' => $this->appId,
+ 'eventTime' => $eventTime,
+ ]);
+
+ return $this->sendRequest('POST', '/events.json', $json);
+ }
+
+ /**
+ * Set an item entity
+ *
+ * @param int|string Item Id
+ * @param array Properties of the item entity to set
+ * @param string Time of the event in ISO 8601 format
+ * (e.g. 2014-09-09T16:17:42.937-08:00).
+ * Default is the current time.
+ *
+ * @return string JSON response
+ *
+ * @throws PredictionIOAPIError Request error
+ */
+ public function setItem($iid, array $properties=array(), $eventTime=null) {
+ $eventTime = $this->getEventTime($eventTime);
+ if (empty($properties)) $properties = (object)$properties;
+ $json = json_encode([
+ 'event' => '$set',
+ 'entityType' => 'pio_item',
+ 'entityId' => $iid,
+ 'appId' => $this->appId,
+ 'properties' => $properties,
+ 'eventTime' => $eventTime,
+ ]);
+
+ return $this->sendRequest('POST', '/events.json', $json);
+ }
+
+ /**
+ * Unset an item entity
+ *
+ * @param int|string Item Id
+ * @param array Properties of the item entity to unset
+ * @param string Time of the event in ISO 8601 format
+ * (e.g. 2014-09-09T16:17:42.937-08:00).
+ * Default is the current time.
+ *
+ * @return string JSON response
+ *
+ * @throws PredictionIOAPIError Request error
+ */
+ public function unsetItem($iid, array $properties, $eventTime=null) {
+ $eventTime = $this->getEventTime($eventTime);
+ if (empty($properties))
+ throw new PredictionIOAPIError('Specify at least one property');
+ $json = json_encode([
+ 'event' => '$unset',
+ 'entityType' => 'pio_item',
+ 'entityId' => $iid,
+ 'appId' => $this->appId,
+ 'properties' => $properties,
+ 'eventTime' => $eventTime,
+ ]);
+
+ return $this->sendRequest('POST', '/events.json', $json);
+ }
+
+ /**
+ * Delete an item entity
+ *
+ * @param int|string Item Id
+ * @param string Time of the event in ISO 8601 format
+ * (e.g. 2014-09-09T16:17:42.937-08:00).
+ * Default is the current time.
+ *
+ * @return string JSON response
+ *
+ * @throws PredictionIOAPIError Request error
+ */
+ public function deleteItem($iid, $eventTime=null) {
+ $eventTime = $this->getEventTime($eventTime);
+
+ $json = json_encode([
+ 'event' => '$delete',
+ 'entityType' => 'pio_item',
+ 'entityId' => $iid,
+ 'appId' => $this->appId,
+ 'eventTime' => $eventTime,
+ ]);
+
+ return $this->sendRequest('POST', '/events.json', $json);
+ }
+
+ /**
+ * Record a user action on an item
+ *
+ * @param string Event name
+ * @param int|string User Id
+ * @param int|string Item Id
+ * @param array Properties of the event
+ * @param string Time of the event in ISO 8601 format
+ * (e.g. 2014-09-09T16:17:42.937-08:00).
+ * Default is the current time.
+ *
+ * @return string JSON response
+ *
+ * @throws PredictionIOAPIError Request error
+ */
+ public function recordUserActionOnItem($event, $uid, $iid,
+ array $properties=array(),
+ $eventTime=null) {
+ $eventTime = $this->getEventTime($eventTime);
+ if (empty($properties)) $properties = (object)$properties;
+ $json = json_encode([
+ 'event' => $event,
+ 'entityType' => 'pio_user',
+ 'entityId' => $uid,
+ 'targetEntityType' => 'pio_item',
+ 'targetEntityId' => $iid,
+ 'appId' => $this->appId,
+ 'properties' => $properties,
+ 'eventTime' => $eventTime,
+ ]);
+
+ return $this->sendRequest('POST', '/events.json', $json);
+ }
+
+ /**
+ * Create an event
+ *
+ * @param array An array describing the event
+ *
+ * @return string JSON response
+ *
+ * @throws PredictionIOAPIError Request error
+ */
+ public function createEvent(array $data) {
+ $data['appId'] = $this->appId;
+ $json = json_encode($data);
+
+ return $this->sendRequest('POST', '/events.json', $json);
+ }
+
+ /**
+ * Retrieve an event
+ *
+ * @param string Event ID
+ *
+ * @return string JSON response
+ *
+ * @throws PredictionIOAPIError Request error
+ */
+ public function getEvent($eventId) {
+ return $this->sendRequest('GET', "/events/$eventId.json", '');
+ }
+}
+
+?>
diff --git a/src/predictionio/PredictionIOAPIError.php b/src/predictionio/PredictionIOAPIError.php
new file mode 100644
index 0000000..ca4cacd
--- /dev/null
+++ b/src/predictionio/PredictionIOAPIError.php
@@ -0,0 +1,9 @@
+<?php
+namespace predictionio;
+/**
+ * Thrown when there is an error with the request.
+ */
+class PredictionIOAPIError extends \Exception {
+
+}
+?>
diff --git a/tests/Unit/Command/CreateItemTest.php b/tests/Unit/Command/CreateItemTest.php
deleted file mode 100644
index 09d9a67..0000000
--- a/tests/Unit/Command/CreateItemTest.php
+++ /dev/null
@@ -1,98 +0,0 @@
-<?php
-
-namespace PredictionIO\Tests\Unit\Command;
-
-use PredictionIO\Command\CreateItem;
-
-/**
- * Class CreateItemTest
- *
- * @package PredictionIO\Tests\Unit\Command
- */
-class CreateItemTest extends \PHPUnit_Framework_TestCase
-{
- public function testCreateItemSetIid()
- {
- $mockIid = '1234';
- $createItemCommand = new CreateItem();
- $createItemCommand->setIid($mockIid);
-
- $this->assertSame($mockIid, $createItemCommand->get('pio_iid'));
- }
-
- public function testCreateItemSetItypesImplodesAnArrayToCommaDelimitedString()
- {
- $mockTypes = array(
- 'happy',
- 'mocked',
- 'types',
- );
- $createItemCommand = new CreateItem();
- $createItemCommand->setItypes($mockTypes);
-
- $this->assertSame(implode(',', $mockTypes), $createItemCommand->get('pio_itypes'));
- }
-
- public function testCreateItemSetItypesFromString()
- {
- $mockType = 'happy.mocked.type';
- $createItemCommand = new CreateItem();
- $createItemCommand->setItypes($mockType);
-
- $this->assertSame($mockType, $createItemCommand->get('pio_itypes'));
- }
-
- public function testCreateItemSetStartTSuccess()
- {
- $mockStartT = 'mock.startT';
- $createItemCommand = new CreateItem();
- $createItemCommand->setStartT($mockStartT);
-
- $this->assertSame($mockStartT, $createItemCommand->get('pio_startT'));
- }
-
- public function testCreateItemSetEndTSuccess()
- {
- $mockEndT = 'mock.endT';
- $createItemCommand = new CreateItem();
- $createItemCommand->setEndT($mockEndT);
-
- $this->assertSame($mockEndT, $createItemCommand->get('pio_endT'));
- }
-
- public function testCreateItemSetPriceSuccess()
- {
- $mockPrice = '1234.56';
- $createItemCommand = new CreateItem();
- $createItemCommand->setPrice($mockPrice);
-
- $this->assertSame($mockPrice, $createItemCommand->get('pio_price'));
- }
-
- public function testCreateItemSetProfitSuccess()
- {
- $mockProfit = '9876.54';
- $createItemCommand = new CreateItem();
- $createItemCommand->setProfit($mockProfit);
-
- $this->assertSame($mockProfit, $createItemCommand->get('pio_profit'));
- }
-
- public function testCreateItemSetLatlngSuccess()
- {
- $mockLatlng = '20.17,114.08';
- $createItemCommand = new CreateItem();
- $createItemCommand->setLatlng($mockLatlng);
-
- $this->assertSame($mockLatlng, $createItemCommand->get('pio_latlng'));
- }
-
- public function testCreateItemSetInactiveSuccess()
- {
- $mockInactive = 'true';
- $createItemCommand = new CreateItem();
- $createItemCommand->setInactive($mockInactive);
-
- $this->assertSame($mockInactive, $createItemCommand->get('pio_inactive'));
- }
-}
diff --git a/tests/Unit/Command/CreateUserTest.php b/tests/Unit/Command/CreateUserTest.php
deleted file mode 100644
index 15ff7ba..0000000
--- a/tests/Unit/Command/CreateUserTest.php
+++ /dev/null
@@ -1,40 +0,0 @@
-<?php
-
-namespace PredictionIO\Tests\Unit\Command;
-
-use PredictionIO\Command\CreateUser;
-
-/**
- * Class CreateUserTest
- *
- * @package PredictionIO\Tests\Unit\Command
- */
-class CreateUserTest extends \PHPUnit_Framework_TestCase
-{
- public function testCreateUserSetIid()
- {
- $mockUid = '1234';
- $createUserCommand = new CreateUser();
- $createUserCommand->setUid($mockUid);
-
- $this->assertSame($mockUid, $createUserCommand->get('pio_uid'));
- }
-
- public function testCreateUserSetLatlngSuccess()
- {
- $mockLatlng = '20.17,114.08';
- $createUserCommand = new CreateUser();
- $createUserCommand->setLatlng($mockLatlng);
-
- $this->assertSame($mockLatlng, $createUserCommand->get('pio_latlng'));
- }
-
- public function testCreateUserSetInactiveSuccess()
- {
- $mockInactive = 'true';
- $createUserCommand = new CreateUser();
- $createUserCommand->setInactive($mockInactive);
-
- $this->assertSame($mockInactive, $createUserCommand->get('pio_inactive'));
- }
-}
diff --git a/tests/Unit/Command/DeleteItemTest.php b/tests/Unit/Command/DeleteItemTest.php
deleted file mode 100644
index 5ab8cad..0000000
--- a/tests/Unit/Command/DeleteItemTest.php
+++ /dev/null
@@ -1,22 +0,0 @@
-<?php
-
-namespace PredictionIO\Tests\Unit\Command;
-
-use PredictionIO\Command\DeleteItem;
-
-/**
- * Class DeleteItemTest
- *
- * @package PredictionIO\Tests\Unit\Command
- */
-class DeleteItemTest extends \PHPUnit_Framework_TestCase
-{
- public function testDeleteItemSetIid()
- {
- $mockIid = '1234';
- $deleteItemCommand = new DeleteItem();
- $deleteItemCommand->setIid($mockIid);
-
- $this->assertSame($mockIid, $deleteItemCommand->get('pio_iid'));
- }
-}
diff --git a/tests/Unit/Command/DeleteUserTest.php b/tests/Unit/Command/DeleteUserTest.php
deleted file mode 100644
index 4b92e02..0000000
--- a/tests/Unit/Command/DeleteUserTest.php
+++ /dev/null
@@ -1,22 +0,0 @@
-<?php
-
-namespace PredictionIO\Tests\Unit\Command;
-
-use PredictionIO\Command\DeleteUser;
-
-/**
- * Class DeleteUserTest
- *
- * @package PredictionIO\Tests\Unit\Command
- */
-class DeleteUserTest extends \PHPUnit_Framework_TestCase
-{
- public function testDeleteUserSetIid()
- {
- $mockUid = '1234';
- $deleteUserCommand = new DeleteUser();
- $deleteUserCommand->setUid($mockUid);
-
- $this->assertSame($mockUid, $deleteUserCommand->get('pio_uid'));
- }
-}
diff --git a/tests/Unit/Command/GetItemTest.php b/tests/Unit/Command/GetItemTest.php
deleted file mode 100644
index 3609abd..0000000
--- a/tests/Unit/Command/GetItemTest.php
+++ /dev/null
@@ -1,22 +0,0 @@
-<?php
-
-namespace PredictionIO\Tests\Unit\Command;
-
-use PredictionIO\Command\GetItem;
-
-/**
- * Class GetItemTest
- *
- * @package PredictionIO\Tests\Unit\Command
- */
-class GetItemTest extends \PHPUnit_Framework_TestCase
-{
- public function testGetItemSetIid()
- {
- $mockIid = '1234';
- $getItemCommand = new GetItem();
- $getItemCommand->setIid($mockIid);
-
- $this->assertSame($mockIid, $getItemCommand->get('pio_iid'));
- }
-}
diff --git a/tests/Unit/Command/GetUserTest.php b/tests/Unit/Command/GetUserTest.php
deleted file mode 100644
index 0c6f8eb..0000000
--- a/tests/Unit/Command/GetUserTest.php
+++ /dev/null
@@ -1,22 +0,0 @@
-<?php
-
-namespace PredictionIO\Tests\Unit\Command;
-
-use PredictionIO\Command\GetUser;
-
-/**
- * Class GetUserTest
- *
- * @package PredictionIO\Tests\Unit\Command
- */
-class GetUserTest extends \PHPUnit_Framework_TestCase
-{
- public function testGetUserSetIid()
- {
- $mockUid = '1234';
- $getUserCommand = new GetUser();
- $getUserCommand->setUid($mockUid);
-
- $this->assertSame($mockUid, $getUserCommand->get('pio_uid'));
- }
-}
diff --git a/tests/Unit/EngineClientTest.php b/tests/Unit/EngineClientTest.php
new file mode 100644
index 0000000..bfa74f5
--- /dev/null
+++ b/tests/Unit/EngineClientTest.php
@@ -0,0 +1,35 @@
+<?php
+namespace predictionio\tests\Unit;
+
+use GuzzleHttp\Subscriber\History;
+use GuzzleHttp\Client;
+use GuzzleHttp\Subscriber\Mock;
+use GuzzleHttp\Message\Response;
+use predictionio\EngineClient;
+
+class EngineClientTest extends \PHPUnit_Framework_TestCase {
+ protected $engineClient;
+ protected $history;
+
+ protected function setUp() {
+ $this->engineClient=new EngineClient();
+ $this->history=new History();
+ $mock = new Mock([new Response(200)]);
+ $this->engineClient->client->getEmitter()->attach($this->history);
+ $this->engineClient->client->getEmitter()->attach($mock);
+ }
+
+ public function testSendQuery() {
+ $this->engineClient->sendQuery(array('uid'=>5, 'iids'=>array(1,2,3)));
+ $request=$this->history->getLastRequest();
+ $body=json_decode($request->getBody(), true);
+
+ $this->assertEquals(5,$body['uid']);
+ $this->assertEquals(array(1,2,3),$body['iids']);
+ $this->assertEquals('POST',$request->getMethod());
+ $this->assertEquals('http://localhost:8000/queries.json',$request->getUrl());
+ }
+
+}
+
+?>
diff --git a/tests/Unit/EventClientTest.php b/tests/Unit/EventClientTest.php
new file mode 100644
index 0000000..eaf72ed
--- /dev/null
+++ b/tests/Unit/EventClientTest.php
@@ -0,0 +1,282 @@
+<?php
+namespace predictionio\tests\Unit;
+
+use GuzzleHttp\Subscriber\History;
+use GuzzleHttp\Client;
+use GuzzleHttp\Subscriber\Mock;
+use GuzzleHttp\Message\Response;
+use predictionio\EventClient;
+
+class EventClientTest extends \PHPUnit_Framework_TestCase {
+ protected $eventClient;
+ protected $history;
+
+ protected function setUp() {
+ $this->eventClient=new EventClient(8);
+ $this->history=new History();
+ $mock = new Mock([new Response(200)]);
+ $this->eventClient->client->getEmitter()->attach($this->history);
+ $this->eventClient->client->getEmitter()->attach($mock);
+ }
+
+ public function testSetUser() {
+ $this->eventClient->setUser(1,array('age'=>20));
+ $request=$this->history->getLastRequest();
+ $body=json_decode($request->getBody(), true);
+
+ $this->assertEquals('$set',$body['event']);
+ $this->assertEquals('pio_user',$body['entityType']);
+ $this->assertEquals(1,$body['entityId']);
+ $this->assertEquals(8,$body['appId']);
+ $this->assertEquals(20,$body['properties']['age']);
+ $this->assertNotNull($body['eventTime']);
+ $this->assertEquals('POST',$request->getMethod());
+ $this->assertEquals('http://localhost:7070/events.json',$request->getUrl());
+ }
+
+ public function testSetUserWithEventTime() {
+ $eventTime='1982-09-25T01:23:45+0800';
+
+ $this->eventClient->setUser(1,array('age'=>20), $eventTime);
+ $request=$this->history->getLastRequest();
+ $body=json_decode($request->getBody(), true);
+
+ $this->assertEquals('$set',$body['event']);
+ $this->assertEquals($eventTime, $body['eventTime']);
+ }
+
+ public function testUnsetUser() {
+ $this->eventClient->unsetUser(1,array('age'=>20));
+ $request=$this->history->getLastRequest();
+ $body=json_decode($request->getBody(), true);
+
+ $this->assertEquals('$unset',$body['event']);
+ $this->assertEquals('pio_user',$body['entityType']);
+ $this->assertEquals(1,$body['entityId']);
+ $this->assertEquals(8,$body['appId']);
+ $this->assertEquals(20,$body['properties']['age']);
+ $this->assertNotNull($body['eventTime']);
+ $this->assertEquals('POST',$request->getMethod());
+ $this->assertEquals('http://localhost:7070/events.json',$request->getUrl());
+ }
+
+ public function testUnsetUserWithEventTime() {
+ $eventTime='1982-09-25T01:23:45+0800';
+
+ $this->eventClient->unsetUser(1,array('age'=>20), $eventTime);
+ $request=$this->history->getLastRequest();
+ $body=json_decode($request->getBody(), true);
+
+ $this->assertEquals('$unset',$body['event']);
+ $this->assertEquals($eventTime, $body['eventTime']);
+ }
+
+ /**
+ * @expectedException predictionio\PredictionIOAPIError
+ */
+ public function testUnsetUserWithoutProperties() {
+ $this->eventClient->unsetUser(1, array());
+ }
+
+ public function testDeleteUser() {
+ $this->eventClient->deleteUser(1);
+ $request=$this->history->getLastRequest();
+ $body=json_decode($request->getBody(), true);
+
+ $this->assertEquals('$delete',$body['event']);
+ $this->assertEquals('pio_user',$body['entityType']);
+ $this->assertEquals(1,$body['entityId']);
+ $this->assertEquals(8,$body['appId']);
+ $this->assertNotNull($body['eventTime']);
+ $this->assertEquals('POST',$request->getMethod());
+ $this->assertEquals('http://localhost:7070/events.json',$request->getUrl());
+ }
+
+ public function testDeleteUserWithEventTime() {
+ $eventTime='1982-09-25T01:23:45+0800';
+
+ $this->eventClient->deleteUser(1, $eventTime);
+ $request=$this->history->getLastRequest();
+ $body=json_decode($request->getBody(), true);
+
+ $this->assertEquals('$delete',$body['event']);
+ $this->assertEquals($eventTime, $body['eventTime']);
+ }
+
+ public function testSetItem() {
+ $this->eventClient->setItem(1,array('type'=>'book'));
+ $request=$this->history->getLastRequest();
+ $body=json_decode($request->getBody(), true);
+
+ $this->assertEquals('$set',$body['event']);
+ $this->assertEquals('pio_item',$body['entityType']);
+ $this->assertEquals(1,$body['entityId']);
+ $this->assertEquals(8,$body['appId']);
+ $this->assertEquals('book',$body['properties']['type']);
+ $this->assertNotNull($body['eventTime']);
+ $this->assertEquals('POST',$request->getMethod());
+ $this->assertEquals('http://localhost:7070/events.json',$request->getUrl());
+ }
+
+ public function testSetItemWithEventTime() {
+ $eventTime='1982-09-25T01:23:45+0800';
+
+ $this->eventClient->setItem(1,array('type'=>'book'), $eventTime);
+ $request=$this->history->getLastRequest();
+ $body=json_decode($request->getBody(), true);
+
+ $this->assertEquals('$set',$body['event']);
+ $this->assertEquals($eventTime, $body['eventTime']);
+ }
+
+ public function testUnsetItem() {
+ $this->eventClient->unsetItem(1,array('type'=>'book'));
+ $request=$this->history->getLastRequest();
+ $body=json_decode($request->getBody(), true);
+
+ $this->assertEquals('$unset',$body['event']);
+ $this->assertEquals('pio_item',$body['entityType']);
+ $this->assertEquals(1,$body['entityId']);
+ $this->assertEquals(8,$body['appId']);
+ $this->assertEquals('book',$body['properties']['type']);
+ $this->assertNotNull($body['eventTime']);
+ $this->assertEquals('POST',$request->getMethod());
+ $this->assertEquals('http://localhost:7070/events.json',$request->getUrl());
+ }
+
+ public function testUnsetItemWithEventTime() {
+ $eventTime='1982-09-25T01:23:45+0800';
+
+ $this->eventClient->unsetItem(1,array('type'=>'book'), $eventTime);
+ $request=$this->history->getLastRequest();
+ $body=json_decode($request->getBody(), true);
+
+ $this->assertEquals('$unset',$body['event']);
+ $this->assertEquals($eventTime, $body['eventTime']);
+ }
+
+ /**
+ * @expectedException predictionio\PredictionIOAPIError
+ */
+ public function testUnsetItemWithoutProperties() {
+ $this->eventClient->unsetItem(1, array());
+ }
+
+ public function testDeleteItem() {
+ $this->eventClient->deleteItem(1);
+ $request=$this->history->getLastRequest();
+ $body=json_decode($request->getBody(), true);
+
+ $this->assertEquals('$delete',$body['event']);
+ $this->assertEquals('pio_item',$body['entityType']);
+ $this->assertEquals(1,$body['entityId']);
+ $this->assertEquals(8,$body['appId']);
+ $this->assertNotNull($body['eventTime']);
+ $this->assertEquals('POST',$request->getMethod());
+ $this->assertEquals('http://localhost:7070/events.json',$request->getUrl());
+ }
+
+ public function testDeleteItemWithEventTime() {
+ $eventTime='1982-09-25T01:23:45+0800';
+
+ $this->eventClient->deleteItem(1, $eventTime);
+ $request=$this->history->getLastRequest();
+ $body=json_decode($request->getBody(), true);
+
+ $this->assertEquals('$delete',$body['event']);
+ $this->assertEquals($eventTime, $body['eventTime']);
+ }
+
+ public function testRecordAction() {
+ $this->eventClient->recordUserActionOnItem('view',1,888, array('count'=>2));
+ $request=$this->history->getLastRequest();
+ $body=json_decode($request->getBody(), true);
+
+ $this->assertEquals('view',$body['event']);
+ $this->assertEquals('pio_user',$body['entityType']);
+ $this->assertEquals(1,$body['entityId']);
+ $this->assertEquals('pio_item',$body['targetEntityType']);
+ $this->assertEquals(888,$body['targetEntityId']);
+ $this->assertEquals(8,$body['appId']);
+ $this->assertEquals(2,$body['properties']['count']);
+ $this->assertNotNull($body['eventTime']);
+ $this->assertEquals('POST',$request->getMethod());
+ $this->assertEquals('http://localhost:7070/events.json',$request->getUrl());
+ }
+
+ public function testRecordActionWithEventTime() {
+ $eventTime='1982-09-25T01:23:45+0800';
+
+ $this->eventClient->recordUserActionOnItem('view',1, 8, array(),$eventTime);
+ $request=$this->history->getLastRequest();
+ $body=json_decode($request->getBody(), true);
+
+ $this->assertEquals('view',$body['event']);
+ $this->assertEquals($eventTime, $body['eventTime']);
+ }
+
+ public function testCreateEvent() {
+ $this->eventClient->createEvent(array(
+ 'appId' => 8,
+ 'event' => 'my_event',
+ 'entityType' => 'user',
+ 'entityId' => 'uid',
+ 'properties' => array('prop1'=>1,
+ 'prop2'=>'value2',
+ 'prop3'=>array(1,2,3),
+ 'prop4'=>true,
+ 'prop5'=>array('a','b','c'),
+ 'prop6'=>4.56
+ ),
+ 'eventTime' => '2004-12-13T21:39:45.618-07:00'
+ ));
+ $request=$this->history->getLastRequest();
+ $body=json_decode($request->getBody(), true);
+
+ $this->assertEquals('my_event',$body['event']);
+ $this->assertEquals('user',$body['entityType']);
+ $this->assertEquals('uid',$body['entityId']);
+ $this->assertEquals(8,$body['appId']);
+ $this->assertEquals(1,$body['properties']['prop1']);
+ $this->assertEquals('value2',$body['properties']['prop2']);
+ $this->assertEquals(array(1,2,3),$body['properties']['prop3']);
+ $this->assertEquals(true,$body['properties']['prop4']);
+ $this->assertEquals(array('a','b','c'),$body['properties']['prop5']);
+ $this->assertEquals(4.56,$body['properties']['prop6']);
+ $this->assertEquals('2004-12-13T21:39:45.618-07:00',$body['eventTime']);
+ $this->assertEquals('POST',$request->getMethod());
+ $this->assertEquals('http://localhost:7070/events.json',$request->getUrl());
+ }
+
+ public function testCreateEventUsesAppIdInClient() {
+ $this->eventClient->createEvent(array(
+ 'appId' => 99,
+ 'event' => 'my_event',
+ 'entityType' => 'user',
+ 'entityId' => 'uid',
+ 'properties' => array('prop1'=>1),
+ 'eventTime' => '2004-12-13T21:39:45.618-07:00'
+ ));
+ $request=$this->history->getLastRequest();
+ $body=json_decode($request->getBody(), true);
+
+ // ignores appId in data and uses the one defined in the event client
+ $this->assertEquals(8,$body['appId']);
+ }
+
+ public function testGetEvent() {
+ $this->eventClient->getEvent('event_id');
+ $request=$this->history->getLastRequest();
+ $body=json_decode($request->getBody(), true);
+
+ $this->assertEquals('GET',$request->getMethod());
+ $this->assertEquals('http://localhost:7070/events/event_id.json',
+ $request->getUrl());
+ }
+
+
+
+
+}
+?>
+
diff --git a/tests/Unit/PredictionIOClientTest.php b/tests/Unit/PredictionIOClientTest.php
deleted file mode 100644
index 2333eee..0000000
--- a/tests/Unit/PredictionIOClientTest.php
+++ /dev/null
@@ -1,146 +0,0 @@
-<?php
-
-namespace PredictionIO\Tests\Unit;
-
-use Guzzle\Common\Collection;
-use Guzzle\Http\Message\RequestInterface;
-use Guzzle\Service\Command\AbstractCommand;
-use PredictionIO\PredictionIOClient;
-
-/**
- * Class PredictionIOClientTest
- *
- * @package PredictionIO\Tests
- */
-class PredictionIOClientTest extends \PHPUnit_Framework_TestCase
-{
- /**
- * @expectedException \Guzzle\Common\Exception\InvalidArgumentException
- * @expectedMessage Config must contain a 'appkey' key
- */
- public function testFactoryThrowsExceptionWithNoAppKey()
- {
- $config = array();
- PredictionIOClient::factory($config);
- }
-
- public function testFactoryReturnsNewClient()
- {
- $config = array(
- 'appkey' => 'mock.appkey',
- );
- $client = PredictionIOClient::factory($config);
-
- $this->assertInstanceOf('\PredictionIO\PredictionIOClient', $client);
- $this->assertSame($config['appkey'], $client->getConfig('appkey'));
- }
-
- public function testFactoryWithDefaultApiUrlSuccess()
- {
- $defaultApiUrl = 'http://localhost:8000';
- $config = array(
- 'appkey' => 'mock.appkey',
- );
- $client = PredictionIOClient::factory($config);
-
- $this->assertSame($defaultApiUrl, $client->getConfig('apiurl'));
- }
-
- public function testFactoryWithDefinedApiUrlSuccess()
- {
- $config = array(
- 'appkey' => 'mock.appkey',
- 'apiurl' => 'http://mock.api:1234',
- );
- $client = PredictionIOClient::factory($config);
-
- $this->assertSame($client->getConfig('apiurl'), $client->getConfig('apiurl'));
- }
-
- public function testFactoryWithCustomConfigSuccess()
- {
- $config = array(
- 'appkey' => 'mock.appkey',
- 'customconfig' => 'mock.option',
- );
- $client = PredictionIOClient::factory($config);
-
- $this->assertSame($client->getConfig('customconfig'), $client->getConfig('customconfig'));
- }
-
- /**
- * @expectedException \PredictionIO\UnidentifiedUserException
- * @expectedExceptionMessage Must call identify() before performing any user-related commands.
- */
- public function testGetIdentityThrowsExceptionWhenNotSet()
- {
- $client = new PredictionIOClient();
- $client->getIdentity();
- }
-
- public function testSetGetIdentitySuccess()
- {
- $mockId = "0";
- $client = new PredictionIOClient();
- $client->identify($mockId);
-
- $this->assertSame($mockId, $client->getIdentity());
- }
-
- public function testCreateRequestReturnsRequestObject()
- {
- $client = new PredictionIOClient();
- $request = $client->createRequest();
-
- $this->assertInstanceOf('\Guzzle\Http\Message\Request', $request);
- }
-
- public function testCreateRequestSetMethodSuccess()
- {
- $mockMethod = RequestInterface::POST;
- $client = new PredictionIOClient();
- $request = $client->createRequest($mockMethod);
-
- $this->assertSame($mockMethod, $request->getMethod());
- }
-
- public function testCreateRequestSetUriSuccess()
- {
- $mockUri = 'http://mock.uri/method';
- $expectedUri = $mockUri.'.json?pio_appkey=';
- $client = new PredictionIOClient();
- $request = $client->createRequest(RequestInterface::GET, $mockUri);
-
- $this->assertSame($expectedUri, $request->getUrl());
- }
-
- public function testCreateRequestSetHeadersSuccess()
- {
- $headers = array(
- 'mock.header' => 'mock.value',
- );
- $client = new PredictionIOClient();
- $request = $client->createRequest(RequestInterface::GET, null, $headers);
-
- $this->assertTrue($request->getHeader('mock.header')->hasValue($headers['mock.header']));
- }
-
- public function testCreateRequestUnsetsGuzzleInternals()
- {
- $body = array(
- AbstractCommand::HEADERS_OPTION => 'mock.HEADERS_OPTION',
- AbstractCommand::ON_COMPLETE => 'mock.ON_COMPLETE',
- AbstractCommand::DISABLE_VALIDATION => 'mock.DISABLE_VALIDATION',
- AbstractCommand::RESPONSE_PROCESSING => 'mock.RESPONSE_PROCESSING',
- AbstractCommand::RESPONSE_BODY => 'mock.RESPONSE_BODY',
- );
- $client = new PredictionIOClient();
- $request = $client->createRequest(RequestInterface::GET, null, null, $body);
-
- $this->assertNull($request->getQuery()->get(AbstractCommand::HEADERS_OPTION));
- $this->assertNull($request->getQuery()->get(AbstractCommand::ON_COMPLETE));
- $this->assertNull($request->getQuery()->get(AbstractCommand::DISABLE_VALIDATION));
- $this->assertNull($request->getQuery()->get(AbstractCommand::RESPONSE_PROCESSING));
- $this->assertNull($request->getQuery()->get(AbstractCommand::RESPONSE_BODY));
- }
-}