diff --git a/lib/influxdb-php/.travis.yml b/lib/influxdb-php/.travis.yml index c71c55677..c0865e17e 100644 --- a/lib/influxdb-php/.travis.yml +++ b/lib/influxdb-php/.travis.yml @@ -1,14 +1,18 @@ language: php +sudo: false + php: - 5.5 - 5.6 + - 7.0 install: + - composer selfupdate - composer install addons: code_climate: - repo_token: 5371d86d298d66eb9007cc8de462d7063e58f6dd85e430928834736edee479a9 + repo_token: 303a289e61e8e11d8bcae115860c4fffc6e1e7fe2d504d20a773e69bd7641284 after_script: - vendor/bin/test-reporter diff --git a/lib/influxdb-php/README.md b/lib/influxdb-php/README.md index 0972aed64..e1b81e675 100644 --- a/lib/influxdb-php/README.md +++ b/lib/influxdb-php/README.md @@ -1,21 +1,23 @@ # influxdb-php ## InfluxDB client library for PHP -[![Build Status](https://travis-ci.org/influxdb/influxdb-php.svg?branch=master)](https://travis-ci.org/influxdb/influxdb-php) -[![Code Climate](https://codeclimate.com/github/influxdb/influxdb-php/badges/gpa.svg)](https://codeclimate.com/github/influxdb/influxdb-php) -[![Test Coverage](https://codeclimate.com/github/influxdb/influxdb-php/badges/coverage.svg)](https://codeclimate.com/github/influxdb/influxdb-php/coverage) +[![Build Status](https://travis-ci.org/influxdata/influxdb-php.svg?branch=master)](https://travis-ci.org/influxdata/influxdb-php) +[![Code Climate](https://codeclimate.com/github/influxdata/influxdb-php/badges/gpa.svg)](https://codeclimate.com/github/influxdata/influxdb-php) +[![Test Coverage](https://codeclimate.com/github/influxdata/influxdb-php/badges/coverage.svg)](https://codeclimate.com/github/influxdata/influxdb-php/coverage) ### Overview -A easy to use library for using InfluxDB with PHP. +A easy to use library for using InfluxDB with PHP. Maintained by [@thecodeassassin](https://github.com/thecodeassassin), [@gianarb](https://github.com/gianarb). -The influxdb-php library was created to have php port of the python influxdb client. +The influxdb-php library was created to have php port of the python influxdb client. This way there will be a common abstraction library between different programming languages. ### Installation Installation can be done with composer: -composer require influxdb/influxdb-php:dev-master +``` bash +$ composer require influxdb/influxdb-php +``` ### NOTE for PHP 5.3 and PHP 5.4 users @@ -27,10 +29,7 @@ The 0.1.x branch will work on PHP 5.3 and PHP 5.4 but doesn't contain all the fe Initialize a new client object: ```php - $client = new InfluxDB\Client($host, $port); - - ``` This will create a new client object which you can use to read and write points to InfluxDB. @@ -38,13 +37,11 @@ This will create a new client object which you can use to read and write points It's also possible to create a client from a DSN (Data Source Name): ```php - - // directly get the database object - $database = InfluxDB\Client::fromDSN(sprintf('influxdb://user:pass@%s:%s/%s', $host, $port, $dbname)); - - // get the client to retrieve other databases - $client = $database->getClient(); - +// directly get the database object +$database = InfluxDB\Client::fromDSN(sprintf('influxdb://user:pass@%s:%s/%s', $host, $port, $dbname)); + +// get the client to retrieve other databases +$client = $database->getClient(); ``` ### Reading @@ -52,37 +49,45 @@ It's also possible to create a client from a DSN (Data Source Name): To fetch records from InfluxDB you can do a query directly on a database: ```php - - // fetch the database - $database = $client->selectDB('influx_test_db'); - - // executing a query will yield a resultset object - $result = $database->query('select * from test_metric LIMIT 5'); - - // get the points from the resultset yields an array - $points = $result->getPoints(); - +// fetch the database +$database = $client->selectDB('influx_test_db'); + +// executing a query will yield a resultset object +$result = $database->query('select * from test_metric LIMIT 5'); + +// get the points from the resultset yields an array +$points = $result->getPoints(); ``` It's also possible to use the QueryBuilder object. This is a class that simplifies the process of building queries. ```php +// retrieve points with the query builder +$result = $database->getQueryBuilder() + ->select('cpucount') + ->from('test_metric') + ->limit(2) + ->getResultSet() + ->getPoints(); - // retrieve points with the query builder - $result = $database->getQueryBuilder() - ->select('cpucount') - ->from('test_metric') - ->limit(2) - ->getResultSet() - ->getPoints(); - - - // get the query from the QueryBuilder - $query = $database->getQueryBuilder() - ->select('cpucount') - ->from('test_metric') - ->getQuery(); - +// get the query from the QueryBuilder +$query = $database->getQueryBuilder() + ->select('cpucount') + ->from('test_metric') + ->where(["region = 'us-west'"]) + ->getQuery(); +``` + +Make sure that you enter single quotes when doing a where query on strings; otherwise InfluxDB will return an empty result. + +You can get the last executed query from the client: + +```php +// use the getLastQuery() method +$lastQuery = $client->getLastQuery(); + +// or access the static variable directly: +$lastQuery = Client::lastQuery; ``` ### Writing data @@ -90,28 +95,26 @@ It's also possible to use the QueryBuilder object. This is a class that simplifi Writing data is done by providing an array of points to the writePoints method on a database: ```php +// create an array of points +$points = array( + new Point( + 'test_metric', // name of the measurement + 0.64, // the measurement value + ['host' => 'server01', 'region' => 'us-west'], // optional tags + ['cpucount' => 10], // optional additional fields + 1435255849 // Time precision has to be set to seconds! + ), + new Point( + 'test_metric', // name of the measurement + 0.84, // the measurement value + ['host' => 'server01', 'region' => 'us-west'], // optional tags + ['cpucount' => 10], // optional additional fields + 1435255849 // Time precision has to be set to seconds! + ) +); - // create an array of points - $points = array( - new Point( - 'test_metric', // name of the measurement - 0.64, // the measurement value - ['host' => 'server01', 'region' => 'us-west'], // optional tags - ['cpucount' => 10], // optional additional fields - 1435255849 // Time precision has to be set to seconds! - ), - new Point( - 'test_metric', // name of the measurement - 0.84, // the measurement value - ['host' => 'server01', 'region' => 'us-west'], // optional tags - ['cpucount' => 10], // optional additional fields - 1435255849 // Time precision has to be set to seconds! - ) - ); - - // we are writing unix timestamps, which have a second precision - $result = $database->writePoints($points, Database::PRECISION_SECONDS); - +// we are writing unix timestamps, which have a second precision +$result = $database->writePoints($points, Database::PRECISION_SECONDS); ``` It's possible to add multiple [fields](https://influxdb.com/docs/v0.9/concepts/key_concepts.html) when writing @@ -123,22 +126,22 @@ InfluxDB takes the current time as the default timestamp. You can also write multiple fields to a measurement without specifying a value: ```php - $points = [ - new Point( - 'instance', // the name of the measurement - null, // measurement value - ['host' => 'server01', 'region' => 'us-west'], // measurement tags - ['cpucount' => 10, 'free' => 1], // measurement fields - exec('date +%s%N') // timestamp in nanoseconds on Linux ONLY - ), - new Point( - 'instance', // the name of the measurement - null, // measurement value - ['host' => 'server01', 'region' => 'us-west'], // measurement tags - ['cpucount' => 10, 'free' => 2], // measurement fields - exec('date +%s%N') // timestamp in nanoseconds on Linux ONLY - ) - ]; +$points = [ + new Point( + 'instance', // the name of the measurement + null, // measurement value + ['host' => 'server01', 'region' => 'us-west'], // measurement tags + ['cpucount' => 10, 'free' => 1], // measurement fields + exec('date +%s%N') // timestamp in nanoseconds on Linux ONLY + ), + new Point( + 'instance', // the name of the measurement + null, // measurement value + ['host' => 'server01', 'region' => 'us-west'], // measurement tags + ['cpucount' => 10, 'free' => 2], // measurement fields + exec('date +%s%N') // timestamp in nanoseconds on Linux ONLY + ) +]; ``` @@ -150,39 +153,37 @@ First, set your InfluxDB host to support incoming UDP sockets: [udp] enabled = true bind-address = ":4444" - database = "test_db" + database = "test_db" ``` Then, configure the UDP driver in the client: ```php - - // set the UDP driver in the client - $client->setDriver(new \InfluxDB\Driver\UDP($client->getHost(), 4444)); - - $points = [ - new Point( - 'test_metric', - 0.84, - ['host' => 'server01', 'region' => 'us-west'], - ['cpucount' => 10], - exec('date +%s%N') // this will produce a nanosecond timestamp on Linux ONLY - ) - ]; - - // now just write your points like you normally would - $result = $database->writePoints($points); +// set the UDP driver in the client +$client->setDriver(new \InfluxDB\Driver\UDP($client->getHost(), 4444)); + +$points = [ + new Point( + 'test_metric', + 0.84, + ['host' => 'server01', 'region' => 'us-west'], + ['cpucount' => 10], + exec('date +%s%N') // this will produce a nanosecond timestamp on Linux ONLY + ) +]; + +// now just write your points like you normally would +$result = $database->writePoints($points); ``` Or simply use a DSN (Data Source Name) to send metrics using UDP: ```php +// get a database object using a DSN (Data Source Name) +$database = \InfluxDB\Client::fromDSN('udp+influxdb://username:pass@localhost:4444/test123'); - // get a database object using a DSN (Data Source Name) - $database = \InfluxDB\Client::fromDSN('udp+influxdb://username:pass@localhost:4444/test123'); - - // write your points - $result = $database->writePoints($points); +// write your points +$result = $database->writePoints($points); ``` *Note:* It is import to note that precision will be *ignored* when you use UDP. You should always use nanosecond @@ -194,66 +195,64 @@ It's important to provide the correct precision when adding a timestamp to a Poi if you specify a timestamp in seconds and the default (nanosecond) precision is set; the entered timestamp will be invalid. ```php - // Points will require a nanosecond precision (this is default as per influxdb standard) - $newPoints = $database->writePoints($points); +// Points will require a nanosecond precision (this is default as per influxdb standard) +$newPoints = $database->writePoints($points); - // Points will require second precision - $newPoints = $database->writePoints($points, Database::PRECISION_SECONDS); - - // Points will require microsecond precision - $newPoints = $database->writePoints($points, Database::PRECISION_MICROSECONDS); +// Points will require second precision +$newPoints = $database->writePoints($points, Database::PRECISION_SECONDS); + +// Points will require microsecond precision +$newPoints = $database->writePoints($points, Database::PRECISION_MICROSECONDS); ``` Please note that `exec('date + %s%N')` does NOT work under MacOS; you can use PHP's `microtime` to get a timestamp with microsecond precision, like such: ```php - list( $usec, $sec ) = explode(' ', microtime() ); - $timestamp = sprintf( '%d%06d', $sec, $usec*1000000 ); +list($usec, $sec) = explode(' ', microtime()); +$timestamp = sprintf('%d%06d', $sec, $usec*1000000); ``` ### Creating databases When creating a database a default retention policy is added. This retention policy does not have a duration -so the data will be flushed with the memory. +so the data will be flushed with the memory. This library makes it easy to provide a retention policy when creating a database: ```php - - // create the client - $client = new \InfluxDB\Client($host, $port, '', ''); +// create the client +$client = new \InfluxDB\Client($host, $port, '', ''); - // select the database - $database = $client->selectDB('influx_test_db'); +// select the database +$database = $client->selectDB('influx_test_db'); - // create the database with a retention policy - $result = $database->create(new RetentionPolicy('test', '5d', 1, true)); - - // check if a database exists then create it if it doesn't - $database = $client->selectDB('test_db'); - - if (!$database->exists()) { - $database->create(new RetentionPolicy('test', '1d', 2, true)); - } - +// create the database with a retention policy +$result = $database->create(new RetentionPolicy('test', '5d', 1, true)); + +// check if a database exists then create it if it doesn't +$database = $client->selectDB('test_db'); + +if (!$database->exists()) { + $database->create(new RetentionPolicy('test', '1d', 2, true)); +} ``` You can also alter retention policies: ```php - $database->alterRetentionPolicy(new RetentionPolicy('test', '2d', 5, true)); +$database->alterRetentionPolicy(new RetentionPolicy('test', '2d', 5, true)); ``` and list them: ```php - $result = $database->listRetentionPolicies(); +$result = $database->listRetentionPolicies(); ``` You can add more retention policies to a database: ```php - $result = $database->createRetentionPolicy(new RetentionPolicy('test2', '30d', 1, true)); +$result = $database->createRetentionPolicy(new RetentionPolicy('test2', '30d', 1, true)); ``` ### Client functions @@ -261,12 +260,11 @@ You can add more retention policies to a database: Some functions are too general for a database. So these are available in the client: ```php +// list users +$result = $client->listUsers(); - // list users - $result = $client->listUsers(); - - // list databases - $result = $client->listDatabases(); +// list databases +$result = $client->listDatabases(); ``` ### Admin functionality @@ -274,49 +272,47 @@ Some functions are too general for a database. So these are available in the cli You can use the client's $client->admin functionality to administer InfluxDB via the API. ```php - // add a new user without privileges - $client->admin->createUser('testuser123', 'testpassword'); +// add a new user without privileges +$client->admin->createUser('testuser123', 'testpassword'); - // add a new user with ALL cluster-wide privileges - $client->admin->createUser('admin_user', 'password', \InfluxDB\Client\Admin::PRIVILEGE_ALL); - - // drop user testuser123 - $client->admin->dropUser('testuser123'); +// add a new user with ALL cluster-wide privileges +$client->admin->createUser('admin_user', 'password', \InfluxDB\Client\Admin::PRIVILEGE_ALL); + +// drop user testuser123 +$client->admin->dropUser('testuser123'); ``` List all the users: ```php - // show a list of all users - $results = $client->admin->showUsers(); - - // show users returns a ResultSet object - $users = $results->getPoints(); +// show a list of all users +$results = $client->admin->showUsers(); + +// show users returns a ResultSet object +$users = $results->getPoints(); ``` #### Granting and revoking privileges -Granting permissions can be done on both the database level and cluster-wide. +Granting permissions can be done on both the database level and cluster-wide. To grant a user specific privileges on a database, provide a database object or a database name. ```php +// grant permissions using a database object +$database = $client->selectDB('test_db'); +$client->admin->grant(\InfluxDB\Client\Admin::PRIVILEGE_READ, 'testuser123', $database); - // grant permissions using a database object - $database = $client->selectDB('test_db'); - $client->admin->grant(\InfluxDB\Client\Admin::PRIVILEGE_READ, 'testuser123', $database); +// give user testuser123 read privileges on database test_db +$client->admin->grant(\InfluxDB\Client\Admin::PRIVILEGE_READ, 'testuser123', 'test_db'); - // give user testuser123 read privileges on database test_db - $client->admin->grant(\InfluxDB\Client\Admin::PRIVILEGE_READ, 'testuser123', 'test_db'); - - // revoke user testuser123's read privileges on database test_db - $client->admin->revoke(\InfluxDB\Client\Admin::PRIVILEGE_READ, 'testuser123', 'test_db'); +// revoke user testuser123's read privileges on database test_db +$client->admin->revoke(\InfluxDB\Client\Admin::PRIVILEGE_READ, 'testuser123', 'test_db'); - // grant a user cluster-wide privileges - $client->admin->grant(\InfluxDB\Client\Admin::PRIVILEGE_READ, 'testuser123'); - - // Revoke an admin's cluster-wide privileges - $client->admin->revoke(\InfluxDB\Client\Admin::PRIVILEGE_ALL, 'admin_user'); - +// grant a user cluster-wide privileges +$client->admin->grant(\InfluxDB\Client\Admin::PRIVILEGE_READ, 'testuser123'); + +// Revoke an admin's cluster-wide privileges +$client->admin->revoke(\InfluxDB\Client\Admin::PRIVILEGE_ALL, 'admin_user'); ``` ## Todo @@ -329,7 +325,38 @@ To grant a user specific privileges on a database, provide a database object or ## Changelog -####1.0.1 +###1.3.0 +* Added quoting of dbname in queries +* Added orderBy to query builder +* Fixed wrong orderby tests +* Travis container-infra and php 7 + +###1.2.2 +* Fixed issue with listUsers() method +* Added more unit tests +* Added getColumns method to \InfluxDB\ResultSet + +###1.2.0 +* Added support for 32 bit systems +* Added setters/getters for Point fields + +###1.1.3 +* Added support for symfony3 + +###1.1.2 +* Fixed issue with authentication when writing data + +###1.1.1 +* Added support for 0.9.4 +* Added if not exists support to database->create() +* Added getLastQuery method + +###1.1.0 +* Added support for 0.9.3 rc2 +* Changed the way we handle the datatypes of values +* Changed list retention policies to reflect the changes in 0.9.3 + +####1.0.1 * Added support for authentication in the guzzle driver * Added admin functionality diff --git a/lib/influxdb-php/Vagrantfile b/lib/influxdb-php/Vagrantfile new file mode 100644 index 000000000..93995aeef --- /dev/null +++ b/lib/influxdb-php/Vagrantfile @@ -0,0 +1,43 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# All Vagrant configuration is done below. The "2" in Vagrant.configure +# configures the configuration version (we support older styles for +# backwards compatibility). Please don't change it unless you know what +# you're doing. +#system(" +# if [ #{ARGV[0]} = 'up' ]; then +# ./requirements.sh +# fi +#") + + +Vagrant.configure(2) do |config| + + # The most common configuration options are documented and commented below. + # For a complete reference, please see the online documentation at + # https://docs.vagrantup.com. + + # Every Vagrant development environment requires a box. You can search for + # boxes at https://atlas.hashicorp.com/search. + config.vm.box = "ubuntu/trusty64" + + config.vm.define :node1 do |node1| + # + # Networking + # + node1.vm.network 'private_network', ip: '192.168.33.10' + # + # VM Setup + # + # Set the hostname to something useful + node1.vm.hostname = 'influxdb-node1' + node1.vm.define :influxdb_node1, {} + + node1.vm.provision 'ansible' do |ansible| + ansible.playbook = 'ansible/main.yml' + ansible.tags = ENV['ANSIBLE_TAGS'] unless ENV['ANSIBLE_TAGS'].to_s.empty? + ansible.sudo = true + end + end +end diff --git a/lib/influxdb-php/ansible/main.yml b/lib/influxdb-php/ansible/main.yml new file mode 100644 index 000000000..912260e63 --- /dev/null +++ b/lib/influxdb-php/ansible/main.yml @@ -0,0 +1,10 @@ +--- +- hosts: all + sudo: yes + + vars: + influxdb_udp_enabled: "true" + influxdb_udp_bind_address: "0.0.0.0:8090" + + roles: + - { role: mtchavez.influxdb } diff --git a/lib/influxdb-php/ansible/requirements.txt b/lib/influxdb-php/ansible/requirements.txt new file mode 100644 index 000000000..49f8dff75 --- /dev/null +++ b/lib/influxdb-php/ansible/requirements.txt @@ -0,0 +1 @@ +mtchavez.influxdb diff --git a/lib/influxdb-php/composer.json b/lib/influxdb-php/composer.json index 7af0fafe8..1164d72fa 100644 --- a/lib/influxdb-php/composer.json +++ b/lib/influxdb-php/composer.json @@ -19,14 +19,19 @@ { "name": "Daniel Martinez", "email": "danimartcas@hotmail.com" + }, + { + "name": "Gianluca Arbezzano", + "email": "gianarb92@gmail.com" } ], "require": { - "php": ">=5.5", + "php": "^5.5 | ^7.0", "guzzlehttp/guzzle": "6.*", - "symfony/event-dispatcher": "2.*" + "symfony/event-dispatcher": "2.*|3.*" }, "require-dev": { + "phpunit/phpunit": "^4.0", "codeclimate/php-test-reporter": "0.*", "symfony/config": "~2.8", "symfony/console": "~2.8", diff --git a/lib/influxdb-php/composer.lock b/lib/influxdb-php/composer.lock index a2fb5ba28..7186e8f19 100644 --- a/lib/influxdb-php/composer.lock +++ b/lib/influxdb-php/composer.lock @@ -4,7 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "ee3f2e2a4eb50f8de36c6efbff37fe71", + "hash": "b8e1dc9e3375bc55cfa2bc06647e5453", + "content-hash": "62f314d125890d134f461ba0bed7c33e", "packages": [ { "name": "guzzlehttp/guzzle", @@ -12,12 +13,12 @@ "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "1879fbe853b0c64d109e369c7aeff09849e62d1e" + "reference": "8c033e192fdcddb3067ca77e0b6829e910ecdd7d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/1879fbe853b0c64d109e369c7aeff09849e62d1e", - "reference": "1879fbe853b0c64d109e369c7aeff09849e62d1e", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/8c033e192fdcddb3067ca77e0b6829e910ecdd7d", + "reference": "8c033e192fdcddb3067ca77e0b6829e910ecdd7d", "shasum": "" }, "require": { @@ -33,7 +34,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "6.0-dev" + "dev-master": "6.2-dev" } }, "autoload": { @@ -66,7 +67,7 @@ "rest", "web service" ], - "time": "2015-07-10 20:04:21" + "time": "2016-01-31 00:19:49" }, { "name": "guzzlehttp/promises", @@ -74,12 +75,12 @@ "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", - "reference": "f596be052ef429a16b2f640812fcf84392dd38f7" + "reference": "b59321a17f3e3ebc14f2bbbf73b4d065a88cf3f6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/f596be052ef429a16b2f640812fcf84392dd38f7", - "reference": "f596be052ef429a16b2f640812fcf84392dd38f7", + "url": "https://api.github.com/repos/guzzle/promises/zipball/b59321a17f3e3ebc14f2bbbf73b4d065a88cf3f6", + "reference": "b59321a17f3e3ebc14f2bbbf73b4d065a88cf3f6", "shasum": "" }, "require": { @@ -117,20 +118,20 @@ "keywords": [ "promise" ], - "time": "2015-06-30 16:39:54" + "time": "2016-02-10 14:20:03" }, { "name": "guzzlehttp/psr7", - "version": "1.1.0", + "version": "1.2.2", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "af0e1758de355eb113917ad79c3c0e3604bce4bd" + "reference": "f5d04bdd2881ac89abde1fb78cc234bce24327bb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/af0e1758de355eb113917ad79c3c0e3604bce4bd", - "reference": "af0e1758de355eb113917ad79c3c0e3604bce4bd", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/f5d04bdd2881ac89abde1fb78cc234bce24327bb", + "reference": "f5d04bdd2881ac89abde1fb78cc234bce24327bb", "shasum": "" }, "require": { @@ -154,7 +155,7 @@ "GuzzleHttp\\Psr7\\": "src/" }, "files": [ - "src/functions.php" + "src/functions_include.php" ] }, "notification-url": "https://packagist.org/downloads/", @@ -175,7 +176,7 @@ "stream", "uri" ], - "time": "2015-06-24 19:55:15" + "time": "2016-01-23 01:23:02" }, { "name": "psr/http-message", @@ -228,28 +229,27 @@ }, { "name": "symfony/event-dispatcher", - "version": "2.8.x-dev", + "version": "dev-master", "source": { "type": "git", - "url": "https://github.com/symfony/EventDispatcher.git", - "reference": "d7246885b7fe4cb5a2786bda34362d2f0e40b730" + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "9d7930726e060b0c45ae10022a4cb307e502500b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/d7246885b7fe4cb5a2786bda34362d2f0e40b730", - "reference": "d7246885b7fe4cb5a2786bda34362d2f0e40b730", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/9d7930726e060b0c45ae10022a4cb307e502500b", + "reference": "9d7930726e060b0c45ae10022a4cb307e502500b", "shasum": "" }, "require": { - "php": ">=5.3.9" + "php": ">=5.5.9" }, "require-dev": { "psr/log": "~1.0", - "symfony/config": "~2.0,>=2.0.5|~3.0.0", - "symfony/dependency-injection": "~2.6|~3.0.0", - "symfony/expression-language": "~2.6|~3.0.0", - "symfony/phpunit-bridge": "~2.7|~3.0.0", - "symfony/stopwatch": "~2.3|~3.0.0" + "symfony/config": "~2.8|~3.0", + "symfony/dependency-injection": "~2.8|~3.0", + "symfony/expression-language": "~2.8|~3.0", + "symfony/stopwatch": "~2.8|~3.0" }, "suggest": { "symfony/dependency-injection": "", @@ -258,13 +258,16 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.8-dev" + "dev-master": "3.1-dev" } }, "autoload": { "psr-4": { "Symfony\\Component\\EventDispatcher\\": "" - } + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -282,7 +285,7 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", - "time": "2015-06-24 15:32:32" + "time": "2016-02-04 12:57:09" } ], "packages-dev": [ @@ -292,12 +295,12 @@ "source": { "type": "git", "url": "https://github.com/codeclimate/php-test-reporter.git", - "reference": "418ae782307841ac50fe26daa4cfe04520b0de9c" + "reference": "02790d733f9eb43d0a5981962c41846092fb387f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/codeclimate/php-test-reporter/zipball/418ae782307841ac50fe26daa4cfe04520b0de9c", - "reference": "418ae782307841ac50fe26daa4cfe04520b0de9c", + "url": "https://api.github.com/repos/codeclimate/php-test-reporter/zipball/02790d733f9eb43d0a5981962c41846092fb387f", + "reference": "02790d733f9eb43d0a5981962c41846092fb387f", "shasum": "" }, "require": { @@ -316,7 +319,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "0.1.x-dev" + "dev-master": "0.2.x-dev" } }, "autoload": { @@ -342,26 +345,80 @@ "codeclimate", "coverage" ], - "time": "2015-04-18 14:43:54" + "time": "2015-12-17 00:52:54" }, { - "name": "guzzle/guzzle", + "name": "doctrine/instantiator", "version": "dev-master", "source": { "type": "git", - "url": "https://github.com/guzzle/guzzle3.git", - "reference": "b3f5050cb6270c7a728a0b74ac2de50a262b3e02" + "url": "https://github.com/doctrine/instantiator.git", + "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle3/zipball/b3f5050cb6270c7a728a0b74ac2de50a262b3e02", - "reference": "b3f5050cb6270c7a728a0b74ac2de50a262b3e02", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", + "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", + "shasum": "" + }, + "require": { + "php": ">=5.3,<8.0-DEV" + }, + "require-dev": { + "athletic/athletic": "~0.1.8", + "ext-pdo": "*", + "ext-phar": "*", + "phpunit/phpunit": "~4.0", + "squizlabs/php_codesniffer": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "http://ocramius.github.com/" + } + ], + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://github.com/doctrine/instantiator", + "keywords": [ + "constructor", + "instantiate" + ], + "time": "2015-06-14 21:17:01" + }, + { + "name": "guzzle/guzzle", + "version": "v3.8.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "4de0618a01b34aa1c8c33a3f13f396dcd3882eba" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/4de0618a01b34aa1c8c33a3f13f396dcd3882eba", + "reference": "4de0618a01b34aa1c8c33a3f13f396dcd3882eba", "shasum": "" }, "require": { "ext-curl": "*", "php": ">=5.3.3", - "symfony/event-dispatcher": "~2.1" + "symfony/event-dispatcher": ">=2.1" }, "replace": { "guzzle/batch": "self.version", @@ -388,21 +445,18 @@ "guzzle/stream": "self.version" }, "require-dev": { - "doctrine/cache": "~1.3", - "monolog/monolog": "~1.0", + "doctrine/cache": "*", + "monolog/monolog": "1.*", "phpunit/phpunit": "3.7.*", - "psr/log": "~1.0", - "symfony/class-loader": "~2.1", - "zendframework/zend-cache": "2.*,<2.3", - "zendframework/zend-log": "2.*,<2.3" - }, - "suggest": { - "guzzlehttp/guzzle": "Guzzle 5 has moved to a new package name. The package you have installed, Guzzle 3, is deprecated." + "psr/log": "1.0.*", + "symfony/class-loader": "*", + "zendframework/zend-cache": "<2.3", + "zendframework/zend-log": "<2.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.9-dev" + "dev-master": "3.8-dev" } }, "autoload": { @@ -426,7 +480,7 @@ "homepage": "https://github.com/guzzle/guzzle/contributors" } ], - "description": "PHP HTTP client. This library is deprecated in favor of https://packagist.org/packages/guzzlehttp/guzzle", + "description": "Guzzle is a PHP HTTP client library and framework for building RESTful web service clients", "homepage": "http://guzzlephp.org/", "keywords": [ "client", @@ -437,7 +491,486 @@ "rest", "web service" ], - "time": "2015-04-29 17:06:53" + "time": "2014-01-28 22:29:15" + }, + { + "name": "phpdocumentor/reflection-docblock", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/d68dbdc53dc358a816f00b300704702b2eaff7b8", + "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "suggest": { + "dflydev/markdown": "~1.0", + "erusev/parsedown": "~1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-0": { + "phpDocumentor": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "mike.vanriel@naenius.com" + } + ], + "time": "2015-02-03 12:10:50" + }, + { + "name": "phpspec/prophecy", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/phpspec/prophecy.git", + "reference": "e55e3e32a870bd4f05425fa4f717b52bd40e5659" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/e55e3e32a870bd4f05425fa4f717b52bd40e5659", + "reference": "e55e3e32a870bd4f05425fa4f717b52bd40e5659", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.0.2", + "php": "^5.3|^7.0", + "phpdocumentor/reflection-docblock": "~2.0", + "sebastian/comparator": "~1.1", + "sebastian/recursion-context": "~1.0" + }, + "require-dev": { + "phpspec/phpspec": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.5.x-dev" + } + }, + "autoload": { + "psr-0": { + "Prophecy\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + }, + { + "name": "Marcello Duarte", + "email": "marcello.duarte@gmail.com" + } + ], + "description": "Highly opinionated mocking framework for PHP 5.3+", + "homepage": "https://github.com/phpspec/prophecy", + "keywords": [ + "Double", + "Dummy", + "fake", + "mock", + "spy", + "stub" + ], + "time": "2015-12-28 13:26:33" + }, + { + "name": "phpunit/php-code-coverage", + "version": "2.2.x-dev", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/eabf68b476ac7d0f73793aada060f1c1a9bf8979", + "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "phpunit/php-file-iterator": "~1.3", + "phpunit/php-text-template": "~1.2", + "phpunit/php-token-stream": "~1.3", + "sebastian/environment": "^1.3.2", + "sebastian/version": "~1.0" + }, + "require-dev": { + "ext-xdebug": ">=2.1.4", + "phpunit/phpunit": "~4" + }, + "suggest": { + "ext-dom": "*", + "ext-xdebug": ">=2.2.1", + "ext-xmlwriter": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.2.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "time": "2015-10-06 15:47:00" + }, + { + "name": "phpunit/php-file-iterator", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/6150bf2c35d3fc379e50c7602b75caceaa39dbf0", + "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "time": "2015-06-21 13:08:43" + }, + { + "name": "phpunit/php-text-template", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "time": "2015-06-21 13:50:34" + }, + { + "name": "phpunit/php-timer", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "3e82f4e9fc92665fafd9157568e4dcb01d014e5b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3e82f4e9fc92665fafd9157568e4dcb01d014e5b", + "reference": "3e82f4e9fc92665fafd9157568e4dcb01d014e5b", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "time": "2015-06-21 08:01:12" + }, + { + "name": "phpunit/php-token-stream", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-token-stream.git", + "reference": "cab6c6fefee93d7b7c3a01292a0fe0884ea66644" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/cab6c6fefee93d7b7c3a01292a0fe0884ea66644", + "reference": "cab6c6fefee93d7b7c3a01292a0fe0884ea66644", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Wrapper around PHP's tokenizer extension.", + "homepage": "https://github.com/sebastianbergmann/php-token-stream/", + "keywords": [ + "tokenizer" + ], + "time": "2015-09-23 14:46:55" + }, + { + "name": "phpunit/phpunit", + "version": "4.8.x-dev", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "6e351261f9cd33daf205a131a1ba61c6d33bd483" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/6e351261f9cd33daf205a131a1ba61c6d33bd483", + "reference": "6e351261f9cd33daf205a131a1ba61c6d33bd483", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-json": "*", + "ext-pcre": "*", + "ext-reflection": "*", + "ext-spl": "*", + "php": ">=5.3.3", + "phpspec/prophecy": "^1.3.1", + "phpunit/php-code-coverage": "~2.1", + "phpunit/php-file-iterator": "~1.4", + "phpunit/php-text-template": "~1.2", + "phpunit/php-timer": ">=1.0.6", + "phpunit/phpunit-mock-objects": "~2.3", + "sebastian/comparator": "~1.1", + "sebastian/diff": "~1.2", + "sebastian/environment": "~1.3", + "sebastian/exporter": "~1.2", + "sebastian/global-state": "~1.0", + "sebastian/version": "~1.0", + "symfony/yaml": "~2.1|~3.0" + }, + "suggest": { + "phpunit/php-invoker": "~1.1" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.8.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "time": "2016-02-11 14:56:33" + }, + { + "name": "phpunit/phpunit-mock-objects", + "version": "2.3.x-dev", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", + "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/ac8e7a3db35738d56ee9a76e78a4e03d97628983", + "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.0.2", + "php": ">=5.3.3", + "phpunit/php-text-template": "~1.2", + "sebastian/exporter": "~1.2" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "suggest": { + "ext-soap": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.3.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Mock Object library for PHPUnit", + "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", + "keywords": [ + "mock", + "xunit" + ], + "time": "2015-10-02 06:51:40" }, { "name": "psr/log", @@ -545,27 +1078,396 @@ ], "time": "2013-05-04 08:07:33" }, + { + "name": "sebastian/comparator", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "937efb279bd37a375bcadf584dec0726f84dbf22" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/937efb279bd37a375bcadf584dec0726f84dbf22", + "reference": "937efb279bd37a375bcadf584dec0726f84dbf22", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "sebastian/diff": "~1.2", + "sebastian/exporter": "~1.2" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "http://www.github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "time": "2015-07-26 15:48:44" + }, + { + "name": "sebastian/diff", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/13edfd8706462032c2f52b4b862974dd46b71c9e", + "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff" + ], + "time": "2015-12-08 07:14:41" + }, + { + "name": "sebastian/environment", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "6e7133793a8e5a5714a551a8324337374be209df" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/6e7133793a8e5a5714a551a8324337374be209df", + "reference": "6e7133793a8e5a5714a551a8324337374be209df", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "http://www.github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "time": "2015-12-02 08:37:27" + }, + { + "name": "sebastian/exporter", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "f88f8936517d54ae6d589166810877fb2015d0a2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/f88f8936517d54ae6d589166810877fb2015d0a2", + "reference": "f88f8936517d54ae6d589166810877fb2015d0a2", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "sebastian/recursion-context": "~1.0" + }, + "require-dev": { + "ext-mbstring": "*", + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "http://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "time": "2015-08-09 04:23:41" + }, + { + "name": "sebastian/global-state", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4", + "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.2" + }, + "suggest": { + "ext-uopz": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "http://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "time": "2015-10-12 03:26:01" + }, + { + "name": "sebastian/recursion-context", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "7ff5b1b3dcc55b8ab8ae61ef99d4730940856ee7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/7ff5b1b3dcc55b8ab8ae61ef99d4730940856ee7", + "reference": "7ff5b1b3dcc55b8ab8ae61ef99d4730940856ee7", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "http://www.github.com/sebastianbergmann/recursion-context", + "time": "2016-01-28 05:39:29" + }, + { + "name": "sebastian/version", + "version": "1.0.6", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", + "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", + "shasum": "" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "time": "2015-06-21 13:59:46" + }, { "name": "symfony/config", "version": "2.8.x-dev", "source": { "type": "git", - "url": "https://github.com/symfony/Config.git", - "reference": "358ec929e494b6f12d8508d88357cbd7383a10ca" + "url": "https://github.com/symfony/config.git", + "reference": "f4d8e2236db888c708d934975070ff6f0a332a24" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Config/zipball/358ec929e494b6f12d8508d88357cbd7383a10ca", - "reference": "358ec929e494b6f12d8508d88357cbd7383a10ca", + "url": "https://api.github.com/repos/symfony/config/zipball/f4d8e2236db888c708d934975070ff6f0a332a24", + "reference": "f4d8e2236db888c708d934975070ff6f0a332a24", "shasum": "" }, "require": { "php": ">=5.3.9", "symfony/filesystem": "~2.3|~3.0.0" }, - "require-dev": { - "symfony/phpunit-bridge": "~2.7|~3.0.0" - }, "type": "library", "extra": { "branch-alias": { @@ -575,7 +1477,10 @@ "autoload": { "psr-4": { "Symfony\\Component\\Config\\": "" - } + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -593,29 +1498,29 @@ ], "description": "Symfony Config Component", "homepage": "https://symfony.com", - "time": "2015-07-09 16:11:14" + "time": "2016-02-04 14:44:13" }, { "name": "symfony/console", "version": "2.8.x-dev", "source": { "type": "git", - "url": "https://github.com/symfony/Console.git", - "reference": "fd85e7517e79a2bceafcee8f7e8b7bbd0919a90a" + "url": "https://github.com/symfony/console.git", + "reference": "d59b01b03451dfc1497b9736120ac6bcb422ff10" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Console/zipball/fd85e7517e79a2bceafcee8f7e8b7bbd0919a90a", - "reference": "fd85e7517e79a2bceafcee8f7e8b7bbd0919a90a", + "url": "https://api.github.com/repos/symfony/console/zipball/d59b01b03451dfc1497b9736120ac6bcb422ff10", + "reference": "d59b01b03451dfc1497b9736120ac6bcb422ff10", "shasum": "" }, "require": { - "php": ">=5.3.9" + "php": ">=5.3.9", + "symfony/polyfill-mbstring": "~1.0" }, "require-dev": { "psr/log": "~1.0", "symfony/event-dispatcher": "~2.1|~3.0.0", - "symfony/phpunit-bridge": "~2.7|~3.0.0", "symfony/process": "~2.1|~3.0.0" }, "suggest": { @@ -632,7 +1537,10 @@ "autoload": { "psr-4": { "Symfony\\Component\\Console\\": "" - } + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -650,28 +1558,25 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2015-07-16 12:22:14" + "time": "2016-02-03 18:01:35" }, { "name": "symfony/filesystem", "version": "2.8.x-dev", "source": { "type": "git", - "url": "https://github.com/symfony/Filesystem.git", - "reference": "9f70c5625a32b2f1e6fc37222f52b4e0eb437b0e" + "url": "https://github.com/symfony/filesystem.git", + "reference": "cbfaa8a24c38911d2d14ef12118514a504c09dd0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Filesystem/zipball/9f70c5625a32b2f1e6fc37222f52b4e0eb437b0e", - "reference": "9f70c5625a32b2f1e6fc37222f52b4e0eb437b0e", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/cbfaa8a24c38911d2d14ef12118514a504c09dd0", + "reference": "cbfaa8a24c38911d2d14ef12118514a504c09dd0", "shasum": "" }, "require": { "php": ">=5.3.9" }, - "require-dev": { - "symfony/phpunit-bridge": "~2.7|~3.0.0" - }, "type": "library", "extra": { "branch-alias": { @@ -681,7 +1586,10 @@ "autoload": { "psr-4": { "Symfony\\Component\\Filesystem\\": "" - } + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -699,28 +1607,84 @@ ], "description": "Symfony Filesystem Component", "homepage": "https://symfony.com", - "time": "2015-07-09 16:11:14" + "time": "2016-01-27 11:34:40" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "1289d16209491b584839022f29257ad859b8532d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/1289d16209491b584839022f29257ad859b8532d", + "reference": "1289d16209491b584839022f29257ad859b8532d", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "time": "2016-01-20 09:13:37" }, { "name": "symfony/stopwatch", "version": "2.8.x-dev", "source": { "type": "git", - "url": "https://github.com/symfony/Stopwatch.git", - "reference": "cd5f0dc1d3d0e2c83461dad77e20a9186beb6146" + "url": "https://github.com/symfony/stopwatch.git", + "reference": "e3bc8e2a984f4382690a438c8bb650f3ffd71e73" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Stopwatch/zipball/cd5f0dc1d3d0e2c83461dad77e20a9186beb6146", - "reference": "cd5f0dc1d3d0e2c83461dad77e20a9186beb6146", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/e3bc8e2a984f4382690a438c8bb650f3ffd71e73", + "reference": "e3bc8e2a984f4382690a438c8bb650f3ffd71e73", "shasum": "" }, "require": { "php": ">=5.3.9" }, - "require-dev": { - "symfony/phpunit-bridge": "~2.7|~3.0.0" - }, "type": "library", "extra": { "branch-alias": { @@ -730,7 +1694,10 @@ "autoload": { "psr-4": { "Symfony\\Component\\Stopwatch\\": "" - } + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -748,28 +1715,25 @@ ], "description": "Symfony Stopwatch Component", "homepage": "https://symfony.com", - "time": "2015-07-01 18:24:26" + "time": "2016-01-03 15:33:41" }, { "name": "symfony/yaml", "version": "2.8.x-dev", "source": { "type": "git", - "url": "https://github.com/symfony/Yaml.git", - "reference": "000e7fc2653335cd42c6d21405dac1c74224a387" + "url": "https://github.com/symfony/yaml.git", + "reference": "33fd1b2cfdde601704665fad343014bba04b0753" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Yaml/zipball/000e7fc2653335cd42c6d21405dac1c74224a387", - "reference": "000e7fc2653335cd42c6d21405dac1c74224a387", + "url": "https://api.github.com/repos/symfony/yaml/zipball/33fd1b2cfdde601704665fad343014bba04b0753", + "reference": "33fd1b2cfdde601704665fad343014bba04b0753", "shasum": "" }, "require": { "php": ">=5.3.9" }, - "require-dev": { - "symfony/phpunit-bridge": "~2.7|~3.0.0" - }, "type": "library", "extra": { "branch-alias": { @@ -779,7 +1743,10 @@ "autoload": { "psr-4": { "Symfony\\Component\\Yaml\\": "" - } + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -797,7 +1764,7 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2015-07-01 14:16:54" + "time": "2016-02-02 09:49:18" } ], "aliases": [], @@ -806,7 +1773,7 @@ "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": ">=5.5" + "php": "^5.5 | ^7.0" }, "platform-dev": [] } diff --git a/lib/influxdb-php/requirements.sh b/lib/influxdb-php/requirements.sh new file mode 100755 index 000000000..f8acc1ba4 --- /dev/null +++ b/lib/influxdb-php/requirements.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +#!/bin/bash + +GLEXEC=$(which ansible-galaxy) + +if [ $? = 1 ]; then + echo + echo "Ansible-galaxy not found, please make sure you have ansible 1.9+ installed." + echo + exit 1 +fi + +$GLEXEC install -f -r ansible/requirements.txt diff --git a/lib/influxdb-php/src/InfluxDB/Client.php b/lib/influxdb-php/src/InfluxDB/Client.php index b724c63f0..51b137ef2 100644 --- a/lib/influxdb-php/src/InfluxDB/Client.php +++ b/lib/influxdb-php/src/InfluxDB/Client.php @@ -88,6 +88,14 @@ class Client */ protected $driver; + + /** + * Stores the last query that ran + * + * @var null + */ + public static $lastQuery = null; + /** * @param string $host * @param int $port @@ -103,7 +111,7 @@ class Client $username = '', $password = '', $ssl = false, - $verifySSL = true, + $verifySSL = false, $timeout = 0 ) { $this->host = (string) $host; @@ -183,6 +191,9 @@ class Client $driver->setParameters($parameters); try { + // store the last query sent + static::$lastQuery = $query; + // perform the query and return the resultset return $driver->query(); @@ -191,6 +202,33 @@ class Client } } + /** + * Write data + * + * @param array $parameters + * @param string $payload + * + * @return bool + */ + public function write(array $parameters, $payload) + { + // retrive the driver + $driver = $this->getDriver(); + + // add authentication to the driver if needed + if (!empty($this->username) && !empty($this->password)) { + $parameters += ['auth' => [$this->username, $this->password]]; + } + + // set the given parameters + $driver->setParameters($parameters); + + // send the points to influxDB + $driver->write(implode("\n", $payload)); + + return $driver->isSuccess(); + } + /** * List all the databases */ @@ -209,9 +247,9 @@ class Client */ public function listUsers() { - $result = $this->query(null, 'SHOW USERS')->getPoints(); + $result = $this->query(null, 'SHOW USERS')->getColumns(); - return $this->pointsToArray($result); + return (array) $result; } /** @@ -306,6 +344,16 @@ class Client return $this->host; } + /** + * Returns the last executed query + * + * @return null|string + */ + public function getLastQuery() + { + return static::$lastQuery; + } + /** * @param Point[] $points * @return array diff --git a/lib/influxdb-php/src/InfluxDB/Database.php b/lib/influxdb-php/src/InfluxDB/Database.php index 3ca7163f8..5c094fde6 100644 --- a/lib/influxdb-php/src/InfluxDB/Database.php +++ b/lib/influxdb-php/src/InfluxDB/Database.php @@ -77,14 +77,21 @@ class Database * Create this database * * @param RetentionPolicy $retentionPolicy + * @param bool $createIfNotExists Only create the database if it does not yet exist + * * @return ResultSet * @throws DatabaseException - * @throws Exception */ - public function create(RetentionPolicy $retentionPolicy = null) + public function create(RetentionPolicy $retentionPolicy = null, $createIfNotExists = true) { try { - $this->query(sprintf('CREATE DATABASE %s', $this->name)); + $query = sprintf( + 'CREATE DATABASE %s"%s"', + ($createIfNotExists ? 'IF NOT EXISTS ' : ''), + $this->name + ); + + $this->query($query); if ($retentionPolicy) { $this->createRetentionPolicy($retentionPolicy); @@ -125,25 +132,13 @@ class Database ); try { - $driver = $this->client->getDriver(); - $parameters = [ 'url' => sprintf('write?db=%s&precision=%s', $this->name, $precision), 'database' => $this->name, 'method' => 'post' ]; - // add authentication to the driver if needed - if (!empty($this->username) && !empty($this->password)) { - $parameters += ['auth' => [$this->username, $this->password]]; - } - - $driver->setParameters($parameters); - - // send the points to influxDB - $driver->write(implode(PHP_EOL, $payload)); - - return $driver->isSuccess(); + return $this->client->write($parameters, $payload); } catch (\Exception $e) { throw new Exception($e->getMessage(), $e->getCode()); @@ -174,7 +169,7 @@ class Database */ public function listRetentionPolicies() { - return $this->query(sprintf('SHOW RETENTION POLICIES %s', $this->name))->getPoints(); + return $this->query(sprintf('SHOW RETENTION POLICIES ON "%s"', $this->name))->getPoints(); } /** @@ -182,7 +177,7 @@ class Database */ public function drop() { - $this->query(sprintf('DROP DATABASE %s', $this->name)); + $this->query(sprintf('DROP DATABASE "%s"', $this->name)); } /** @@ -210,12 +205,8 @@ class Database */ protected function getRetentionPolicyQuery($method, RetentionPolicy $retentionPolicy) { - if (!in_array($method, ['CREATE', 'ALTER'])) { - throw new \InvalidArgumentException(sprintf('%s is not a valid method')); - } - $query = sprintf( - '%s RETENTION POLICY %s ON %s DURATION %s REPLICATION %s', + '%s RETENTION POLICY "%s" ON "%s" DURATION %s REPLICATION %s', $method, $retentionPolicy->name, $this->name, diff --git a/lib/influxdb-php/src/InfluxDB/Driver/DriverInterface.php b/lib/influxdb-php/src/InfluxDB/Driver/DriverInterface.php index fc3a2c2f9..317099644 100644 --- a/lib/influxdb-php/src/InfluxDB/Driver/DriverInterface.php +++ b/lib/influxdb-php/src/InfluxDB/Driver/DriverInterface.php @@ -30,6 +30,11 @@ interface DriverInterface */ public function setParameters(array $parameters); + /** + * @return array + */ + public function getParameters(); + /** * Send the data * diff --git a/lib/influxdb-php/src/InfluxDB/Driver/Guzzle.php b/lib/influxdb-php/src/InfluxDB/Driver/Guzzle.php index a3f1d9111..c3c2952ee 100644 --- a/lib/influxdb-php/src/InfluxDB/Driver/Guzzle.php +++ b/lib/influxdb-php/src/InfluxDB/Driver/Guzzle.php @@ -68,6 +68,14 @@ class Guzzle implements DriverInterface, QueryDriverInterface $this->parameters = $parameters; } + /** + * @return array + */ + public function getParameters() + { + return $this->parameters; + } + /** * Send the data * @@ -87,17 +95,10 @@ class Guzzle implements DriverInterface, QueryDriverInterface */ public function query() { - $response = $this->httpClient->get($this->parameters['url'], $this->getRequestParameters()); $raw = (string) $response->getBody(); - $responseJson = json_encode($raw); - - if (isset($responseJson->error)) { - throw new Exception($responseJson->error); - } - return new ResultSet($raw); } @@ -109,7 +110,14 @@ class Guzzle implements DriverInterface, QueryDriverInterface */ public function isSuccess() { - return in_array($this->response->getStatusCode(), ['200', '204']); + $statuscode = $this->response->getStatusCode(); + + if(!in_array($statuscode, ['200', '204'])) + { + throw new Exception('HTTP Code ' . $statuscode . ' ' . $this->response->getBody()); + } + + return true; } /** diff --git a/lib/influxdb-php/src/InfluxDB/Driver/UDP.php b/lib/influxdb-php/src/InfluxDB/Driver/UDP.php index ac2be0ebb..9aa6c5004 100644 --- a/lib/influxdb-php/src/InfluxDB/Driver/UDP.php +++ b/lib/influxdb-php/src/InfluxDB/Driver/UDP.php @@ -58,6 +58,14 @@ class UDP implements DriverInterface $this->parameters = $parameters; } + /** + * @return array + */ + public function getParameters() + { + return $this->parameters; + } + /** * Send the data * diff --git a/lib/influxdb-php/src/InfluxDB/Point.php b/lib/influxdb-php/src/InfluxDB/Point.php index cd757e209..f9cf8db17 100644 --- a/lib/influxdb-php/src/InfluxDB/Point.php +++ b/lib/influxdb-php/src/InfluxDB/Point.php @@ -14,22 +14,22 @@ class Point /** * @var string */ - private $measurement; + protected $measurement; /** * @var array */ - private $tags = []; + protected $tags = []; /** * @var array */ - private $fields = []; + protected $fields = []; /** * @var string */ - private $timestamp; + protected $timestamp; /** * The timestamp is optional. If you do not specify a timestamp the server’s @@ -55,12 +55,14 @@ class Point $this->measurement = (string) $measurement; $this->tags = $tags; - $this->fields = $additionalFields; + $fields = $additionalFields; - if ($value) { - $this->fields['value'] = $value; + if ($value !== null) { + $fields['value'] = $value; } + $this->setFields($fields); + if ($timestamp && !$this->isValidTimeStamp($timestamp)) { throw new DatabaseException(sprintf('%s is not a valid timestamp', $timestamp)); } @@ -80,10 +82,10 @@ class Point $string = $this->measurement; if (count($this->tags) > 0) { - $string .= ',' . $this->arrayToString($this->tags); + $string .= ',' . $this->arrayToString($this->escapeCharacters($this->tags)); } - $string .= ' ' . $this->arrayToString($this->fields); + $string .= ' ' . $this->arrayToString($this->escapeCharacters($this->fields)); if ($this->timestamp) { $string .= ' '.$this->timestamp; @@ -92,6 +94,116 @@ class Point return $string; } + /** + * @return string + */ + public function getMeasurement() + { + return $this->measurement; + } + + /** + * @param string $measurement + */ + public function setMeasurement($measurement) + { + $this->measurement = $measurement; + } + + /** + * @return array + */ + public function getTags() + { + return $this->tags; + } + + /** + * @param array $tags + */ + public function setTags($tags) + { + $this->tags = $tags; + } + + /** + * @return array + */ + public function getFields() + { + return $this->fields; + } + + /** + * @param array $fields + */ + public function setFields($fields) + { + foreach ($fields as &$field) { + if (is_integer($field)) { + $field = sprintf('%di', $field); + } elseif (is_string($field)) { + $field = sprintf("\"%s\"", $field); + } elseif (is_bool($field)) { + $field = ($field ? "true" : "false"); + } + } + + $this->fields = $fields; + } + + /** + * @return string + */ + public function getTimestamp() + { + return $this->timestamp; + } + + /** + * @param string $timestamp + */ + public function setTimestamp($timestamp) + { + $this->timestamp = $timestamp; + } + + /** + * Escapes invalid characters in both the array key and array value + * + * @param array $arr + * @return array + */ + private function escapeCharacters(array $arr) + { + $returnArr = []; + + foreach ($arr as $key => $value) { + $returnArr[$this->addSlashes($key)] = $this->addSlashes($value); + } + + return $returnArr; + } + + /** + * Returns strings with space, comma, or equals sign characters backslashed per Influx write protocol syntax + * + * @param string $value + * @return string + */ + private function addSlashes($value) + { + return str_replace([ + ' ', + ',', + '=' + ],[ + '\ ', + '\,', + '\=' + ], $value); + } + /** * @param array $arr * @return string @@ -113,14 +225,26 @@ class Point */ private function isValidTimeStamp($timestamp) { - if ((int) $timestamp === $timestamp) { + + // if the code is run on a 32bit system, loosely check if the timestamp is a valid numeric + if (PHP_INT_SIZE == 4 && is_numeric($timestamp)) { return true; } - if ($timestamp <= PHP_INT_MAX && $timestamp >= ~PHP_INT_MAX) { - return true; + if (!is_numeric($timestamp)) { + return false; } - return false; + if (intval($timestamp) != $timestamp) { + return false; + } + + if (!($timestamp <= PHP_INT_MAX && $timestamp >= ~PHP_INT_MAX)) { + return false; + } + + return true; + + } } diff --git a/lib/influxdb-php/src/InfluxDB/Query/Builder.php b/lib/influxdb-php/src/InfluxDB/Query/Builder.php index 1060bc39d..6f1de9196 100644 --- a/lib/influxdb-php/src/InfluxDB/Query/Builder.php +++ b/lib/influxdb-php/src/InfluxDB/Query/Builder.php @@ -60,6 +60,16 @@ class Builder */ protected $limitClause = ''; + /** + * @var array + */ + protected $groupBy; + + /** + * @var array + */ + protected $orderBy; + /** * @param Database $db */ @@ -178,6 +188,18 @@ class Builder return $this; } + public function groupBy($field = 'type') { + $this->groupBy[] = $field; + + return $this; + } + + public function orderBy($field = 'type', $order = 'ASC') { + $this->orderBy[] = "$field $order"; + + return $this; + } + /** * Set's the time range to select data from * @@ -244,7 +266,7 @@ class Builder */ protected function parseQuery() { - $query = sprintf("SELECT %s FROM %s", $this->selection, $this->metric); + $query = sprintf('SELECT %s FROM "%s"', $this->selection, $this->metric); if (! $this->metric) { throw new \InvalidArgumentException('No metric provided to from()'); @@ -262,6 +284,14 @@ class Builder } + if (!empty($this->groupBy)) { + $query .= ' GROUP BY ' . implode(',', $this->groupBy); + } + + if (!empty($this->orderBy)) { + $query .= ' ORDER BY ' . implode(',', $this->orderBy); + } + if ($this->limitClause) { $query .= $this->limitClause; } diff --git a/lib/influxdb-php/src/InfluxDB/ResultSet.php b/lib/influxdb-php/src/InfluxDB/ResultSet.php index 66330ab42..b9faa977d 100644 --- a/lib/influxdb-php/src/InfluxDB/ResultSet.php +++ b/lib/influxdb-php/src/InfluxDB/ResultSet.php @@ -89,6 +89,14 @@ class ResultSet return array_shift($series); } + /** + * @return mixed + */ + public function getColumns() + { + return $this->getSeries()[0]['columns']; + } + /** * @param array $serie * @return array diff --git a/lib/influxdb-php/test_library.php b/lib/influxdb-php/test_library.php new file mode 100644 index 000000000..02978e16f --- /dev/null +++ b/lib/influxdb-php/test_library.php @@ -0,0 +1,68 @@ +selectDB('test'); + +if ($database->exists()) { + $database->drop(); +} + +$database->create(new \InfluxDB\Database\RetentionPolicy('test', '12w', 1, true)); + + +$start = microtime(true); + +$countries = ['nl', 'gb', 'us', 'be', 'th', 'jp', 'nl', 'sa']; +$colors = ['orange', 'black', 'yellow', 'white', 'red', 'purple']; +$points = []; + +for ($i=0; $i < 1000; $i++) { + $points[] = new \InfluxDB\Point( + 'flags', + randFloat(1, 999), + ['country' => $countries[array_rand($countries)]], + ['color' => $colors[array_rand($colors)]], + (int) shell_exec('date +%s%N')+mt_rand(1,1000) + ); +}; + +// insert the points +$database->writePoints($points); + +$end = microtime(true); + +$country = $countries[array_rand($countries)]; +$color = $colors[array_rand($colors)]; + +$results = $database->query("SELECT * FROM flags WHERE country = '$country' LIMIT 5")->getPoints(); +$results2 = $database->query("SELECT * FROM flags WHERE color = '$color' LIMIT 5")->getPoints(); + +echo "Showing top 5 flags from country $country:" . PHP_EOL; +print_r($results); +echo PHP_EOL; + +echo "Showing top 5 flags with color $color:" . PHP_EOL; +print_r($results2); + + +echo PHP_EOL; +echo sprintf('Executed 1000 inserts in %.2f seconds', $end - $start); diff --git a/lib/influxdb-php/tests/unit/AbstractTest.php b/lib/influxdb-php/tests/unit/AbstractTest.php index 160f6aea6..7afcc49be 100644 --- a/lib/influxdb-php/tests/unit/AbstractTest.php +++ b/lib/influxdb-php/tests/unit/AbstractTest.php @@ -10,7 +10,7 @@ use GuzzleHttp\Handler\MockHandler; use GuzzleHttp\HandlerStack; use InfluxDB\Client; use InfluxDB\Database; -use InfluxDB\Driver\Guzzle; +use InfluxDB\Driver\Guzzle as GuzzleDriver; use InfluxDB\ResultSet; use PHPUnit_Framework_MockObject_MockObject; use GuzzleHttp\Client as GuzzleClient; @@ -44,7 +44,7 @@ abstract class AbstractTest extends \PHPUnit_Framework_TestCase ->disableOriginalConstructor() ->getMock(); - $this->resultData = file_get_contents(dirname(__FILE__) . '/result.example.json'); + $this->resultData = file_get_contents(dirname(__FILE__) . '/json/result.example.json'); $this->mockClient->expects($this->any()) ->method('getBaseURI') @@ -52,9 +52,17 @@ abstract class AbstractTest extends \PHPUnit_Framework_TestCase $this->mockClient->expects($this->any()) ->method('query') - ->will($this->returnValue(new ResultSet($this->resultData))); + ->will($this->returnCallback(function ($db, $query) { + Client::$lastQuery = $query; - $httpMockClient = new Guzzle($this->buildHttpMockClient('')); + return new ResultSet($this->resultData); + })); + + $this->mockClient->expects($this->any()) + ->method('write') + ->will($this->returnValue(true)); + + $httpMockClient = new GuzzleDriver($this->buildHttpMockClient('')); // make sure the client has a valid driver $this->mockClient->expects($this->any()) @@ -88,7 +96,13 @@ abstract class AbstractTest extends \PHPUnit_Framework_TestCase public function buildHttpMockClient($body) { // Create a mock and queue two responses. - $mock = new MockHandler([new Response(200, array(), $body)]); + $mock = new MockHandler([ + new Response(200, array(), $body), + new Response(200, array(), $body), + new Response(400, array(), 'fault{'), + new Response(400, array(), $body), + new Response(400, array(), $body), + ]); $handler = HandlerStack::create($mock); return new GuzzleClient(['handler' => $handler]); @@ -114,7 +128,7 @@ abstract class AbstractTest extends \PHPUnit_Framework_TestCase ->getMock(); if ($emptyResult) { - $mockClient->expects($this->once()) + $mockClient->expects($this->any()) ->method('query') ->will($this->returnValue(new ResultSet($this->getEmptyResult()))); } diff --git a/lib/influxdb-php/tests/unit/AdminTest.php b/lib/influxdb-php/tests/unit/AdminTest.php index 889874f4c..835e9869a 100644 --- a/lib/influxdb-php/tests/unit/AdminTest.php +++ b/lib/influxdb-php/tests/unit/AdminTest.php @@ -47,7 +47,7 @@ class AdminTest extends AbstractTest public function testShowUsers() { - $testJson = file_get_contents(dirname(__FILE__) . '/result-test-users.example.json'); + $testJson = file_get_contents(dirname(__FILE__) . '/json/result-test-users.example.json'); $clientMock = $this->getClientMock(); $testResult = new ResultSet($testJson); diff --git a/lib/influxdb-php/tests/unit/ClientTest.php b/lib/influxdb-php/tests/unit/ClientTest.php index 09f420d1b..a75b979d1 100644 --- a/lib/influxdb-php/tests/unit/ClientTest.php +++ b/lib/influxdb-php/tests/unit/ClientTest.php @@ -4,6 +4,7 @@ namespace InfluxDB\Test; use InfluxDB\Client; use InfluxDB\Driver\Guzzle; +use InfluxDB\Point; class ClientTest extends AbstractTest { @@ -19,16 +20,26 @@ class ClientTest extends AbstractTest /** @var Client $client */ protected $client = null; + public function testGetters() + { + $client = $this->getClient(); + + $this->assertEquals('http://localhost:8086', $client->getBaseURI()); + $this->assertInstanceOf('InfluxDB\Driver\Guzzle', $client->getDriver()); + $this->assertEquals('localhost', $client->getHost()); + $this->assertEquals('0', $client->getTimeout()); + } + public function testBaseURl() { - $client = new Client('localhost', 8086); + $client = $this->getClient(); $this->assertEquals($client->getBaseURI(), 'http://localhost:8086'); } public function testSelectDbShouldReturnDatabaseInstance() { - $client = new Client('localhost', 8086); + $client = $this->getClient(); $dbName = 'test-database'; $database = $client->selectDB($dbName); @@ -38,23 +49,110 @@ class ClientTest extends AbstractTest $this->assertEquals($dbName, $database->getName()); } + public function testSecureInstance() + { + $client = $this->getClient('test', 'test', true); + $urlParts = parse_url($client->getBaseURI()); + + $this->assertEquals('https', $urlParts['scheme']); + } /** */ public function testGuzzleQuery() { - $client = new Client('localhost', 8086); + $client = $this->getClient('test', 'test'); $query = "some-bad-query"; - $bodyResponse = file_get_contents(dirname(__FILE__) . '/result.example.json'); + $bodyResponse = file_get_contents(dirname(__FILE__) . '/json/result.example.json'); $httpMockClient = $this->buildHttpMockClient($bodyResponse); $client->setDriver(new Guzzle($httpMockClient)); /** @var \InfluxDB\ResultSet $result */ - $result = $client->query(null, $query); + $result = $client->query('somedb', $query); + $parameters = $client->getDriver()->getParameters(); + + $this->assertEquals(['test', 'test'], $parameters['auth']); + $this->assertEquals('somedb', $parameters['database']); $this->assertInstanceOf('\InfluxDB\ResultSet', $result); + + $this->assertEquals( + true, + $client->write( + [ + 'url' => 'http://localhost', + 'database' => 'influx_test_db', + 'method' => 'post' + ], + [new Point('test', 1.0)] + ) + ); + + $this->setExpectedException('\InvalidArgumentException'); + $client->query('test', 'bad-query'); + + $this->setExpectedException('\InfluxDB\Driver\Exception'); + $client->query('test', 'bad-query'); + } + + public function testGetLastQuery() + { + $this->mockClient->query('test', 'SELECT * from test_metric'); + $this->assertEquals($this->getClient()->getLastQuery(), 'SELECT * from test_metric'); + } + + public function testListDatabases() + { + $this->doTestResponse('databases.example.json', ['test', 'test1', 'test2'], 'listDatabases'); + } + public function testListUsers() + { + $this->doTestResponse('users.example.json', ['user', 'admin'], 'listUsers'); + } + + public function testFactoryMethod() + { + $client = $this->getClient('test', 'test', true); + + $staticClient = \InfluxDB\Client::fromDSN('https+influxdb://test:test@localhost:8086/'); + + $this->assertEquals($client, $staticClient); + + $db = $client->selectDB('testdb'); + $staticDB = \InfluxDB\Client::fromDSN('https+influxdb://test:test@localhost:8086/testdb'); + + $this->assertEquals($db, $staticDB); + + } + + /** + * @param string $responseFile + * @param array $result + * @param string $method + */ + protected function doTestResponse($responseFile, array $result, $method) + { + $client = $this->getClient(); + $bodyResponse = file_get_contents(dirname(__FILE__) . '/json/'. $responseFile); + $httpMockClient = $this->buildHttpMockClient($bodyResponse); + + $client->setDriver(new Guzzle($httpMockClient)); + + $this->assertEquals($result, $client->$method()); + } + + /** + * @param string $username + * @param string $password + * @param bool|false $ssl + * + * @return Client + */ + protected function getClient($username = '', $password = '', $ssl = false) + { + return new Client('localhost', 8086, $username, $password, $ssl); } } \ No newline at end of file diff --git a/lib/influxdb-php/tests/unit/DatabaseTest.php b/lib/influxdb-php/tests/unit/DatabaseTest.php index e41038547..b90fe3318 100644 --- a/lib/influxdb-php/tests/unit/DatabaseTest.php +++ b/lib/influxdb-php/tests/unit/DatabaseTest.php @@ -27,34 +27,54 @@ class DatabaseTest extends AbstractTest { parent::setUp(); - $this->resultData = file_get_contents(dirname(__FILE__) . '/result.example.json'); + $this->resultData = file_get_contents(dirname(__FILE__) . '/json/result.example.json'); $this->mockClient->expects($this->any()) ->method('listDatabases') ->will($this->returnValue(array('test123', 'test'))); - $this->dataToInsert = file_get_contents(dirname(__FILE__) . '/input.example.json'); + $this->dataToInsert = file_get_contents(dirname(__FILE__) . '/json/input.example.json'); } + public function testGetters() + { + $this->assertInstanceOf('InfluxDB\Client', $this->database->getClient()); + $this->assertInstanceOf('InfluxDB\Query\Builder', $this->database->getQueryBuilder()); + } + + /** * */ - public function testQuery() + public function testQueries() { $testResultSet = new ResultSet($this->resultData); $this->assertEquals($this->database->query('SELECT * FROM test_metric'), $testResultSet); + + $this->database->drop(); + $this->assertEquals('DROP DATABASE "influx_test_db"', Client::$lastQuery); + } - public function testCreateRetentionPolicy() + + public function testRetentionPolicyQueries() { - $retentionPolicy = new Database\RetentionPolicy('test', '1d', 1, true); + $retentionPolicy = $this->getTestRetentionPolicy(); - $mockClient = $this->getClientMock(true); + $this->assertEquals( + $this->getTestDatabase()->createRetentionPolicy($retentionPolicy), + new ResultSet($this->getEmptyResult()) + ); - $database = new Database('test', $mockClient); + $this->database->listRetentionPolicies(); + $this->assertEquals('SHOW RETENTION POLICIES ON "influx_test_db"', Client::$lastQuery); - $this->assertEquals($database->createRetentionPolicy($retentionPolicy), new ResultSet($this->getEmptyResult())); + $this->database->alterRetentionPolicy($this->getTestRetentionPolicy()); + $this->assertEquals( + 'ALTER RETENTION POLICY "test" ON "influx_test_db" DURATION 1d REPLICATION 1 DEFAULT', + Client::$lastQuery + ); } /** @@ -65,6 +85,38 @@ class DatabaseTest extends AbstractTest new Database(null, $this->mockClient); } + public function testCreate() + { + // test create with retention policy + $this->database->create($this->getTestRetentionPolicy('influx_test_db'), true); + $this->assertEquals( + 'CREATE RETENTION POLICY "influx_test_db" ON "influx_test_db" DURATION 1d REPLICATION 1 DEFAULT', + Client::$lastQuery + ); + + // test creating a database without create if not exists + $this->database->create(null, true); + $this->assertEquals('CREATE DATABASE IF NOT EXISTS "influx_test_db"', Client::$lastQuery); + + // test creating a database without create if not exists + $this->database->create(null, false); + $this->assertEquals('CREATE DATABASE "influx_test_db"', Client::$lastQuery); + + + $this->mockClient->expects($this->any()) + ->method('query') + ->will($this->returnCallback(function () { + throw new \Exception('test exception'); + })); + + + // test an exception being handled correctly + $this->setExpectedException('\InfluxDB\Database\Exception'); + $this->database->create($this->getTestRetentionPolicy('influx_test_db'), false); + + } + + public function testExists() { $database = new Database('test', $this->mockClient); @@ -96,5 +148,76 @@ class DatabaseTest extends AbstractTest ); $this->assertEquals(true, $this->database->writePoints(array($point1, $point2))); + + $this->mockClient->expects($this->once()) + ->method('write') + ->will($this->throwException(new \Exception('Test exception'))); + + $this->setExpectedException('InfluxDB\Exception'); + + $this->database->writePoints(array($point1, $point2)); + } -} \ No newline at end of file + + public function testQueryBuilderOrderBy() + { + $this->assertEquals( + $this->database->getQueryBuilder() + ->from('test_metric') + ->orderBy('time', 'DESC')->getQuery(), + 'SELECT * FROM "test_metric" ORDER BY time DESC'); + + $this->assertEquals( + $this->database->getQueryBuilder() + ->from('test_metric') + ->orderBy('time', 'DESC') + ->orderBy('some_field', 'ASC') + ->getQuery(), + 'SELECT * FROM "test_metric" ORDER BY time DESC,some_field ASC'); + } + + /** + * @see https://github.com/influxdata/influxdb-php/pull/36 + */ + public function testReservedNames() + { + $database = new Database('stats', $this->mockClient); + + // test handling of reserved keywords in database name + $database->create(); + $this->assertEquals('CREATE DATABASE IF NOT EXISTS "stats"', Client::$lastQuery); + + $database->listRetentionPolicies(); + $this->assertEquals('SHOW RETENTION POLICIES ON "stats"', Client::$lastQuery); + + // test handling of reserved keywords in retention policy names + $database->create($this->getTestRetentionPolicy('default')); + $this->assertEquals( + 'CREATE RETENTION POLICY "default" ON "stats" DURATION 1d REPLICATION 1 DEFAULT', + Client::$lastQuery + ); + + // test handling of reserved keywords in measurement names + $this->assertEquals($database->getQueryBuilder()->from('server')->getQuery(), 'SELECT * FROM "server"'); + } + + /** + * @param string $name + * + * @return Database + */ + protected function getTestDatabase($name = 'test') + { + return new Database($name, $this->getClientMock(true)); + } + + /** + * @param string $name + * + * @return Database\RetentionPolicy + */ + protected function getTestRetentionPolicy($name = 'test') + { + return new Database\RetentionPolicy($name, '1d', 1, true); + } +} diff --git a/lib/influxdb-php/tests/unit/PointTest.php b/lib/influxdb-php/tests/unit/PointTest.php index eaee63fe7..1b757cc63 100644 --- a/lib/influxdb-php/tests/unit/PointTest.php +++ b/lib/influxdb-php/tests/unit/PointTest.php @@ -1,10 +1,4 @@ 'server01', 'region' => 'us-west'), - array('cpucount' => 10), - 1435222310 - ); + $point = $this->getPoint('1440494531376778481'); $this->assertEquals($expected, (string) $point); } -} \ No newline at end of file + + /** + * Check if the Point class throw an exception when invalid timestamp are given. + * + * @dataProvider wrongTimestampProvider + * @expectedException \InfluxDB\Database\Exception + */ + public function testPointWrongTimestamp($timestamp) + { + $this->getPoint($timestamp); + } + + /** + * Check if the Point class accept all valid timestamp given. + * + * @dataProvider validTimestampProvider + */ + public function testPointValidTimestamp($timestamp) + { + $expected = 'instance,host=server01,region=us-west cpucount=10i,free=1i,test="string",bool=false,value=1.11' . (($timestamp) ? ' ' . $timestamp : ''); + + $point = $this->getPoint($timestamp); + + $this->assertEquals($expected, (string) $point); + } + + public function testGettersAndSetters() + { + $timestamp = time(); + $timestamp2 = time() + 3600; + $point = $this->getPoint($timestamp); + + $this->assertEquals($timestamp, $point->getTimestamp()); + $point->setTimestamp($timestamp2); + $this->assertEquals($timestamp2, $point->getTimestamp()); + + $this->assertEquals('instance', $point->getMeasurement()); + $point->setMeasurement('test'); + $this->assertEquals('test', $point->getMeasurement()); + + $fields = $point->getFields(); + $this->assertEquals(1.11, $fields['value']); + $this->assertEquals([ + 'cpucount' => '10i', + 'free' => '1i', + 'test' => "\"string\"", + 'bool' => 'false', + 'value' => '1.1100000000000001' + ], $fields); + + $point->setFields(['cpucount' => 11]); + $this->assertEquals(['cpucount' => '11i'], $point->getFields()); + + $this->assertEquals(['host' => 'server01', 'region' => 'us-west'], $point->getTags()); + $point->setTags(['test' => 'value']); + $this->assertEquals(['test' => 'value'], $point->getTags()); + + } + + + /** + * Provide wrong timestamp value for testing. + */ + public function wrongTimestampProvider() + { + return [ + ['2015-10-27 14:17:40'], + ['INVALID'], + ['aa778481'], + ['1477aee'], + ['15.258'], + ['15,258'], + [15.258], + [true] + ]; + } + + /** + * Provide valid timestamp value for testing. + */ + public function validTimestampProvider() + { + return [ + [time()], // Current time returned by the PHP time function. + [0], // Day 0 + [~PHP_INT_MAX], // Minimum value integer + [PHP_INT_MAX], // Maximum value integer + ['1440494531376778481'] // Text timestamp + ]; + } + + /** + * Returns an instance of \InfluxDB\Point + * + * @param int $timestamp + * + * @return Point + */ + private function getPoint($timestamp) + { + return new Point( + 'instance', // the name of the measurement + 1.11, // measurement value + ['host' => 'server01', 'region' => 'us-west'], + ['cpucount' => 10, 'free' => 1, 'test' => "string", 'bool' => false], + $timestamp + ); + } + +} diff --git a/lib/influxdb-php/tests/unit/ResultSetTest.php b/lib/influxdb-php/tests/unit/ResultSetTest.php index 4c04bf1e9..f1a3669ee 100644 --- a/lib/influxdb-php/tests/unit/ResultSetTest.php +++ b/lib/influxdb-php/tests/unit/ResultSetTest.php @@ -10,7 +10,7 @@ class ResultSetTest extends \PHPUnit_Framework_TestCase public function setUp() { - $resultJsonExample = file_get_contents(dirname(__FILE__) . '/result.example.json'); + $resultJsonExample = file_get_contents(dirname(__FILE__) . '/json/result.example.json'); $this->resultSet = new ResultSet($resultJsonExample); } @@ -65,7 +65,7 @@ EOD; */ public function testGetPointsFromNameWithoudTags() { - $resultJsonExample = file_get_contents(dirname(__FILE__) . '/result-no-tags.example.json'); + $resultJsonExample = file_get_contents(dirname(__FILE__) . '/json/result-no-tags.example.json'); $this->resultSet = new ResultSet($resultJsonExample); $measurementName = 'cpu_load_short'; @@ -95,6 +95,11 @@ EOD; } + public function testGetSeries() + { + $this->assertEquals(['time', 'value'], $this->resultSet->getColumns()); + } + /** * We can get points from measurement */ diff --git a/lib/influxdb-php/tests/unit/json/databases.example.json b/lib/influxdb-php/tests/unit/json/databases.example.json new file mode 100644 index 000000000..fae386bb9 --- /dev/null +++ b/lib/influxdb-php/tests/unit/json/databases.example.json @@ -0,0 +1,25 @@ +{ + "results":[ + { + "series":[ + { + "name":"databases", + "columns":[ + "name" + ], + "values":[ + [ + "test" + ], + [ + "test1" + ], + [ + "test2" + ] + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/lib/influxdb-php/tests/unit/input.example.json b/lib/influxdb-php/tests/unit/json/input.example.json similarity index 100% rename from lib/influxdb-php/tests/unit/input.example.json rename to lib/influxdb-php/tests/unit/json/input.example.json diff --git a/lib/influxdb-php/tests/unit/result-no-tags.example.json b/lib/influxdb-php/tests/unit/json/result-no-tags.example.json similarity index 100% rename from lib/influxdb-php/tests/unit/result-no-tags.example.json rename to lib/influxdb-php/tests/unit/json/result-no-tags.example.json diff --git a/lib/influxdb-php/tests/unit/result-test-users.example.json b/lib/influxdb-php/tests/unit/json/result-test-users.example.json similarity index 100% rename from lib/influxdb-php/tests/unit/result-test-users.example.json rename to lib/influxdb-php/tests/unit/json/result-test-users.example.json diff --git a/lib/influxdb-php/tests/unit/result.example.json b/lib/influxdb-php/tests/unit/json/result.example.json similarity index 100% rename from lib/influxdb-php/tests/unit/result.example.json rename to lib/influxdb-php/tests/unit/json/result.example.json diff --git a/lib/influxdb-php/tests/unit/json/users.example.json b/lib/influxdb-php/tests/unit/json/users.example.json new file mode 100644 index 000000000..272794e6c --- /dev/null +++ b/lib/influxdb-php/tests/unit/json/users.example.json @@ -0,0 +1,14 @@ +{ + "results":[ + { + "series":[ + { + "columns":[ + "user", + "admin" + ] + } + ] + } + ] +} \ No newline at end of file