From 30e63b0a76357d144f86ac8288f87c8f6df16105 Mon Sep 17 00:00:00 2001 From: Nuno Chaves Date: Wed, 29 Jun 2022 19:53:56 +0100 Subject: [PATCH] refactor and improvements code refactor and improvements. bug fixes min php version upgrade to 8.0. --- README.md | 113 ++++++++------ composer.json | 5 +- examples/example1.php | 201 +++++++++++++------------ src/CosmosDb.php | 294 +++++++++++++++++++------------------ src/CosmosDbCollection.php | 34 +---- src/CosmosDbDatabase.php | 70 ++++----- src/QueryBuilder.php | 174 ++++++++-------------- 7 files changed, 428 insertions(+), 463 deletions(-) diff --git a/README.md b/README.md index e33a5d5..164c00a 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,8 @@ PHP wrapper for Azure Cosmos DB +https://docs.microsoft.com/pt-pt/rest/api/cosmos-db/common-tasks-using-the-cosmosdb-rest-api + ## Installation Include jupitern/cosmosdb in your project, by adding it to your composer.json file. @@ -16,36 +18,31 @@ Include jupitern/cosmosdb in your project, by adding it to your composer.json fi ## Changelog -### v2.5.0 +### v2.6.0 +- code refactor. min PHP verion supported is now 8.0 +- selectCollection no longer creates a colletion if not exist. use createCollection for that +- bug fixes +### v2.5.0 - support partitioned queries using new method "setPartitionValue()" - - support creating partitioned collections - - support for nested partition keys ### v2.0.0 - - support for cross partition queries - - selectCollection method removed from all methods for performance improvements ### v1.4.4 - - replaced pear package http_request2 by guzzle - - added method to provide guzzle configuration ### v1.3.0 - - added support for parameterized queries ## Note - This package adds additional functionalities to the [AzureDocumentDB-PHP](https://github.com/cocteau666/AzureDocumentDB-PHP) package. All other functionality exists in this package as well. ## Limitations - Use of `limit()` or `order()` in cross-partition queries is currently not supported. ## Usage @@ -53,65 +50,59 @@ Use of `limit()` or `order()` in cross-partition queries is currently not suppor ### Connecting ```php -$conn = new \Jupitern\CosmosDb\CosmosDb('hostName', 'primaryKey'); -$conn->setHttpClientOptions(['verify' => false]); # optional: set guzzle client options. -$db = $conn->selectDB('dbName'); -$collection = $db->selectCollection('collectionName'); - -# if a collection does not exist, it will be created when you -# attempt to select the collection. however, if you have created -# your database with shared throughput, then all collections require a partition key. -# selectCollection() supports a second parameter for this purpose. -$conn = new \Jupitern\CosmosDb\CosmosDb('hostName', 'primaryKey'); +$conn = new \Jupitern\CosmosDb\CosmosDb('https://localhost:8081', 'primaryKey'); $conn->setHttpClientOptions(['verify' => false]); # optional: set guzzle client options. -$db = $conn->selectDB('dbName'); -$collection = $db->selectCollection('collectionName', 'myPartitionKey'); +$db = $conn->selectDB('testdb'); + +# create a new collection +$collection = $db->createCollection('Users', 'country'); + +# select existing collection +$collection = $db->selectCollection('Users'); ``` ### Inserting Records ```php - -# consider a existing collection called "Users" with a partition key "country" - -# insert a record $rid = \Jupitern\CosmosDb\QueryBuilder::instance() ->setCollection($collection) ->setPartitionKey('country') - ->save(['id' => '1', 'name' => 'John Doe', 'age' => 22, 'country' => 'Portugal']); - -# insert a record against a collection with a nested partition key -# note: this follows the same string format as is used when creating -# a collection with a partition key via the Azure Portal -$rid = \Jupitern\CosmosDb\QueryBuilder::instance() - ->setCollection($collection) - ->setPartitionKey('/form/person/country') - ->save(['id' => '2', 'name' => 'Jane doe', 'age' => 35, 'country' => 'Portugal']); + ->save([ + 'id' => '2', + 'name' => 'Jane doe', + 'age' => 35, + 'country' => 'Portugal' + ]); ``` ### Updating Records ```php -# update a record $rid = \Jupitern\CosmosDb\QueryBuilder::instance() ->setCollection($collection) ->setPartitionKey('country') - ->save(["_rid" => $rid, 'id' => '2', 'name' => 'Jane Doe Something', 'age' => 36, 'country' => 'Portugal']); + ->save([ + "_rid" => $rid, + 'id' => '2', + 'name' => 'Jane Doe Something', + 'age' => 36, + 'country' => 'Portugal' + ]); ``` ### Querying Records ```php -# query a document and return it as an array +# cross partition query to get a single document and return it as an array $res = \Jupitern\CosmosDb\QueryBuilder::instance() ->setCollection($collection) ->select("c.id, c.name") ->where("c.age > @age and c.country = @country") - ->params(['@age' => 30, '@country' => 'Portugal']) + ->params(['@age' => 10, '@country' => 'Portugal']) ->find(true) # pass true if is cross partition query ->toArray(); -# query a document using a known partition value, +# query a document using a known partition value # and return as an array. note: setting a known # partition value will result in a more efficient # query against your database as it will not rely @@ -120,21 +111,21 @@ $res = \Jupitern\CosmosDb\QueryBuilder::instance() ->setCollection($collection) ->setPartitionValue('Portugal') ->select("c.id, c.name") - ->where("c.age > @age and c.country = @country") - ->params(['@age' => 30, '@country' => 'Portugal']) + ->where("c.age > @age") + ->params(['@age' => 10]) ->find() ->toArray(); -# query the top 5 documents as an array, with the +# query to get the top 5 documents as an array, with the # document ID as the array key. # note: refer to limitations section $res = \Jupitern\CosmosDb\QueryBuilder::instance() ->setCollection($collection) - ->select("c.id, c.username") + ->select("c.id, c.name") ->where("c.age > @age and c.country = @country") ->params(['@age' => 10, '@country' => 'Portugal']) ->limit(5) - ->findAll() # cannot limit cross-partition queries + ->findAll() ->toArray('id'); # query a document using a collection alias and cross partition query @@ -142,7 +133,8 @@ $res = \Jupitern\CosmosDb\QueryBuilder::instance() ->setCollection($collection) ->select("TestColl.id, TestColl.name") ->from("TestColl") - ->where("TestColl.age > 30") + ->where("TestColl.age > @age") + ->params(['@age' => 10]) ->findAll(true) # pass true if is cross partition query ->toArray(); ``` @@ -154,7 +146,7 @@ $res = \Jupitern\CosmosDb\QueryBuilder::instance() $res = \Jupitern\CosmosDb\QueryBuilder::instance() ->setCollection($collection) ->setPartitionKey('country') - ->where("c.age > 30 and c.country = 'Portugal'") + ->where("c.age > 20 and c.country = 'Portugal'") ->delete(); # delete all documents that match criteria (cross partition) @@ -164,3 +156,30 @@ $res = \Jupitern\CosmosDb\QueryBuilder::instance() ->where("c.age > 20") ->deleteAll(true); ``` + +### Error handling + +```php +try { + $res = QueryBuilder::instance() + ->setCollection($collection) + ->deleteAll(true); + +} catch (\GuzzleHttp\Exception\ClientException $e) { + $response = json_decode($e->getResponse()->getBody()); + echo "ERROR: ".$response->code ." => ". $response->message .PHP_EOL.PHP_EOL; + + echo $e->getTraceAsString(); +} +``` + + +## Contributing + +- welcome to discuss a bugs, features and ideas. + +## License + +jupitern/cosmosdb is release under the MIT license. + +You are free to use, modify and distribute this software, as long as the copyright header is left intact diff --git a/composer.json b/composer.json index a4858cb..0032ebe 100644 --- a/composer.json +++ b/composer.json @@ -8,8 +8,9 @@ "source": "https://github.com/jupitern/cosmosdb", "issues": "https://github.com/jupitern/cosmosdb/issues" }, - "require" :{ - "php":">=7.0", + "require": { + "php": ">=8.0", + "ext-curl": "*", "guzzlehttp/guzzle": "^7.4" }, "autoload": { diff --git a/examples/example1.php b/examples/example1.php index 06b4739..47cdd89 100644 --- a/examples/example1.php +++ b/examples/example1.php @@ -4,95 +4,112 @@ ini_set("display_errors", 1); require __DIR__ .'/../vendor/autoload.php'; -// consider a existing collection called "Users" with a partition key "country" - -$conn = new \Jupitern\CosmosDb\CosmosDb('host', 'pk'); -$conn->setHttpClientOptions(['verify' => false]); // optional: set guzzle client options. -$db = $conn->selectDB('dbName'); -$collection = $db->selectCollection('collectionName'); - -// insert a record -$rid = \Jupitern\CosmosDb\QueryBuilder::instance() - ->setCollection($collection) - ->setPartitionKey('country') - ->save(['id' => '1', 'name' => 'John Doe', 'age' => 22, 'country' => 'Portugal']); - -echo "record inserted: $rid".PHP_EOL; - -// insert a record -$rid = \Jupitern\CosmosDb\QueryBuilder::instance() - ->setCollection($collection) - ->setPartitionKey('country') - ->save(['id' => '2', 'name' => 'Jane doe', 'age' => 35, 'country' => 'Portugal']); - -echo "record inserted: $rid".PHP_EOL; - -// update a record -$rid = \Jupitern\CosmosDb\QueryBuilder::instance() - ->setCollection($collection) - ->setPartitionKey('country') - ->save(["_rid" => $rid, 'id' => '2', 'name' => 'Jane Doe Something', 'age' => 36, 'country' => 'Portugal']); - -echo "record updated: $rid".PHP_EOL; - -echo "get one row as array:".PHP_EOL; - -// get one row as array -$res = \Jupitern\CosmosDb\QueryBuilder::instance() - ->setCollection($collection) - ->select("c.id, c.name") - ->where("c.age > @age and c.country = @country") - ->params(['@age' => 30, '@country' => 'Portugal']) - ->find(true) // pass true if is cross partition query - ->toArray(); - -var_dump($res); - -echo "get 5 rows as array with id as array key:".PHP_EOL; - -// get top 5 rows as array with id as array key -$res = \Jupitern\CosmosDb\QueryBuilder::instance() - ->setCollection($collection) - ->select("c.id, c.username") - ->where("c.age > @age and c.country = @country") - ->params(['@age' => 10, '@country' => 'Portugal']) - ->limit(5) - ->findAll() // pass true if is cross partition query - ->toArray('id'); - -var_dump($res); - -echo "get rows as array of objects with collection alias and cross partition query:".PHP_EOL; - -// get rows as array of objects with collection alias and cross partition query -$res = \Jupitern\CosmosDb\QueryBuilder::instance() - ->setCollection($collection) - ->select("Users.id, Users.name") - ->from("Users") - ->where("Users.age > 30") - ->findAll(true) // pass true if is cross partition query - ->toArray(); - -var_dump($res); - -echo "delete one document:".PHP_EOL; - -// delete one document that match criteria -$res = \Jupitern\CosmosDb\QueryBuilder::instance() - ->setCollection($collection) - ->setPartitionKey('country') - ->where("c.age > 30 and c.country = 'Portugal'") - ->delete(); - -var_dump($res); - -echo "delete all documents:".PHP_EOL; - -// delete all documents that match criteria -$res = \Jupitern\CosmosDb\QueryBuilder::instance() - ->setPartitionKey('country') - ->setCollection($collection) - ->where("c.age > 20") - ->deleteAll(true); - -var_dump($res); +use \Jupitern\CosmosDb\CosmosDb; +use \Jupitern\CosmosDb\QueryBuilder; + +try { + $conn = new CosmosDb('https://localhost:8081', 'C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=='); + $conn->setHttpClientOptions(['verify' => false]); // optional: set guzzle client options. + $db = $conn->selectDB('testdb'); + $collection = $db->selectCollection('Users'); + + if ($collection == null) { + $collection = $db->createCollection('Users', '/country'); + } + + echo "delete all documents" . PHP_EOL; + + $res = QueryBuilder::instance() + ->setCollection($collection) + ->deleteAll(true); + + die(); + + $rid = null; + for ($i = 1; $i <= 30; ++$i) { + $rid = QueryBuilder::instance() + ->setCollection($collection) + ->setPartitionKey('country') + ->save(['id' => (string)$i, 'name' => 'Person #' . $i, 'age' => rand(10, 40), 'country' => 'Portugal']); + + echo "{$i} => record inserted: $rid" . PHP_EOL; + } + + // update a record + $rid = QueryBuilder::instance() + ->setCollection($collection) + ->setPartitionKey('country') + ->save(["_rid" => $rid, 'id' => '30', 'name' => 'Jane Doe Something', 'age' => 36, 'country' => 'Portugal']); + + echo "record updated: $rid" . PHP_EOL; + + echo "get one row as array:" . PHP_EOL; + + // get one row as array + $res = QueryBuilder::instance() + ->setCollection($collection) + ->select("c.id, c.name") + ->where("c.age > @age and c.country = @country") + ->params(['@age' => 30, '@country' => 'Portugal']) + ->find(false) // pass true if is cross partition query + ->toArray(); + + var_dump($res); + + echo "get 5 rows as array with id as array key:" . PHP_EOL; + + // get top 5 rows as array with id as array key + $res = QueryBuilder::instance() + ->setCollection($collection) + ->select("c.id, c.name") + ->where("c.age > @age and c.country = @country") + ->params(['@age' => 10, '@country' => 'Portugal']) + ->limit(5) + ->findAll() // pass true if is cross partition query + ->toArray('id'); + + var_dump($res); + + echo "get age > 30 rows as array of objects with collection alias and cross partition query:" . PHP_EOL; + + // get rows as array of objects with collection alias and cross partition query + $res = QueryBuilder::instance() + ->setCollection($collection) + ->select("Users.id, Users.name") + ->from("Users") + ->where("Users.age > 30") + ->findAll(true) // pass true if is cross partition query + ->toObject(); + + var_dump($res); + + echo "delete one document:" . PHP_EOL; + + // delete one document that match criteria + $res = QueryBuilder::instance() + ->setCollection($collection) + ->setPartitionKey('country') + ->where("c.age > @age and c.country = @country") + ->params(['@age' => 30, '@country' => 'Portugal']) + ->delete(); + + var_dump($res); + + echo "delete all documents age > 20:" . PHP_EOL; + + // delete all documents that match criteria + $res = QueryBuilder::instance() + ->setPartitionKey('country') + ->setCollection($collection) + ->where("c.age > @age") + ->params(['@age' => 20]) + ->deleteAll(true); + + var_dump($res); + +} catch (\GuzzleHttp\Exception\ClientException $e) { + $response = json_decode($e->getResponse()->getBody()); + echo "ERROR: ".$response->code ." => ". $response->message .PHP_EOL.PHP_EOL; + + echo $e->getTraceAsString(); +} diff --git a/src/CosmosDb.php b/src/CosmosDb.php index 860fbed..c76ad82 100644 --- a/src/CosmosDb.php +++ b/src/CosmosDb.php @@ -2,48 +2,26 @@ namespace Jupitern\CosmosDb; -/* - * Based on the AzureDocumentDB-PHP library written by Takeshi Sakurai. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * Microsoft Azure Document DB Library for PHP - * @link http://msdn.microsoft.com/en-us/library/azure/dn781481.aspx - * @link https://github.com/jupitern/cosmosdb - */ +use GuzzleHttp\Exception\GuzzleException; +use Psr\Http\Message\ResponseInterface; class CosmosDb { - private $host; - private $private_key; - private $debug; - public $httpClientOptions = true; + private string $host; + private string $private_key; + public array $httpClientOptions; /** * __construct * * @access public - * @param string $host: URI of hostname - * @param string $private_key: Primary (or Secondary key) private key - * @param bool $debug: return Response Headers and JSON(if you need), false(default): return JSON only + * @param string $host URI of hostname + * @param string $private_key Primary (or Secondary key) private key */ - public function __construct($host, $private_key, $debug = false) + public function __construct(string $host, string $private_key) { $this->host = $host; $this->private_key = $private_key; - $this->debug = $debug; } /** @@ -51,7 +29,7 @@ public function __construct($host, $private_key, $debug = false) * * @param array $options */ - public function setHttpClientOptions($options = []) + public function setHttpClientOptions(array $options = []) { $this->httpClientOptions = $options; } @@ -66,12 +44,12 @@ public function setHttpClientOptions($options = []) * @param string $resource_id Resource ID * @return array of Request Headers */ - private function getAuthHeaders($verb, $resource_type, $resource_id) + private function getAuthHeaders(string $verb, string $resource_type, string $resource_id): array { $x_ms_date = gmdate('D, d M Y H:i:s T', strtotime('+2 minutes')); $master = 'master'; $token = '1.0'; - $x_ms_version = '2017-02-22'; + $x_ms_version = '2018-12-31'; $key = base64_decode($this->private_key); $string_to_sign = $verb . "\n" . @@ -102,9 +80,10 @@ private function getAuthHeaders($verb, $resource_type, $resource_id) * @param string $method request method * @param array $headers request headers * @param string $body request body (JSON or QUERY) - * @return string JSON response + * @return ResponseInterface JSON response + * @throws GuzzleException */ - private function request($path, $method, $headers, $body = NULL) + private function request(string $path, string $method, array $headers, $body = NULL): ResponseInterface { $client = new \GuzzleHttp\Client(); @@ -112,27 +91,11 @@ private function request($path, $method, $headers, $body = NULL) 'headers' => $headers, 'body' => $body, ]; - try { - $response = $client->request($method, $this->host . $path, array_merge( - $options, - (array)$this->httpClientOptions - )); - return $response; - } - catch (\GuzzleHttp\Exception\ClientException $e) { - /* - * If CosmosDB returns a 'x-ms-retry-after' header due to throtteling, we sleep for the given period plus a - * small buffer and then try again. - */ - if ($e->getResponse()->getHeader('x-ms-retry-after-ms') !== []) { - $sleeptime = (int)($e->getResponse()->getHeader('x-ms-retry-after-ms')[0]*1000)+50; - usleep($sleeptime); - return $this->request($path, $method, $headers, $body); - } - else { - throw $e; - } - } + + return $client->request($method, $this->host . $path, array_merge( + $options, + (array)$this->httpClientOptions + )); } /** @@ -140,12 +103,14 @@ private function request($path, $method, $headers, $body = NULL) * * @access public * @param string $db_name Database name - * @return CosmosDbDatabase class + * @return ?CosmosDbDatabase class + * @throws GuzzleException */ - public function selectDB($db_name) + public function selectDB(string $db_name): ?CosmosDbDatabase { $rid_db = false; $object = json_decode($this->listDatabases()); + $db_list = $object->Databases; for ($i = 0; $i < count($db_list); $i++) { if ($db_list[$i]->id === $db_name) { @@ -156,11 +121,8 @@ public function selectDB($db_name) $object = json_decode($this->createDatabase('{"id":"' . $db_name . '"}')); $rid_db = $object->_rid; } - if ($rid_db) { - return new CosmosDbDatabase($this, $rid_db); - } else { - return false; - } + + return $rid_db ? new CosmosDbDatabase($this, $rid_db) : null; } /** @@ -168,8 +130,9 @@ public function selectDB($db_name) * * @access public * @return string JSON response + * @throws GuzzleException */ - public function getInfo() + public function getInfo(): string { $headers = $this->getAuthHeaders('GET', '', ''); $headers['Content-Length'] = '0'; @@ -185,9 +148,10 @@ public function getInfo() * @param string $rid_col Resource Collection ID * @param string $query Query * @param boolean $isCrossPartition used for cross partition query - * @return string JSON response + * @return array JSON response + * @throws GuzzleException */ - public function query($rid_id, $rid_col, $query, $isCrossPartition = false, $partitionValue = null) + public function query(string $rid_id, string $rid_col, string $query, bool $isCrossPartition = false, $partitionValue = null): array { $headers = $this->getAuthHeaders('POST', 'docs', $rid_col); $headers['Content-Length'] = strlen($query); @@ -244,37 +208,38 @@ public function query($rid_id, $rid_col, $query, $isCrossPartition = false, $par throw $e; } } + return $results; } - /** - * getPkRanges - * - * @param $rid_id - * @param $rid_col - * @param bool $raw - * - * @return mixed|string - */ - public function getPkRanges($rid_id, $rid_col) - { + /** + * getPkRanges + * + * @param string $rid_id + * @param string $rid_col + * @return mixed + * @throws GuzzleException + */ + public function getPkRanges(string $rid_id, string $rid_col): mixed + { $headers = $this->getAuthHeaders('GET', 'pkranges', $rid_col); $headers['Accept'] = 'application/json'; $headers['x-ms-max-item-count'] = -1; $result = $this->request("/dbs/{$rid_id}/colls/{$rid_col}/pkranges", "GET", $headers); - return json_decode($result); + return json_decode($result->getBody()->getContents()); } - /** - * getPkFullRange - * - * @param $rid_id - * @param $rid_col - * - * @return string - */ - public function getPkFullRange($rid_id, $rid_col) - { + /** + * getPkFullRange + * + * @param $rid_id + * @param $rid_col + * + * @return string + * @throws GuzzleException + */ + public function getPkFullRange($rid_id, $rid_col): string + { $result = $this->getPkRanges($rid_id, $rid_col); $ids = \array_column($result->PartitionKeyRanges, "id"); return $result->_rid . "," . \implode(",", $ids); @@ -286,8 +251,9 @@ public function getPkFullRange($rid_id, $rid_col) * @link http://msdn.microsoft.com/en-us/library/azure/dn803945.aspx * @access public * @return string JSON response + * @throws GuzzleException */ - public function listDatabases() + public function listDatabases(): string { $headers = $this->getAuthHeaders('GET', 'dbs', ''); $headers['Content-Length'] = '0'; @@ -301,8 +267,9 @@ public function listDatabases() * @access public * @param string $rid_id Resource ID * @return string JSON response + * @throws GuzzleException */ - public function getDatabase($rid_id) + public function getDatabase(string $rid_id): string { $headers = $this->getAuthHeaders('GET', 'dbs', $rid_id); $headers['Content-Length'] = '0'; @@ -316,8 +283,9 @@ public function getDatabase($rid_id) * @access public * @param string $json JSON request * @return string JSON response + * @throws GuzzleException */ - public function createDatabase($json) + public function createDatabase(string $json): string { $headers = $this->getAuthHeaders('POST', 'dbs', ''); $headers['Content-Length'] = strlen($json); @@ -332,8 +300,9 @@ public function createDatabase($json) * @param string $rid_id Resource ID * @param string $json JSON request * @return string JSON response + * @throws GuzzleException */ - public function replaceDatabase($rid_id, $json) + public function replaceDatabase(string $rid_id, string $json): string { $headers = $this->getAuthHeaders('PUT', 'dbs', $rid_id); $headers['Content-Length'] = strlen($json); @@ -348,7 +317,7 @@ public function replaceDatabase($rid_id, $json) * @param string $rid_id Resource ID * @return string JSON response */ - public function deleteDatabase($rid_id) + public function deleteDatabase(string $rid_id): string { $headers = $this->getAuthHeaders('DELETE', 'dbs', $rid_id); $headers['Content-Length'] = '0'; @@ -362,8 +331,9 @@ public function deleteDatabase($rid_id) * @access public * @param string $rid_id Resource ID * @return string JSON response + * @throws GuzzleException */ - public function listUsers($rid_id) + public function listUsers(string $rid_id): string { $headers = $this->getAuthHeaders('GET', 'users', $rid_id); $headers['Content-Length'] = '0'; @@ -378,8 +348,9 @@ public function listUsers($rid_id) * @param string $rid_id Resource ID * @param string $rid_user Resource User ID * @return string JSON response + * @throws GuzzleException */ - public function getUser($rid_id, $rid_user) + public function getUser(string $rid_id, string $rid_user): string { $headers = $this->getAuthHeaders('GET', 'users', $rid_user); $headers['Content-Length'] = '0'; @@ -394,8 +365,9 @@ public function getUser($rid_id, $rid_user) * @param string $rid_id Resource ID * @param string $json JSON request * @return string JSON response + * @throws GuzzleException */ - public function createUser($rid_id, $json) + public function createUser(string $rid_id, string $json): string { $headers = $this->getAuthHeaders('POST', 'users', $rid_id); $headers['Content-Length'] = strlen($json); @@ -411,8 +383,9 @@ public function createUser($rid_id, $json) * @param string $rid_user Resource User ID * @param string $json JSON request * @return string JSON response + * @throws GuzzleException */ - public function replaceUser($rid_id, $rid_user, $json) + public function replaceUser(string $rid_id, string $rid_user, string $json): string { $headers = $this->getAuthHeaders('PUT', 'users', $rid_user); $headers['Content-Length'] = strlen($json); @@ -427,8 +400,9 @@ public function replaceUser($rid_id, $rid_user, $json) * @param string $rid_id Resource ID * @param string $rid_user Resource User ID * @return string JSON response + * @throws GuzzleException */ - public function deleteUser($rid_id, $rid_user) + public function deleteUser(string $rid_id, string $rid_user): string { $headers = $this->getAuthHeaders('DELETE', 'users', $rid_user); $headers['Content-Length'] = '0'; @@ -442,8 +416,9 @@ public function deleteUser($rid_id, $rid_user) * @access public * @param string $rid_id Resource ID * @return string JSON response + * @throws GuzzleException */ - public function listCollections($rid_id) + public function listCollections(string $rid_id): string { $headers = $this->getAuthHeaders('GET', 'colls', $rid_id); $headers['Content-Length'] = '0'; @@ -458,8 +433,9 @@ public function listCollections($rid_id) * @param string $rid_id Resource ID * @param string $rid_col Resource Collection ID * @return string JSON response + * @throws GuzzleException */ - public function getCollection($rid_id, $rid_col) + public function getCollection(string $rid_id, string $rid_col): string { $headers = $this->getAuthHeaders('GET', 'colls', $rid_col); $headers['Content-Length'] = '0'; @@ -474,8 +450,9 @@ public function getCollection($rid_id, $rid_col) * @param string $rid_id Resource ID * @param string $json JSON request * @return string JSON response + * @throws GuzzleException */ - public function createCollection($rid_id, $json) + public function createCollection(string $rid_id, string $json): string { $headers = $this->getAuthHeaders('POST', 'colls', $rid_id); $headers['Content-Length'] = strlen($json); @@ -490,8 +467,9 @@ public function createCollection($rid_id, $json) * @param string $rid_id Resource ID * @param string $rid_col Resource Collection ID * @return string JSON response + * @throws GuzzleException */ - public function deleteCollection($rid_id, $rid_col) + public function deleteCollection(string $rid_id, string $rid_col): string { $headers = $this->getAuthHeaders('DELETE', 'colls', $rid_col); $headers['Content-Length'] = '0'; @@ -504,10 +482,11 @@ public function deleteCollection($rid_id, $rid_col) * @link http://msdn.microsoft.com/en-us/library/azure/dn803955.aspx * @access public * @param string $rid_id Resource ID - * @param string $rid_colResource Collection ID + * @param string $rid_col * @return string JSON response + * @throws GuzzleException */ - public function listDocuments($rid_id, $rid_col) + public function listDocuments(string $rid_id, string $rid_col): string { $headers = $this->getAuthHeaders('GET', 'docs', $rid_col); $headers['Content-Length'] = '0'; @@ -523,8 +502,9 @@ public function listDocuments($rid_id, $rid_col) * @param string $rid_col Resource Collection ID * @param string $rid_doc Resource Doc ID * @return string JSON response + * @throws GuzzleException */ - public function getDocument($rid_id, $rid_col, $rid_doc) + public function getDocument(string $rid_id, string $rid_col, string $rid_doc): string { $headers = $this->getAuthHeaders('GET', 'docs', $rid_doc); $headers['Content-Length'] = '0'; @@ -543,11 +523,12 @@ public function getDocument($rid_id, $rid_col, $rid_doc) * @param string $rid_id Resource ID * @param string $rid_col Resource Collection ID * @param string $json JSON request - * @param string $partitionKey + * @param string|null $partitionKey * @param array $headers Optional headers to send along with the request * @return string JSON response + * @throws GuzzleException */ - public function createDocument($rid_id, $rid_col, $json, $partitionKey = null, array $headers = []) + public function createDocument(string $rid_id, string $rid_col, string $json, string $partitionKey = null, array $headers = []): string { $authHeaders = $this->getAuthHeaders('POST', 'docs', $rid_col); $headers = \array_merge($headers, $authHeaders); @@ -568,11 +549,12 @@ public function createDocument($rid_id, $rid_col, $json, $partitionKey = null, a * @param string $rid_col Resource Collection ID * @param string $rid_doc Resource Doc ID * @param string $json JSON request - * @param string $partitionKey + * @param string|null $partitionKey * @param array $headers Optional headers to send along with the request * @return string JSON response + * @throws GuzzleException */ - public function replaceDocument($rid_id, $rid_col, $rid_doc, $json, $partitionKey = null, array $headers = []) + public function replaceDocument(string $rid_id, string $rid_col, string $rid_doc, string $json, string $partitionKey = null, array $headers = []): string { $authHeaders = $this->getAuthHeaders('PUT', 'docs', $rid_doc); $headers = \array_merge($headers, $authHeaders); @@ -592,11 +574,12 @@ public function replaceDocument($rid_id, $rid_col, $rid_doc, $json, $partitionKe * @param string $rid_id Resource ID * @param string $rid_col Resource Collection ID * @param string $rid_doc Resource Doc ID - * @param string $partitionKey + * @param string|null $partitionKey * @param array $headers Optional headers to send along with the request * @return string JSON response + * @throws GuzzleException */ - public function deleteDocument($rid_id, $rid_col, $rid_doc, $partitionKey = null, array $headers = []) + public function deleteDocument(string $rid_id, string $rid_col, string $rid_doc, string $partitionKey = null, array $headers = []): string { $authHeaders = $this->getAuthHeaders('DELETE', 'docs', $rid_doc); $headers = \array_merge($headers, $authHeaders); @@ -614,11 +597,12 @@ public function deleteDocument($rid_id, $rid_col, $rid_doc, $partitionKey = null * @link http:// * @access public * @param string $rid_id Resource ID - * @param string $rid_colResource Collection ID + * @param string $rid_col * @param string $rid_doc Resource Doc ID * @return string JSON response + * @throws GuzzleException */ - public function listAttachments($rid_id, $rid_col, $rid_doc) + public function listAttachments(string $rid_id, string $rid_col, string $rid_doc): string { $headers = $this->getAuthHeaders('GET', 'attachments', $rid_doc); $headers['Content-Length'] = '0'; @@ -635,8 +619,9 @@ public function listAttachments($rid_id, $rid_col, $rid_doc) * @param string $rid_doc Resource Doc ID * @param string $rid_at Resource Attachment ID * @return string JSON response + * @throws GuzzleException */ - public function getAttachment($rid_id, $rid_col, $rid_doc, $rid_at) + public function getAttachment(string $rid_id, string $rid_col, string $rid_doc, string $rid_at): string { $headers = $this->getAuthHeaders('GET', 'attachments', $rid_at); $headers['Content-Length'] = '0'; @@ -655,8 +640,9 @@ public function getAttachment($rid_id, $rid_col, $rid_doc, $rid_at) * @param string $filename Attachement file name * @param string $file URL encoded Attachement file (Raw Media) * @return string JSON response + * @throws GuzzleException */ - public function createAttachment($rid_id, $rid_col, $rid_doc, $content_type, $filename, $file) + public function createAttachment(string $rid_id, string $rid_col, string $rid_doc, string $content_type, string $filename, string $file): string { $headers = $this->getAuthHeaders('POST', 'attachments', $rid_doc); $headers['Content-Length'] = strlen($file); @@ -678,8 +664,9 @@ public function createAttachment($rid_id, $rid_col, $rid_doc, $content_type, $fi * @param string $filename Attachement file name * @param string $file URL encoded Attachement file (Raw Media) * @return string JSON response + * @throws GuzzleException */ - public function replaceAttachment($rid_id, $rid_col, $rid_doc, $rid_at, $content_type, $filename, $file) + public function replaceAttachment(string $rid_id, string $rid_col, string $rid_doc, string $rid_at, string $content_type, string $filename, string $file): string { $headers = $this->getAuthHeaders('PUT', 'attachments', $rid_at); $headers['Content-Length'] = strlen($file); @@ -698,8 +685,9 @@ public function replaceAttachment($rid_id, $rid_col, $rid_doc, $rid_at, $content * @param string $rid_doc Resource Doc ID * @param string $rid_at Resource Attachment ID * @return string JSON response + * @throws GuzzleException */ - public function deleteAttachment($rid_id, $rid_col, $rid_doc, $rid_at) + public function deleteAttachment(string $rid_id, string $rid_col, string $rid_doc, string $rid_at): string { $headers = $this->getAuthHeaders('DELETE', 'attachments', $rid_at); $headers['Content-Length'] = '0'; @@ -712,8 +700,9 @@ public function deleteAttachment($rid_id, $rid_col, $rid_doc, $rid_at) * @link http:// * @access public * @return string JSON response + * @throws GuzzleException */ - public function listOffers() + public function listOffers(): string { $headers = $this->getAuthHeaders('GET', 'offers', ''); $headers['Content-Length'] = '0'; @@ -727,8 +716,9 @@ public function listOffers() * @access public * @param string $rid Resource ID * @return string JSON response + * @throws GuzzleException */ - public function getOffer($rid) + public function getOffer(string $rid): string { $headers = $this->getAuthHeaders('GET', 'offers', $rid); $headers['Content-Length'] = '0'; @@ -743,8 +733,9 @@ public function getOffer($rid) * @param string $rid Resource ID * @param string $json JSON request * @return string JSON response + * @throws GuzzleException */ - public function replaceOffer($rid, $json) + public function replaceOffer(string $rid, string $json): string { $headers = $this->getAuthHeaders('PUT', 'offers', $rid); $headers['Content-Length'] = strlen($json); @@ -758,8 +749,9 @@ public function replaceOffer($rid, $json) * @access public * @param string $json JSON request * @return string JSON response + * @throws GuzzleException */ - public function queryingOffers($json) + public function queryingOffers(string $json): string { $headers = $this->getAuthHeaders('POST', 'offers', ''); $headers['Content-Length'] = strlen($json); @@ -776,8 +768,9 @@ public function queryingOffers($json) * @param string $rid_id Resource ID * @param string $rid_user Resource User ID * @return string JSON response + * @throws GuzzleException */ - public function listPermissions($rid_id, $rid_user) + public function listPermissions(string $rid_id, string $rid_user): string { $headers = $this->getAuthHeaders('GET', 'permissions', $rid_user); $headers['Content-Length'] = '0'; @@ -793,8 +786,9 @@ public function listPermissions($rid_id, $rid_user) * @param string $rid_user Resource User ID * @param string $json JSON request * @return string JSON response + * @throws GuzzleException */ - public function createPermission($rid_id, $rid_user, $json) + public function createPermission(string $rid_id, string $rid_user, string $json): string { $headers = $this->getAuthHeaders('POST', 'permissions', $rid_user); $headers['Content-Length'] = strlen($json); @@ -810,8 +804,9 @@ public function createPermission($rid_id, $rid_user, $json) * @param string $rid_user Resource User ID * @param string $rid_permission Resource Permission ID * @return string JSON response + * @throws GuzzleException */ - public function getPermission($rid_id, $rid_user, $rid_permission) + public function getPermission(string $rid_id, string $rid_user, string $rid_permission): string { $headers = $this->getAuthHeaders('GET', 'permissions', $rid_permission); $headers['Content-Length'] = '0'; @@ -828,8 +823,9 @@ public function getPermission($rid_id, $rid_user, $rid_permission) * @param string $rid_permission Resource Permission ID * @param string $json JSON request * @return string JSON response + * @throws GuzzleException */ - public function replacePermission($rid_id, $rid_user, $rid_permission, $json) + public function replacePermission(string $rid_id, string $rid_user, string $rid_permission, string $json): string { $headers = $this->getAuthHeaders('PUT', 'permissions', $rid_permission); $headers['Content-Length'] = strlen($json); @@ -845,8 +841,9 @@ public function replacePermission($rid_id, $rid_user, $rid_permission, $json) * @param string $rid_user Resource User ID * @param string $rid_permission Resource Permission ID * @return string JSON response + * @throws GuzzleException */ - public function deletePermission($rid_id, $rid_user, $rid_permission) + public function deletePermission(string $rid_id, string $rid_user, string $rid_permission): string { $headers = $this->getAuthHeaders('DELETE', 'permissions', $rid_permission); $headers['Content-Length'] = '0'; @@ -859,10 +856,11 @@ public function deletePermission($rid_id, $rid_user, $rid_permission) * @link http:// * @access public * @param string $rid_id Resource ID - * @param string $rid_colResource Collection ID + * @param string $rid_col * @return string JSON response + * @throws GuzzleException */ - public function listStoredProcedures($rid_id, $rid_col) + public function listStoredProcedures(string $rid_id, string $rid_col): string { $headers = $this->getAuthHeaders('GET', 'sprocs', $rid_col); $headers['Content-Length'] = '0'; @@ -879,8 +877,9 @@ public function listStoredProcedures($rid_id, $rid_col) * @param string $rid_sproc Resource ID of Stored Procedurea * @param string $json Parameters * @return string JSON response + * @throws GuzzleException */ - public function executeStoredProcedure($rid_id, $rid_col, $rid_sproc, $json) + public function executeStoredProcedure(string $rid_id, string $rid_col, string $rid_sproc, string $json): string { $headers = $this->getAuthHeaders('POST', 'sprocs', $rid_sproc); $headers['Content-Length'] = strlen($json); @@ -896,8 +895,9 @@ public function executeStoredProcedure($rid_id, $rid_col, $rid_sproc, $json) * @param string $rid_col Resource Collection ID * @param string $json JSON of function * @return string JSON response + * @throws GuzzleException */ - public function createStoredProcedure($rid_id, $rid_col, $json) + public function createStoredProcedure(string $rid_id, string $rid_col, string $json): string { $headers = $this->getAuthHeaders('POST', 'sprocs', $rid_col); $headers['Content-Length'] = strlen($json); @@ -914,8 +914,9 @@ public function createStoredProcedure($rid_id, $rid_col, $json) * @param string $rid_sproc Resource ID of Stored Procedurea * @param string $json Parameters * @return string JSON response + * @throws GuzzleException */ - public function replaceStoredProcedure($rid_id, $rid_col, $rid_sproc, $json) + public function replaceStoredProcedure(string $rid_id, string $rid_col, string $rid_sproc, string $json): string { $headers = $this->getAuthHeaders('PUT', 'sprocs', $rid_sproc); $headers['Content-Length'] = strlen($json); @@ -931,8 +932,9 @@ public function replaceStoredProcedure($rid_id, $rid_col, $rid_sproc, $json) * @param string $rid_col Resource Collection ID * @param string $rid_sproc Resource ID of Stored Procedurea * @return string JSON response + * @throws GuzzleException */ - public function deleteStoredProcedure($rid_id, $rid_col, $rid_sproc) + public function deleteStoredProcedure(string $rid_id, string $rid_col, string $rid_sproc): string { $headers = $this->getAuthHeaders('DELETE', 'sprocs', $rid_sproc); $headers['Content-Length'] = '0'; @@ -945,10 +947,11 @@ public function deleteStoredProcedure($rid_id, $rid_col, $rid_sproc) * @link http:// * @access public * @param string $rid_id Resource ID - * @param string $rid_colResource Collection ID + * @param string $rid_col * @return string JSON response + * @throws GuzzleException */ - public function listUserDefinedFunctions($rid_id, $rid_col) + public function listUserDefinedFunctions(string $rid_id, string $rid_col): string { $headers = $this->getAuthHeaders('GET', 'udfs', $rid_col); $headers['Content-Length'] = '0'; @@ -964,8 +967,9 @@ public function listUserDefinedFunctions($rid_id, $rid_col) * @param string $rid_col Resource Collection ID * @param string $json JSON of function * @return string JSON response + * @throws GuzzleException */ - public function createUserDefinedFunction($rid_id, $rid_col, $json) + public function createUserDefinedFunction(string $rid_id, string $rid_col, string $json): string { $headers = $this->getAuthHeaders('POST', 'udfs', $rid_col); $headers['Content-Length'] = strlen($json); @@ -982,8 +986,9 @@ public function createUserDefinedFunction($rid_id, $rid_col, $json) * @param string $rid_udf Resource ID of User Defined Function * @param string $json Parameters * @return string JSON response + * @throws GuzzleException */ - public function replaceUserDefinedFunction($rid_id, $rid_col, $rid_udf, $json) + public function replaceUserDefinedFunction(string $rid_id, string $rid_col, string $rid_udf, string $json): string { $headers = $this->getAuthHeaders('PUT', 'udfs', $rid_udf); $headers['Content-Length'] = strlen($json); @@ -999,8 +1004,9 @@ public function replaceUserDefinedFunction($rid_id, $rid_col, $rid_udf, $json) * @param string $rid_col Resource Collection ID * @param string $rid_udf Resource ID of User Defined Function * @return string JSON response + * @throws GuzzleException */ - public function deleteUserDefinedFunction($rid_id, $rid_col, $rid_udf) + public function deleteUserDefinedFunction(string $rid_id, string $rid_col, string $rid_udf): string { $headers = $this->getAuthHeaders('DELETE', 'udfs', $rid_udf); $headers['Content-Length'] = '0'; @@ -1013,10 +1019,11 @@ public function deleteUserDefinedFunction($rid_id, $rid_col, $rid_udf) * @link http:// * @access public * @param string $rid_id Resource ID - * @param string $rid_colResource Collection ID + * @param string $rid_col * @return string JSON response + * @throws GuzzleException */ - public function listTriggers($rid_id, $rid_col) + public function listTriggers(string $rid_id, string $rid_col): string { $headers = $this->getAuthHeaders('GET', 'triggers', $rid_col); $headers['Content-Length'] = '0'; @@ -1032,8 +1039,9 @@ public function listTriggers($rid_id, $rid_col) * @param string $rid_col Resource Collection ID * @param string $json JSON of function * @return string JSON response + * @throws GuzzleException */ - public function createTrigger($rid_id, $rid_col, $json) + public function createTrigger(string $rid_id, string $rid_col, string $json): string { $headers = $this->getAuthHeaders('POST', 'triggers', $rid_col); $headers['Content-Length'] = strlen($json); @@ -1050,8 +1058,9 @@ public function createTrigger($rid_id, $rid_col, $json) * @param string $rid_trigger Resource ID of Trigger * @param string $json Parameters * @return string JSON response + * @throws GuzzleException */ - public function replaceTrigger($rid_id, $rid_col, $rid_trigger, $json) + public function replaceTrigger(string $rid_id, string $rid_col, string $rid_trigger, string $json): string { $headers = $this->getAuthHeaders('PUT', 'triggers', $rid_trigger); $headers['Content-Length'] = strlen($json); @@ -1067,8 +1076,9 @@ public function replaceTrigger($rid_id, $rid_col, $rid_trigger, $json) * @param string $rid_col Resource Collection ID * @param string $rid_trigger Resource ID of Trigger * @return string JSON response + * @throws GuzzleException */ - public function deleteTrigger($rid_id, $rid_col, $rid_trigger) + public function deleteTrigger(string $rid_id, string $rid_col, string $rid_trigger): string { $headers = $this->getAuthHeaders('DELETE', 'triggers', $rid_trigger); $headers['Content-Length'] = '0'; diff --git a/src/CosmosDbCollection.php b/src/CosmosDbCollection.php index c8c2f5c..5c5c983 100644 --- a/src/CosmosDbCollection.php +++ b/src/CosmosDbCollection.php @@ -2,33 +2,11 @@ namespace Jupitern\CosmosDb; -/* - * Based on the AzureDocumentDB-PHP library written by Takeshi Sakurai. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * Microsoft Azure Document DB Library for PHP - * @link http://msdn.microsoft.com/en-us/library/azure/dn781481.aspx - * @link https://github.com/jupitern/cosmosdb - */ - class CosmosDbCollection { - private $document_db; - private $rid_db; - private $rid_col; + private CosmosDb $document_db; + private string $rid_db; + private string $rid_col; /** * __construct @@ -38,7 +16,7 @@ class CosmosDbCollection * @param string $rid_db Database ID * @param string $rid_col Collection ID */ - public function __construct($document_db, $rid_db, $rid_col) + public function __construct(CosmosDb $document_db, string $rid_db, string $rid_col) { $this->document_db = $document_db; $this->rid_db = $rid_db; @@ -51,7 +29,7 @@ public function __construct($document_db, $rid_db, $rid_col) * @param string $query Query * @param array $params * @param boolean $isCrossPartition used for cross partition query - * @return string JSON strings + * @return array JSON strings */ public function query($query, $params = [], $isCrossPartition = false, $partitionValue = null) { @@ -179,7 +157,7 @@ public function replaceStoredProcedure($sproc_name, $json) public function deleteStoredProcedure($sproc_name) { - return $this->document_db->deleteStoredProcedure($this->rid_db, $this->rid_col, $sporc_name); + return $this->document_db->deleteStoredProcedure($this->rid_db, $this->rid_col, $sproc_name); } public function listUserDefinedFunctions() diff --git a/src/CosmosDbDatabase.php b/src/CosmosDbDatabase.php index 355f9ea..a1696b1 100644 --- a/src/CosmosDbDatabase.php +++ b/src/CosmosDbDatabase.php @@ -1,35 +1,14 @@ document_db = $document_db; $this->rid_db = $rid_db; @@ -40,8 +19,9 @@ public function __construct($document_db, $rid_db) * * @access public * @param string $col_name Collection name + * @throws GuzzleException */ - public function selectCollection($col_name, $partitionKey = null) + public function selectCollection(string $col_name): CosmosDbCollection|null { $rid_col = false; $object = json_decode($this->document_db->listCollections($this->rid_db)); @@ -51,22 +31,30 @@ public function selectCollection($col_name, $partitionKey = null) $rid_col = $col_list[$i]->_rid; } } - if (!$rid_col) { - $col_body["id"] = $col_name; - if ($partitionKey) { - $col_body["partitionKey"] = [ - "paths" => [$partitionKey], - "kind" => "Hash" - ]; - } - $object = json_decode($this->document_db->createCollection($this->rid_db, json_encode($col_body))); - $rid_col = $object->_rid; - } - if ($rid_col) { - return new CosmosDbCollection($this->document_db, $this->rid_db, $rid_col); - } else { - return false; + + return $rid_col ? new CosmosDbCollection($this->document_db, $this->rid_db, $rid_col) : null; + } + + + /** + * @param string $col_name + * @param string|null $partitionKey + * @return CosmosDbCollection|null + * @throws GuzzleException + */ + public function createCollection(string $col_name, string $partitionKey = null): CosmosDbCollection|null + { + $col_body = ["id" => $col_name]; + if ($partitionKey) { + $col_body["partitionKey"] = [ + "paths" => [$partitionKey], + "kind" => "Hash" + ]; } + + $object = json_decode($this->document_db->createCollection($this->rid_db, json_encode($col_body))); + + return $object->_rid ? new CosmosDbCollection($this->document_db, $this->rid_db, $object->_rid) : null; } } diff --git a/src/QueryBuilder.php b/src/QueryBuilder.php index 9f57af4..10904c8 100644 --- a/src/QueryBuilder.php +++ b/src/QueryBuilder.php @@ -2,31 +2,9 @@ namespace Jupitern\CosmosDb; -/* - * Based on the AzureDocumentDB-PHP library written by Takeshi Sakurai. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * Microsoft Azure Document DB Library for PHP - * @link http://msdn.microsoft.com/en-us/library/azure/dn781481.aspx - * @link https://github.com/jupitern/cosmosdb - */ - class QueryBuilder { - private $collection = ""; + private CosmosDbCollection $collection; private $partitionKey = null; private $partitionValue = null; private $queryString = ""; @@ -55,17 +33,17 @@ public static function instance() * @param CosmosDbCollection $collection * @return $this */ - public function setCollection(CosmosDbCollection $collection) + public function setCollection(CosmosDbCollection $collection): static { $this->collection = $collection; return $this; } /** - * @param string|array $fields + * @param array|string $fields * @return $this */ - public function select($fields) + public function select(array|string $fields): static { if (is_array($fields)) $fields = 'c["' . implode('"], c["', $fields) . '"]'; @@ -77,7 +55,7 @@ public function select($fields) * @param string $from * @return $this */ - public function from($from) + public function from(string $from): static { $this->from = $from; return $this; @@ -87,7 +65,7 @@ public function from($from) * @param string $join * @return $this */ - public function join($join) + public function join(string $join): static { $this->join .= " {$join} "; return $this; @@ -97,7 +75,7 @@ public function join($join) * @param string $where * @return $this */ - public function where($where) + public function where(string $where): static { if (empty($where)) return $this; $this->where .= !empty($this->where) ? " and {$where} " : "{$where}"; @@ -107,31 +85,31 @@ public function where($where) /** * @param string $field - * @param string $value + * @param mixed $value * @return QueryBuilder */ - public function whereStartsWith($field, $value) + public function whereStartsWith(string $field, mixed $value): static { return $this->where("STARTSWITH($field, '{$value}')"); } /** * @param string $field - * @param string $value + * @param mixed $value * @return QueryBuilder */ - public function whereEndsWith($field, $value) - { + public function whereEndsWith(string $field, mixed $value): static + { return $this->where("ENDSWITH($field, '{$value}')"); } /** * @param string $field - * @param string $value + * @param mixed $value * @return QueryBuilder */ - public function whereContains($field, $value) - { + public function whereContains(string $field, mixed $value): static + { return $this->where("CONTAINS($field, '{$value}'"); } @@ -140,12 +118,11 @@ public function whereContains($field, $value) * @param array $values * @return $this|QueryBuilder */ - public function whereIn($field, $values) + public function whereIn(string $field, array $values): QueryBuilder|static { - if (!is_array($values) || empty($values)) return $this; - if (is_array($values)) $values = implode("', '", $values); + if (empty($values)) return $this; - return $this->where("$field IN('{$values}')"); + return $this->where("$field IN('".implode("', '", $values)."')"); } /** @@ -153,19 +130,18 @@ public function whereIn($field, $values) * @param array $values * @return $this|QueryBuilder */ - public function whereNotIn($field, $values) + public function whereNotIn(string $field, array $values): QueryBuilder|static { - if (!is_array($values) || empty($values)) return $this; - if (is_array($values)) $values = implode("', '", $values); + if (empty($values)) return $this; - return $this->where("$field NOT IN('{$values}')"); + return $this->where("$field NOT IN('".implode("', '", $values)."')"); } /** * @param string $order * @return $this */ - public function order($order) + public function order(string $order): static { $this->order = $order; return $this; @@ -175,9 +151,9 @@ public function order($order) * @param int $limit * @return $this */ - public function limit($limit) + public function limit(int $limit): static { - $this->limit = (int)$limit; + $this->limit = $limit; return $this; } @@ -185,9 +161,9 @@ public function limit($limit) * @param array $params * @return $this */ - public function params($params) + public function params(array $params): static { - $this->params = (array)$params; + $this->params = $params; return $this; } @@ -195,7 +171,7 @@ public function params($params) * @param boolean $isCrossPartition * @return $this */ - public function findAll($isCrossPartition = false) + public function findAll(bool $isCrossPartition = false): static { $this->response = null; $this->multipleResults = true; @@ -218,7 +194,7 @@ public function findAll($isCrossPartition = false) * @param boolean $isCrossPartition * @return $this */ - public function find($isCrossPartition = false) + public function find(bool $isCrossPartition = false): static { $this->response = null; $this->multipleResults = false; @@ -238,24 +214,11 @@ public function find($isCrossPartition = false) /* insert / update */ - /** - * @param $document - * @return $this - */ - public function setDocument($document) - { - if (is_array($document) || is_object($document)) { - $this->document = json_encode($document); - } - - return $this; - } - /** * @param $fieldName * @return $this */ - public function setPartitionKey($fieldName) + public function setPartitionKey($fieldName): static { $this->partitionKey = $fieldName; @@ -274,7 +237,7 @@ public function getPartitionKey() * @param $fieldName * @return $this */ - public function setPartitionValue($fieldName) + public function setPartitionValue($fieldName): static { $this->partitionValue = $fieldName; @@ -290,28 +253,28 @@ public function getPartitionValue() } /** - * @param $fieldName + * @param string $string * @return $this */ - public function setQueryString(string $string) + public function setQueryString(string $string): static { $this->queryString .= $string; return $this; } /** - * @return null + * @return string|null */ - public function getQueryString() - { + public function getQueryString(): ?string + { return $this->queryString; } /** - * @param boolean $isCrossPartition - * @return $this + * @param string $partitionKey + * @return bool|QueryBuilder */ - public function isNested(string $partitionKey) + public function isNested(string $partitionKey): bool|static { # strip any slashes from the beginning # and end of the partition key @@ -319,11 +282,7 @@ public function isNested(string $partitionKey) # if the partition key contains slashes, the user # is referencing a nested value, so we should search for it - if (strpos($partitionKey, '/') !== false) { - return true; - } - - return false; + return str_contains($partitionKey, '/'); } /** @@ -401,7 +360,7 @@ public function save($document) * @param boolean $isCrossPartition * @return boolean */ - public function delete($isCrossPartition = false) + public function delete(bool $isCrossPartition = false) :bool { $this->response = null; @@ -423,7 +382,7 @@ public function delete($isCrossPartition = false) * @param boolean $isCrossPartition * @return boolean */ - public function deleteAll($isCrossPartition = false) + public function deleteAll(bool $isCrossPartition = false) :bool { $this->response = null; @@ -523,9 +482,10 @@ public function toJson() } /** + * @param $arrayKey * @return mixed */ - public function toObject() + public function toObject($arrayKey = null) { /* * If the CosmosDB result set contains many documents, CosmosDB might apply pagination. If this is detected, @@ -535,44 +495,37 @@ public function toObject() * $results holds the documents returned by each of the responses. */ $results = []; - foreach ($this->response as $response) { + foreach ((array)$this->response as $response) { $res = json_decode($response); - $docs = $res->Documents ?? []; - $results = array_merge($results, $docs); + if (isset($res->Documents)) { + array_push($results, ...$res->Documents); + } else { + $results[] = $res; + } } - if (!is_array($results || empty($results))) return []; - if ($this->multipleResults) { - return $results; + if ($this->multipleResults && $arrayKey != null) { + $results = array_combine(array_column($results, $arrayKey), $results); } - return isset($results[0]) ? $results[0] : null; + + return $this->multipleResults ? $results : ($results[0] ?? null); } /** * @param $arrayKey * @return array|mixed */ - public function toArray($arrayKey = null) + public function toArray($arrayKey = null): array|null { - /* - * If the CosmosDB result set contains many documents, CosmosDB might apply pagination. If this is detected, - * all pages are requested one by one, until all results are loaded. These individual responses are contained - * in $this->response. If no pagination is applied, $this->response is an array containing a single response. - * - * $results holds the documents returned by each of the responses. - */ - $results = []; - foreach ($this->response as $response) { - $res = json_decode($response); - $docs = $res->Documents ?? []; - if ($this->multipleResults) { - $docs = $arrayKey != null ? array_combine(array_column($docs, $arrayKey), $docs) : $docs; - } else { - $docs = isset($docs[0]) ? $docs[0] : null; - } - $results = array_merge($results, $docs); + $results = (array)$this->toObject($arrayKey); + + if ($this->multipleResults && is_array($results)) { + array_walk($results, function(&$value) { + $value = (array)$value; + }); } - return $results; + + return $this->multipleResults ? $results : ((array)$results ?? null); } /** @@ -582,8 +535,7 @@ public function toArray($arrayKey = null) */ public function getValue($fieldName, $default = null) { - $obj = $this->toObject(); - return isset($obj->{$fieldName}) ? $obj->{$fieldName} : $default; + return ($this->toObject())->{$fieldName} ?? $default; } }