From 5f9049f540809562063c848b622098b6ca955dc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Gallego?= Date: Wed, 4 Dec 2013 18:04:27 +0100 Subject: [PATCH 1/8] PSR-1 compliant --- src/KeenIO/Client/KeenIOClient.php | 224 +-- .../Exception/CommandTransferException.php | 1 - src/KeenIO/Resources/config/keen-io-3_0.json | 1202 ++++++++--------- 3 files changed, 720 insertions(+), 707 deletions(-) diff --git a/src/KeenIO/Client/KeenIOClient.php b/src/KeenIO/Client/KeenIOClient.php index 0eec9f4..33faf06 100755 --- a/src/KeenIO/Client/KeenIOClient.php +++ b/src/KeenIO/Client/KeenIOClient.php @@ -5,11 +5,29 @@ use Guzzle\Common\Collection; use Guzzle\Service\Client; use Guzzle\Service\Description\ServiceDescription; +use KeenIO\Exception\CommandTransferException; /** * Class KeenIOClient * * @package KeenIO\Client + * + * @method array getResources(array $args = array()) {@command KeenIO getResources} + * @method array getProjects(array $args = array()) {@command KeenIO getProjects} + * @method array getProject(array $args = array()) {@command KeenIO getProject} + * @method array getEventSchemas(array $args = array()) {@command KeenIO getEventSchemas} + * @method array addEvent(array $args = array()) {@command KeenIO addEvent} + * @method array addEvents(array $args = array()) {@command KeenIO addEvents} + * @method array count(array $args = array()) {@command KeenIO count} + * @method array countUnique(array $args = array()) {@command KeenIO countUnique} + * @method array minimum(array $args = array()) {@command KeenIO minimum} + * @method array maximum(array $args = array()) {@command KeenIO maximum} + * @method array average(array $args = array()) {@command KeenIO average} + * @method array sum(array $args = array()) {@command KeenIO sum} + * @method array selectUnique(array $args = array()) {@command KeenIO selectUnique} + * @method array funnel(array $args = array()) {@command KeenIO funnel} + * @method array multiAnalysis(array $args = array()) {@command KeenIO multiAnalysis} + * @method array extraction(array $args = array()) {@command KeenIO extraction} */ class KeenIOClient extends Client { @@ -20,7 +38,7 @@ class KeenIOClient extends Client * * @returns \KeenIO\Client\KeenIOClient */ - public static function factory( $config = array() ) + public static function factory($config = array()) { $default = array( 'baseUrl' => "https://api.keen.io/{version}/", @@ -32,30 +50,30 @@ public static function factory( $config = array() ) ); // Validate the configuration options - self::validateConfig( $config ); + self::validateConfig($config); // Create client configuration - $config = Collection::fromConfig( $config, $default ); + $config = Collection::fromConfig($config, $default); /** * Because each API Resource uses a separate type of API Key, we need to expose them all in * `commands.params`. Doing it this way allows the Service Definitions to set what API Key is used. */ $parameters = array(); - foreach( array( 'masterKey', 'writeKey', 'readKey' ) as $key ) { - $parameters[ $key ] = $config->get( $key ); + foreach(array('masterKey', 'writeKey', 'readKey') as $key) { + $parameters[$key] = $config->get($key); } - $config->set( 'command.params', $parameters ); + $config->set('command.params', $parameters); // Create the new Keen IO Client with our Configuration - $client = new self( $config->get( 'baseUrl' ), $config ); + $client = new self($config->get('baseUrl'), $config); // Set the Service Definition from the versioned file - $file = 'keen-io-' . str_replace( '.', '_', $client->getConfig( 'version' ) ) . '.json'; - $client->setDescription( ServiceDescription::factory( __DIR__ . "/../Resources/config/{$file}" ) ); + $file = 'keen-io-' . str_replace('.', '_', $client->getConfig('version')) . '.json'; + $client->setDescription(ServiceDescription::factory(__DIR__ . "/../Resources/config/{$file}")); // Set the content type header to use "application/json" for all requests - $client->setDefaultOption( 'headers', array( 'Content-Type' => 'application/json' ) ); + $client->setDefaultOption('headers', array('Content-Type' => 'application/json')); return $client; } @@ -69,16 +87,14 @@ public static function factory( $config = array() ) * @param array $args Arguments to pass to the command * * @return mixed Returns the result of the command - * @throws BadMethodCallException when a command is not found */ - public function __call( $method, $args = array() ) + public function __call($method, $args = array()) { - if ( isset( $args[0] ) && is_string( $args[0] ) ) - { - $args[0] = array( 'event_collection' => $args[0] ); + if (isset($args[0]) && is_string($args[0])) { + $args[0] = array('event_collection' => $args[0]); - if ( isset( $args[1] ) && is_array( $args[1] ) ) - $args[0] = array_merge( $args[1], $args[0] ); + if (isset($args[1]) && is_array($args[1])) + $args[0] = array_merge($args[1], $args[0]); } return $this->getCommand($method, isset($args[0]) ? $args[0] : array())->getResult(); @@ -94,55 +110,55 @@ public function __call( $method, $args = array() ) * * @return array */ - public function addBatchedEvents( $collection, $events = array(), $size = 500 ) + public function addBatchedEvents($collection, $events = array(), $size = 500) { $commands = array(); - $eventChunks = array_chunk( $events, $size ); - foreach( $eventChunks as $eventChunk ) { - $commands[ ] = $this->getCommand( "sendEvents", array( 'data' => array( $collection => $eventChunk ) ) ); + $eventChunks = array_chunk($events, $size); + foreach($eventChunks as $eventChunk) { + $commands[] = $this->getCommand('sendEvents', array('data' => array($collection => $eventChunk))); } try { - $result = $this->execute( $commands ); - } catch( CommandTransferException $e ) { + $result = $this->execute($commands); + } catch(CommandTransferException $e) { return array( - 'total' => sizeof( $eventChunks ), - 'succeeded' => sizeof( $e->getSuccessfulCommands() ), - 'failed' => sizeof( $e->getFailedCommands() ) - ); + 'total' => count($eventChunks), + 'succeeded' => count($e->getSuccessfulCommands()), + 'failed' => count($e->getFailedCommands()) + ); } - return array( 'batches' => sizeof( $eventChunks ), 'succeeded' => sizeof( $result ), 'failed' => 0 ); + return array('batches' => count($eventChunks), 'succeeded' => count($result), 'failed' => 0); } /** * Get a scoped key for an array of filters * - * @param string $apiKey The master API key to use for encryption - * @param array $filters What filters to encode into a scoped key - * @param array $allowed_operations What operations the generated scoped key will allow + * @param string $apiKey The master API key to use for encryption + * @param array $filters What filters to encode into a scoped key + * @param array $allowedOperations What operations the generated scoped key will allow * @param int $source * * @return string */ - public function getScopedKey( $apiKey, $filters, $allowed_operations, $source = MCRYPT_DEV_RANDOM ) + public function getScopedKey( $apiKey, $filters, $allowedOperations, $source = MCRYPT_DEV_RANDOM ) { $options = array( 'filters' => $filters ); - if( $allowed_operations ) { - $options[ 'allowed_operations' ] = $allowed_operations; + if (!empty($allowedOperations)) { + $options['allowed_operations'] = $allowedOperations; } - $optionsJson = $this->padString( json_encode( $options ) ); + $optionsJson = $this->padString(json_encode($options)); - $ivLength = mcrypt_get_iv_size( MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC ); - $iv = mcrypt_create_iv( $ivLength, $source ); + $ivLength = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC); + $iv = mcrypt_create_iv($ivLength, $source); - $encrypted = mcrypt_encrypt( MCRYPT_RIJNDAEL_128, $apiKey, $optionsJson, MCRYPT_MODE_CBC, $iv ); + $encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $apiKey, $optionsJson, MCRYPT_MODE_CBC, $iv); - $ivHex = bin2hex( $iv ); - $encryptedHex = bin2hex( $encrypted ); + $ivHex = bin2hex($iv); + $encryptedHex = bin2hex($encrypted); $scopedKey = $ivHex . $encryptedHex; @@ -157,11 +173,10 @@ public function getScopedKey( $apiKey, $filters, $allowed_operations, $source = * * @return string */ - protected function padString( $string, $blockSize = 32 ) + protected function padString($string, $blockSize = 32) { - - $paddingSize = $blockSize - ( strlen( $string ) % $blockSize ); - $string .= str_repeat( chr( $paddingSize ), $paddingSize ); + $paddingSize = $blockSize - (strlen($string) % $blockSize); + $string .= str_repeat(chr($paddingSize), $paddingSize); return $string; } @@ -171,46 +186,38 @@ protected function padString( $string, $blockSize = 32 ) * * @param string $apiKey The master API key to use for decryption * @param string $scopedKey The scoped Key to decrypt - * * @return mixed */ - public function decryptScopedKey( $apiKey, $scopedKey ) + public function decryptScopedKey($apiKey, $scopedKey) { + $ivLength = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC) * 2; + $ivHex = substr($scopedKey, 0, $ivLength); - $ivLength = mcrypt_get_iv_size( MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC ) * 2; - $ivHex = substr( $scopedKey, 0, $ivLength ); - - $encryptedHex = substr( $scopedKey, $ivLength ); + $encryptedHex = substr($scopedKey, $ivLength); $resultPadded = mcrypt_decrypt( - MCRYPT_RIJNDAEL_128, - $apiKey, - pack( 'H*', $encryptedHex ), - MCRYPT_MODE_CBC, - pack( 'H*', $ivHex ) - ); - - $result = $this->unpadString( $resultPadded ); - - $options = json_decode( $result, true ); + MCRYPT_RIJNDAEL_128, + $apiKey, + pack('H*', $encryptedHex), + MCRYPT_MODE_CBC, + pack('H*', $ivHex) + ); - return $options; + return json_decode($this->unpadString($resultPadded), true); } /** * Remove padding for a PKCS7-padded string * * @param string $string - * * @return string */ - protected function unpadString( $string ) + protected function unpadString($string) { + $len = strlen($string); + $pad = ord($string[$len - 1]); - $len = strlen( $string ); - $pad = ord( $string[ $len - 1 ] ); - - return substr( $string, 0, $len - $pad ); + return substr($string, 0, $len - $pad); } /** @@ -218,17 +225,16 @@ protected function unpadString( $string ) * * @param string $projectId */ - public function setProjectId( $projectId ) + public function setProjectId($projectId) { - self::validateConfig( array( 'projectId' => $projectId ) ); - - $this->getConfig()->set( 'projectId', $projectId ); + self::validateConfig(array('projectId' => $projectId)); + $this->getConfig()->set('projectId', $projectId); } /** * Gets the Project Id being used by the Keen IO Client * - * returns string|null Value of the ProjectId or NULL + * @return string|null Value of the ProjectId or NULL */ public function getProjectId() { @@ -240,23 +246,24 @@ public function getProjectId() * * @param string $writeKey */ - public function setWriteKey( $writeKey ) + public function setWriteKey($writeKey) { - self::validateConfig( array( 'writeKey' => $writeKey ) ); + self::validateConfig(array('writeKey' => $writeKey)); - $this->getConfig()->set( 'writeKey', $writeKey ); + $this->getConfig()->set('writeKey', $writeKey); // Add API Read Key to `command.params` - $params = $this->getConfig( 'command.params' ); + $params = $this->getConfig('command.params'); $params['writeKey'] = $writeKey; - $this->getConfig()->set( 'command.params', $params ); + + $this->getConfig()->set('command.params', $params); } /** * Gets the API Write Key being used by the Keen IO Client * - * returns string|null Value of the WriteKey or NULL + * @return string|null Value of the WriteKey or NULL */ public function getWriteKey() { @@ -268,22 +275,23 @@ public function getWriteKey() * * @param string $readKey */ - public function setReadKey( $readKey ) + public function setReadKey($readKey) { - self::validateConfig( array( 'readKey' => $readKey ) ); + self::validateConfig(array('readKey' => $readKey)); - $this->getConfig()->set( 'readKey', $readKey ); + $this->getConfig()->set('readKey', $readKey); // Add API Read Key to `command.params` - $params = $this->getConfig( 'command.params' ); + $params = $this->getConfig('command.params'); $params['readKey'] = $readKey; - $this->getConfig()->set( 'command.params', $params ); + + $this->getConfig()->set('command.params', $params); } /** * Gets the API Read Key being used by the Keen IO Client * - * returns string|null Value of the ReadKey or NULL + * @return string|null Value of the ReadKey or NULL */ public function getReadKey() { @@ -295,22 +303,23 @@ public function getReadKey() * * @param string $masterKey */ - public function setMasterKey( $masterKey ) + public function setMasterKey($masterKey) { - self::validateConfig( array( 'masterKey' => $masterKey ) ); + self::validateConfig(array('masterKey' => $masterKey)); - $this->getConfig()->set( 'masterKey', $masterKey ); + $this->getConfig()->set('masterKey', $masterKey); // Add API Master Key to `command.params` - $params = $this->getConfig( 'command.params' ); + $params = $this->getConfig('command.params'); $params['masterKey'] = $masterKey; - $this->getConfig()->set( 'command.params', $params ); + + $this->getConfig()->set('command.params', $params); } /** * Gets the API Master Key being used by the Keen IO Client * - * returns string|null Value of the MasterKey or NULL + * @return string|null Value of the MasterKey or NULL */ public function getMasterKey() { @@ -323,21 +332,21 @@ public function getMasterKey() * * @param string $version */ - public function setVersion( $version ) + public function setVersion($version) { - self::validateConfig( array( 'version' => $version ) ); + self::validateConfig(array('version' => $version)); - $this->getConfig()->set( 'version', $version ); + $this->getConfig()->set('version', $version); /* Set the Service Definition from the versioned file */ - $file = 'keen-io-' . str_replace( '.', '_', $this->getConfig( 'version' ) ) . '.json'; - $this->setDescription( ServiceDescription::factory( __DIR__ . "/../Resources/config/{$file}" ) ); + $file = 'keen-io-' . str_replace('.', '_', $this->getConfig('version')) . '.json'; + $this->setDescription(ServiceDescription::factory(__DIR__ . "/../Resources/config/{$file}")); } /** * Gets the Version being used by the Keen IO Client * - * returns string|null Value of the Version or NULL + * @return string|null Value of the Version or NULL */ public function getVersion() { @@ -347,27 +356,32 @@ public function getVersion() /** * Validates the Keen IO Client configuration options * - * @params array $config - * @throws InvalidArgumentException When a config value does not meet its validation criteria + * @params array $config + * @throws \InvalidArgumentException When a config value does not meet its validation criteria */ - static function validateConfig( $config = array() ) + static function validateConfig($config = array()) { - foreach( $config as $option => $value ) + foreach($config as $option => $value) { - if ( $option == 'version' && empty( $config['version'] ) ) + if ($option === 'version' && empty($config['version'])) { throw new \InvalidArgumentException("Version can not be empty"); + } - if ( $option == "readKey" && ! ctype_alnum( $value ) ) + if ($option === "readKey" && ! ctype_alnum($value)) { throw new \InvalidArgumentException( "Read Key '{$value}' contains invalid characters or spaces." ); + } - if ( $option == "writeKey" && ! ctype_alnum( $value ) ) + if ($option === "writeKey" && ! ctype_alnum($value)) { throw new \InvalidArgumentException( "Write Key '{$value}' contains invalid characters or spaces." ); + } - if ( $option == "masterKey" && ! ctype_alnum( $value ) ) + if ($option === "masterKey" && ! ctype_alnum($value)) { throw new \InvalidArgumentException( "Write Key '{$value}' contains invalid characters or spaces." ); + } - if ( $option == "projectId" && ! ctype_alnum( $value ) ) + if ($option === "projectId" && ! ctype_alnum($value)) { throw new \InvalidArgumentException( "Project ID '{$value}' contains invalid characters or spaces."); + } } } } diff --git a/src/KeenIO/Exception/CommandTransferException.php b/src/KeenIO/Exception/CommandTransferException.php index 71e4116..9327c5a 100755 --- a/src/KeenIO/Exception/CommandTransferException.php +++ b/src/KeenIO/Exception/CommandTransferException.php @@ -6,5 +6,4 @@ class CommandTransferException extends GuzzleCommandTransferException { - } diff --git a/src/KeenIO/Resources/config/keen-io-3_0.json b/src/KeenIO/Resources/config/keen-io-3_0.json index 9f59081..b91ed8a 100755 --- a/src/KeenIO/Resources/config/keen-io-3_0.json +++ b/src/KeenIO/Resources/config/keen-io-3_0.json @@ -1,603 +1,603 @@ { - "operations": { - "getResources": { - "uri": "/", - "description": "Returns the available child resources. Currently, the only child resource is the Projects Resource.", - "httpMethod": "GET", - "parameters": { - "masterKey": { - "location": "header", - "description": "The Master Api Key", - "sentAs": "Authorization", - "required": true - } - } - }, - "getProjects": { - "uri": "projects", - "description": "Returns the projects accessible to the API user, as well as links to project sub-resources for discovery.", - "httpMethod": "GET", - "parameters": { - "masterKey": { - "location": "header", - "description": "The Master API Key.", - "sentAs": "Authorization", - "required": true - } - } - }, - "getProject": { - "uri": "projects/{projectId}", - "description": "GET returns detailed information about the specific project, as well as links to related resources.", - "httpMethod": "GET", - "parameters": { - "masterKey": { - "location": "header", - "description": "The Master API Key.", - "sentAs": "Authorization", - "required": true - } - } - }, - "getEventSchemas": { - "uri": "projects/{projectId}/events", - "description": "GET returns schema information for all the event collections in this project, including properties and their type. It also returns links to sub-resources.", - "httpMethod": "GET", - "parameters": { - "masterKey": { - "location": "header", - "description": "The Master API Key.", - "sentAs": "Authorization", - "required": true - } - } - }, - "addEvent": { - "uri": "projects/{projectId}/events/{event_collection}", - "description": "POST inserts an event into the specified collection.", - "httpMethod": "POST", - "parameters": { - "writeKey": { - "location": "header", - "description": "The Write Key for the project.", - "sentAs": "Authorization", - "required": true - }, - "event_collection": { - "location": "uri", - "description": "The event collection.", - "required": true - }, - "data": { - "location": "body", - "type": "array", - "filters": [ "json_encode" ] - } - } - }, - "addEvents": { - "uri": "projects/{projectId}/events", - "description": "POST inserts multiple events in one or more collections, in a single request. The API expects a JSON object whose keys are the names of each event collection you want to insert into. Each key should point to a list of events to insert for that event collection.", - "httpMethod": "POST", - "parameters": { - "writeKey": { - "location": "header", - "description": "The Write Key for the project.", - "sentAs": "Authorization", - "required": true - }, - "data": { - "location": "body", - "type": "array", - "filters": [ "json_encode" ] - } - } - }, - "count": { - "uri": "projects/{projectId}/queries/count", - "description": "GET returns the number of resources in the event collection matching the given criteria. The response will be a simple JSON object with one key: a numeric result.", - "httpMethod": "GET", - "parameters": { - "readKey": { - "location": "header", - "description": "The Read Key for the project.", - "sentAs": "Authorization", - "required": true - }, - "event_collection": { - "location": "query", - "description": "The name of the event collection you are analyzing.", - "type": "string", - "required": true - }, - "filters": { - "location": "query", - "description": "Filters are used to narrow down the events used in an analysis request based on event property values.", - "type": "array", - "required": false - }, - "timeframe": { - "location": "query", - "description": "A Timeframe specifies the events to use for analysis based on a window of time. If no timeframe is specified, all events will be counted.", - "type": "string", - "required": false - }, - "interval": { - "location": "query", - "description": "Intervals are used when creating a Series API call. The interval specifies the length of each sub-timeframe in a Series.", - "type": "string", - "required": false - }, - "timezone": { - "location": "query", - "description": "Modifies the timeframe filters for Relative Timeframes to match a specific timezone.", - "type": "number", - "required": false - }, - "group_by": { - "location": "query", - "description": "The group_by parameter specifies the name of a property by which you would like to group the results.", - "type": [ "string", "array" ], - "filters": [ "json_encode" ], - "required": false - } - } - }, - "countUnique": { - "uri": "projects/{projectId}/queries/count_unique", - "description": "GET returns the number of UNIQUE resources in the event collection matching the given criteria. The response will be a simple JSON object with one key: result, which maps to the numeric result described previously.", - "httpMethod": "GET", - "parameters": { - "readKey": { - "location": "header", - "description": "The Read Key for the project.", - "sentAs": "Authorization", - "required": true - }, - "event_collection": { - "location": "query", - "description": "The name of the event collection you are analyzing.", - "type": "string", - "required": true - }, - "target_property": { - "location": "query", - "description": "The name of the property you are analyzing.", - "type": "string", - "required": true - }, - "filters": { - "location": "query", - "description": "Filters are used to narrow down the events used in an analysis request based on event property values.", - "type": "array", - "required": false - }, - "timeframe": { - "location": "query", - "description": "A Timeframe specifies the events to use for analysis based on a window of time. If no timeframe is specified, all events will be counted.", - "type": "string", - "required": false - }, - "interval": { - "location": "query", - "description": "Intervals are used when creating a Series API call. The interval specifies the length of each sub-timeframe in a Series.", - "type": "string", - "required": false - }, - "timezone": { - "location": "query", - "description": "Modifies the timeframe filters for Relative Timeframes to match a specific timezone.", - "type": "number", - "required": false - }, - "group_by": { - "location": "query", - "description": "The group_by parameter specifies the name of a property by which you would like to group the results.", - "type": [ "string", "array" ], - "filters": [ "json_encode" ], - "required": false - } - } - }, - "minimum": { - "uri": "projects/{projectId}/queries/minimum", - "description": "GET returns the minimum numeric value for the target property in the event collection matching the given criteria. Non-numeric values are ignored. The response will be a simple JSON object with one key: result, which maps to the numeric result described previously.", - "httpMethod": "GET", - "parameters": { - "readKey": { - "location": "header", - "description": "The Read Key for the project.", - "sentAs": "Authorization", - "required": true - }, - "event_collection": { - "location": "query", - "description": "The name of the event collection you are analyzing.", - "type": "string", - "required": true - }, - "target_property": { - "location": "query", - "description": "The name of the property you are analyzing.", - "type": "string", - "required": true - }, - "filters": { - "location": "query", - "description": "Filters are used to narrow down the events used in an analysis request based on event property values.", - "type": "array", - "required": false - }, - "timeframe": { - "location": "query", - "description": "A Timeframe specifies the events to use for analysis based on a window of time. If no timeframe is specified, all events will be counted.", - "type": "string", - "required": false - }, - "interval": { - "location": "query", - "description": "Intervals are used when creating a Series API call. The interval specifies the length of each sub-timeframe in a Series.", - "type": "string", - "required": false - }, - "timezone": { - "location": "query", - "description": "Modifies the timeframe filters for Relative Timeframes to match a specific timezone.", - "type": "number", - "required": false - }, - "group_by": { - "location": "query", - "description": "The group_by parameter specifies the name of a property by which you would like to group the results.", - "type": [ "string", "array" ], - "filters": [ "json_encode" ], - "required": false - } - } - }, - "maximum": { - "uri": "projects/{projectId}/queries/maximum", - "description": "GET returns the maximum numeric value for the target property in the event collection matching the given criteria. Non-numeric values are ignored. The response will be a simple JSON object with one key: result, which maps to the numeric result described previously.", - "httpMethod": "GET", - "parameters": { - "readKey": { - "location": "header", - "description": "The Read Key for the project.", - "sentAs": "Authorization", - "required": true - }, - "event_collection": { - "location": "query", - "description": "The name of the event collection you are analyzing.", - "type": "string", - "required": true - }, - "target_property": { - "location": "query", - "description": "The name of the property you are analyzing.", - "type": "string", - "required": true - }, - "filters": { - "location": "query", - "description": "Filters are used to narrow down the events used in an analysis request based on event property values.", - "type": "array", - "required": false - }, - "timeframe": { - "location": "query", - "description": "A Timeframe specifies the events to use for analysis based on a window of time. If no timeframe is specified, all events will be counted.", - "type": "string", - "required": false - }, - "interval": { - "location": "query", - "description": "Intervals are used when creating a Series API call. The interval specifies the length of each sub-timeframe in a Series.", - "type": "string", - "required": false - }, - "timezone": { - "location": "query", - "description": "Modifies the timeframe filters for Relative Timeframes to match a specific timezone.", - "type": "number", - "required": false - }, - "group_by": { - "location": "query", - "description": "The group_by parameter specifies the name of a property by which you would like to group the results.", - "type": [ "string", "array" ], - "filters": [ "json_encode" ], - "required": false - } - } - }, - "average": { - "uri": "projects/{projectId}/queries/average", - "description": "GET returns the average across all numeric values for the target property in the event collection matching the given criteria. Non-numeric values are ignored. The response will be a simple JSON object with one key: result, which maps to the numeric result described previously.", - "httpMethod": "GET", - "parameters": { - "readKey": { - "location": "header", - "description": "The Read Key for the project.", - "sentAs": "Authorization", - "required": true - }, - "event_collection": { - "location": "query", - "description": "The name of the event collection you are analyzing.", - "type": "string", - "required": true - }, - "target_property": { - "location": "query", - "description": "The name of the property you are analyzing.", - "type": "string", - "required": true - }, - "filters": { - "location": "query", - "description": "Filters are used to narrow down the events used in an analysis request based on event property values.", - "type": "array", - "required": false - }, - "timeframe": { - "location": "query", - "description": "A Timeframe specifies the events to use for analysis based on a window of time. If no timeframe is specified, all events will be counted.", - "type": "string", - "required": false - }, - "interval": { - "location": "query", - "description": "Intervals are used when creating a Series API call. The interval specifies the length of each sub-timeframe in a Series.", - "type": "string", - "required": false - }, - "timezone": { - "location": "query", - "description": "Modifies the timeframe filters for Relative Timeframes to match a specific timezone.", - "type": "number", - "required": false - }, - "group_by": { - "location": "query", - "description": "The group_by parameter specifies the name of a property by which you would like to group the results.", - "type": [ "string", "array" ], - "filters": [ "json_encode" ], - "required": false - } - } - }, - "sum": { - "uri": "projects/{projectId}/queries/sum", - "description": "GET returns the sum if all numeric values for the target property in the event collection matching the given criteria. Non-numeric values are ignored. The response will be a simple JSON object with one key: result, which maps to the numeric result described previously.", - "httpMethod": "GET", - "parameters": { - "readKey": { - "location": "header", - "description": "The Read Key for the project.", - "sentAs": "Authorization", - "required": true - }, - "event_collection": { - "location": "query", - "description": "The name of the event collection you are analyzing.", - "type": "string", - "required": true - }, - "target_property": { - "location": "query", - "description": "The name of the property you are analyzing.", - "type": "string", - "required": true - }, - "filters": { - "location": "query", - "description": "Filters are used to narrow down the events used in an analysis request based on event property values.", - "type": "array", - "required": false - }, - "timeframe": { - "location": "query", - "description": "A Timeframe specifies the events to use for analysis based on a window of time. If no timeframe is specified, all events will be counted.", - "type": "string", - "required": false - }, - "interval": { - "location": "query", - "description": "Intervals are used when creating a Series API call. The interval specifies the length of each sub-timeframe in a Series.", - "type": "string", - "required": false - }, - "timezone": { - "location": "query", - "description": "Modifies the timeframe filters for Relative Timeframes to match a specific timezone.", - "type": "number", - "required": false - }, - "group_by": { - "location": "query", - "description": "The group_by parameter specifies the name of a property by which you would like to group the results.", - "type": [ "string", "array" ], - "filters": [ "json_encode" ], - "required": false - } - } - }, - "selectUnique": { - "uri": "projects/{projectId}/queries/select_unique", - "description": "GET returns a list of UNIQUE resources in the event collection matching the given criteria. The response will be a simple JSON object with one key: result, which maps to an array of unique property values.", - "httpMethod": "GET", - "parameters": { - "readKey": { - "location": "header", - "description": "The Read Key for the project.", - "sentAs": "Authorization", - "required": true - }, - "event_collection": { - "location": "query", - "description": "The name of the event collection you are analyzing.", - "type": "string", - "required": true - }, - "target_property": { - "location": "query", - "description": "The name of the property you are analyzing.", - "type": "string", - "required": true - }, - "filters": { - "location": "query", - "description": "Filters are used to narrow down the events used in an analysis request based on event property values.", - "type": "array", - "required": false - }, - "timeframe": { - "location": "query", - "description": "A Timeframe specifies the events to use for analysis based on a window of time. If no timeframe is specified, all events will be counted.", - "type": "string", - "required": false - }, - "interval": { - "location": "query", - "description": "Intervals are used when creating a Series API call. The interval specifies the length of each sub-timeframe in a Series.", - "type": "string", - "required": false - }, - "timezone": { - "location": "query", - "description": "Modifies the timeframe filters for Relative Timeframes to match a specific timezone.", - "type": "number", - "required": false - }, - "group_by": { - "location": "query", - "description": "The group_by parameter specifies the name of a property by which you would like to group the results.", - "type": [ "string", "array" ], - "filters": [ "json_encode" ], - "required": false - } - } - }, - "funnel": { - "uri": "projects/{projectId}/queries/funnel", - "description": "Funnels count relevant events in succession.", - "httpMethod": "GET", - "parameters": { - "readKey": { - "location": "header", - "description": "The Read Key for the project.", - "sentAs": "Authorization", - "required": true - }, - "steps": { - "location": "query", - "description": "A URL encoded JSON Array defining the Steps in the Funnel.", - "type": "array", - "filters": [ "json_encode" ], - "required": false - } - } - }, - "multiAnalysis": { - "uri": "projects/{projectId}/queries/multi_analysis", - "description": "Multi-analysis lets you run multiple types of analysis over the same data. Performing a multi-analysis call is very similar to a Metric or a Series.", - "httpMethod": "GET", - "parameters": { - "readKey": { - "location": "header", - "description": "The Read Key for the project.", - "sentAs": "Authorization", - "required": true - }, - "event_collection": { - "location": "query", - "description": "The name of the event collection you are analyzing.", - "type": "string", - "required": true - }, - "analyses": { - "location": "query", - "description": "A URL encoded JSON object that defines the multiple types of analyses to perform.", - "type": "array", - "filters": [ "json_encode" ], - "required": true - }, - "filters": { - "location": "query", - "description": "Filters are used to narrow down the events used in an analysis request based on event property values.", - "type": "array", - "required": false - }, - "timeframe": { - "location": "query", - "description": "A Timeframe specifies the events to use for analysis based on a window of time. If no timeframe is specified, all events will be counted.", - "type": "string", - "required": false - }, - "interval": { - "location": "query", - "description": "Intervals are used when creating a Series API call. The interval specifies the length of each sub-timeframe in a Series.", - "type": "string", - "required": false - }, - "timezone": { - "location": "query", - "description": "Modifies the timeframe filters for Relative Timeframes to match a specific timezone.", - "type": "number", - "required": false - }, - "group_by": { - "location": "query", - "description": "The group_by parameter specifies the name of a property by which you would like to group the results.", - "type": [ "string", "array" ], - "filters": [ "json_encode" ], - "required": false - } - } - }, - "extraction": { - "uri": "projects/{projectId}/queries/select_unique", - "description": "GET creates an extraction request for full-form event data with all property values. If the query string parameter email is specified, then the extraction will be processed asynchronously and an e-mail will be sent to the specified address when it completes. The email will include a link to a downloadable CSV file. If email is omitted, then the extraction will be processed in-line and JSON results will be returned in the GET request.", - "httpMethod": "GET", - "parameters": { - "readKey": { - "location": "header", - "description": "The Read Key for the project.", - "sentAs": "Authorization", - "required": true - }, - "event_collection": { - "location": "query", - "description": "The name of the event collection you are analyzing.", - "type": "string", - "required": true - }, - "filters": { - "location": "query", - "description": "Filters are used to narrow down the events used in an analysis request based on event property values.", - "type": "array", - "required": false - }, - "timeframe": { - "location": "query", - "description": "A Timeframe specifies the events to use for analysis based on a window of time. If no timeframe is specified, all events will be counted.", - "type": "string", - "required": false - }, - "email": { - "location": "query", - "description": "Email that will be notified when your extraction is ready for download.", - "type": "string", - "required": false - }, - "latest": { - "location": "query", - "description": "Use this parameter to specifically request the most recent events added to a given collection. Extract up to 100 of your most recent events.", - "type": "integer", - "required": false - } - } - } - } + "operations": { + "getResources": { + "uri": "/", + "description": "Returns the available child resources. Currently, the only child resource is the Projects Resource.", + "httpMethod": "GET", + "parameters": { + "masterKey": { + "location": "header", + "description": "The Master Api Key", + "sentAs": "Authorization", + "required": true + } + } + }, + "getProjects": { + "uri": "projects", + "description": "Returns the projects accessible to the API user, as well as links to project sub-resources for discovery.", + "httpMethod": "GET", + "parameters": { + "masterKey": { + "location": "header", + "description": "The Master API Key.", + "sentAs": "Authorization", + "required": true + } + } + }, + "getProject": { + "uri": "projects/{projectId}", + "description": "GET returns detailed information about the specific project, as well as links to related resources.", + "httpMethod": "GET", + "parameters": { + "masterKey": { + "location": "header", + "description": "The Master API Key.", + "sentAs": "Authorization", + "required": true + } + } + }, + "getEventSchemas": { + "uri": "projects/{projectId}/events", + "description": "GET returns schema information for all the event collections in this project, including properties and their type. It also returns links to sub-resources.", + "httpMethod": "GET", + "parameters": { + "masterKey": { + "location": "header", + "description": "The Master API Key.", + "sentAs": "Authorization", + "required": true + } + } + }, + "addEvent": { + "uri": "projects/{projectId}/events/{event_collection}", + "description": "POST inserts an event into the specified collection.", + "httpMethod": "POST", + "parameters": { + "writeKey": { + "location": "header", + "description": "The Write Key for the project.", + "sentAs": "Authorization", + "required": true + }, + "event_collection": { + "location": "uri", + "description": "The event collection.", + "required": true + }, + "data": { + "location": "body", + "type": "array", + "filters": [ "json_encode" ] + } + } + }, + "addEvents": { + "uri": "projects/{projectId}/events", + "description": "POST inserts multiple events in one or more collections, in a single request. The API expects a JSON object whose keys are the names of each event collection you want to insert into. Each key should point to a list of events to insert for that event collection.", + "httpMethod": "POST", + "parameters": { + "writeKey": { + "location": "header", + "description": "The Write Key for the project.", + "sentAs": "Authorization", + "required": true + }, + "data": { + "location": "body", + "type": "array", + "filters": [ "json_encode" ] + } + } + }, + "count": { + "uri": "projects/{projectId}/queries/count", + "description": "GET returns the number of resources in the event collection matching the given criteria. The response will be a simple JSON object with one key: a numeric result.", + "httpMethod": "GET", + "parameters": { + "readKey": { + "location": "header", + "description": "The Read Key for the project.", + "sentAs": "Authorization", + "required": true + }, + "event_collection": { + "location": "query", + "description": "The name of the event collection you are analyzing.", + "type": "string", + "required": true + }, + "filters": { + "location": "query", + "description": "Filters are used to narrow down the events used in an analysis request based on event property values.", + "type": "array", + "required": false + }, + "timeframe": { + "location": "query", + "description": "A Timeframe specifies the events to use for analysis based on a window of time. If no timeframe is specified, all events will be counted.", + "type": "string", + "required": false + }, + "interval": { + "location": "query", + "description": "Intervals are used when creating a Series API call. The interval specifies the length of each sub-timeframe in a Series.", + "type": "string", + "required": false + }, + "timezone": { + "location": "query", + "description": "Modifies the timeframe filters for Relative Timeframes to match a specific timezone.", + "type": "number", + "required": false + }, + "group_by": { + "location": "query", + "description": "The group_by parameter specifies the name of a property by which you would like to group the results.", + "type": [ "string", "array" ], + "filters": [ "json_encode" ], + "required": false + } + } + }, + "countUnique": { + "uri": "projects/{projectId}/queries/count_unique", + "description": "GET returns the number of UNIQUE resources in the event collection matching the given criteria. The response will be a simple JSON object with one key: result, which maps to the numeric result described previously.", + "httpMethod": "GET", + "parameters": { + "readKey": { + "location": "header", + "description": "The Read Key for the project.", + "sentAs": "Authorization", + "required": true + }, + "event_collection": { + "location": "query", + "description": "The name of the event collection you are analyzing.", + "type": "string", + "required": true + }, + "target_property": { + "location": "query", + "description": "The name of the property you are analyzing.", + "type": "string", + "required": true + }, + "filters": { + "location": "query", + "description": "Filters are used to narrow down the events used in an analysis request based on event property values.", + "type": "array", + "required": false + }, + "timeframe": { + "location": "query", + "description": "A Timeframe specifies the events to use for analysis based on a window of time. If no timeframe is specified, all events will be counted.", + "type": "string", + "required": false + }, + "interval": { + "location": "query", + "description": "Intervals are used when creating a Series API call. The interval specifies the length of each sub-timeframe in a Series.", + "type": "string", + "required": false + }, + "timezone": { + "location": "query", + "description": "Modifies the timeframe filters for Relative Timeframes to match a specific timezone.", + "type": "number", + "required": false + }, + "group_by": { + "location": "query", + "description": "The group_by parameter specifies the name of a property by which you would like to group the results.", + "type": [ "string", "array" ], + "filters": [ "json_encode" ], + "required": false + } + } + }, + "minimum": { + "uri": "projects/{projectId}/queries/minimum", + "description": "GET returns the minimum numeric value for the target property in the event collection matching the given criteria. Non-numeric values are ignored. The response will be a simple JSON object with one key: result, which maps to the numeric result described previously.", + "httpMethod": "GET", + "parameters": { + "readKey": { + "location": "header", + "description": "The Read Key for the project.", + "sentAs": "Authorization", + "required": true + }, + "event_collection": { + "location": "query", + "description": "The name of the event collection you are analyzing.", + "type": "string", + "required": true + }, + "target_property": { + "location": "query", + "description": "The name of the property you are analyzing.", + "type": "string", + "required": true + }, + "filters": { + "location": "query", + "description": "Filters are used to narrow down the events used in an analysis request based on event property values.", + "type": "array", + "required": false + }, + "timeframe": { + "location": "query", + "description": "A Timeframe specifies the events to use for analysis based on a window of time. If no timeframe is specified, all events will be counted.", + "type": "string", + "required": false + }, + "interval": { + "location": "query", + "description": "Intervals are used when creating a Series API call. The interval specifies the length of each sub-timeframe in a Series.", + "type": "string", + "required": false + }, + "timezone": { + "location": "query", + "description": "Modifies the timeframe filters for Relative Timeframes to match a specific timezone.", + "type": "number", + "required": false + }, + "group_by": { + "location": "query", + "description": "The group_by parameter specifies the name of a property by which you would like to group the results.", + "type": [ "string", "array" ], + "filters": [ "json_encode" ], + "required": false + } + } + }, + "maximum": { + "uri": "projects/{projectId}/queries/maximum", + "description": "GET returns the maximum numeric value for the target property in the event collection matching the given criteria. Non-numeric values are ignored. The response will be a simple JSON object with one key: result, which maps to the numeric result described previously.", + "httpMethod": "GET", + "parameters": { + "readKey": { + "location": "header", + "description": "The Read Key for the project.", + "sentAs": "Authorization", + "required": true + }, + "event_collection": { + "location": "query", + "description": "The name of the event collection you are analyzing.", + "type": "string", + "required": true + }, + "target_property": { + "location": "query", + "description": "The name of the property you are analyzing.", + "type": "string", + "required": true + }, + "filters": { + "location": "query", + "description": "Filters are used to narrow down the events used in an analysis request based on event property values.", + "type": "array", + "required": false + }, + "timeframe": { + "location": "query", + "description": "A Timeframe specifies the events to use for analysis based on a window of time. If no timeframe is specified, all events will be counted.", + "type": "string", + "required": false + }, + "interval": { + "location": "query", + "description": "Intervals are used when creating a Series API call. The interval specifies the length of each sub-timeframe in a Series.", + "type": "string", + "required": false + }, + "timezone": { + "location": "query", + "description": "Modifies the timeframe filters for Relative Timeframes to match a specific timezone.", + "type": "number", + "required": false + }, + "group_by": { + "location": "query", + "description": "The group_by parameter specifies the name of a property by which you would like to group the results.", + "type": [ "string", "array" ], + "filters": [ "json_encode" ], + "required": false + } + } + }, + "average": { + "uri": "projects/{projectId}/queries/average", + "description": "GET returns the average across all numeric values for the target property in the event collection matching the given criteria. Non-numeric values are ignored. The response will be a simple JSON object with one key: result, which maps to the numeric result described previously.", + "httpMethod": "GET", + "parameters": { + "readKey": { + "location": "header", + "description": "The Read Key for the project.", + "sentAs": "Authorization", + "required": true + }, + "event_collection": { + "location": "query", + "description": "The name of the event collection you are analyzing.", + "type": "string", + "required": true + }, + "target_property": { + "location": "query", + "description": "The name of the property you are analyzing.", + "type": "string", + "required": true + }, + "filters": { + "location": "query", + "description": "Filters are used to narrow down the events used in an analysis request based on event property values.", + "type": "array", + "required": false + }, + "timeframe": { + "location": "query", + "description": "A Timeframe specifies the events to use for analysis based on a window of time. If no timeframe is specified, all events will be counted.", + "type": "string", + "required": false + }, + "interval": { + "location": "query", + "description": "Intervals are used when creating a Series API call. The interval specifies the length of each sub-timeframe in a Series.", + "type": "string", + "required": false + }, + "timezone": { + "location": "query", + "description": "Modifies the timeframe filters for Relative Timeframes to match a specific timezone.", + "type": "number", + "required": false + }, + "group_by": { + "location": "query", + "description": "The group_by parameter specifies the name of a property by which you would like to group the results.", + "type": [ "string", "array" ], + "filters": [ "json_encode" ], + "required": false + } + } + }, + "sum": { + "uri": "projects/{projectId}/queries/sum", + "description": "GET returns the sum if all numeric values for the target property in the event collection matching the given criteria. Non-numeric values are ignored. The response will be a simple JSON object with one key: result, which maps to the numeric result described previously.", + "httpMethod": "GET", + "parameters": { + "readKey": { + "location": "header", + "description": "The Read Key for the project.", + "sentAs": "Authorization", + "required": true + }, + "event_collection": { + "location": "query", + "description": "The name of the event collection you are analyzing.", + "type": "string", + "required": true + }, + "target_property": { + "location": "query", + "description": "The name of the property you are analyzing.", + "type": "string", + "required": true + }, + "filters": { + "location": "query", + "description": "Filters are used to narrow down the events used in an analysis request based on event property values.", + "type": "array", + "required": false + }, + "timeframe": { + "location": "query", + "description": "A Timeframe specifies the events to use for analysis based on a window of time. If no timeframe is specified, all events will be counted.", + "type": "string", + "required": false + }, + "interval": { + "location": "query", + "description": "Intervals are used when creating a Series API call. The interval specifies the length of each sub-timeframe in a Series.", + "type": "string", + "required": false + }, + "timezone": { + "location": "query", + "description": "Modifies the timeframe filters for Relative Timeframes to match a specific timezone.", + "type": "number", + "required": false + }, + "group_by": { + "location": "query", + "description": "The group_by parameter specifies the name of a property by which you would like to group the results.", + "type": [ "string", "array" ], + "filters": [ "json_encode" ], + "required": false + } + } + }, + "selectUnique": { + "uri": "projects/{projectId}/queries/select_unique", + "description": "GET returns a list of UNIQUE resources in the event collection matching the given criteria. The response will be a simple JSON object with one key: result, which maps to an array of unique property values.", + "httpMethod": "GET", + "parameters": { + "readKey": { + "location": "header", + "description": "The Read Key for the project.", + "sentAs": "Authorization", + "required": true + }, + "event_collection": { + "location": "query", + "description": "The name of the event collection you are analyzing.", + "type": "string", + "required": true + }, + "target_property": { + "location": "query", + "description": "The name of the property you are analyzing.", + "type": "string", + "required": true + }, + "filters": { + "location": "query", + "description": "Filters are used to narrow down the events used in an analysis request based on event property values.", + "type": "array", + "required": false + }, + "timeframe": { + "location": "query", + "description": "A Timeframe specifies the events to use for analysis based on a window of time. If no timeframe is specified, all events will be counted.", + "type": "string", + "required": false + }, + "interval": { + "location": "query", + "description": "Intervals are used when creating a Series API call. The interval specifies the length of each sub-timeframe in a Series.", + "type": "string", + "required": false + }, + "timezone": { + "location": "query", + "description": "Modifies the timeframe filters for Relative Timeframes to match a specific timezone.", + "type": "number", + "required": false + }, + "group_by": { + "location": "query", + "description": "The group_by parameter specifies the name of a property by which you would like to group the results.", + "type": [ "string", "array" ], + "filters": [ "json_encode" ], + "required": false + } + } + }, + "funnel": { + "uri": "projects/{projectId}/queries/funnel", + "description": "Funnels count relevant events in succession.", + "httpMethod": "GET", + "parameters": { + "readKey": { + "location": "header", + "description": "The Read Key for the project.", + "sentAs": "Authorization", + "required": true + }, + "steps": { + "location": "query", + "description": "A URL encoded JSON Array defining the Steps in the Funnel.", + "type": "array", + "filters": [ "json_encode" ], + "required": false + } + } + }, + "multiAnalysis": { + "uri": "projects/{projectId}/queries/multi_analysis", + "description": "Multi-analysis lets you run multiple types of analysis over the same data. Performing a multi-analysis call is very similar to a Metric or a Series.", + "httpMethod": "GET", + "parameters": { + "readKey": { + "location": "header", + "description": "The Read Key for the project.", + "sentAs": "Authorization", + "required": true + }, + "event_collection": { + "location": "query", + "description": "The name of the event collection you are analyzing.", + "type": "string", + "required": true + }, + "analyses": { + "location": "query", + "description": "A URL encoded JSON object that defines the multiple types of analyses to perform.", + "type": "array", + "filters": [ "json_encode" ], + "required": true + }, + "filters": { + "location": "query", + "description": "Filters are used to narrow down the events used in an analysis request based on event property values.", + "type": "array", + "required": false + }, + "timeframe": { + "location": "query", + "description": "A Timeframe specifies the events to use for analysis based on a window of time. If no timeframe is specified, all events will be counted.", + "type": "string", + "required": false + }, + "interval": { + "location": "query", + "description": "Intervals are used when creating a Series API call. The interval specifies the length of each sub-timeframe in a Series.", + "type": "string", + "required": false + }, + "timezone": { + "location": "query", + "description": "Modifies the timeframe filters for Relative Timeframes to match a specific timezone.", + "type": "number", + "required": false + }, + "group_by": { + "location": "query", + "description": "The group_by parameter specifies the name of a property by which you would like to group the results.", + "type": [ "string", "array" ], + "filters": [ "json_encode" ], + "required": false + } + } + }, + "extraction": { + "uri": "projects/{projectId}/queries/select_unique", + "description": "GET creates an extraction request for full-form event data with all property values. If the query string parameter email is specified, then the extraction will be processed asynchronously and an e-mail will be sent to the specified address when it completes. The email will include a link to a downloadable CSV file. If email is omitted, then the extraction will be processed in-line and JSON results will be returned in the GET request.", + "httpMethod": "GET", + "parameters": { + "readKey": { + "location": "header", + "description": "The Read Key for the project.", + "sentAs": "Authorization", + "required": true + }, + "event_collection": { + "location": "query", + "description": "The name of the event collection you are analyzing.", + "type": "string", + "required": true + }, + "filters": { + "location": "query", + "description": "Filters are used to narrow down the events used in an analysis request based on event property values.", + "type": "array", + "required": false + }, + "timeframe": { + "location": "query", + "description": "A Timeframe specifies the events to use for analysis based on a window of time. If no timeframe is specified, all events will be counted.", + "type": "string", + "required": false + }, + "email": { + "location": "query", + "description": "Email that will be notified when your extraction is ready for download.", + "type": "string", + "required": false + }, + "latest": { + "location": "query", + "description": "Use this parameter to specifically request the most recent events added to a given collection. Extract up to 100 of your most recent events.", + "type": "integer", + "required": false + } + } + } + } } From ef5eccef54c10d731716fa3118c7e68ccfeae6a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Gallego?= Date: Wed, 4 Dec 2013 19:15:02 +0100 Subject: [PATCH 2/8] Remove unused method --- src/KeenIO/Client/KeenIOClient.php | 33 ------------------- .../Exception/CommandTransferException.php | 9 ----- 2 files changed, 42 deletions(-) delete mode 100755 src/KeenIO/Exception/CommandTransferException.php diff --git a/src/KeenIO/Client/KeenIOClient.php b/src/KeenIO/Client/KeenIOClient.php index 33faf06..bdfc93f 100755 --- a/src/KeenIO/Client/KeenIOClient.php +++ b/src/KeenIO/Client/KeenIOClient.php @@ -5,7 +5,6 @@ use Guzzle\Common\Collection; use Guzzle\Service\Client; use Guzzle\Service\Description\ServiceDescription; -use KeenIO\Exception\CommandTransferException; /** * Class KeenIOClient @@ -100,38 +99,6 @@ public function __call($method, $args = array()) return $this->getCommand($method, isset($args[0]) ? $args[0] : array())->getResult(); } - /** - * Bulk insert events into a single event collection. - * @TODO: Better response & error handling needed before using / documenting... - * - * @param string $collection - * @param array $events - * @param int $size - * - * @return array - */ - public function addBatchedEvents($collection, $events = array(), $size = 500) - { - $commands = array(); - - $eventChunks = array_chunk($events, $size); - foreach($eventChunks as $eventChunk) { - $commands[] = $this->getCommand('sendEvents', array('data' => array($collection => $eventChunk))); - } - - try { - $result = $this->execute($commands); - } catch(CommandTransferException $e) { - return array( - 'total' => count($eventChunks), - 'succeeded' => count($e->getSuccessfulCommands()), - 'failed' => count($e->getFailedCommands()) - ); - } - - return array('batches' => count($eventChunks), 'succeeded' => count($result), 'failed' => 0); - } - /** * Get a scoped key for an array of filters * diff --git a/src/KeenIO/Exception/CommandTransferException.php b/src/KeenIO/Exception/CommandTransferException.php deleted file mode 100755 index 9327c5a..0000000 --- a/src/KeenIO/Exception/CommandTransferException.php +++ /dev/null @@ -1,9 +0,0 @@ - Date: Mon, 9 Dec 2013 20:58:13 +0100 Subject: [PATCH 3/8] Homogenize --- src/KeenIO/Client/KeenIOClient.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/KeenIO/Client/KeenIOClient.php b/src/KeenIO/Client/KeenIOClient.php index bdfc93f..e1cbfa2 100755 --- a/src/KeenIO/Client/KeenIOClient.php +++ b/src/KeenIO/Client/KeenIOClient.php @@ -40,7 +40,7 @@ class KeenIOClient extends Client public static function factory($config = array()) { $default = array( - 'baseUrl' => "https://api.keen.io/{version}/", + 'baseUrl' => 'https://api.keen.io/{version}/', 'version' => '3.0', 'masterKey' => null, 'writeKey' => null, @@ -334,19 +334,19 @@ static function validateConfig($config = array()) throw new \InvalidArgumentException("Version can not be empty"); } - if ($option === "readKey" && ! ctype_alnum($value)) { + if ($option === 'readKey' && ! ctype_alnum($value)) { throw new \InvalidArgumentException( "Read Key '{$value}' contains invalid characters or spaces." ); } - if ($option === "writeKey" && ! ctype_alnum($value)) { + if ($option === 'writeKey' && ! ctype_alnum($value)) { throw new \InvalidArgumentException( "Write Key '{$value}' contains invalid characters or spaces." ); } - if ($option === "masterKey" && ! ctype_alnum($value)) { + if ($option === 'masterKey' && ! ctype_alnum($value)) { throw new \InvalidArgumentException( "Write Key '{$value}' contains invalid characters or spaces." ); } - if ($option === "projectId" && ! ctype_alnum($value)) { + if ($option === 'projectId' && ! ctype_alnum($value)) { throw new \InvalidArgumentException( "Project ID '{$value}' contains invalid characters or spaces."); } } From 535d8b7c64700da41f90d7ac2f2f779687288b1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Gallego?= Date: Mon, 9 Dec 2013 21:07:21 +0100 Subject: [PATCH 4/8] Add deletion methods --- src/KeenIO/Resources/config/keen-io-3_0.json | 60 ++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/src/KeenIO/Resources/config/keen-io-3_0.json b/src/KeenIO/Resources/config/keen-io-3_0.json index b91ed8a..20fe3ca 100755 --- a/src/KeenIO/Resources/config/keen-io-3_0.json +++ b/src/KeenIO/Resources/config/keen-io-3_0.json @@ -93,6 +93,66 @@ } } }, + "deleteEvent": { + "uri": "projects/{projectId}/events/{event_collection}", + "description": "DELETE one or multiple events from a collection. You can optionally add filters, timeframe or timezone. You can delete up to 50,000 events using one method call", + "httpMethod": "DELETE", + "parameters": { + "masterKey": { + "location": "header", + "description": "The Master API key.", + "sentAs": "Authorization", + "required": true + }, + "event_collection": { + "location": "uri", + "description": "The event collection.", + "required": true + }, + "filters": { + "location": "query", + "description": "Filters are used to narrow down the events used in an analysis request based on event property values.", + "type": "array", + "required": false + }, + "timeframe": { + "location": "query", + "description": "A Timeframe specifies the events to use for analysis based on a window of time. If no timeframe is specified, all events will be counted.", + "type": "string", + "required": false + }, + "timezone": { + "location": "query", + "description": "Modifies the timeframe filters for Relative Timeframes to match a specific timezone.", + "type": "number", + "required": false + } + } + }, + "deleteEventProperties": { + "uri": "projects/{projectId}/events/{event_collection}/properties/{property_name}", + "description": "DELETE one property for events. This only work for properties with less than 10,000 events.", + "httpMethod": "DELETE", + "parameters": { + "writeKey": { + "location": "header", + "description": "The Write Key for the project.", + "sentAs": "Authorization", + "required": true + }, + "event_collection": { + "location": "uri", + "description": "The event collection.", + "required": true + }, + "property_name": { + "location": "query", + "description": "Name of the property to delete.", + "type": "string", + "required": true + } + } + }, "count": { "uri": "projects/{projectId}/queries/count", "description": "GET returns the number of resources in the event collection matching the given criteria. The response will be a simple JSON object with one key: a numeric result.", From 54ff809713b333803aebf263eec69f58ff007277 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Gallego?= Date: Mon, 9 Dec 2013 21:07:33 +0100 Subject: [PATCH 5/8] Add delete methods --- src/KeenIO/Client/KeenIOClient.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/KeenIO/Client/KeenIOClient.php b/src/KeenIO/Client/KeenIOClient.php index e1cbfa2..a532231 100755 --- a/src/KeenIO/Client/KeenIOClient.php +++ b/src/KeenIO/Client/KeenIOClient.php @@ -17,6 +17,8 @@ * @method array getEventSchemas(array $args = array()) {@command KeenIO getEventSchemas} * @method array addEvent(array $args = array()) {@command KeenIO addEvent} * @method array addEvents(array $args = array()) {@command KeenIO addEvents} + * @method array deleteEvents(array $args = array()) {@command KeenIO deleteEvents} + * @method array deleteEventProperties(array $args = array()) {@command KeenIO deleteEventProperties} * @method array count(array $args = array()) {@command KeenIO count} * @method array countUnique(array $args = array()) {@command KeenIO countUnique} * @method array minimum(array $args = array()) {@command KeenIO minimum} From 6b5603ce699990307295dd5c7eb6396529628a7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Gallego?= Date: Mon, 9 Dec 2013 21:14:09 +0100 Subject: [PATCH 6/8] Try to backport fix to fix conflicts --- src/KeenIO/Resources/config/keen-io-3_0.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/KeenIO/Resources/config/keen-io-3_0.json b/src/KeenIO/Resources/config/keen-io-3_0.json index 20fe3ca..90a8f09 100755 --- a/src/KeenIO/Resources/config/keen-io-3_0.json +++ b/src/KeenIO/Resources/config/keen-io-3_0.json @@ -617,7 +617,7 @@ } }, "extraction": { - "uri": "projects/{projectId}/queries/select_unique", + "uri": "projects/{projectId}/queries/extraction", "description": "GET creates an extraction request for full-form event data with all property values. If the query string parameter email is specified, then the extraction will be processed asynchronously and an e-mail will be sent to the specified address when it completes. The email will include a link to a downloadable CSV file. If email is omitted, then the extraction will be processed in-line and JSON results will be returned in the GET request.", "httpMethod": "GET", "parameters": { From 5a30ccc12e74720912dcdca00e11e460c9e20c14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Gallego?= Date: Mon, 9 Dec 2013 21:17:24 +0100 Subject: [PATCH 7/8] Remove documentation that does not apply anymore --- README.md | 54 ++++++++++-------------------------------------------- 1 file changed, 10 insertions(+), 44 deletions(-) diff --git a/README.md b/README.md index 12cbb5b..3b3f889 100755 --- a/README.md +++ b/README.md @@ -25,13 +25,13 @@ This client was built using [Guzzle](http://guzzlephp.org/), a PHP HTTP client & When you first create a new `KeenIOClient` instance you can pass configuration settings like your Project Id and API Keys in an array to the factory method. These are optional and can be later specified through Setter methods. -For certain API Resources, the Master API Key is required and can also be passed to the factory method in the configuration array. +For certain API Resources, the Master API Key is required and can also be passed to the factory method in the configuration array. Please read the [Security Documentation](https://keen.io/docs/security/) regarding this Master API key. For Requests, the `KeenIOClient` will determine what API Key should be passed based on the type of Request and configuration in the [Service Description](/src/KeenIO/Resources/config/keen-io-3_0.json). The API Key is passed in the `Authorization` header of the request. -For a list of required and available parameters for the different API Endpoints, please consult the Keen IO +For a list of required and available parameters for the different API Endpoints, please consult the Keen IO [API Reference Docs](https://keen.io/docs/api/reference/). @@ -47,7 +47,7 @@ Read API Key | `readKey` | The Read API Key - used for access to read only (GET| Write API Key | `writeKey` | The Write API Key - used for write (PUT|POST Requests) operations of the API API Version | `version` | The API Version. Currently used to version the API URL and Service Description -When passing `version` to the factory method or using the `setVersion()` method, the Client will try to load a client Service Description +When passing `version` to the factory method or using the `setVersion()` method, the Client will try to load a client Service Description that matches that version. That Service Description defines the operations available to the Webservice Client. Currently the Keen IO Webservice Client only supports - and automatically defaults - to the current version (`3.0`) of the API. @@ -56,10 +56,10 @@ Currently the Keen IO Webservice Client only supports - and automatically defaul ```php use KeenIO\Client\KeenIOClient; -$client = KeenIOClient::factory([ +$client = KeenIOClient::factory([ 'projectId' => $projectId, 'writeKey' => $writeKey, - 'readKey' => $readKey + 'readKey' => $readKey ]); ``` @@ -96,9 +96,9 @@ $client->addEvent( 'purchases', [ 'data' => $event ] ); ``` ####Send batched events to Keen -You can upload multiple Events to multiple Event Collections at once! +You can upload multiple Events to multiple Event Collections at once! -In the example below, we will create two new purchase events in the `purchases` event collection and a single +In the example below, we will create two new purchase events in the `purchases` event collection and a single new event in the `sign_ups` event collection. Note that the keys of the `data` array specify the `event_collection` where those events should be stored. @@ -115,40 +115,6 @@ $signUps = [ $client->addEvents([ 'data' => [ 'purchases' => $purchases, 'sign_ups' => $signUps ] ]); ``` -####Send batched events in Parallel -Useful for large batch processing jobs. The client will serialize each request and send them all in parallel. - -If an error is encountered during the transfer, then a `KeenIO\Exception\CommandTransferException` is thrown, which allows -you to retrieve a list of commands that succeeded and a list of commands that failed. - -For more information on parallel commands, you can check the [Guzzle docs](http://guzzlephp.org/webservice-client/webservice-client.html#executing-commands-in-parallel). - -######Example: -```php -// Split the events into chunks -$eventChunks = array_chunk( $events, 500 ); - -$commands = []; -foreach( $eventChunks as $eventChunk ) -{ - // Using getCommand will create the command with out immediately executing it - // versus using the magic methods - $commands[] = $this->getCommand( "sendEvents", [ 'data' => [ 'purchases' => $eventChunk ] ] ); -} - -try -{ - // The commands can then be passed to the client's execute method to be run - // in parallel - $result = $this->execute( $commands ); -} -catch( \KeenIO\Exception\CommandTransferException $e ) -{ - // Handle any errored commands... - $failedCommands = $e->getFailedCommands(); -} -``` - ####Get Analysis on Events All Analysis Endpoints should be supported. See the [API Reference Docs](https://keen.io/docs/api/reference/) for required parameters. You can also check the [Service Description](/src/KeenIO/Resources/config/keen-io-3_0.json) for configured API Endpoints. @@ -178,14 +144,14 @@ $stats = $client->multiAnalysis( 'purchases', [ 'analyses' => $analyses ]); ###Create a Scoped Key Scoped keys allow you to secure the requests to the API Endpoints and are especially useful when you are providing -access to multiple clients or applications. You should read the Keen IO docs concerning [Scoped Keys](https://keen.io/docs/security/#scoped-key) +access to multiple clients or applications. You should read the Keen IO docs concerning [Scoped Keys](https://keen.io/docs/security/#scoped-key) for more details. ######Example ```php $filter = [ - 'property_name' => 'user_id', - 'operator' => 'eq', + 'property_name' => 'user_id', + 'operator' => 'eq', 'property_value' => '123' ]; From 870835af00cd96006712cafe22867237e9f09a6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Gallego?= Date: Mon, 9 Dec 2013 21:20:55 +0100 Subject: [PATCH 8/8] Conventions in doc too --- README.md | 74 +++++++++++++++++++++++++++---------------------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/README.md b/README.md index 3b3f889..14c3bce 100755 --- a/README.md +++ b/README.md @@ -5,20 +5,20 @@ The Keen IO API lets developers build analytics features directly into their app [![Build Status](https://travis-ci.org/keenlabs/KeenClient-PHP.png?branch=master)](https://travis-ci.org/keenlabs/KeenClient-PHP) Installation with Composer ------------- +-------------------------- 1. Install composer via via `curl -s http://getcomposer.org/installer | php` (on windows, download http://getcomposer.org/installer and execute it with PHP) - 1. Edit your `composer.json` file with following contents: + 2. Edit your `composer.json` file with following contents: ```json "require": { - "keen-io/keen-io": "dev-master" + "keen-io/keen-io": "~1.1" } ``` 3. Run `php composer.phar install` Usage ---- +----- This client was built using [Guzzle](http://guzzlephp.org/), a PHP HTTP client & framework for building RESTful web service clients. @@ -35,7 +35,7 @@ For a list of required and available parameters for the different API Endpoints, [API Reference Docs](https://keen.io/docs/api/reference/). -####Configuring the Client +#### Configuring the Client The factory method accepts an array of configuration settings for the Keen IO Webservice Client. @@ -52,36 +52,36 @@ that matches that version. That Service Description defines the operations avail Currently the Keen IO Webservice Client only supports - and automatically defaults - to the current version (`3.0`) of the API. -######Example +###### Example ```php use KeenIO\Client\KeenIOClient; $client = KeenIOClient::factory([ 'projectId' => $projectId, - 'writeKey' => $writeKey, - 'readKey' => $readKey + 'writeKey' => $writeKey, + 'readKey' => $readKey ]); ``` -####Configuration can be updated to reuse the same Client: +#### Configuration can be updated to reuse the same Client: You can reconfigure the Keen IO Client configuration options through available getters and setters. You can get and set the following options: `projectId`, `readKey`, `writeKey`, `masterKey`, & `version`. -######Example +###### Example ```php //Get the current Project Id $client->getProjectId(); //Set a new Project Id -$client->setProjectId( $someNewProjectId ); +$client->setProjectId($someNewProjectId); //Get the current Read Key $client->getReadKey(); //Set a new Read Key -$newReadKey = $client->getScopedKey( $masterKey, $filters, $allowed_operations ); -$client->setReadKey( $newReadKey ); +$newReadKey = $client->getScopedKey($masterKey, $filters, $allowedOperations); +$client->setReadKey($newReadKey); ``` @@ -90,58 +90,58 @@ Once you've created a `KeenIOClient`, sending events is simple: ######Example ```php -$event = [ 'purchase' => [ 'item' => 'Golden Elephant' ] ]; +$event = ['purchase' => ['item' => 'Golden Elephant']]; -$client->addEvent( 'purchases', [ 'data' => $event ] ); +$client->addEvent('purchases', ['data' => $event]); ``` -####Send batched events to Keen +#### Send batched events to Keen You can upload multiple Events to multiple Event Collections at once! In the example below, we will create two new purchase events in the `purchases` event collection and a single new event in the `sign_ups` event collection. Note that the keys of the `data` array specify the `event_collection` where those events should be stored. -######Example +###### Example ```php $purchases = [ - [ 'purchase' => [ 'item' => 'Golden Elephant' ] ], - [ 'purchase' => [ 'item' => 'Magenta Elephant' ] ] + ['purchase' => ['item' => 'Golden Elephant']], + ['purchase' => ['item' => 'Magenta Elephant']] ]; $signUps = [ - [ 'name' => 'foo', 'email' => 'bar@baz.com' ] + ['name' => 'foo', 'email' => 'bar@baz.com'] ]; -$client->addEvents([ 'data' => [ 'purchases' => $purchases, 'sign_ups' => $signUps ] ]); +$client->addEvents(['data' => ['purchases' => $purchases, 'sign_ups' => $signUps]]); ``` -####Get Analysis on Events +#### Get Analysis on Events All Analysis Endpoints should be supported. See the [API Reference Docs](https://keen.io/docs/api/reference/) for required parameters. You can also check the [Service Description](/src/KeenIO/Resources/config/keen-io-3_0.json) for configured API Endpoints. Below are a few example calls to some of the Analysis methods available. -######Example -```php +###### Example +```php //Count -$totalPurchases = $client->count( 'purchases' ); +$totalPurchases = $client->count('purchases'); //Count Unqiue -$totalItems = $client->countUnique( 'purchases', [ 'target_property' => 'purchase.item' ]); +$totalItems = $client->countUnique('purchases', ['target_property' => 'purchase.item']); //Select Unique -$items = $client->selectUnique( 'purchases', [ 'target_property' => 'purchase.item' ]); +$items = $client->selectUnique('purchases', ['target_property' => 'purchase.item']); //Multi Analysis $analyses = [ - 'clicks' => [ "analysis_type" => "count" ], - 'average price' => [ "analysis_type" => "average", "target_property" => "purchase.price" ] + 'clicks' => ['analysis_type' => 'count'], + 'average price' => ['analysis_type' => 'average', 'target_property' => 'purchase.price'] ]; -$stats = $client->multiAnalysis( 'purchases', [ 'analyses' => $analyses ]); +$stats = $client->multiAnalysis('purchases', ['analyses' => $analyses]); ``` -###Create a Scoped Key +### Create a Scoped Key Scoped keys allow you to secure the requests to the API Endpoints and are especially useful when you are providing access to multiple clients or applications. You should read the Keen IO docs concerning [Scoped Keys](https://keen.io/docs/security/#scoped-key) @@ -150,14 +150,14 @@ for more details. ######Example ```php $filter = [ - 'property_name' => 'user_id', - 'operator' => 'eq', - 'property_value' => '123' + 'property_name' => 'user_id', + 'operator' => 'eq', + 'property_value' => '123' ]; -$filters = [ $filter ]; -$allowed_operations = [ 'read' ]; +$filters = [$filter]; +$allowed_operations = ['read']; -$scopedKey = $client->getScopedKey( $masterKey, $filters, $allowed_operations ); +$scopedKey = $client->getScopedKey($masterKey, $filters, $allowedOperations); ```