diff --git a/.circleci/config.yml b/.circleci/config.yml index 36c8a6ac..561b6054 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -141,7 +141,7 @@ jobs: shell: bash steps: - checkout - - run: choco install php --version=7.3.15 --params '"/ThreadSafe /InstallDir:c:\tools\php"' + - run: choco install php --version=7.4.33 --params '"/ThreadSafe /InstallDir:c:\tools\php"' - run: cp ~/project/.circleci/php.ini /c/tools/php/ - run: /c/tools/php/php.exe -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" - run: /c/tools/php/php.exe composer-setup.php @@ -157,8 +157,8 @@ jobs: - checkout - run: | mkdir -p tools/php-cs-fixer - composer require --working-dir=tools/php-cs-fixer friendsofphp/php-cs-fixer:2.18.7 - tools/php-cs-fixer/vendor/bin/php-cs-fixer fix --dry-run --verbose --show-progress=estimating --using-cache=no --diff + composer require --working-dir=tools/php-cs-fixer friendsofphp/php-cs-fixer:3.95.18 + tools/php-cs-fixer/vendor/bin/php-cs-fixer fix --dry-run --verbose --show-progress=bar --using-cache=no --diff phpstan: docker: - image: *default-php-image @@ -201,6 +201,14 @@ workflows: name: php-8.2 php-image: "cimg/php:8.2" xdebug-package: "xdebug" + - tests-php: + name: php-8.3 + php-image: "cimg/php:8.3" + xdebug-package: "xdebug" + - tests-php: + name: php-8.4 + php-image: "cimg/php:8.4" + xdebug-package: "xdebug" - tests-php: name: php-8.5 php-image: "cimg/php:8.5" @@ -208,9 +216,6 @@ workflows: - tests-php: name: php-7.4-nightly influxdb-image: "quay.io/influxdb/influxdb:nightly" - - tests-php: - name: php-7.3 - php-image: "cimg/php:7.3" - tests-windows: name: php-windows - tests-cURL: diff --git a/.php_cs.dist b/.php-cs-fixer.dist.php similarity index 89% rename from .php_cs.dist rename to .php-cs-fixer.dist.php index 22859441..0a273b22 100644 --- a/.php_cs.dist +++ b/.php-cs-fixer.dist.php @@ -1,5 +1,6 @@ setFinder( PhpCsFixer\Finder::create() ->exclude('src/InfluxDB2/Model') @@ -8,4 +9,4 @@ ->notPath('src/InfluxDB2/ObjectSerializer.php') ->in(__DIR__) ) -; \ No newline at end of file +; diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b80b26d..9af13d59 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ ## 3.9.0 [unreleased] +### Features +1. [#178](https://github.com/influxdata/influxdb-client-php/pull/178): Add PHP 7.4 typehints. PHP minimum version is PHP 7.4. + ### Bug Fixes 1. [#170](https://github.com/influxdata/influxdb-client-php/pull/170): Fix PHP 8.5 deprecations. 2. [#177](https://github.com/influxdata/influxdb-client-php/pull/177): Fix invalid typehints for Point, add missing typehints for BatchItemKey diff --git a/Dockerfile b/Dockerfile index e22e8ba4..cb3a3ac8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM php:7.2-cli AS dev +FROM php:7.4-cli AS dev COPY --from=composer /usr/bin/composer /usr/bin/ diff --git a/composer.json b/composer.json index 1ca088d7..58c78ac5 100644 --- a/composer.json +++ b/composer.json @@ -7,7 +7,7 @@ "homepage": "https://www.github.com/influxdata/influxdb-client-php", "license": "MIT", "require": { - "php": ">=7.2", + "php": ">=7.4", "ext-curl": "*", "ext-json": "*", "ext-mbstring": "*", @@ -16,14 +16,14 @@ "psr/http-client": "^1.0.1" }, "require-dev": { - "phpunit/phpunit": "^8.5.27", + "phpunit/phpunit": "^9.6.35", "squizlabs/php_codesniffer": "~4.0", - "guzzlehttp/guzzle": "^7.0.1", - "guzzlehttp/psr7": "^2.0.0", - "phpstan/phpstan": "^1.12.33 || ^2.2.6", - "phpstan/phpstan-deprecation-rules": "^1.2.1 || ^2.0.4", - "phpstan/phpstan-phpunit": "^1.4.2 || ^2.0.18", - "phpstan/phpstan-strict-rules": "^1.6.2 || ^2.0.12" + "guzzlehttp/guzzle": "^7.0.1 || ^8.0.0", + "guzzlehttp/psr7": "^2.0.0 || ^3.0.0", + "phpstan/phpstan": "^2.2.6", + "phpstan/phpstan-deprecation-rules": "^2.0.4", + "phpstan/phpstan-phpunit": "^2.0.18", + "phpstan/phpstan-strict-rules": "^2.0.12" }, "suggest": { "ext-sockets": "Required for UDP writer." @@ -39,6 +39,8 @@ } }, "scripts": { + "phpstan": "vendor/bin/phpstan analyse", + "phpstan-baseline": "vendor/bin/phpstan analyse --generate-baseline", "test": "vendor/bin/phpunit tests", "test-coverage": "vendor/bin/phpunit tests --log-junit build/junit.xml -v --coverage-html=build/coverage-report" }, diff --git a/examples/BucketManagementExample.php b/examples/BucketManagementExample.php index 7455652e..acd998fd 100644 --- a/examples/BucketManagementExample.php +++ b/examples/BucketManagementExample.php @@ -1,4 +1,5 @@ createService(OrganizationsService::class); - $orgs = $orgService->getOrgs()->getOrgs(); - foreach ($orgs as $org) { - if ($org->getName() == $client->options["org"]) { + assert($orgService instanceof OrganizationsService); + $orgs = $orgService->getOrgs(); + assert($orgs instanceof Organizations); + foreach ($orgs->getOrgs() as $org) { + assert($org instanceof Organization); + if ($org->getName() === $client->options["org"]) { return $org; } } @@ -62,9 +68,9 @@ function findMyOrg($client): ?Organization ->setOrgId(findMyOrg($client)->getId()); $respBucket = $bucketsService->postBuckets($bucketRequest); - +assert($respBucket instanceof Bucket); $bucketName = $respBucket->getName(); -$bucketId = $respBucket->getID(); +$bucketId = $respBucket->getId(); $createdAt = $respBucket->getCreatedAt()->format('Y-m-d H:i:s'); print "ID: $bucketId Created: $createdAt Name: $bucketName was created\n"; @@ -74,10 +80,12 @@ function findMyOrg($client): ?Organization // print "\n\n----------------------------------------- Bucket List -----------------------------------------\n"; $bucketList = $bucketsService->getBuckets(); +assert($bucketList instanceof Buckets); foreach ($bucketList->getBuckets() as $item) { + assert($item instanceof Bucket); $bucketName = $item->getName(); - $bucketId = $item->getID(); + $bucketId = $item->getId(); $createdAt = $item->getCreatedAt()->format('Y-m-d H:i:s'); print "ID: $bucketId Created: $createdAt Name: $bucketName \n"; @@ -88,7 +96,9 @@ function findMyOrg($client): ?Organization // print "\n\n----------------------------------------- Bucket delete -----------------------------------------\n"; $bucketList = $bucketsService->getBuckets(); +assert($bucketList instanceof Buckets); foreach ($bucketList->getBuckets() as $item) { + assert($item instanceof Bucket); $bucketName = $item->getName(); if (strpos($bucketName, 'example-bucket') !== false) { $createdAt = $item->getCreatedAt()->format('Y-m-d H:i:s'); diff --git a/examples/DeleteDataExample.php b/examples/DeleteDataExample.php index 23d7a536..ea1d189c 100644 --- a/examples/DeleteDataExample.php +++ b/examples/DeleteDataExample.php @@ -1,4 +1,5 @@ query($contents); @@ -74,7 +84,7 @@ function getDayName(int $weekDay): string { - switch ($weekDay) { + switch ((string) $weekDay) { case "1": return "Monday"; case "2": diff --git a/examples/WriteBatchingExample.php b/examples/WriteBatchingExample.php index bef05d23..32821d3b 100644 --- a/examples/WriteBatchingExample.php +++ b/examples/WriteBatchingExample.php @@ -1,4 +1,5 @@ range(start: 0) diff --git a/examples/WriteUDPExample.php b/examples/WriteUDPExample.php index 8f9a4169..ec579b37 100644 --- a/examples/WriteUDPExample.php +++ b/examples/WriteUDPExample.php @@ -56,7 +56,7 @@ print "$measurement: Temperature in $location at $dateTime is $temperature °C\n"; } } -} catch (Exception|Throwable $e) { +} catch (Throwable $e) { print "\n\n $e \n\n"; } diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 6a42df12..debaffb1 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1,1270 +1,268 @@ parameters: ignoreErrors: - - message: '#^Call to an undefined method object\:\:deleteBucketsID\(\)\.$#' - identifier: method.notFound - count: 1 - path: examples/BucketManagementExample.php - - - - message: '#^Call to an undefined method object\:\:getBuckets\(\)\.$#' - identifier: method.notFound - count: 2 - path: examples/BucketManagementExample.php - - - - message: '#^Call to an undefined method object\:\:postBuckets\(\)\.$#' - identifier: method.notFound - count: 1 - path: examples/BucketManagementExample.php - - - - message: '#^Cannot call method getOrgs\(\) on object\|string\.$#' - identifier: method.nonObject - count: 1 - path: examples/BucketManagementExample.php - - - - message: '#^Function findMyOrg\(\) has parameter \$client with no type specified\.$#' - identifier: missingType.parameter - count: 1 - path: examples/BucketManagementExample.php - - - - message: '#^Loose comparison via "\=\=" is not allowed\.$#' - identifier: equal.notAllowed - count: 1 - path: examples/BucketManagementExample.php - - - - message: '#^Parameter \#1 \$start of method InfluxDB2\\Model\\DeletePredicateRequest\:\:setStart\(\) expects DateTime, DateTime\|false given\.$#' - identifier: argument.type - count: 1 - path: examples/DeleteDataExample.php - - - - message: '#^Parameter \#2 \$params of method InfluxDB2\\InvokableScriptsApi\:\:invokeScript\(\) expects array\\|null, array\ given\.$#' - identifier: argument.type - count: 1 - path: examples/InvokableScripts.php - - - - message: '#^Parameter \#2 \$params of method InfluxDB2\\InvokableScriptsApi\:\:invokeScriptStream\(\) expects array\\|null, array\ given\.$#' - identifier: argument.type - count: 1 - path: examples/InvokableScripts.php - - - - message: '#^Call to an undefined method object\:\:postDelete\(\)\.$#' - identifier: method.notFound - count: 1 - path: examples/QueryExample.php - - - - message: '#^Parameter \#1 \$start of method InfluxDB2\\Model\\DeletePredicateRequest\:\:setStart\(\) expects DateTime, DateTime\|false given\.$#' - identifier: argument.type - count: 1 - path: examples/QueryExample.php - - - - message: '#^Parameter \#1 \$fp of function fclose expects resource, resource\|false given\.$#' - identifier: argument.type - count: 1 - path: examples/QueryFromFileExample.php - - - - message: '#^Parameter \#1 \$fp of function fread expects resource, resource\|false given\.$#' - identifier: argument.type - count: 1 - path: examples/QueryFromFileExample.php - - - - message: '#^Parameter \#1 \$query of method InfluxDB2\\QueryApi\:\:query\(\) expects InfluxDB2\\Model\\Query\|string, string\|false given\.$#' - identifier: argument.type - count: 1 - path: examples/QueryFromFileExample.php - - - - message: '#^Parameter \#2 \$length of function fread expects int\<1, max\>, int\<0, max\>\|false given\.$#' - identifier: argument.type - count: 1 - path: examples/QueryFromFileExample.php - - - - message: '#^Switch condition type \(int\) does not match case condition "0" \(string\)\.$#' - identifier: switch.type - count: 1 - path: examples/QueryFromFileExample.php - - - - message: '#^Switch condition type \(int\) does not match case condition "1" \(string\)\.$#' - identifier: switch.type - count: 1 - path: examples/QueryFromFileExample.php - - - - message: '#^Switch condition type \(int\) does not match case condition "2" \(string\)\.$#' - identifier: switch.type - count: 1 - path: examples/QueryFromFileExample.php - - - - message: '#^Switch condition type \(int\) does not match case condition "3" \(string\)\.$#' - identifier: switch.type - count: 1 - path: examples/QueryFromFileExample.php - - - - message: '#^Switch condition type \(int\) does not match case condition "4" \(string\)\.$#' - identifier: switch.type - count: 1 - path: examples/QueryFromFileExample.php - - - - message: '#^Switch condition type \(int\) does not match case condition "5" \(string\)\.$#' - identifier: switch.type - count: 1 - path: examples/QueryFromFileExample.php - - - - message: '#^Switch condition type \(int\) does not match case condition "6" \(string\)\.$#' - identifier: switch.type - count: 1 - path: examples/QueryFromFileExample.php - - - - message: '#^Function checkResult\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: examples/WriteExample.php - - - - message: '#^Dead catch \- Exception is never thrown in the try block\.$#' - identifier: catch.neverThrown - count: 1 - path: examples/WriteUDPExample.php - - - - message: '#^Method InfluxDB2\\BatchItem\:\:__construct\(\) has parameter \$data with no type specified\.$#' - identifier: missingType.parameter - count: 1 - path: src/InfluxDB2/BatchItem.php - - - - message: '#^Method InfluxDB2\\BatchItem\:\:__construct\(\) has parameter \$key with no type specified\.$#' - identifier: missingType.parameter - count: 1 - path: src/InfluxDB2/BatchItem.php - - - - message: '#^Call to an undefined method object\:\:getPingWithHttpInfo\(\)\.$#' - identifier: method.notFound - count: 1 - path: src/InfluxDB2/Client.php - - - - message: '#^Method InfluxDB2\\Client\:\:__construct\(\) has parameter \$options with no value type specified in iterable type array\.$#' - identifier: missingType.iterableValue - count: 1 - path: src/InfluxDB2/Client.php - - - - message: '#^Method InfluxDB2\\Client\:\:close\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: src/InfluxDB2/Client.php - - - - message: '#^Method InfluxDB2\\Client\:\:createService\(\) has parameter \$serviceClass with no type specified\.$#' - identifier: missingType.parameter - count: 1 - path: src/InfluxDB2/Client.php - - - - message: '#^Method InfluxDB2\\Client\:\:createWriteApi\(\) has parameter \$pointSettings with no value type specified in iterable type array\.$#' - identifier: missingType.iterableValue - count: 1 - path: src/InfluxDB2/Client.php - - - - message: '#^Method InfluxDB2\\Client\:\:createWriteApi\(\) has parameter \$writeOptions with no value type specified in iterable type array\.$#' - identifier: missingType.iterableValue - count: 1 - path: src/InfluxDB2/Client.php - - - - message: '#^Method InfluxDB2\\Client\:\:ping\(\) return type has no value type specified in iterable type array\.$#' - identifier: missingType.iterableValue - count: 1 - path: src/InfluxDB2/Client.php - - - - message: '#^Property InfluxDB2\\Client\:\:\$autoCloseable has no type specified\.$#' - identifier: missingType.property - count: 1 - path: src/InfluxDB2/Client.php - - - - message: '#^Property InfluxDB2\\Client\:\:\$closed has no type specified\.$#' - identifier: missingType.property - count: 1 - path: src/InfluxDB2/Client.php - - - - message: '#^Property InfluxDB2\\Client\:\:\$options has no type specified\.$#' - identifier: missingType.property - count: 1 - path: src/InfluxDB2/Client.php - - - - message: '#^Method InfluxDB2\\DefaultApi\:\:__construct\(\) has parameter \$options with no value type specified in iterable type array\.$#' - identifier: missingType.iterableValue - count: 1 - path: src/InfluxDB2/DefaultApi.php - - - - message: '#^Method InfluxDB2\\DefaultApi\:\:check\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: src/InfluxDB2/DefaultApi.php - - - - message: '#^Method InfluxDB2\\DefaultApi\:\:check\(\) has parameter \$key with no type specified\.$#' - identifier: missingType.parameter - count: 1 - path: src/InfluxDB2/DefaultApi.php - - - - message: '#^Method InfluxDB2\\DefaultApi\:\:check\(\) has parameter \$value with no type specified\.$#' - identifier: missingType.parameter - count: 1 - path: src/InfluxDB2/DefaultApi.php - - - - message: '#^Method InfluxDB2\\DefaultApi\:\:get\(\) has parameter \$payload with no type specified\.$#' - identifier: missingType.parameter - count: 1 - path: src/InfluxDB2/DefaultApi.php - - - - message: '#^Method InfluxDB2\\DefaultApi\:\:get\(\) has parameter \$queryParams with no type specified\.$#' - identifier: missingType.parameter - count: 1 - path: src/InfluxDB2/DefaultApi.php - - - - message: '#^Method InfluxDB2\\DefaultApi\:\:get\(\) has parameter \$uriPath with no type specified\.$#' - identifier: missingType.parameter - count: 1 - path: src/InfluxDB2/DefaultApi.php - - - - message: '#^Method InfluxDB2\\DefaultApi\:\:log\(\) has parameter \$options with no value type specified in iterable type array\.$#' - identifier: missingType.iterableValue - count: 1 - path: src/InfluxDB2/DefaultApi.php - - - - message: '#^Method InfluxDB2\\DefaultApi\:\:post\(\) has parameter \$payload with no type specified\.$#' - identifier: missingType.parameter - count: 1 - path: src/InfluxDB2/DefaultApi.php - - - - message: '#^Method InfluxDB2\\DefaultApi\:\:post\(\) has parameter \$queryParams with no type specified\.$#' - identifier: missingType.parameter - count: 1 - path: src/InfluxDB2/DefaultApi.php - - - - message: '#^Method InfluxDB2\\DefaultApi\:\:post\(\) has parameter \$uriPath with no type specified\.$#' - identifier: missingType.parameter - count: 1 - path: src/InfluxDB2/DefaultApi.php - - - - message: '#^Method InfluxDB2\\DefaultApi\:\:request\(\) has parameter \$method with no type specified\.$#' - identifier: missingType.parameter - count: 1 - path: src/InfluxDB2/DefaultApi.php - - - - message: '#^Method InfluxDB2\\DefaultApi\:\:request\(\) has parameter \$payload with no type specified\.$#' - identifier: missingType.parameter - count: 1 - path: src/InfluxDB2/DefaultApi.php - - - - message: '#^Method InfluxDB2\\DefaultApi\:\:request\(\) has parameter \$queryParams with no type specified\.$#' - identifier: missingType.parameter - count: 1 - path: src/InfluxDB2/DefaultApi.php - - - - message: '#^Method InfluxDB2\\DefaultApi\:\:request\(\) has parameter \$uriPath with no type specified\.$#' - identifier: missingType.parameter - count: 1 - path: src/InfluxDB2/DefaultApi.php - - - - message: '#^Only booleans are allowed in a ternary operator condition, Psr\\Http\\Message\\ResponseInterface given\.$#' - identifier: ternary.condNotBoolean - count: 2 - path: src/InfluxDB2/DefaultApi.php - - - - message: '#^Parameter \#3 \$responseHeaders of class InfluxDB2\\ApiException constructor expects array\\|null, array\\> given\.$#' - identifier: argument.type - count: 2 - path: src/InfluxDB2/DefaultApi.php - - - - message: '#^Property InfluxDB2\\DefaultApi\:\:\$options has no type specified\.$#' - identifier: missingType.property - count: 1 - path: src/InfluxDB2/DefaultApi.php - - - - message: '#^Method InfluxDB2\\FluxColumn\:\:__construct\(\) has parameter \$dataType with no type specified\.$#' - identifier: missingType.parameter - count: 1 - path: src/InfluxDB2/FluxColumn.php - - - - message: '#^Method InfluxDB2\\FluxColumn\:\:__construct\(\) has parameter \$defaultValue with no type specified\.$#' - identifier: missingType.parameter - count: 1 - path: src/InfluxDB2/FluxColumn.php - - - - message: '#^Method InfluxDB2\\FluxColumn\:\:__construct\(\) has parameter \$group with no type specified\.$#' - identifier: missingType.parameter - count: 1 - path: src/InfluxDB2/FluxColumn.php - - - - message: '#^Method InfluxDB2\\FluxColumn\:\:__construct\(\) has parameter \$index with no type specified\.$#' - identifier: missingType.parameter - count: 1 - path: src/InfluxDB2/FluxColumn.php - - - - message: '#^Method InfluxDB2\\FluxColumn\:\:__construct\(\) has parameter \$label with no type specified\.$#' - identifier: missingType.parameter - count: 1 - path: src/InfluxDB2/FluxColumn.php - - - - message: '#^Property InfluxDB2\\FluxColumn\:\:\$dataType has no type specified\.$#' - identifier: missingType.property - count: 1 - path: src/InfluxDB2/FluxColumn.php - - - - message: '#^Property InfluxDB2\\FluxColumn\:\:\$defaultValue has no type specified\.$#' - identifier: missingType.property - count: 1 - path: src/InfluxDB2/FluxColumn.php - - - - message: '#^Property InfluxDB2\\FluxColumn\:\:\$group has no type specified\.$#' - identifier: missingType.property - count: 1 - path: src/InfluxDB2/FluxColumn.php - - - - message: '#^Property InfluxDB2\\FluxColumn\:\:\$index has no type specified\.$#' - identifier: missingType.property - count: 1 - path: src/InfluxDB2/FluxColumn.php - - - - message: '#^Property InfluxDB2\\FluxColumn\:\:\$label has no type specified\.$#' - identifier: missingType.property - count: 1 - path: src/InfluxDB2/FluxColumn.php - - - - message: '#^Call to function base64_decode\(\) requires parameter \#2 to be set\.$#' - identifier: function.strict - count: 1 - path: src/InfluxDB2/FluxCsvParser.php - - - - message: '#^Call to function in_array\(\) requires parameter \#3 to be set\.$#' - identifier: function.strict - count: 1 - path: src/InfluxDB2/FluxCsvParser.php - - - - message: '#^Construct empty\(\) is not allowed\. Use more strict comparison\.$#' - identifier: empty.notAllowed - count: 2 - path: src/InfluxDB2/FluxCsvParser.php - - - - message: '#^Loose comparison via "\!\=" is not allowed\.$#' - identifier: notEqual.notAllowed - count: 1 - path: src/InfluxDB2/FluxCsvParser.php - - - - message: '#^Loose comparison via "\=\=" is not allowed\.$#' - identifier: equal.notAllowed - count: 25 - path: src/InfluxDB2/FluxCsvParser.php - - - - message: '#^Method InfluxDB2\\FluxCsvParser\:\:__construct\(\) has parameter \$response with no type specified\.$#' - identifier: missingType.parameter - count: 1 - path: src/InfluxDB2/FluxCsvParser.php - - - - message: '#^Method InfluxDB2\\FluxCsvParser\:\:addColumnNamesAndTags\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: src/InfluxDB2/FluxCsvParser.php - - - - message: '#^Method InfluxDB2\\FluxCsvParser\:\:addColumnNamesAndTags\(\) has parameter \$csv with no value type specified in iterable type array\.$#' - identifier: missingType.iterableValue - count: 1 - path: src/InfluxDB2/FluxCsvParser.php - - - - message: '#^Method InfluxDB2\\FluxCsvParser\:\:addDataTypes\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: src/InfluxDB2/FluxCsvParser.php - - - - message: '#^Method InfluxDB2\\FluxCsvParser\:\:addDataTypes\(\) has parameter \$data_types with no value type specified in iterable type array\.$#' - identifier: missingType.iterableValue - count: 1 - path: src/InfluxDB2/FluxCsvParser.php - - - - message: '#^Method InfluxDB2\\FluxCsvParser\:\:addDefaultEmptyValues\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: src/InfluxDB2/FluxCsvParser.php - - - - message: '#^Method InfluxDB2\\FluxCsvParser\:\:addDefaultEmptyValues\(\) has parameter \$defaultValues with no type specified\.$#' - identifier: missingType.parameter - count: 1 - path: src/InfluxDB2/FluxCsvParser.php - - - - message: '#^Method InfluxDB2\\FluxCsvParser\:\:addGroups\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: src/InfluxDB2/FluxCsvParser.php - - - - message: '#^Method InfluxDB2\\FluxCsvParser\:\:addGroups\(\) has parameter \$csv with no type specified\.$#' - identifier: missingType.parameter - count: 1 - path: src/InfluxDB2/FluxCsvParser.php - - - - message: '#^Method InfluxDB2\\FluxCsvParser\:\:closeConnection\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: src/InfluxDB2/FluxCsvParser.php - - - - message: '#^Method InfluxDB2\\FluxCsvParser\:\:each\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: src/InfluxDB2/FluxCsvParser.php - - - - message: '#^Method InfluxDB2\\FluxCsvParser\:\:parse\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: src/InfluxDB2/FluxCsvParser.php - - - - message: '#^Method InfluxDB2\\FluxCsvParser\:\:parseLine\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: src/InfluxDB2/FluxCsvParser.php - - - - message: '#^Method InfluxDB2\\FluxCsvParser\:\:parseLine\(\) has parameter \$csv with no value type specified in iterable type array\.$#' - identifier: missingType.iterableValue - count: 1 - path: src/InfluxDB2/FluxCsvParser.php - - - - message: '#^Method InfluxDB2\\FluxCsvParser\:\:parseRecord\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: src/InfluxDB2/FluxCsvParser.php - - - - message: '#^Method InfluxDB2\\FluxCsvParser\:\:parseRecord\(\) has parameter \$csv with no value type specified in iterable type array\.$#' - identifier: missingType.iterableValue - count: 1 - path: src/InfluxDB2/FluxCsvParser.php - - - - message: '#^Method InfluxDB2\\FluxCsvParser\:\:parseValues\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: src/InfluxDB2/FluxCsvParser.php - - - - message: '#^Method InfluxDB2\\FluxCsvParser\:\:parseValues\(\) has parameter \$csv with no value type specified in iterable type array\.$#' - identifier: missingType.iterableValue - count: 1 - path: src/InfluxDB2/FluxCsvParser.php - - - - message: '#^Method InfluxDB2\\FluxCsvParser\:\:stringToStream\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: src/InfluxDB2/FluxCsvParser.php - - - - message: '#^Method InfluxDB2\\FluxCsvParser\:\:toValue\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: src/InfluxDB2/FluxCsvParser.php - - - - message: '#^Method InfluxDB2\\FluxCsvParser\:\:toValue\(\) has parameter \$strVal with no type specified\.$#' - identifier: missingType.parameter - count: 1 - path: src/InfluxDB2/FluxCsvParser.php - - - - message: '#^Parameter \#1 \$fp of function fwrite expects resource, resource\|false given\.$#' - identifier: argument.type - count: 1 - path: src/InfluxDB2/FluxCsvParser.php - - - - message: '#^Parameter \#1 \$fp of function rewind expects resource, resource\|false given\.$#' - identifier: argument.type - count: 1 - path: src/InfluxDB2/FluxCsvParser.php - - - - message: '#^Parameter \#2 \$code of class InfluxDB2\\FluxQueryError constructor expects int, int\|string given\.$#' - identifier: argument.type - count: 1 - path: src/InfluxDB2/FluxCsvParser.php - - - - message: '#^Property InfluxDB2\\FluxCsvParser\:\:\$closed has no type specified\.$#' - identifier: missingType.property - count: 1 - path: src/InfluxDB2/FluxCsvParser.php - - - - message: '#^Property InfluxDB2\\FluxCsvParser\:\:\$groups has no type specified\.$#' - identifier: missingType.property - count: 1 - path: src/InfluxDB2/FluxCsvParser.php - - - - message: '#^Property InfluxDB2\\FluxCsvParser\:\:\$parsingStateError has no type specified\.$#' - identifier: missingType.property - count: 1 - path: src/InfluxDB2/FluxCsvParser.php - - - - message: '#^Property InfluxDB2\\FluxCsvParser\:\:\$resource has no type specified\.$#' - identifier: missingType.property - count: 1 - path: src/InfluxDB2/FluxCsvParser.php - - - - message: '#^Property InfluxDB2\\FluxCsvParser\:\:\$response has no type specified\.$#' - identifier: missingType.property - count: 1 - path: src/InfluxDB2/FluxCsvParser.php - - - - message: '#^Property InfluxDB2\\FluxCsvParser\:\:\$responseMode has no type specified\.$#' - identifier: missingType.property - count: 1 - path: src/InfluxDB2/FluxCsvParser.php - - - - message: '#^Property InfluxDB2\\FluxCsvParser\:\:\$startNewTable has no type specified\.$#' - identifier: missingType.property - count: 1 - path: src/InfluxDB2/FluxCsvParser.php - - - - message: '#^Property InfluxDB2\\FluxCsvParser\:\:\$stream has no type specified\.$#' - identifier: missingType.property - count: 1 - path: src/InfluxDB2/FluxCsvParser.php - - - - message: '#^Property InfluxDB2\\FluxCsvParser\:\:\$tableId has no type specified\.$#' - identifier: missingType.property - count: 1 - path: src/InfluxDB2/FluxCsvParser.php - - - - message: '#^Property InfluxDB2\\FluxCsvParser\:\:\$tableIndex has no type specified\.$#' - identifier: missingType.property - count: 1 - path: src/InfluxDB2/FluxCsvParser.php - - - - message: '#^Property InfluxDB2\\FluxCsvParser\:\:\$tables has no type specified\.$#' - identifier: missingType.property - count: 1 - path: src/InfluxDB2/FluxCsvParser.php - - - - message: '#^Class InfluxDB2\\FluxRecord implements generic interface ArrayAccess but does not specify its types\: TKey, TValue$#' - identifier: missingType.generics - count: 1 - path: src/InfluxDB2/FluxRecord.php - - - - message: '#^Method InfluxDB2\\FluxRecord\:\:__construct\(\) has parameter \$row with no type specified\.$#' - identifier: missingType.parameter - count: 1 - path: src/InfluxDB2/FluxRecord.php - - - - message: '#^Method InfluxDB2\\FluxRecord\:\:__construct\(\) has parameter \$table with no type specified\.$#' - identifier: missingType.parameter - count: 1 - path: src/InfluxDB2/FluxRecord.php - - - - message: '#^Method InfluxDB2\\FluxRecord\:\:__construct\(\) has parameter \$values with no type specified\.$#' - identifier: missingType.parameter - count: 1 - path: src/InfluxDB2/FluxRecord.php - - - - message: '#^PHPDoc tag @return with type mixed is not subtype of native type string\.$#' - identifier: return.phpDocType - count: 1 - path: src/InfluxDB2/FluxRecord.php - - - - message: '#^Property InfluxDB2\\FluxRecord\:\:\$row has no type specified\.$#' - identifier: missingType.property - count: 1 - path: src/InfluxDB2/FluxRecord.php - - - - message: '#^Property InfluxDB2\\FluxRecord\:\:\$table has no type specified\.$#' - identifier: missingType.property - count: 1 - path: src/InfluxDB2/FluxRecord.php - - - - message: '#^Property InfluxDB2\\FluxRecord\:\:\$values has no type specified\.$#' - identifier: missingType.property - count: 1 - path: src/InfluxDB2/FluxRecord.php - - - - message: '#^Method InfluxDB2\\FluxTable\:\:getGroupKey\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: src/InfluxDB2/FluxTable.php - - - - message: '#^Method InfluxDB2\\HealthApi\:\:__construct\(\) has parameter \$options with no value type specified in iterable type array\.$#' - identifier: missingType.iterableValue - count: 1 - path: src/InfluxDB2/HealthApi.php - - - - message: '#^Method InfluxDB2\\HealthApi\:\:health\(\) should return InfluxDB2\\Model\\HealthCheck but returns array\|object\|null\.$#' - identifier: return.type - count: 1 - path: src/InfluxDB2/HealthApi.php - - - - message: '#^Loose comparison via "\=\=" is not allowed\.$#' - identifier: equal.notAllowed - count: 1 - path: src/InfluxDB2/Internal/DebugHttpPlugin.php - - - - message: '#^Method InfluxDB2\\Internal\\DebugHttpPlugin\:\:__construct\(\) has parameter \$options with no value type specified in iterable type array\.$#' - identifier: missingType.iterableValue - count: 1 - path: src/InfluxDB2/Internal/DebugHttpPlugin.php - - - - message: '#^Property InfluxDB2\\Internal\\DebugHttpPlugin\:\:\$options has no type specified\.$#' - identifier: missingType.property - count: 1 - path: src/InfluxDB2/Internal/DebugHttpPlugin.php - - - - message: '#^Method InfluxDB2\\InvokableScriptsApi\:\:__construct\(\) has parameter \$options with no value type specified in iterable type array\.$#' - identifier: missingType.iterableValue - count: 1 - path: src/InfluxDB2/InvokableScriptsApi.php - - - - message: '#^Method InfluxDB2\\InvokableScriptsApi\:\:invokeScriptRaw\(\) has parameter \$params with no value type specified in iterable type array\.$#' - identifier: missingType.iterableValue - count: 1 - path: src/InfluxDB2/InvokableScriptsApi.php - - - - message: '#^Property InfluxDB2\\InvokableScriptsApi\:\:\$service has no type specified\.$#' - identifier: missingType.property - count: 1 - path: src/InfluxDB2/InvokableScriptsApi.php - - - - message: '#^Method InfluxDB2\\PointSettings\:\:__construct\(\) has parameter \$defaultTags with no value type specified in iterable type array\.$#' - identifier: missingType.iterableValue - count: 1 - path: src/InfluxDB2/PointSettings.php - - - - message: '#^Method InfluxDB2\\PointSettings\:\:addDefaultTag\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: src/InfluxDB2/PointSettings.php - - - - message: '#^Method InfluxDB2\\PointSettings\:\:getDefaultTags\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: src/InfluxDB2/PointSettings.php - - - - message: '#^Method InfluxDB2\\PointSettings\:\:getValue\(\) should return string but returns string\|false\.$#' - identifier: return.type - count: 1 - path: src/InfluxDB2/PointSettings.php - - - - message: '#^Property InfluxDB2\\PointSettings\:\:\$defaultTags has no type specified\.$#' - identifier: missingType.property - count: 1 - path: src/InfluxDB2/PointSettings.php - - - - message: '#^Loose comparison via "\=\=" is not allowed\.$#' - identifier: equal.notAllowed - count: 4 - path: src/InfluxDB2/QueryApi.php - - - - message: '#^Method InfluxDB2\\QueryApi\:\:__construct\(\) has parameter \$options with no value type specified in iterable type array\.$#' - identifier: missingType.iterableValue - count: 1 - path: src/InfluxDB2/QueryApi.php - - - - message: '#^Method InfluxDB2\\QueryApi\:\:generatePayload\(\) has parameter \$dialect with no type specified\.$#' - identifier: missingType.parameter - count: 1 - path: src/InfluxDB2/QueryApi.php - - - - message: '#^Method InfluxDB2\\QueryApi\:\:generatePayload\(\) has parameter \$query with no type specified\.$#' - identifier: missingType.parameter - count: 1 - path: src/InfluxDB2/QueryApi.php - - - - message: '#^Method InfluxDB2\\QueryApi\:\:postQuery\(\) has parameter \$dialect with no type specified\.$#' - identifier: missingType.parameter - count: 1 - path: src/InfluxDB2/QueryApi.php - - - - message: '#^Method InfluxDB2\\QueryApi\:\:postQuery\(\) has parameter \$org with no type specified\.$#' - identifier: missingType.parameter - count: 1 - path: src/InfluxDB2/QueryApi.php - - - - message: '#^Method InfluxDB2\\QueryApi\:\:postQuery\(\) has parameter \$query with no type specified\.$#' - identifier: missingType.parameter - count: 1 - path: src/InfluxDB2/QueryApi.php - - - - message: '#^Property InfluxDB2\\QueryApi\:\:\$DEFAULT_DIALECT has no type specified\.$#' - identifier: missingType.property - count: 1 - path: src/InfluxDB2/QueryApi.php - - - - message: '#^Short ternary operator is not allowed\. Use null coalesce operator if applicable or consider using long ternary\.$#' - identifier: ternary.shortNotAllowed - count: 4 - path: src/InfluxDB2/QueryApi.php - - - - message: '#^Construct empty\(\) is not allowed\. Use more strict comparison\.$#' - identifier: empty.notAllowed - count: 4 - path: src/InfluxDB2/UdpWriter.php - - - - message: '#^Method InfluxDB2\\UdpWriter\:\:__construct\(\) has parameter \$options with no value type specified in iterable type array\.$#' - identifier: missingType.iterableValue - count: 1 - path: src/InfluxDB2/UdpWriter.php - - - - message: '#^Method InfluxDB2\\UdpWriter\:\:close\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: src/InfluxDB2/UdpWriter.php - - - - message: '#^Method InfluxDB2\\UdpWriter\:\:write\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: src/InfluxDB2/UdpWriter.php - - - - message: '#^Method InfluxDB2\\UdpWriter\:\:write\(\) has parameter \$data with no value type specified in iterable type array\.$#' - identifier: missingType.iterableValue - count: 1 - path: src/InfluxDB2/UdpWriter.php - - - - message: '#^Only booleans are allowed in an if condition, resource\|false given\.$#' - identifier: if.condNotBoolean - count: 1 - path: src/InfluxDB2/UdpWriter.php - - - - message: '#^Property InfluxDB2\\UdpWriter\:\:\$options has no type specified\.$#' - identifier: missingType.property - count: 1 - path: src/InfluxDB2/UdpWriter.php - - - - message: '#^Property InfluxDB2\\UdpWriter\:\:\$socket \(resource\) does not accept null\.$#' - identifier: assign.propertyType - count: 1 - path: src/InfluxDB2/UdpWriter.php - - - - message: '#^Property InfluxDB2\\UdpWriter\:\:\$socket \(resource\) does not accept resource\|false\.$#' - identifier: assign.propertyType - count: 1 - path: src/InfluxDB2/UdpWriter.php - - - - message: '#^Property InfluxDB2\\UdpWriter\:\:\$socket \(resource\) in empty\(\) is not falsy\.$#' - identifier: empty.property - count: 1 - path: src/InfluxDB2/UdpWriter.php - - - - message: '#^Property InfluxDB2\\UdpWriter\:\:\$socket \(resource\) in isset\(\) is not nullable\.$#' - identifier: isset.property - count: 1 - path: src/InfluxDB2/UdpWriter.php - - - - message: '#^Call to function array_search\(\) requires parameter \#3 to be set\.$#' - identifier: function.strict - count: 1 - path: src/InfluxDB2/Worker.php - - - - message: '#^Construct empty\(\) is not allowed\. Use more strict comparison\.$#' - identifier: empty.notAllowed - count: 1 - path: src/InfluxDB2/Worker.php - - - - message: '#^Loose comparison via "\!\=" is not allowed\.$#' - identifier: notEqual.notAllowed - count: 2 - path: src/InfluxDB2/Worker.php - - - - message: '#^Method InfluxDB2\\Worker\:\:__construct\(\) has parameter \$client with no type specified\.$#' - identifier: missingType.parameter - count: 1 - path: src/InfluxDB2/Worker.php - - - - message: '#^Method InfluxDB2\\Worker\:\:checkBackgroundQueue\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: src/InfluxDB2/Worker.php - - - - message: '#^Method InfluxDB2\\Worker\:\:existsKey\(\) has parameter \$data with no type specified\.$#' - identifier: missingType.parameter - count: 1 - path: src/InfluxDB2/Worker.php - - - - message: '#^Method InfluxDB2\\Worker\:\:existsKey\(\) has parameter \$key with no type specified\.$#' - identifier: missingType.parameter - count: 1 - path: src/InfluxDB2/Worker.php - - - - message: '#^Method InfluxDB2\\Worker\:\:existsKey\(\) should return int\|null but returns int\|string\|false\.$#' - identifier: return.type - count: 1 - path: src/InfluxDB2/Worker.php - - - - message: '#^Method InfluxDB2\\Worker\:\:flush\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: src/InfluxDB2/Worker.php - - - - message: '#^Method InfluxDB2\\Worker\:\:push\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: src/InfluxDB2/Worker.php - - - - message: '#^Method InfluxDB2\\Worker\:\:push\(\) has parameter \$payload with no type specified\.$#' - identifier: missingType.parameter - count: 1 - path: src/InfluxDB2/Worker.php - - - - message: '#^Method InfluxDB2\\Worker\:\:write\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: src/InfluxDB2/Worker.php - - - - message: '#^Method InfluxDB2\\Worker\:\:write\(\) has parameter \$data with no type specified\.$#' - identifier: missingType.parameter - count: 1 - path: src/InfluxDB2/Worker.php - - - - message: '#^Property InfluxDB2\\Worker\:\:\$queue has no type specified\.$#' - identifier: missingType.property - count: 1 - path: src/InfluxDB2/Worker.php - - - - message: '#^Property InfluxDB2\\Worker\:\:\$writeOptions has no type specified\.$#' - identifier: missingType.property - count: 1 - path: src/InfluxDB2/Worker.php - - - - message: '#^Loose comparison via "\=\=" is not allowed\.$#' - identifier: equal.notAllowed - count: 2 - path: src/InfluxDB2/WriteApi.php - - - - message: '#^Method InfluxDB2\\WriteApi\:\:__construct\(\) has parameter \$options with no value type specified in iterable type array\.$#' - identifier: missingType.iterableValue + message: '#^Call to method InfluxDB2\\Model\\Bucket\:\:getId\(\) with incorrect case\: getID$#' + identifier: method.nameCase count: 1 - path: src/InfluxDB2/WriteApi.php + path: examples/BucketManagementExample.php - - message: '#^Method InfluxDB2\\WriteApi\:\:__construct\(\) has parameter \$pointSettings with no value type specified in iterable type array\.$#' - identifier: missingType.iterableValue + message: '#^Cannot access offset ''org'' on InfluxDB2\\ClientOptions\.$#' + identifier: offsetAccess.nonOffsetAccessible count: 1 - path: src/InfluxDB2/WriteApi.php + path: examples/BucketManagementExample.php - - message: '#^Method InfluxDB2\\WriteApi\:\:__construct\(\) has parameter \$writeOptions with no value type specified in iterable type array\.$#' - identifier: missingType.iterableValue + message: '#^Parameter \#1 \$start of method InfluxDB2\\Model\\DeletePredicateRequest\:\:setStart\(\) expects DateTime, DateTime\|false given\.$#' + identifier: argument.type count: 1 - path: src/InfluxDB2/WriteApi.php + path: examples/DeleteDataExample.php - - message: '#^Method InfluxDB2\\WriteApi\:\:addDefaultTags\(\) has no return type specified\.$#' - identifier: missingType.return + message: '#^Parameter \#2 \$params of method InfluxDB2\\InvokableScriptsApi\:\:invokeScript\(\) expects array\\|null, array\ given\.$#' + identifier: argument.type count: 1 - path: src/InfluxDB2/WriteApi.php + path: examples/InvokableScripts.php - - message: '#^Method InfluxDB2\\WriteApi\:\:addDefaultTags\(\) has parameter \$data with no type specified\.$#' - identifier: missingType.parameter + message: '#^Parameter \#2 \$params of method InfluxDB2\\InvokableScriptsApi\:\:invokeScriptStream\(\) expects array\\|null, array\ given\.$#' + identifier: argument.type count: 1 - path: src/InfluxDB2/WriteApi.php + path: examples/InvokableScripts.php - - message: '#^Method InfluxDB2\\WriteApi\:\:close\(\) has no return type specified\.$#' - identifier: missingType.return + message: '#^Parameter \#1 \$start of method InfluxDB2\\Model\\DeletePredicateRequest\:\:setStart\(\) expects DateTime, DateTime\|false given\.$#' + identifier: argument.type count: 1 - path: src/InfluxDB2/WriteApi.php + path: examples/QueryExample.php - - message: '#^Method InfluxDB2\\WriteApi\:\:write\(\) has no return type specified\.$#' - identifier: missingType.return + message: '#^Parameter \#2 \$length of function fread expects int\<1, max\>, int\<0, max\> given\.$#' + identifier: argument.type count: 1 - path: src/InfluxDB2/WriteApi.php + path: examples/QueryFromFileExample.php - - message: '#^Method InfluxDB2\\WriteApi\:\:write\(\) has parameter \$data with no value type specified in iterable type array\.$#' + message: '#^Method InfluxDB2\\Client\:\:ping\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 - path: src/InfluxDB2/WriteApi.php + path: src/InfluxDB2/Client.php - - message: '#^Method InfluxDB2\\WriteApi\:\:writeRaw\(\) has no return type specified\.$#' - identifier: missingType.return + message: '#^Method InfluxDB2\\ClientOptionsUdp\:\:toArray\(\) should return array\{udpHost\: string, udpPort\: int\<1, 65535\>, ipVersion\: 4\|6\} but returns array\{udpHost\: string, udpPort\: int, ipVersion\: 4\|6\}\.$#' + identifier: return.type count: 1 - path: src/InfluxDB2/WriteApi.php + path: src/InfluxDB2/ClientOptionsUdp.php - - message: '#^Parameter \#1 \$data of method InfluxDB2\\WriteApi\:\:writeRaw\(\) expects string, InfluxDB2\\BatchItem\|string given\.$#' - identifier: argument.type + message: '#^Binary operation "\." between ''allow_redirects\=''\|''bucket\=''\|''debug\=''\|''httpClient\=''\|''ipVersion\=''\|''logFile\=''\|''org\=''\|''precision\=''\|''proxy\=''\|''tags\=''\|''timeout\=''\|''token\=''\|''udpHost\=''\|''udpPort\=''\|''url\=''\|''verifySSL\='' and bool\|int\|Psr\\Http\\Client\\ClientInterface\|string\|null results in an error\.$#' + identifier: binaryOp.invalid count: 1 - path: src/InfluxDB2/WriteApi.php + path: src/InfluxDB2/DefaultApi.php - - message: '#^Parameter \#1 \$key of method InfluxDB2\\Point\:\:addTag\(\) expects string, int\|string given\.$#' - identifier: argument.type + message: '#^Instanceof between Psr\\Http\\Message\\ResponseInterface and Psr\\Http\\Message\\ResponseInterface will always evaluate to true\.$#' + identifier: instanceof.alwaysTrue count: 1 - path: src/InfluxDB2/WriteApi.php + path: src/InfluxDB2/DefaultApi.php - - message: '#^Parameter \#1 \$key of method InfluxDB2\\PointSettings\:\:addDefaultTag\(\) expects string, int\|string given\.$#' - identifier: argument.type + message: '#^Method InfluxDB2\\DefaultApi\:\:check\(\) has parameter \$value with no type specified\.$#' + identifier: missingType.parameter count: 1 - path: src/InfluxDB2/WriteApi.php + path: src/InfluxDB2/DefaultApi.php - - message: '#^Parameter \#2 \$precision of static method InfluxDB2\\WritePayloadSerializer\:\:generatePayload\(\) expects ''ms''\|''ns''\|''s''\|''us''\|null, string given\.$#' + message: '#^Parameter \#2 \$array of function implode expects array\, array\\|bool\|Psr\\Http\\Message\\StreamFactoryInterface\|string\> given\.$#' identifier: argument.type count: 1 - path: src/InfluxDB2/WriteApi.php - - - - message: '#^Property InfluxDB2\\WriteApi\:\:\$closed has no type specified\.$#' - identifier: missingType.property - count: 1 - path: src/InfluxDB2/WriteApi.php - - - - message: '#^Property InfluxDB2\\WriteApi\:\:\$pointSettings has no type specified\.$#' - identifier: missingType.property - count: 1 - path: src/InfluxDB2/WriteApi.php - - - - message: '#^Property InfluxDB2\\WriteApi\:\:\$worker \(InfluxDB2\\Worker\) in isset\(\) is not nullable\.$#' - identifier: isset.property - count: 2 - path: src/InfluxDB2/WriteApi.php - - - - message: '#^Property InfluxDB2\\WriteApi\:\:\$writeOptions has no type specified\.$#' - identifier: missingType.property - count: 1 - path: src/InfluxDB2/WriteApi.php + path: src/InfluxDB2/DefaultApi.php - - message: '#^Short ternary operator is not allowed\. Use null coalesce operator if applicable or consider using long ternary\.$#' - identifier: ternary.shortNotAllowed + message: '#^Parameter \#3 \$responseHeaders of class InfluxDB2\\ApiException constructor expects array\\|null, array\\> given\.$#' + identifier: argument.type count: 2 - path: src/InfluxDB2/WriteApi.php + path: src/InfluxDB2/DefaultApi.php - - message: '#^Ternary operator condition is always true\.$#' - identifier: ternary.alwaysTrue + message: '#^Construct empty\(\) is not allowed\. Use more strict comparison\.$#' + identifier: empty.notAllowed count: 2 - path: src/InfluxDB2/WriteApi.php + path: src/InfluxDB2/FluxCsvParser.php - - message: '#^Method InfluxDB2\\WriteOptions\:\:__construct\(\) has parameter \$writeOptions with no value type specified in iterable type array\.$#' - identifier: missingType.iterableValue + message: '#^Loose comparison via "\=\=" is not allowed\.$#' + identifier: equal.notAllowed count: 1 - path: src/InfluxDB2/WriteOptions.php + path: src/InfluxDB2/FluxCsvParser.php - - message: '#^Property InfluxDB2\\WriteOptions\:\:\$batchSize has no type specified\.$#' - identifier: missingType.property + message: '#^Method InfluxDB2\\FluxCsvParser\:\:parseLine\(\) has parameter \$csv with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 - path: src/InfluxDB2/WriteOptions.php + path: src/InfluxDB2/FluxCsvParser.php - - message: '#^Property InfluxDB2\\WriteOptions\:\:\$exponentialBase has no type specified\.$#' - identifier: missingType.property + message: '#^Method InfluxDB2\\FluxCsvParser\:\:parseValues\(\) has parameter \$csv with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 - path: src/InfluxDB2/WriteOptions.php + path: src/InfluxDB2/FluxCsvParser.php - - message: '#^Property InfluxDB2\\WriteOptions\:\:\$jitterInterval has no type specified\.$#' - identifier: missingType.property + message: '#^Method InfluxDB2\\FluxCsvParser\:\:toValue\(\) has no return type specified\.$#' + identifier: missingType.return count: 1 - path: src/InfluxDB2/WriteOptions.php + path: src/InfluxDB2/FluxCsvParser.php - - message: '#^Property InfluxDB2\\WriteOptions\:\:\$maxRetries has no type specified\.$#' - identifier: missingType.property + message: '#^Method InfluxDB2\\FluxCsvParser\:\:toValue\(\) has parameter \$strVal with no type specified\.$#' + identifier: missingType.parameter count: 1 - path: src/InfluxDB2/WriteOptions.php + path: src/InfluxDB2/FluxCsvParser.php - - message: '#^Property InfluxDB2\\WriteOptions\:\:\$maxRetryDelay has no type specified\.$#' - identifier: missingType.property + message: '#^Parameter \#1 \$fp of function fgetcsv expects resource, resource\|false given\.$#' + identifier: argument.type count: 1 - path: src/InfluxDB2/WriteOptions.php + path: src/InfluxDB2/FluxCsvParser.php - - message: '#^Property InfluxDB2\\WriteOptions\:\:\$maxRetryTime has no type specified\.$#' - identifier: missingType.property + message: '#^Property InfluxDB2\\FluxCsvParser\:\:\$tables type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 - path: src/InfluxDB2/WriteOptions.php + path: src/InfluxDB2/FluxCsvParser.php - - message: '#^Property InfluxDB2\\WriteOptions\:\:\$retryInterval has no type specified\.$#' - identifier: missingType.property + message: '#^Class InfluxDB2\\FluxRecord implements generic interface ArrayAccess but does not specify its types\: TKey, TValue$#' + identifier: missingType.generics count: 1 - path: src/InfluxDB2/WriteOptions.php + path: src/InfluxDB2/FluxRecord.php - - message: '#^Property InfluxDB2\\WriteOptions\:\:\$writeType has no type specified\.$#' - identifier: missingType.property + message: '#^PHPDoc tag @return with type mixed is not subtype of native type string\.$#' + identifier: return.phpDocType count: 1 - path: src/InfluxDB2/WriteOptions.php + path: src/InfluxDB2/FluxRecord.php - - message: '#^Binary operation "\." between InfluxDB2\\BatchItem\|string\|null and "\\n" results in an error\.$#' - identifier: binaryOp.invalid + message: '#^Method InfluxDB2\\HealthApi\:\:health\(\) should return InfluxDB2\\Model\\HealthCheck but returns array\|object\|null\.$#' + identifier: return.type count: 1 - path: src/InfluxDB2/WritePayloadSerializer.php + path: src/InfluxDB2/HealthApi.php - - message: '#^Construct empty\(\) is not allowed\. Use more strict comparison\.$#' - identifier: empty.notAllowed + message: '#^Call to an undefined method object\:\:getScripts\(\)\.$#' + identifier: method.notFound count: 1 - path: src/InfluxDB2/WritePayloadSerializer.php - - - - message: '#^Loose comparison via "\=\=" is not allowed\.$#' - identifier: equal.notAllowed - count: 2 - path: src/InfluxDB2/WritePayloadSerializer.php + path: src/InfluxDB2/InvokableScriptsApi.php - - message: '#^Method InfluxDB2\\WritePayloadSerializer\:\:generatePayload\(\) has parameter \$data with no type specified\.$#' - identifier: missingType.parameter + message: '#^Method InfluxDB2\\InvokableScriptsApi\:\:createScript\(\) should return InfluxDB2\\Model\\Script but returns object\.$#' + identifier: return.type count: 1 - path: src/InfluxDB2/WritePayloadSerializer.php + path: src/InfluxDB2/InvokableScriptsApi.php - - message: '#^Variable \$payload in isset\(\) always exists and is not nullable\.$#' - identifier: isset.variable + message: '#^Method InfluxDB2\\InvokableScriptsApi\:\:invokeScriptRaw\(\) has parameter \$params with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 - path: src/InfluxDB2/WritePayloadSerializer.php + path: src/InfluxDB2/InvokableScriptsApi.php - - message: '#^Loose comparison via "\!\=" is not allowed\.$#' - identifier: notEqual.notAllowed + message: '#^Method InfluxDB2\\PointSettings\:\:getValue\(\) should return string but returns string\|false\.$#' + identifier: return.type count: 1 - path: src/InfluxDB2/WriteRetry.php + path: src/InfluxDB2/PointSettings.php - - message: '#^Loose comparison via "\=\=" is not allowed\.$#' - identifier: equal.notAllowed + message: '#^Construct empty\(\) is not allowed\. Use more strict comparison\.$#' + identifier: empty.notAllowed count: 1 - path: src/InfluxDB2/WriteRetry.php + path: src/InfluxDB2/UdpWriter.php - - message: '#^Method InfluxDB2\\WriteRetry\:\:__construct\(\) has parameter \$options with no value type specified in iterable type array\.$#' + message: '#^Method InfluxDB2\\UdpWriter\:\:write\(\) has parameter \$data with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue count: 1 - path: src/InfluxDB2/WriteRetry.php + path: src/InfluxDB2/UdpWriter.php - - message: '#^Method InfluxDB2\\WriteRetry\:\:getBackoffTime\(\) has no return type specified\.$#' - identifier: missingType.return + message: '#^Property InfluxDB2\\UdpWriter\:\:\$socket \(resource\|null\) does not accept resource\|false\.$#' + identifier: assign.propertyType count: 1 - path: src/InfluxDB2/WriteRetry.php + path: src/InfluxDB2/UdpWriter.php - - message: '#^Method InfluxDB2\\WriteRetry\:\:retry\(\) has no return type specified\.$#' - identifier: missingType.return + message: '#^Construct empty\(\) is not allowed\. Use more strict comparison\.$#' + identifier: empty.notAllowed count: 1 - path: src/InfluxDB2/WriteRetry.php + path: src/InfluxDB2/Worker.php - - message: '#^Method InfluxDB2\\WriteRetry\:\:retry\(\) has parameter \$attempts with no type specified\.$#' - identifier: missingType.parameter + message: '#^Parameter \#1 \$data of method InfluxDB2\\Worker\:\:write\(\) expects array\\}\>, non\-empty\-array\\}\> given\.$#' + identifier: argument.type count: 1 - path: src/InfluxDB2/WriteRetry.php + path: src/InfluxDB2/Worker.php - - message: '#^Method InfluxDB2\\WriteRetry\:\:retry\(\) has parameter \$callable with no type specified\.$#' - identifier: missingType.parameter + message: '#^Parameter \#2 \$data of method InfluxDB2\\Worker\:\:existsKey\(\) expects array\\}\>, array\\}\> given\.$#' + identifier: argument.type count: 1 - path: src/InfluxDB2/WriteRetry.php + path: src/InfluxDB2/Worker.php - - message: '#^Property InfluxDB2\\WriteRetry\:\:\$exponentialBase has no type specified\.$#' - identifier: missingType.property + message: '#^Method InfluxDB2\\WriteApi\:\:addDefaultTags\(\) has parameter \$data with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 - path: src/InfluxDB2/WriteRetry.php + path: src/InfluxDB2/WriteApi.php - - message: '#^Property InfluxDB2\\WriteRetry\:\:\$jitterInterval has no type specified\.$#' - identifier: missingType.property + message: '#^Method InfluxDB2\\WriteApi\:\:write\(\) has parameter \$data with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 - path: src/InfluxDB2/WriteRetry.php + path: src/InfluxDB2/WriteApi.php - - message: '#^Property InfluxDB2\\WriteRetry\:\:\$maxRetries has no type specified\.$#' - identifier: missingType.property + message: '#^Parameter \#1 \$data of method InfluxDB2\\WriteApi\:\:addDefaultTags\(\) expects array\|InfluxDB2\\Point, array\|InfluxDB2\\Point\|string given\.$#' + identifier: argument.type count: 1 - path: src/InfluxDB2/WriteRetry.php + path: src/InfluxDB2/WriteApi.php - - message: '#^Property InfluxDB2\\WriteRetry\:\:\$maxRetryDelay has no type specified\.$#' - identifier: missingType.property + message: '#^Parameter \#2 \$precision of static method InfluxDB2\\WritePayloadSerializer\:\:generatePayload\(\) expects ''ms''\|''ns''\|''s''\|''us''\|null, string given\.$#' + identifier: argument.type count: 1 - path: src/InfluxDB2/WriteRetry.php + path: src/InfluxDB2/WriteApi.php - - message: '#^Property InfluxDB2\\WriteRetry\:\:\$maxRetryTime has no type specified\.$#' - identifier: missingType.property + message: '#^Binary operation "\." between InfluxDB2\\BatchItem\|string\|null and "\\n" results in an error\.$#' + identifier: binaryOp.invalid count: 1 - path: src/InfluxDB2/WriteRetry.php + path: src/InfluxDB2/WritePayloadSerializer.php - - message: '#^Property InfluxDB2\\WriteRetry\:\:\$options type has no value type specified in iterable type array\.$#' - identifier: missingType.iterableValue + message: '#^Construct empty\(\) is not allowed\. Use more strict comparison\.$#' + identifier: empty.notAllowed count: 1 - path: src/InfluxDB2/WriteRetry.php + path: src/InfluxDB2/WritePayloadSerializer.php - - message: '#^Property InfluxDB2\\WriteRetry\:\:\$retryInterval has no type specified\.$#' - identifier: missingType.property + message: '#^Method InfluxDB2\\WritePayloadSerializer\:\:generatePayload\(\) has parameter \$data with no type specified\.$#' + identifier: missingType.parameter count: 1 - path: src/InfluxDB2/WriteRetry.php + path: src/InfluxDB2/WritePayloadSerializer.php - - message: '#^Property InfluxDB2\\WriteRetry\:\:\$retryTimout has no type specified\.$#' - identifier: missingType.property + message: '#^Method InfluxDB2\\WriteRetry\:\:retry\(\) has no return type specified\.$#' + identifier: missingType.return count: 1 path: src/InfluxDB2/WriteRetry.php - - message: '#^Method InfluxDB2\\Writer\:\:write\(\) has no return type specified\.$#' - identifier: missingType.return + message: '#^Method InfluxDB2\\WriteRetry\:\:retry\(\) has parameter \$callable with no type specified\.$#' + identifier: missingType.parameter count: 1 - path: src/InfluxDB2/Writer.php + path: src/InfluxDB2/WriteRetry.php - message: '#^Method InfluxDB2\\Writer\:\:write\(\) has parameter \$data with no value type specified in iterable type array\.$#' @@ -1273,71 +271,11 @@ parameters: path: src/InfluxDB2/Writer.php - - message: '#^Property InfluxDB2Test\\BasicTest\:\:\$requests \(array\\}\>\) does not accept array\|ArrayAccess\\.$#' + message: '#^Property InfluxDB2Test\\BasicTest\:\:\$requests \(array\\}\>\) does not accept array\\}\>\|ArrayAccess\\}\>\.$#' identifier: assign.propertyType count: 1 path: tests/BasicTest.php - - - message: '#^Offset ''uri'' might not exist on array\{timed_out\: bool, blocked\: bool, eof\: bool, unread_bytes\: int, stream_type\: string, wrapper_type\: string, wrapper_data\: mixed, mode\: string, \.\.\.\}\.$#' - identifier: offsetAccess.notFound - count: 1 - path: tests/ClientTest.php - - - - message: '#^Parameter \#2 \$haystack of static method PHPUnit\\Framework\\Assert\:\:assertStringContainsString\(\) expects string, string\|false given\.$#' - identifier: argument.type - count: 1 - path: tests/ClientTest.php - - - - message: '#^Call to an undefined method object\:\:getConfig\(\)\.$#' - identifier: method.notFound - count: 2 - path: tests/DefaultApiTest.php - - - - message: '#^Method InfluxDB2Test\\FluxCsvParserTest\:\:assertColumns\(\) has parameter \$columnHeaders with no value type specified in iterable type array\.$#' - identifier: missingType.iterableValue - count: 1 - path: tests/FluxCsvParserTest.php - - - - message: '#^Method InfluxDB2Test\\FluxCsvParserTest\:\:assertColumns\(\) has parameter \$values with no value type specified in iterable type array\.$#' - identifier: missingType.iterableValue - count: 1 - path: tests/FluxCsvParserTest.php - - - - message: '#^Method InfluxDB2Test\\FluxCsvParserTest\:\:assertMultipleRecords\(\) has parameter \$tables with no value type specified in iterable type array\.$#' - identifier: missingType.iterableValue - count: 1 - path: tests/FluxCsvParserTest.php - - - - message: '#^Call to an undefined method object\:\:getBuckets\(\)\.$#' - identifier: method.notFound - count: 2 - path: tests/ITBucketServiceTest.php - - - - message: '#^Call to an undefined method object\:\:getHealth\(\)\.$#' - identifier: method.notFound - count: 1 - path: tests/ITBucketServiceTest.php - - - - message: '#^Call to an undefined method object\:\:getId\(\)\.$#' - identifier: method.notFound - count: 1 - path: tests/ITBucketServiceTest.php - - - - message: '#^Call to an undefined method object\:\:getName\(\)\.$#' - identifier: method.notFound - count: 1 - path: tests/ITBucketServiceTest.php - - message: '#^Parameter object of print cannot be converted to string\.$#' identifier: print.nonString @@ -1345,28 +283,34 @@ parameters: path: tests/ITBucketServiceTest.php - - message: '#^Call to an undefined method object\:\:getName\(\)\.$#' - identifier: method.notFound + message: '#^Offset ''org'' might not exist on array\{url\: string, token\: string, bucket\?\: string, org\?\: string, precision\?\: ''ms''\|''ns''\|''s''\|''us'', allow_redirects\?\: bool, debug\?\: bool, logFile\?\: string, \.\.\.\}\.$#' + identifier: offsetAccess.notFound count: 1 - path: tests/ITTaskServiceTest.php + path: tests/IntegrationBaseTestCase.php - - message: '#^Cannot call method getUsers\(\) on InfluxDB2\\Model\\Error\|InfluxDB2\\Model\\Users\|string\.$#' - identifier: method.nonObject + message: '#^Call to static method PHPUnit\\Framework\\Assert\:\:assertInstanceOf\(\) with ''InfluxDB2\\\\InvokableScriptsApi'' and InfluxDB2\\InvokableScriptsApi will always evaluate to true\.$#' + identifier: staticMethod.alreadyNarrowedType count: 1 - path: tests/ITUsersServiceTest.php + path: tests/InvokableScriptsApiTest.php - - message: '#^Cannot call method getOrgs\(\) on object\|string\.$#' - identifier: method.nonObject + message: ''' + #^Call to deprecated method expectWarning\(\) of class PHPUnit\\Framework\\TestCase\: + https\://github\.com/sebastianbergmann/phpunit/issues/5062$# + ''' + identifier: method.deprecated count: 1 - path: tests/IntegrationBaseTestCase.php + path: tests/PointTest.php - - message: '#^Offset ''org'' might not exist on array\{url\: string, token\: string, bucket\?\: string, org\?\: string, precision\?\: ''ms''\|''ns''\|''s''\|''us'', allow_redirects\?\: bool, debug\?\: bool, logFile\?\: string, \.\.\.\}\.$#' - identifier: offsetAccess.notFound + message: ''' + #^Call to deprecated method expectWarningMessage\(\) of class PHPUnit\\Framework\\TestCase\: + https\://github\.com/sebastianbergmann/phpunit/issues/5062$# + ''' + identifier: method.deprecated count: 1 - path: tests/IntegrationBaseTestCase.php + path: tests/PointTest.php - message: '#^Parameter \#1 \$data of static method InfluxDB2\\Point\:\:fromArray\(\) expects array\{name\: string, tags\?\: array\, fields\?\: array\, time\?\: DateTimeInterface\|float\|int\|null, precision\?\: ''ms''\|''ns''\|''s''\|''us''\|null\}, array\{tags\: array\{host\: ''aws'', region\: ''us''\}, fields\: array\{level\: 5, saturation\: ''99%%''\}, time\: 123\} given\.$#' @@ -1410,12 +354,6 @@ parameters: count: 1 path: tests/WriteApiBatchingTest.php - - - message: '#^Parameter \#2 \$haystack of static method PHPUnit\\Framework\\Assert\:\:assertStringContainsString\(\) expects string, string\|false given\.$#' - identifier: argument.type - count: 1 - path: tests/WriteApiBatchingTest.php - - message: '#^Parameter \#1 \$glue of function implode expects array, string given\.$#' identifier: argument.type diff --git a/src/InfluxDB2/ApiException.php b/src/InfluxDB2/ApiException.php index ed116216..7e75537c 100644 --- a/src/InfluxDB2/ApiException.php +++ b/src/InfluxDB2/ApiException.php @@ -1,4 +1,5 @@ key = $key; $this->data = $data; diff --git a/src/InfluxDB2/BatchItemKey.php b/src/InfluxDB2/BatchItemKey.php index 3cf770ca..ff253daf 100644 --- a/src/InfluxDB2/BatchItemKey.php +++ b/src/InfluxDB2/BatchItemKey.php @@ -9,12 +9,10 @@ */ class BatchItemKey { - /** @var string */ - public $bucket; - /** @var string */ - public $org; + public string $bucket; + public string $org; /** @var WritePrecision::S|WritePrecision::MS|WritePrecision::US|WritePrecision::NS|null */ - public $precision; + public ?string $precision; /** * @param string $bucket diff --git a/src/InfluxDB2/Client.php b/src/InfluxDB2/Client.php index 613cb6f8..5288b3dd 100644 --- a/src/InfluxDB2/Client.php +++ b/src/InfluxDB2/Client.php @@ -4,6 +4,7 @@ use Exception; use InfluxDB2\Model\HealthCheck; +use InfluxDB2\Model\WritePrecision; use InfluxDB2\Service\InvokableScriptsService; use InfluxDB2\Service\PingService; use ReflectionClass; @@ -15,11 +16,12 @@ class Client /** * Client version updated by: 'make release VERSION=1.5.0' */ - const VERSION = 'dev'; + public const VERSION = 'dev'; - public $options; - public $closed = false; - private $autoCloseable = array(); + public ClientOptions $options; + public bool $closed = false; + /** @var array */ + private array $autoCloseable = array(); /** * Client constructor. @@ -56,11 +58,31 @@ class Client * - allow_redirects: Describes the redirect behavior for requests. * - ipVersion: Specifies which version of IP to use, supports 4 and 6 as possible values (UDP Writer). * - * @param array $options + * @param array{ + * url: string, + * token: string, + * bucket?: string, + * org?: string, + * precision?: WritePrecision::S|WritePrecision::MS|WritePrecision::US|WritePrecision::NS, + * allow_redirects?: bool, + * debug?: bool, + * logFile?: string, + * httpClient?: \Psr\Http\Client\ClientInterface, + * verifySSL?: bool, + * timeout?: int, + * proxy?: string, + * udpHost?: string, + * udpPort?: int<1, 65535>, + * ipVersion?: 4|6, + * tags?: array, + * }|ClientOptions $options Client options */ - public function __construct(array $options) + public function __construct($options) { - $this->options = $options; + if (!is_array($options) && !$options instanceof ClientOptions) { + throw new \InvalidArgumentException('Options must be an array or ClientOptions'); + } + $this->options = is_array($options) ? ClientOptions::fromArray($options) : $options; } /** @@ -69,8 +91,17 @@ public function __construct(array $options) * 'writeType' => methods of write (WriteType::SYNCHRONOUS - default, WriteType::BATCHING) * 'batchSize' => the number of data point to collect in batch * ] - * @param array|null $writeOptions Array containing the write parameters (See above) - * @param array|null $pointSettings Array of default tags + * @param array{ + * writeType?: WriteType::SYNCHRONOUS|WriteType::BATCHING, + * batchSize?: int, + * retryInterval?: int, + * maxRetries?: int, + * maxRetryDelay?: int, + * maxRetryTime?: int, + * exponentialBase?: int, + * jitterInterval?: int, + * }|null $writeOptions Array containing the write parameters (See above) + * @param array|null $pointSettings Array of default tags * @return WriteApi */ public function createWriteApi(?array $writeOptions = null, ?array $pointSettings = null): WriteApi @@ -86,6 +117,9 @@ public function createWriteApi(?array $writeOptions = null, ?array $pointSetting */ public function createUdpWriter(): UdpWriter { + if ($this->options->udp === null) { + throw new Exception('UDP options are not set'); + } return new UdpWriter($this->options); } @@ -137,7 +171,7 @@ public function ping(): array /** * Close all connections into InfluxDB */ - public function close() + public function close(): void { $this->closed = true; @@ -150,10 +184,11 @@ public function close() /** * Creates the instance of api service * - * @param $serviceClass - * @return object service instance + * @template C of object + * @param class-string $serviceClass + * @return C service instance */ - public function createService($serviceClass) + public function createService(string $serviceClass): object { try { $class = new ReflectionClass($serviceClass); diff --git a/src/InfluxDB2/ClientOptions.php b/src/InfluxDB2/ClientOptions.php new file mode 100644 index 00000000..5cbfbc93 --- /dev/null +++ b/src/InfluxDB2/ClientOptions.php @@ -0,0 +1,172 @@ +|null $tags */ + public ?array $tags; + + public function __construct( + string $url, + string $token + ) { + $this->url = $url; + $this->token = $token; + } + + /** + * @param array{ + * url: string, + * token: string, + * bucket?: string, + * org?: string, + * precision?: WritePrecision::S|WritePrecision::MS|WritePrecision::US|WritePrecision::NS, + * allow_redirects?: array{ + * 'preserve_header'?: bool|string[], + * 'use_default_for_multiple'?: bool, + * 'strict'?: bool, + * 'stream_factory'?: StreamFactoryInterface, + * }|bool, + * debug?: bool, + * logFile?: string, + * httpClient?: ClientInterface, + * verifySSL?: bool, + * timeout?: int, + * proxy?: string, + * udpHost?: string, + * udpPort?: int<1, 65535>, + * ipVersion?: 4|6, + * tags?: array, + * } $options + */ + public static function fromArray(array $options): self + { + if ( + !array_key_exists('url', $options) || + !is_string($options['url']) || + filter_var($options['url'], FILTER_VALIDATE_URL) === false + ) { + throw new InvalidArgumentException('url is required and must be a string'); + } + if ( + !array_key_exists('token', $options) || + !is_string($options['token']) + ) { + throw new InvalidArgumentException('token is required and must be a string'); + } + if ( + array_key_exists('precision', $options) && + !in_array($options['precision'], WritePrecision::getAllowableEnumValues(), true) + ) { + throw new InvalidArgumentException('precision must be a valid WritePrecision value'); + } + if ( + array_key_exists('httpClient', $options) && + !($options['httpClient'] instanceof ClientInterface) + ) { + throw new InvalidArgumentException('httpClient must be an instance of Psr\Http\Client\ClientInterface'); + } + if ( + array_key_exists('ipVersion', $options) && + !in_array($options['ipVersion'], [4, 6], true) + ) { + throw new InvalidArgumentException('ipVersion must be 4, 6'); + } + $clientOptions = new self( + $options['url'], + $options['token'], + ); + $clientOptions->bucket = $options['bucket'] ?? null; + $clientOptions->org = $options['org'] ?? null; + $clientOptions->precision = $options['precision'] ?? null; + $clientOptions->allowRedirects = $options['allow_redirects'] ?? null; + $clientOptions->debug = $options['debug'] ?? null; + $clientOptions->logFile = $options['logFile'] ?? null; + $clientOptions->httpClient = $options['httpClient'] ?? null; + $clientOptions->verifySSL = $options['verifySSL'] ?? null; + $clientOptions->timeout = $options['timeout'] ?? null; + $clientOptions->proxy = $options['proxy'] ?? null; + if (array_key_exists('udpPort', $options)) { + $clientOptions->udp = ClientOptionsUdp::fromArray($options); + } else { + $clientOptions->udp = null; + } + $clientOptions->tags = $options['tags'] ?? null; + return $clientOptions; + } + + /** + * @return array{ + * url: string, + * token: string, + * bucket?: string, + * org?: string, + * precision?: WritePrecision::S|WritePrecision::MS|WritePrecision::US|WritePrecision::NS, + * allow_redirects?: array{ + * 'preserve_header'?: bool|string[], + * 'use_default_for_multiple'?: bool, + * 'strict'?: bool, + * 'stream_factory'?: StreamFactoryInterface, + * }|bool|null, + * debug?: bool, + * logFile?: string, + * httpClient?: ClientInterface, + * verifySSL?: bool, + * timeout?: int, + * proxy?: string, + * udpHost?: string, + * udpPort?: int<1, 65535>, + * ipVersion?: 4|6, + * tags?: array, + * } + */ + public function toArray(): array + { + return array_merge( + [ + 'url' => $this->url, + 'token' => $this->token, + 'bucket' => $this->bucket, + 'org' => $this->org, + 'precision' => $this->precision, + 'allow_redirects' => $this->allowRedirects, + 'debug' => $this->debug, + 'logFile' => $this->logFile, + 'httpClient' => $this->httpClient, + 'verifySSL' => $this->verifySSL, + 'timeout' => $this->timeout, + 'proxy' => $this->proxy, + 'tags' => $this->tags, + ], + ($this->udp instanceof ClientOptionsUdp) ? $this->udp->toArray() : [], + ); + } +} diff --git a/src/InfluxDB2/ClientOptionsUdp.php b/src/InfluxDB2/ClientOptionsUdp.php new file mode 100644 index 00000000..71e034d6 --- /dev/null +++ b/src/InfluxDB2/ClientOptionsUdp.php @@ -0,0 +1,104 @@ + $udpPort */ + public int $port; + /** @var 4|6 $ipVersion */ + public int $ipVersion; + + public function __construct( + string $host, + int $port, + int $ipVersion + ) { + if ( + filter_var($host, FILTER_VALIDATE_IP) === false && + filter_var($host, FILTER_VALIDATE_DOMAIN) === false + ) { + throw new \InvalidArgumentException('UDP host must be a valid IP or domain name'); + } + if ($port < 1 || $port > 65535) { + throw new \InvalidArgumentException('UDP port must be an integer between 1 and 65535'); + } + if (!in_array($ipVersion, [4, 6], true)) { + throw new \InvalidArgumentException('IP version must be 4 or 6'); + } + $this->host = $host; + $this->port = $port; + $this->ipVersion = $ipVersion; + } + + /** + * @param array{ + * url: string, + * udpHost?: string, + * udpPort?: int<1, 65535>, + * ipVersion?: 4|6, + * } $options + */ + public static function fromArray(array $options): self + { + if ( + !array_key_exists('udpHost', $options) && + !array_key_exists('url', $options) + ) { + throw new \InvalidArgumentException('Either udpHost or url must be provided'); + } + if (!array_key_exists('udpHost', $options)) { + $host = parse_url($options['url'], PHP_URL_HOST); + if ($host === false) { + throw new \InvalidArgumentException('url must be a valid URL'); + } + } else { + $host = $options['udpHost']; + } + if (!array_key_exists('udpPort', $options)) { + throw new \InvalidArgumentException('udpPort must be provided'); + } + return new self( + $host, + $options['udpPort'], + $options['ipVersion'] ?? 4 + ); + } + + /** + * @return array{ + * udpHost: string, + * udpPort: int<1, 65535>, + * ipVersion: 4|6, + * } + */ + public function toArray(): array + { + return [ + 'udpHost' => $this->host, + 'udpPort' => $this->port, + 'ipVersion' => $this->ipVersion, + ]; + } + + /** + * Returns the socket domain for the UDP connection. + * + * @return int The socket domain (AF_INET or AF_INET6). + * @throws \InvalidArgumentException When invalid IP version is provided + */ + public function getSocketDomain(): int + { + if (!in_array($this->ipVersion, [4, 6], true)) { + throw new \InvalidArgumentException('IP version must be 4 or 6'); + } + return $this->ipVersion === 4 ? AF_INET : AF_INET6; + } + +} diff --git a/src/InfluxDB2/Configuration.php b/src/InfluxDB2/Configuration.php index cda59b21..7f475e1c 100644 --- a/src/InfluxDB2/Configuration.php +++ b/src/InfluxDB2/Configuration.php @@ -1,4 +1,5 @@ options = $options; $guzzleHttp = "GuzzleHttp\Client"; - if ($this->options['httpClient'] ?? false) { - $client = $this->options['httpClient']; + if ($this->options->httpClient instanceof ClientInterface) { + $client = $this->options->httpClient; } elseif (ClassDiscovery::safeClassExists($guzzleHttp)) { $client = new $guzzleHttp([ - 'timeout' => $this->options['timeout'] ?? 10, - 'verify' => $this->options['verifySSL'] ?? true, - 'proxy' => $this->options['proxy'] ?? null + 'timeout' => $this->options->timeout ?? 10, + 'verify' => $this->options->verifySSL ?? true, + 'proxy' => $this->options->proxy ?? null ]); } else { $client = Psr18ClientDiscovery::find(); @@ -69,17 +54,23 @@ public function __construct(array $options) } /** - * @param $payload - * @param $uriPath - * @param $queryParams + * @param string $payload String content with which to populate the stream. + * @param string $uriPath The URI associated with the request. + * @param array $queryParams The query string to use with the new instance. * @return ResponseInterface */ - public function post($payload, $uriPath, $queryParams): ResponseInterface + public function post(string $payload, string $uriPath, array $queryParams): ResponseInterface { return $this->request($payload, $uriPath, $queryParams, 'POST'); } - public function get($payload, $uriPath, $queryParams): ResponseInterface + /** + * @param string $payload String content with which to populate the stream. + * @param string $uriPath The URI associated with the request. + * @param array $queryParams The query string to use with the new instance. + * @return ResponseInterface + */ + public function get(string $payload, string $uriPath, array $queryParams): ResponseInterface { return $this->request($payload, $uriPath, $queryParams, 'GET'); } @@ -95,15 +86,15 @@ public function configuredClient(ClientInterface $client): ClientInterface $plugins = [ new Plugin\HeaderDefaultsPlugin([ 'User-Agent' => 'influxdb-client-php/' . Client::VERSION, - 'Authorization' => "Token {$this->options['token']}", + 'Authorization' => "Token {$this->options->token}", ]), ]; - $allow_redirects = $this->options['allow_redirects'] ?? true; - if ($allow_redirects) { + $allow_redirects = $this->options->allowRedirects ?? true; + if ($allow_redirects !== false) { $plugins[] = new Plugin\RedirectPlugin(is_array($allow_redirects) ? $allow_redirects : []); } - if ($this->options['debug'] ?? false) { + if ($this->options->debug ?? false) { $plugins[] = new DebugHttpPlugin($this->options); } return new PluginClient($client, $plugins); @@ -127,7 +118,7 @@ public function createRequest( array $queryParams ): RequestInterface { $uri = $this->uriFactory - ->createUri($this->options['url']) + ->createUri($this->options->url) ->withPath($uriPath) ->withQuery(http_build_query($queryParams, '', '&', PHP_QUERY_RFC3986)); $request = $this->requestFactory->createRequest($method, $uri); @@ -178,8 +169,8 @@ public function sendRequest(RequestInterface $request): ResponseInterface throw new ApiException( "[{$e->getCode()}] {$e->getMessage()}", $e->getCode(), - $e->getResponse() ? $e->getResponse()->getHeaders() : null, - $e->getResponse() ? $e->getResponse()->getBody()->getContents() : null, + $e->getResponse() instanceof ResponseInterface ? $e->getResponse()->getHeaders() : null, + $e->getResponse() instanceof ResponseInterface ? $e->getResponse()->getBody()->getContents() : null, $e ); } catch (ClientExceptionInterface $e) { @@ -193,9 +184,10 @@ public function sendRequest(RequestInterface $request): ResponseInterface } } - protected function check($key, $value) + protected function check(string $key, $value): void { - if ((!isset($value) || trim($value) === '')) { + $optionsArray = $this->options->toArray(); + if (!isset($value) || trim($value) === '') { $options = implode(', ', array_map( function ($v, $k) { if (is_array($v)) { @@ -204,14 +196,21 @@ function ($v, $k) { return $k . '=' . $v; } }, - $this->options, - array_keys($this->options) + $optionsArray, + array_keys($optionsArray) )); throw new InvalidArgumentException("The '{$key}' should be defined as argument or default option: {$options}"); } } - private function request($payload, $uriPath, $queryParams, $method): ResponseInterface + /** + * @param string $payload String content with which to populate the stream. + * @param string $uriPath The URI associated with the request. + * @param array $queryParams The query string to use with the new instance. + * @param string $method The HTTP method associated with the request. + * @return ResponseInterface + */ + private function request(string $payload, string $uriPath, array $queryParams, string $method): ResponseInterface { $headers = [ 'Content-Type' => 'application/json' @@ -226,12 +225,13 @@ private function request($payload, $uriPath, $queryParams, $method): ResponseInt * * @param string $level LOG level * @param string $message Message to log - * @param array $options Client options with logFile. + * @param ClientOptions|null $options Client options with logFile. * @return void */ - public static function log(string $level, string $message, array $options): void + public static function log(string $level, string $message, ?ClientOptions $options): void { $logDate = date('H:i:s d-M-Y'); - file_put_contents($options["logFile"] ?? "php://output", "[$logDate]: [$level] - $message" . PHP_EOL, FILE_APPEND); + $logFileName = ($options instanceof ClientOptions) ? $options->logFile : null; + file_put_contents($logFileName ?? "php://output", "[$logDate]: [$level] - $message" . PHP_EOL, FILE_APPEND); } } diff --git a/src/InfluxDB2/FluxColumn.php b/src/InfluxDB2/FluxColumn.php index 3ceaf403..2655f93c 100644 --- a/src/InfluxDB2/FluxColumn.php +++ b/src/InfluxDB2/FluxColumn.php @@ -8,22 +8,27 @@ */ class FluxColumn { - public $index; - public $label; - public $dataType; - public $group; - public $defaultValue; + public ?int $index; + public ?string $label; + public ?string $dataType; + public ?bool $group; + public ?string $defaultValue; /** * FluxColumn constructor. - * @param $index int column number - * @param $label string column label - * @param $dataType string data type - * @param $group bool is group column - * @param $defaultValue string default empty value + * @param ?int $index column number + * @param ?string $label column label + * @param ?string $dataType data type + * @param ?bool $group is group column + * @param ?string $defaultValue default empty value */ - public function __construct($index = null, $label = null, $dataType = null, $group = null, $defaultValue = null) - { + public function __construct( + ?int $index = null, + ?string $label = null, + ?string $dataType = null, + ?bool $group = null, + ?string $defaultValue = null + ) { $this->index = $index; $this->label = $label; $this->dataType = $dataType; diff --git a/src/InfluxDB2/FluxCsvParser.php b/src/InfluxDB2/FluxCsvParser.php index 78830149..b0288b46 100644 --- a/src/InfluxDB2/FluxCsvParser.php +++ b/src/InfluxDB2/FluxCsvParser.php @@ -2,6 +2,8 @@ namespace InfluxDB2; +use Psr\Http\Message\StreamInterface; + /** * Class FluxCsvParser us used to construct FluxResult from CSV. * @package InfluxDB2 @@ -13,36 +15,33 @@ class FluxCsvParser private const ANNOTATION_DEFAULT = '#default'; private const ANNOTATIONS = [self::ANNOTATION_DATATYPE, self::ANNOTATION_GROUP, self::ANNOTATION_DEFAULT]; - /* @var $variable FluxTable[] */ - public $tables; + /* @var array $variable */ + public array $tables; - private $response; - private $stream; - private $responseMode; + private ?StreamInterface $response; + private bool $stream; + private string $responseMode; + /** @var resource|false $resource */ private $resource; - /* @var $variable int */ - private $tableIndex = 0; - private $tableId; - - private $startNewTable; + private int $tableIndex = 0; + private int $tableId = -1; + private bool $startNewTable = false; /** @var FluxTable */ private $table; - private $groups = []; - - private $parsingStateError; + /** @var array */ + private array $groups = []; - public $closed; + private bool $parsingStateError = false; - /** @var FluxColumn[] */ - private $fluxColumns; + public bool $closed; /** * FluxCsvParser constructor. - * @param $response mixed response to by parsed - * @param $stream bool use streaming - * @param $responseMode string metadata expected in response ('full', 'only_names') + * @param StreamInterface|string $response mixed response to by parsed + * @param bool $stream use streaming + * @param string $responseMode string metadata expected in response ('full', 'only_names') */ public function __construct($response, bool $stream = false, string $responseMode = "full") { @@ -58,31 +57,41 @@ public function __construct($response, bool $stream = false, string $responseMod $this->closed = false; } + /** + * @param string $string + * @return false|resource + */ private function stringToStream(string $string) { $stream = fopen('php://memory', 'r+'); + if ($stream === false) { + return false; + } fwrite($stream, $string); rewind($stream); return $stream; } - public function parse() + public function parse(): self { iterator_to_array($this->each()); return $this; } - public function each() + /** + * @return \Generator + */ + public function each(): \Generator { try { while (($csv = fgetcsv($this->resource, null, ',', '"', '\\')) !== false) { - if (!isset($csv) || (count($csv) == 1 && $csv[0] == null)) { + if (!isset($csv) || (count($csv) === 1 && $csv[0] == null)) { continue; } //skip empty csv row - if ($csv[1] == 'error' && $csv[2] == 'reference') { + if ($csv[1] === 'error' && $csv[2] === 'reference') { $this->parsingStateError = true; continue; } @@ -93,7 +102,7 @@ public function each() $referenceValue = $csv[2]; throw new FluxQueryError( $error, - !isset($referenceValue) || trim($referenceValue) === '' ? 0 : $referenceValue + !isset($referenceValue) || trim($referenceValue) === '' ? 0 : (int) $referenceValue ); } @@ -108,12 +117,12 @@ public function each() } } - private function parseLine(array $csv) + private function parseLine(array $csv): ?FluxRecord { $token = $csv[0]; # start new table - if ((in_array($token, self::ANNOTATIONS) && !$this->startNewTable) - || ($this->responseMode == "only_names" && is_null($this->table))) { + if ((in_array($token, self::ANNOTATIONS, true) && !$this->startNewTable) + || ($this->responseMode === "only_names" && is_null($this->table))) { # Return already parsed DataFrame $this->startNewTable = true; $this->table = new FluxTable(); @@ -125,15 +134,15 @@ private function parseLine(array $csv) $this->tableIndex += 1; $this->tableId = -1; - } elseif ($this->table == null) { + } elseif ($this->table === null) { throw new FluxCsvParserException('Unable to parse CSV response. FluxTable definition was not found.'); } - if (self::ANNOTATION_DATATYPE == $token) { + if (self::ANNOTATION_DATATYPE === $token) { $this->addDataTypes($this->table, $csv); - } elseif (self::ANNOTATION_GROUP == $token) { + } elseif (self::ANNOTATION_GROUP === $token) { $this->groups = $csv; - } elseif (self::ANNOTATION_DEFAULT == $token) { + } elseif (self::ANNOTATION_DEFAULT === $token) { $this->addDefaultEmptyValues($this->table, $csv); } else { return $this->parseValues($csv); @@ -141,7 +150,13 @@ private function parseLine(array $csv) return null; } - private function parseRecord(int $tableIndex, FluxTable $table, array $csv) + /** + * @param int $tableIndex + * @param FluxTable $table + * @param array $csv + * @return FluxRecord + */ + private function parseRecord(int $tableIndex, FluxTable $table, array $csv): FluxRecord { $record = new FluxRecord($tableIndex); foreach ($table->columns as $fluxColumn) { @@ -154,35 +169,51 @@ private function parseRecord(int $tableIndex, FluxTable $table, array $csv) return $record; } - private function addDataTypes(FluxTable $table, array $data_types) + /** + * @param FluxTable $table + * @param array $data_types + */ + private function addDataTypes(FluxTable $table, array $data_types): void { for ($i = 1; $i < sizeof($data_types); ++$i) { $columnDef = new FluxColumn(); $columnDef->index = $i - 1; $columnDef->dataType = $data_types[$i]; - array_push($table->columns, $columnDef); + $table->columns[] = $columnDef; } } - private function addGroups(FluxTable $table, $csv) + /** + * @param FluxTable $table + * @param array $csv + */ + private function addGroups(FluxTable $table, array $csv): void { $i = 1; - foreach ($table->columns as &$column) { - $column->group = $csv[$i] == 'true'; + foreach ($table->columns as $column) { + $column->group = $csv[$i] === 'true' || $csv[$i] === true; $i++; } } - private function addDefaultEmptyValues(FluxTable $table, $defaultValues) + /** + * @param FluxTable $table + * @param array $defaultValues + */ + private function addDefaultEmptyValues(FluxTable $table, array $defaultValues): void { $i = 1; - foreach ($table->columns as &$column) { + foreach ($table->columns as $column) { $column->defaultValue = $defaultValues[$i]; $i++; } } - private function addColumnNamesAndTags(FluxTable $table, array $csv) + /** + * @param FluxTable $table + * @param array $csv + */ + private function addColumnNamesAndTags(FluxTable $table, array $csv): void { $i = 1; @@ -191,14 +222,14 @@ private function addColumnNamesAndTags(FluxTable $table, array $csv) $i++; } - $duplicates = array(); + $duplicates = []; foreach (array_count_values($csv) as $label => $count) { if ($count > 1) { $duplicates[] = $label; } } - if (count($duplicates) > 0) { + if ($duplicates !== []) { $duplicatesStr = implode(", ", $duplicates); print "The response contains columns with duplicated names: {$duplicatesStr}\n"; print "You should use the 'FluxRecord.row' to access your data instead of 'FluxRecord.values'."; @@ -206,11 +237,11 @@ private function addColumnNamesAndTags(FluxTable $table, array $csv) } - private function parseValues(array $csv) + private function parseValues(array $csv): ?FluxRecord { # parse column names if ($this->startNewTable) { - if ($this->responseMode == 'only_names' && empty($this->table->columns)) { + if ($this->responseMode === 'only_names' && empty($this->table->columns)) { $this->addDataTypes($this->table, array_fill(0, sizeof($csv), 'string')); $this->groups = array_fill(0, sizeof($csv), 'false'); } @@ -221,17 +252,17 @@ private function parseValues(array $csv) } $currentId = (int)$csv[2]; - if ($this->tableId == -1) { + if ($this->tableId === -1) { $this->tableId = $currentId; } - if ($this->tableId != $currentId) { + if ($this->tableId !== $currentId) { # create new table with previous column headers settings - $this->fluxColumns = $this->table->columns; + $fluxColumns = $this->table->columns; $this->table = new FluxTable(); - foreach ($this->fluxColumns as &$column) { - array_push($this->table->columns, $column); + foreach ($fluxColumns as $column) { + $this->table->columns[] = $column; } if (!$this->stream) { @@ -248,7 +279,7 @@ private function parseValues(array $csv) return $fluxRecord; } else { $fluxTable = $this->tables[$this->tableIndex - 1]; - array_push($fluxTable->records, $fluxRecord); + $fluxTable->records[] = $fluxRecord; } return null; @@ -256,7 +287,7 @@ private function parseValues(array $csv) private function toValue($strVal, FluxColumn $column) { - if ($strVal == null || $strVal == '') { + if ($strVal === null || $strVal === '') { $defaultValue = $column->defaultValue; if (empty($defaultValue)) { return null; @@ -264,33 +295,33 @@ private function toValue($strVal, FluxColumn $column) return $this->toValue($defaultValue, $column); } - if ('string' == $column->dataType) { + if ('string' === $column->dataType) { return $strVal; } - if ('boolean' == $column->dataType) { - return "true" == $strVal; + if ('boolean' === $column->dataType) { + return "true" === $strVal; } - if ('unsignedLong' == $column->dataType || 'long' == $column->dataType) { + if ('unsignedLong' === $column->dataType || 'long' === $column->dataType) { return intval($strVal); } - if ('double' == $column->dataType) { - if ($strVal == '+Inf') { + if ('double' === $column->dataType) { + if ($strVal === '+Inf') { return INF; } - if ($strVal == '-Inf') { + if ($strVal === '-Inf') { return -INF; } return (float)$strVal; } - if ('base64Binary' == $column->dataType) { - return base64_decode($strVal); + if ('base64Binary' === $column->dataType) { + return base64_decode($strVal, true); } - if ('dateTime:RFC3339' == $column->dataType || 'dateTime:RFC3339Nano' == $column->dataType) { + if ('dateTime:RFC3339' === $column->dataType || 'dateTime:RFC3339Nano' === $column->dataType) { ##todo nanoseconds precission, php datetime is only in microseconds precision return $strVal; } @@ -298,7 +329,7 @@ private function toValue($strVal, FluxColumn $column) return $strVal; } - private function closeConnection() + private function closeConnection(): void { # Close CSV Parser $this->closed = true; diff --git a/src/InfluxDB2/FluxCsvParserException.php b/src/InfluxDB2/FluxCsvParserException.php index d51dee2d..7c192248 100644 --- a/src/InfluxDB2/FluxCsvParserException.php +++ b/src/InfluxDB2/FluxCsvParserException.php @@ -1,6 +1,5 @@ |null */ + public ?array $values; + /** @var array|null */ + public ?array $row; /** * FluxRecord constructor. - * @param $table int table index - * @param $values array array with record values, key is the column name + * @param int $table table index + * @param array|null $values array with record values, key is the column name + * @param array|null $row array with record values, index is the column index */ - public function __construct($table, $values = null, $row = null) + public function __construct(int $table, ?array $values = null, ?array $row = null) { $this->table = $table; $this->values = $values; diff --git a/src/InfluxDB2/FluxTable.php b/src/InfluxDB2/FluxTable.php index fff4adaa..7a8c38a8 100644 --- a/src/InfluxDB2/FluxTable.php +++ b/src/InfluxDB2/FluxTable.php @@ -1,4 +1,5 @@ columns = []; } - public function getGroupKey() + /** + * @return FluxColumn[] + */ + public function getGroupKey(): array { - return array_values(array_filter($this->columns, function ($column) { + return array_values(array_filter($this->columns, static function (FluxColumn $column): bool { return $column->group; })); } diff --git a/src/InfluxDB2/HealthApi.php b/src/InfluxDB2/HealthApi.php index 9ce2ccf5..0b63cad4 100644 --- a/src/InfluxDB2/HealthApi.php +++ b/src/InfluxDB2/HealthApi.php @@ -9,9 +9,9 @@ class HealthApi extends DefaultApi { /** * HealthApi constructor. - * @param array $options + * @param ClientOptions $options */ - public function __construct(array $options) + public function __construct(ClientOptions $options) { parent::__construct($options); } diff --git a/src/InfluxDB2/Internal/DebugHttpPlugin.php b/src/InfluxDB2/Internal/DebugHttpPlugin.php index 4e369ff5..8098c74d 100644 --- a/src/InfluxDB2/Internal/DebugHttpPlugin.php +++ b/src/InfluxDB2/Internal/DebugHttpPlugin.php @@ -4,6 +4,7 @@ use Http\Client\Common\Plugin; use Http\Promise\Promise; +use InfluxDB2\ClientOptions; use InfluxDB2\DefaultApi; use Psr\Http\Message\MessageInterface; use Psr\Http\Message\RequestInterface; @@ -11,9 +12,9 @@ class DebugHttpPlugin implements Plugin { - private $options; + private ClientOptions $options; - public function __construct(array $options) + public function __construct(ClientOptions $options) { $this->options = $options; } @@ -51,7 +52,7 @@ private function headers(MessageInterface $message, string $prefix): void { foreach ($message->getHeaders() as $key => $values) { $value = implode(', ', $values); - if (strcasecmp($key, 'Authorization') == 0) { + if (strcasecmp($key, 'Authorization') === 0) { $value = '***'; } DefaultApi::log("DEBUG", $prefix . " $key: " . $value, $this->options); diff --git a/src/InfluxDB2/InvokableScriptsApi.php b/src/InfluxDB2/InvokableScriptsApi.php index 7545b14c..1c68468e 100644 --- a/src/InfluxDB2/InvokableScriptsApi.php +++ b/src/InfluxDB2/InvokableScriptsApi.php @@ -19,15 +19,15 @@ */ class InvokableScriptsApi extends DefaultApi { - private $service; + private InvokableScriptsService $service; /** * InvokableScriptsApi constructor. * - * @param array $options default array options + * @param ClientOptions $options default array options * @param InvokableScriptsService $service HTTP API for Invokable Scripts */ - public function __construct(array $options, InvokableScriptsService $service) + public function __construct(ClientOptions $options, InvokableScriptsService $service) { parent::__construct($options); $this->service = $service; diff --git a/src/InfluxDB2/Point.php b/src/InfluxDB2/Point.php index 0acf9bd3..4ab00791 100644 --- a/src/InfluxDB2/Point.php +++ b/src/InfluxDB2/Point.php @@ -9,16 +9,15 @@ class Point { public const DEFAULT_WRITE_PRECISION = WritePrecision::NS; - /** @var string */ - private $name; + private string $name; /** @var array|null */ - private $tags; + private ?array $tags; /** @var array|null */ - private $fields; + private ?array $fields; /** @var int|float|DateTimeInterface|null */ private $time; /** @var WritePrecision::S|WritePrecision::MS|WritePrecision::US|WritePrecision::NS|null */ - private $precision; + private ?string $precision; /** Create DataPoint instance for specified measurement name. * diff --git a/src/InfluxDB2/PointSettings.php b/src/InfluxDB2/PointSettings.php index b012001d..d9f9cd53 100644 --- a/src/InfluxDB2/PointSettings.php +++ b/src/InfluxDB2/PointSettings.php @@ -1,18 +1,21 @@ */ + private array $defaultTags; + /** + * @param array|null $defaultTags + */ public function __construct(?array $defaultTags = null) { $this->defaultTags = is_null($defaultTags) ? [] : $defaultTags; } - public function addDefaultTag(string $key, string $expression) + public function addDefaultTag(string $key, string $expression): void { $this->defaultTags[$key] = $expression; } @@ -26,7 +29,10 @@ public static function getValue(string $value): string return $value; } - public function getDefaultTags() + /** + * @return array + */ + public function getDefaultTags(): array { return $this->defaultTags; } diff --git a/src/InfluxDB2/QueryApi.php b/src/InfluxDB2/QueryApi.php index d5391250..2ae56fd9 100644 --- a/src/InfluxDB2/QueryApi.php +++ b/src/InfluxDB2/QueryApi.php @@ -13,13 +13,13 @@ */ class QueryApi extends DefaultApi { - private $DEFAULT_DIALECT; + private Dialect $DEFAULT_DIALECT; /** * QueryApi constructor. - * @param array $options + * @param ClientOptions $options */ - public function __construct(array $options) + public function __construct(ClientOptions $options) { parent::__construct($options); $this->DEFAULT_DIALECT = new Dialect([ @@ -40,9 +40,9 @@ public function __construct(array $options) */ public function queryRaw($query, ?string $org = null, ?Dialect $dialect = null): ?string { - $result = $this->postQuery($query, $org, $dialect ?: $this->DEFAULT_DIALECT); + $result = $this->postQuery($query, $org, $dialect ?? $this->DEFAULT_DIALECT); - if ($result == null) { + if ($result === null) { return null; } @@ -64,9 +64,9 @@ public function query($query, ?string $org = null, ?Dialect $dialect = null): ?a $query->setDialect($this->DEFAULT_DIALECT); } - $response = $this->postQuery($query, $org, $dialect ?: $this->DEFAULT_DIALECT); + $response = $this->postQuery($query, $org, $dialect ?? $this->DEFAULT_DIALECT); - if ($response == null) { + if ($response === null) { return null; } @@ -79,7 +79,7 @@ public function query($query, ?string $org = null, ?Dialect $dialect = null): ?a /** * Executes the Flux query against the InfluxDB 2.x and returns generator to stream the result. * - * @param string| Query $query + * @param string|Query $query * @param string|null $org * @param Dialect|null $dialect * @@ -91,33 +91,44 @@ public function queryStream($query, ?string $org = null, ?Dialect $dialect = nul $query->setDialect($this->DEFAULT_DIALECT); } - $response = $this->postQuery($query, $org, $dialect ?: $this->DEFAULT_DIALECT); + $response = $this->postQuery($query, $org, $dialect ?? $this->DEFAULT_DIALECT); - if ($response == null) { + if ($response === null) { return null; } return new FluxCsvParser($response->getBody(), true); } - private function postQuery($query, $org, $dialect): ?ResponseInterface + /** + * @param string|Query $query + * @param string|null $org + * @param Dialect|null $dialect + * @return ResponseInterface|null + */ + private function postQuery($query, ?string $org = null, ?Dialect $dialect = null): ?ResponseInterface { - $orgParam = $org ?: $this->options["org"]; + $orgParam = $org ?? $this->options->org; $this->check("org", $orgParam); $payload = $this->generatePayload($query, $dialect); $queryParams = ["org" => $orgParam]; - if ($payload == null) { + if ($payload === null) { return null; } return $this->post($payload->__toString(), "/api/v2/query", $queryParams); } - private function generatePayload($query, $dialect): ?Query + /** + * @param string|Query $query + * @param Dialect|null $dialect + * @return Query|null + */ + private function generatePayload($query, ?Dialect $dialect = null): ?Query { - if ((!isset($query) || trim($query) === '')) { + if (!isset($query) || trim($query) === '') { return null; } diff --git a/src/InfluxDB2/UdpWriter.php b/src/InfluxDB2/UdpWriter.php index 775f620e..75c293ee 100644 --- a/src/InfluxDB2/UdpWriter.php +++ b/src/InfluxDB2/UdpWriter.php @@ -1,6 +1,5 @@ options = $options; - if (empty($this->options['udpPort'])) { - throw new \Exception('udpPort option does not specified'); - } - if (empty($this->options['udpHost'])) { - $this->options['udpHost'] = parse_url($this->options['url'], PHP_URL_HOST); - } + $this->options = $options->udp; } /** * @inheritDoc */ - public function write($data) + public function write($data): void { $payload = WritePayloadSerializer::generatePayload($data); if (empty($payload)) { @@ -72,55 +65,41 @@ public function write($data) * @return false|int * @throws \Exception */ - protected function writeSocket($payload) + protected function writeSocket(string $payload) { $bytesSent = false; - if ($socket = $this->getSocket()) { - $bytesSent = socket_sendto($socket, $payload, strlen($payload), 0, $this->options['udpHost'], $this->options['udpPort']); + if (is_resource($socket = $this->getSocket())) { + $bytesSent = socket_sendto($socket, $payload, strlen($payload), 0, $this->options->host, $this->options->port); } return $bytesSent; } /** * Create (if not exists) socket to write UDP datagrams - * @return false|resource + * @return resource * @throws \Exception */ protected function getSocket() { - if (empty($this->socket)) { - $this->socket = socket_create($this->getConfiguredInetVersion(), SOCK_DGRAM, SOL_UDP); - } - return $this->socket; - } - - /** - * @throws \Exception - * @return int socket domain constant - */ - private function getConfiguredInetVersion() - { - $configuredIpVersion = $this->options['ipVersion'] ?? 4; + if (!is_resource($this->socket)) { + $this->socket = socket_create($this->options->getSocketDomain(), SOCK_DGRAM, SOL_UDP); - switch ($configuredIpVersion) { - case 4: - return AF_INET; - case 6: - return AF_INET6; - default: - throw new \Exception('ipVersion option invalid!'); + if (!is_resource($this->socket)) { + throw new \Exception('Unable to create socket'); + } } + return $this->socket; } /** * Closes connection */ - public function close() + public function close(): void { - if (isset($this->socket)) { + if (is_resource($this->socket)) { socket_close($this->socket); - - $this->socket = null; } + + $this->socket = null; } } diff --git a/src/InfluxDB2/Worker.php b/src/InfluxDB2/Worker.php index 5c5be62d..e356ac04 100644 --- a/src/InfluxDB2/Worker.php +++ b/src/InfluxDB2/Worker.php @@ -7,13 +7,12 @@ class Worker { - /** @var WriteApi */ - private $client; + private WriteApi $client; + /** @var SplQueue */ + private SplQueue $queue; + private WriteOptions $writeOptions; - private $queue; - private $writeOptions; - - public function __construct($client) + public function __construct(WriteApi $client) { $this->client = $client; $this->writeOptions = $client->writeOptions; @@ -21,7 +20,7 @@ public function __construct($client) $this->queue = new SplQueue(); } - public function push($payload) + public function push(BatchItem $payload): void { $this->queue->enqueue($payload); @@ -30,14 +29,14 @@ public function push($payload) } } - public function flush() + public function flush(): void { - while ($this->queue->count() != 0) { + while ($this->queue->count() !== 0) { $this->checkBackgroundQueue(false); } } - private function checkBackgroundQueue(bool $size) + private function checkBackgroundQueue(bool $size): void { $data = array(); $points = 0; @@ -46,7 +45,7 @@ private function checkBackgroundQueue(bool $size) return; } - while (($points < $this->writeOptions->batchSize) && $this->queue->count() != 0) { + while (($points < $this->writeOptions->batchSize) && $this->queue->count() !== 0) { try { $item = $this->queue->dequeue(); @@ -55,7 +54,7 @@ private function checkBackgroundQueue(bool $size) if ($index === null) { $data[] = array('key' => $key, 'data' => array()); - $index = array_keys($data)[count($data)-1]; + $index = array_keys($data)[count($data) - 1]; } $data[$index]['data'][] = $item->data; @@ -70,21 +69,32 @@ private function checkBackgroundQueue(bool $size) } } - private function existsKey($key, $data): ?int + /** + * @param BatchItemKey $key + * @param array}> $data + * @return int|null + */ + private function existsKey(BatchItemKey $key, array $data): ?int { foreach ($data as $item) { $itemKey = $item['key']; if ($key->precision === $itemKey->precision && $key->bucket === $itemKey->bucket && $key->org === $itemKey->org) { - return array_search($item, $data); + $found = array_search($item, $data, true); + if ($found !== false) { + return $found; + } } } return null; } - private function write($data) + /** + * @param array}> $data + */ + private function write(array $data): void { foreach ($data as $item) { $key = $item['key']; diff --git a/src/InfluxDB2/WriteApi.php b/src/InfluxDB2/WriteApi.php index 3db5cc3a..fbfc93d1 100644 --- a/src/InfluxDB2/WriteApi.php +++ b/src/InfluxDB2/WriteApi.php @@ -10,28 +10,35 @@ */ class WriteApi extends DefaultApi implements Writer { - public $writeOptions; - public $pointSettings; - - /** @var Worker */ - private $worker; - public $closed = false; + public WriteOptions $writeOptions; + public PointSettings $pointSettings; + private Worker $worker; + public bool $closed = false; /** * WriteApi constructor. - * @param $options - * @param array|null $writeOptions - * @param array|null $pointSettings + * @param ClientOptions $options + * @param array{ + * writeType?: WriteType::SYNCHRONOUS|WriteType::BATCHING, + * batchSize?: int, + * retryInterval?: int, + * maxRetries?: int, + * maxRetryDelay?: int, + * maxRetryTime?: int, + * exponentialBase?: int, + * jitterInterval?: int, + * }|null $writeOptions + * @param array|null $pointSettings */ - public function __construct($options, ?array $writeOptions = null, ?array $pointSettings = null) + public function __construct(ClientOptions $options, ?array $writeOptions = null, ?array $pointSettings = null) { parent::__construct($options); - $this->writeOptions = new WriteOptions($writeOptions) ?: new WriteOptions(); - $this->pointSettings = new PointSettings($pointSettings) ?: new PointSettings(); + $this->writeOptions = new WriteOptions($writeOptions ?? []); + $this->pointSettings = new PointSettings($pointSettings ?? []); - if (array_key_exists('tags', $options)) { - foreach (array_keys($options['tags']) as $key) { - $this->pointSettings->addDefaultTag($key, $options['tags'][$key]); + if ($options->tags !== null) { + foreach (array_keys($options->tags) as $key) { + $this->pointSettings->addDefaultTag($key, $options->tags[$key]); } } } @@ -64,7 +71,7 @@ public function __construct($options, ?array $writeOptions = null, ?array $point * @param string|null $org specifies the destination organization for writes * @throws ApiException */ - public function write($data, ?string $precision = null, ?string $bucket = null, ?string $org = null) + public function write($data, ?string $precision = null, ?string $bucket = null, ?string $org = null): void { $precisionParam = $this->getOption("precision", $precision); $bucketParam = $this->getOption("bucket", $bucket); @@ -78,18 +85,22 @@ public function write($data, ?string $precision = null, ?string $bucket = null, $payload = WritePayloadSerializer::generatePayload($data, $precisionParam, $bucketParam, $orgParam, $this->writeOptions->writeType); - if ($payload == null) { + if ($payload === null) { return; } - if (WriteType::BATCHING == $this->writeOptions->writeType) { + if ($payload instanceof BatchItem) { $this->worker()->push($payload); } else { $this->writeRaw($payload, $precisionParam, $bucketParam, $orgParam); } } - private function addDefaultTags(&$data) + /** + * @param array|Point $data + * @return void + */ + private function addDefaultTags(&$data): void { $defaultTags = $this->pointSettings->getDefaultTags(); @@ -121,7 +132,7 @@ private function addDefaultTags(&$data) * * @see \InfluxDB2\Model\WritePrecision */ - public function writeRaw(string $data, ?string $precision = null, ?string $bucket = null, ?string $org = null) + public function writeRaw(string $data, ?string $precision = null, ?string $bucket = null, ?string $org = null): void { $precisionParam = $this->getOption("precision", $precision); $bucketParam = $this->getOption("bucket", $bucket); @@ -147,7 +158,7 @@ public function writeRaw(string $data, ?string $precision = null, ?string $bucke $this->post($data, "/api/v2/write", $queryParams); }); } - public function close() + public function close(): void { $this->closed = true; @@ -167,8 +178,26 @@ private function worker(): Worker return $this->worker; } - private function getOption(string $optionName, ?string $precision = null): string + /** + * @param 'bucket'|'precision'|'org' $optionName + * @param string|null $optionalValue + * @return string + */ + private function getOption(string $optionName, ?string $optionalValue = null): string { - return $precision ?? $this->options["$optionName"]; + switch ($optionName) { + case 'precision': + $default = $this->options->precision; + break; + case 'bucket': + $default = $this->options->bucket; + break; + case 'org': + $default = $this->options->org; + break; + default: + throw new \InvalidArgumentException("Invalid option name: $optionName"); + } + return $optionalValue ?? $default; } } diff --git a/src/InfluxDB2/WriteOptions.php b/src/InfluxDB2/WriteOptions.php index a1d2635e..95cc956d 100644 --- a/src/InfluxDB2/WriteOptions.php +++ b/src/InfluxDB2/WriteOptions.php @@ -4,22 +4,23 @@ class WriteOptions { - const DEFAULT_BATCH_SIZE = 10; - const DEFAULT_RETRY_INTERVAL = 5000; - const DEFAULT_MAX_RETRIES = 5; - const DEFAULT_MAX_RETRY_DELAY = 125000; - const DEFAULT_MAX_RETRY_TIME = 180000; - const DEFAULT_EXPONENTIAL_BASE = 2; - const DEFAULT_JITTER_INTERVAL = 0; + public const DEFAULT_BATCH_SIZE = 10; + public const DEFAULT_RETRY_INTERVAL = 5000; + public const DEFAULT_MAX_RETRIES = 5; + public const DEFAULT_MAX_RETRY_DELAY = 125000; + public const DEFAULT_MAX_RETRY_TIME = 180000; + public const DEFAULT_EXPONENTIAL_BASE = 2; + public const DEFAULT_JITTER_INTERVAL = 0; - public $writeType; - public $batchSize; - public $retryInterval; - public $maxRetries; - public $maxRetryDelay; - public $exponentialBase; - public $jitterInterval; - public $maxRetryTime; + /** @var WriteType::SYNCHRONOUS|WriteType::BATCHING $writeType */ + public int $writeType; + public int $batchSize; + public int $retryInterval; + public int $maxRetries; + public int $maxRetryDelay; + public int $exponentialBase; + public int $jitterInterval; + public int $maxRetryTime; /** * WriteOptions constructor. @@ -40,7 +41,16 @@ class WriteOptions * ``[5000-10000, 10000-20000, 20000-40000, 40000-80000, 80000-125000]`` * 'jitterInterval' => the number of milliseconds before the data is written increased by a random amount * ] - * @param array|null $writeOptions Array containing the write parameters (See above) + * @param array{ + * writeType?: WriteType::SYNCHRONOUS|WriteType::BATCHING, + * batchSize?: int, + * retryInterval?: int, + * maxRetries?: int, + * maxRetryDelay?: int, + * maxRetryTime?: int, + * exponentialBase?: int, + * jitterInterval?: int, + * }|null $writeOptions Array containing the write parameters (See above) */ public function __construct(?array $writeOptions = null) { diff --git a/src/InfluxDB2/WritePayloadSerializer.php b/src/InfluxDB2/WritePayloadSerializer.php index 2763c60b..dcb05a54 100644 --- a/src/InfluxDB2/WritePayloadSerializer.php +++ b/src/InfluxDB2/WritePayloadSerializer.php @@ -1,6 +1,5 @@ maxRetries = $maxRetries; $this->retryInterval = $retryInterval; @@ -57,14 +54,14 @@ public function __construct( $this->jitterInterval = $jitterInterval; $this->options = $options; - //retry timout - $this->retryTimout = microtime(true) * 1000 + $maxRetryTime; + //retry timeout + $this->retryTimeout = (int) microtime(true) * 1000 + $maxRetryTime; } /** * @throws ApiException */ - public function retry($callable, $attempts = 0) + public function retry($callable, int $attempts = 0) { try { return call_user_func($callable); @@ -81,13 +78,13 @@ public function retry($callable, $attempts = 0) } // throws exception when max retry time is exceeded - if (microtime(true) * 1000 > $this->retryTimout) { + if (microtime(true) * 1000 > $this->retryTimeout) { DefaultApi::log("ERROR", "Maximum retry time $this->maxRetryTime ms exceeded", $this->options); throw $e; } $headers = $e->getResponseHeaders(); - if ($headers != null && array_key_exists('Retry-After', $headers)) { + if ($headers !== null && array_key_exists('Retry-After', $headers)) { //jitter add in microseconds $jitterMicro = rand(0, $this->jitterInterval) * 1000; $timeout = (int)$headers['Retry-After'][0] * 1000000.0 + $jitterMicro; @@ -99,7 +96,7 @@ public function retry($callable, $attempts = 0) $message = "The retryable error occurred during writing of data. Reason: '$error'. Retry in: {$timeoutInSec}s."; DefaultApi::log("WARNING", $message, $this->options); - usleep($timeout); + usleep((int) $timeout); $this->retry($callable, $attempts); } } @@ -107,14 +104,14 @@ public function retry($callable, $attempts = 0) public function isRetryable(ApiException $e): bool { $code = $e->getCode(); - if (($code == null || $code < 429) && + if (($code === null || $code < 429) && !($e->getPrevious() instanceof NetworkException)) { return false; } return true; } - public function getBackoffTime(int $attempt) + public function getBackoffTime(int $attempt): float { $range_start = $this->retryInterval; $range_stop = $this->retryInterval * $this->exponentialBase; diff --git a/src/InfluxDB2/WriteType.php b/src/InfluxDB2/WriteType.php index 9978a341..de83aaa5 100644 --- a/src/InfluxDB2/WriteType.php +++ b/src/InfluxDB2/WriteType.php @@ -4,6 +4,6 @@ class WriteType { - const SYNCHRONOUS = 1; - const BATCHING = 2; + public const SYNCHRONOUS = 1; + public const BATCHING = 2; } diff --git a/src/InfluxDB2/Writer.php b/src/InfluxDB2/Writer.php index 0804b87e..279cecbf 100644 --- a/src/InfluxDB2/Writer.php +++ b/src/InfluxDB2/Writer.php @@ -1,11 +1,9 @@ }> */ - protected $requests; + protected Client $client; + protected WriteApi $writeApi; + protected QueryApi $queryApi; + protected MockHandler $mockHandler; + /** @var array}> */ + protected array $requests; /** * @before diff --git a/tests/ClientTest.php b/tests/ClientTest.php index 140f1fe8..13e52fb3 100644 --- a/tests/ClientTest.php +++ b/tests/ClientTest.php @@ -60,7 +60,10 @@ public function test_ping_not_running(): void public function test_debug(): void { - $logFilePath = stream_get_meta_data(tmpfile())['uri']; + $logFileMetadata = stream_get_meta_data(tmpfile()); + self::assertArrayHasKey('uri', $logFileMetadata); + $logFilePath = $logFileMetadata['uri']; + self::assertIsString($logFilePath); $this->client->close(); $this->client = new Client([ "url" => "http://localhost:8086", @@ -72,7 +75,9 @@ public function test_debug(): void $tables = $this->client->createQueryApi()->query("buckets()", "my-org"); self::assertCount(1, $tables); - self::assertStringContainsString('Authorization: ***', file_get_contents($logFilePath)); + $logFileContents = file_get_contents($logFilePath); + self::assertIsString($logFileContents); + self::assertStringContainsString('Authorization: ***', $logFileContents); unlink($logFilePath); } } diff --git a/tests/DefaultApiTest.php b/tests/DefaultApiTest.php index d7fcd9de..c97fa0db 100644 --- a/tests/DefaultApiTest.php +++ b/tests/DefaultApiTest.php @@ -2,12 +2,12 @@ namespace InfluxDB2Test; -use GuzzleHttp\Psr7\Request; use GuzzleHttp\Psr7\Response; use InfluxDB2\ApiException; use InfluxDB2\Client; use InfluxDB2\Model\WritePrecision; use InvalidArgumentException; +use Psr\Http\Message\RequestInterface; use ReflectionObject; require_once('BasicTest.php'); @@ -21,6 +21,7 @@ public function testUserAgent(): void $request = $this->mockHandler->getLastRequest(); + self::assertInstanceOf(RequestInterface::class, $request); self::assertStringStartsWith( 'influxdb-client-php/', strval($request->getHeader("User-Agent")[0]) @@ -34,6 +35,7 @@ public function testTrailingSlashInUrl(): void $request = $this->mockHandler->getLastRequest(); + self::assertInstanceOf(RequestInterface::class, $request); self::assertEquals('http://localhost:8086/api/v2/write?org=my-org&bucket=my-bucket&precision=ns', strval($request->getUri())); $this->tearDown(); @@ -44,6 +46,7 @@ public function testTrailingSlashInUrl(): void $request = $this->mockHandler->getLastRequest(); + self::assertInstanceOf(RequestInterface::class, $request); self::assertEquals('http://localhost:8086/api/v2/write?org=my-org&bucket=my-bucket&precision=ns', strval($request->getUri())); } @@ -70,7 +73,7 @@ public function testInvalidArgument(): void { $this->mockHandler->append(new Response(204)); - $this->writeApi->options["org"] = ''; + $this->writeApi->options->org = ''; $this->expectException(InvalidArgumentException::class); @@ -81,6 +84,7 @@ public function testDefaultVerifySSL(): void { $guzzle = $this->property_value($this->property_value($this->writeApi->http, 'client'), 'httpClient'); + self::assertInstanceOf(\GuzzleHttp\Client::class, $guzzle); self::assertTrue($guzzle->getConfig()['verify']); } @@ -98,6 +102,7 @@ public function testConfigureVerifySSL(): void $guzzle = $this->property_value($this->property_value($client->createQueryApi()->http, 'client'), 'httpClient'); + self::assertInstanceOf(\GuzzleHttp\Client::class, $guzzle); self::assertFalse($guzzle->getConfig()['verify']); $client->close(); @@ -141,10 +146,10 @@ public function testJsonBodyWithErrorReturnsMessage(): void } /** - * @param Request $request with headers + * @param RequestInterface $request with headers * @return string Authorization headers */ - private function getHeader(Request $request): string + private function getHeader(RequestInterface $request): string { return implode(' ', $request->getHeaders()['Authorization']); } diff --git a/tests/FluxCsvParserTest.php b/tests/FluxCsvParserTest.php index 91bd6b64..f64074eb 100644 --- a/tests/FluxCsvParserTest.php +++ b/tests/FluxCsvParserTest.php @@ -3,6 +3,7 @@ namespace InfluxDB2Test; use Exception; +use InfluxDB2\FluxColumn; use InfluxDB2\FluxCsvParser; use InfluxDB2\FluxCsvParserException; use InfluxDB2\FluxQueryError; @@ -465,6 +466,10 @@ public function testParseDuplicateColumnNames(): void self::assertEquals(25.3, $tables[0]->records[0]->row[7]); } + /** + * @param array $columnHeaders + * @param array $values + */ private function assertColumns(array $columnHeaders, array $values): void { $i = 0; @@ -474,6 +479,9 @@ private function assertColumns(array $columnHeaders, array $values): void } } + /** + * @param array $tables + */ private function assertMultipleRecords(array $tables): void { #Record 1 diff --git a/tests/ITBucketServiceTest.php b/tests/ITBucketServiceTest.php index 331fc355..69eebbed 100644 --- a/tests/ITBucketServiceTest.php +++ b/tests/ITBucketServiceTest.php @@ -3,7 +3,10 @@ namespace InfluxDB2Test; use InfluxDB2\ApiException; +use InfluxDB2\Model\Bucket; use InfluxDB2\Model\BucketRetentionRules; +use InfluxDB2\Model\Buckets; +use InfluxDB2\Model\HealthCheck; use InfluxDB2\Model\PostBucketRequest; use InfluxDB2\ObjectSerializer; use InfluxDB2\Service\BucketsService; @@ -20,6 +23,7 @@ public function testHealthService(): void { $healthService = $this->client->createService(HealthService::class); $healthCheck = $healthService->getHealth(); + self::assertInstanceOf(HealthCheck::class, $healthCheck); self::assertEquals("influxdb", $healthCheck->getName()); self::assertEquals("ready for queries and writes", $healthCheck->getMessage()); } @@ -64,10 +68,11 @@ public function testFixNanosTimeSerialization(): void public function testBucketService(): void { - /** @var BucketsService $bucketsService */ $bucketsService = $this->client->createService(BucketsService::class); - $buckets = $bucketsService->getBuckets(null, null, 100, null)->getBuckets(); - foreach ($buckets as $bucket) { + self::assertInstanceOf(BucketsService::class, $bucketsService); + $buckets = $bucketsService->getBuckets(null, null, 100, null); + self::assertInstanceOf(Buckets::class, $buckets); + foreach ($buckets->getBuckets() as $bucket) { self::assertNotEmpty($bucket->getName()); self::assertNotEmpty($bucket->getId()); } @@ -75,8 +80,8 @@ public function testBucketService(): void public function testBucketServiceCreateBucket(): void { - /** @var BucketsService $bucketsService */ $bucketsService = $this->client->createService(BucketsService::class); + self::assertInstanceOf(BucketsService::class, $bucketsService); $rule = new BucketRetentionRules(); $rule->setEverySeconds(3600); @@ -90,12 +95,15 @@ public function testBucketServiceCreateBucket(): void //create bucket $respBucket = $bucketsService->postBuckets($bucketRequest); print $respBucket; + self::assertInstanceOf(Bucket::class, $respBucket); self::assertEquals($bucketName, $respBucket->getName()); //find bucket - $buckets = $bucketsService->getBuckets(null, null, 100, null)->getBuckets(); + $buckets = $bucketsService->getBuckets(null, null, 100, null); + self::assertInstanceOf(Buckets::class, $buckets); $findBucket = null; - foreach ($buckets as $bucket) { + foreach ($buckets->getBuckets() as $bucket) { + self::assertInstanceOf(Bucket::class, $bucket); self::assertNotEmpty($bucket->getName()); self::assertNotEmpty($bucket->getId()); if ($bucket->getId() === $respBucket->getId()) { diff --git a/tests/ITTaskServiceTest.php b/tests/ITTaskServiceTest.php index 8cd36407..5aa37054 100644 --- a/tests/ITTaskServiceTest.php +++ b/tests/ITTaskServiceTest.php @@ -2,6 +2,7 @@ namespace InfluxDB2Test; +use InfluxDB2\Model\Task; use InfluxDB2\Model\TaskCreateRequest; use InfluxDB2\Service\TasksService; @@ -14,8 +15,8 @@ class ITTaskServiceTest extends IntegrationBaseTestCase { public function testCreateTask(): void { - /** @var TasksService $taskService */ $taskService = $this->client->createService(TasksService::class); + self::assertInstanceOf(TasksService::class, $taskService); $flux = "option task = { name: \"task-name\", @@ -31,6 +32,7 @@ public function testCreateTask(): void $task = $taskService->postTasks($taskCreateRequest); + self::assertInstanceOf(Task::class, $task); self::assertEquals("task-name", $task->getName()); } } diff --git a/tests/ITUsersServiceTest.php b/tests/ITUsersServiceTest.php index 6d81bd5c..f5027755 100644 --- a/tests/ITUsersServiceTest.php +++ b/tests/ITUsersServiceTest.php @@ -2,6 +2,8 @@ namespace InfluxDB2Test; +use InfluxDB2\Model\User; +use InfluxDB2\Model\Users; use InfluxDB2\Service\UsersService; require_once('IntegrationBaseTestCase.php'); @@ -13,10 +15,12 @@ class ITUsersServiceTest extends IntegrationBaseTestCase { public function testUserService(): void { - /** @var UsersService $usersService */ $usersService = $this->client->createService(UsersService::class); - $users = $usersService->getUsers()->getUsers(); - foreach ($users as $user) { + self::assertInstanceOf(UsersService::class, $usersService); + $users = $usersService->getUsers(); + self::assertInstanceOf(Users::class, $users); + foreach ($users->getUsers() as $user) { + self::assertInstanceOf(User::class, $user); self::assertNotEmpty($user->getName()); self::assertNotEmpty($user->getId()); self::assertNotEmpty($user->getLinks()->getSelf()); diff --git a/tests/IntegrationBaseTestCase.php b/tests/IntegrationBaseTestCase.php index d8786afe..6317ccee 100644 --- a/tests/IntegrationBaseTestCase.php +++ b/tests/IntegrationBaseTestCase.php @@ -4,14 +4,14 @@ use InfluxDB2\Client; use InfluxDB2\Model\Organization; +use InfluxDB2\Model\Organizations; use InfluxDB2\Model\WritePrecision; use InfluxDB2\Service\OrganizationsService; use PHPUnit\Framework\TestCase; class IntegrationBaseTestCase extends TestCase { - /** @var Client */ - public $client; + public Client $client; /** * @var array{ * url: string, @@ -31,7 +31,7 @@ class IntegrationBaseTestCase extends TestCase * tags?: array, * } $options */ - public $options; + public array $options; public function setUp(): void { @@ -49,10 +49,11 @@ public function setUp(): void public function findMyOrg(): ?Organization { - /** @var OrganizationsService $orgService */ $orgService = $this->client->createService(OrganizationsService::class); - $orgs = $orgService->getOrgs()->getOrgs(); - foreach ($orgs as $org) { + self::assertInstanceOf(OrganizationsService::class, $orgService); + $orgs = $orgService->getOrgs(); + self::assertInstanceOf(Organizations::class, $orgs); + foreach ($orgs->getOrgs() as $org) { if ($org->getName() === $this->options["org"]) { return $org; } diff --git a/tests/InvokableScriptsApiTest.php b/tests/InvokableScriptsApiTest.php index 26fdc70a..fa25c74f 100644 --- a/tests/InvokableScriptsApiTest.php +++ b/tests/InvokableScriptsApiTest.php @@ -2,6 +2,8 @@ namespace InfluxDB2Test; +use InfluxDB2\InvokableScriptsApi; + require_once('BasicTest.php'); /** @@ -14,6 +16,6 @@ public function testCreateInstance(): void { $invokableScriptsApi = $this->client->createInvokableScriptsApi(); - self::assertNotNull($invokableScriptsApi); + self::assertInstanceOf(InvokableScriptsApi::class, $invokableScriptsApi); } } diff --git a/tests/PointSettingsTest.php b/tests/PointSettingsTest.php index 8a2717c1..db5eaecf 100644 --- a/tests/PointSettingsTest.php +++ b/tests/PointSettingsTest.php @@ -11,8 +11,7 @@ class PointSettingsTest extends TestCase private const ID_TAG = "132-987-655"; private const CUSTOMER_TAG = "California Miner"; - /** @var Client */ - private $client; + private Client $client; public function setUp(): void { diff --git a/tests/QueryApiIntegrationTest.php b/tests/QueryApiIntegrationTest.php index 86e3a461..9bd3fd7a 100644 --- a/tests/QueryApiIntegrationTest.php +++ b/tests/QueryApiIntegrationTest.php @@ -15,12 +15,9 @@ */ class QueryApiIntegrationTest extends TestCase { - /** @var Client */ - private $client; - /** @var WriteApi */ - private $writeApi; - /** @var QueryApi */ - private $queryApi; + private Client $client; + private WriteApi $writeApi; + private QueryApi $queryApi; /** * @before @@ -39,12 +36,6 @@ public function setUp(): void $this->queryApi = $this->client->createQueryApi(); } - public function testExistsApi(): void - { - self::assertNotNull($this->writeApi); - self::assertNotNull($this->queryApi); - } - public function testQueryRaw(): void { $now = new DateTime(); @@ -55,6 +46,7 @@ public function testQueryRaw(): void $result = $this->queryApi->queryRaw($query); + self::assertIsString($result); self::assertStringContainsString(',result,table,_start,_stop,_time,_value,_field,_measurement,location', $result); self::assertStringContainsString($measurement, $result); } diff --git a/tests/QueryApiStreamTest.php b/tests/QueryApiStreamTest.php index 7c0689a4..8461b22b 100644 --- a/tests/QueryApiStreamTest.php +++ b/tests/QueryApiStreamTest.php @@ -15,14 +15,10 @@ */ class QueryApiStreamTest extends TestCase { - /** @var Client */ - private $client; - /** @var WriteApi */ - private $writeApi; - /** @var QueryApi */ - private $queryApi; - /** @var DateTime */ - private $now; + private Client $client; + private WriteApi $writeApi; + private QueryApi $queryApi; + private DateTime $now; /** * @before diff --git a/tests/QueryApiTest.php b/tests/QueryApiTest.php index 4a170375..4928262f 100644 --- a/tests/QueryApiTest.php +++ b/tests/QueryApiTest.php @@ -5,6 +5,7 @@ use DateInterval; use DateTime; use GuzzleHttp\Psr7\Response; +use InfluxDB2\FluxTable; use InfluxDB2\Model\Query; require_once('BasicTest.php'); diff --git a/tests/WriteApiBatchingTest.php b/tests/WriteApiBatchingTest.php index 1cf35948..e4d3d308 100644 --- a/tests/WriteApiBatchingTest.php +++ b/tests/WriteApiBatchingTest.php @@ -43,7 +43,9 @@ public function testBatchSize(): void $result2 = "h2o_feet,location=coyote_creek level\\ water_level=3.0 3\n" . "h2o_feet,location=coyote_creek level\\ water_level=4.0 4"; + self::assertInstanceOf(RequestInterface::class, $this->requests[0]['request']); self::assertEquals($result1, $this->requests[0]['request']->getBody()); + self::assertInstanceOf(RequestInterface::class, $this->requests[1]['request']); self::assertEquals($result2, $this->requests[1]['request']->getBody()); } @@ -101,6 +103,7 @@ public function testBatchSizeGroupBy(): void $request = $this->requests[0]['request']; + self::assertInstanceOf(RequestInterface::class, $request); self::assertEquals( 'http://localhost:8086/api/v2/write?org=my-org&bucket=my-bucket&precision=ns', strval($request->getUri()) @@ -109,6 +112,7 @@ public function testBatchSizeGroupBy(): void $request = $this->requests[1]['request']; + self::assertInstanceOf(RequestInterface::class, $request); self::assertEquals( 'http://localhost:8086/api/v2/write?org=my-org&bucket=my-bucket&precision=s', strval($request->getUri()) @@ -117,6 +121,7 @@ public function testBatchSizeGroupBy(): void $request = $this->requests[2]['request']; + self::assertInstanceOf(RequestInterface::class, $request); self::assertEquals( 'http://localhost:8086/api/v2/write?org=my-org-a&bucket=my-bucket&precision=ns', strval($request->getUri()) @@ -126,6 +131,7 @@ public function testBatchSizeGroupBy(): void $request = $this->requests[3]['request']; + self::assertInstanceOf(RequestInterface::class, $request); self::assertEquals( 'http://localhost:8086/api/v2/write?org=my-org-a&bucket=my-bucket2&precision=ns', strval($request->getUri()) @@ -134,6 +140,7 @@ public function testBatchSizeGroupBy(): void $request = $this->requests[4]['request']; + self::assertInstanceOf(RequestInterface::class, $request); self::assertEquals( 'http://localhost:8086/api/v2/write?org=my-org-a&bucket=my-bucket&precision=ns', strval($request->getUri()) @@ -158,7 +165,6 @@ public function testFlushAllByCloseClient(): void $request = $this->mockHandler->getLastRequest(); self::assertInstanceOf(RequestInterface::class, $request); - self::assertEquals( 'http://localhost:8086/api/v2/write?org=my-org&bucket=my-bucket&precision=ns', strval($request->getUri()) @@ -185,6 +191,7 @@ public function testRetryIntervalByConfig(): void self::assertCount(2, $this->requests); $request = $this->mockHandler->getLastRequest(); + self::assertInstanceOf(RequestInterface::class, $request); self::assertEquals( 'http://localhost:8086/api/v2/write?org=my-org&bucket=my-bucket&precision=ns', strval($request->getUri()) @@ -211,6 +218,7 @@ public function testRetryIntervalByHeader(): void self::assertCount(2, $this->requests); $request = $this->mockHandler->getLastRequest(); + self::assertInstanceOf(RequestInterface::class, $request); self::assertEquals( 'http://localhost:8086/api/v2/write?org=my-org&bucket=my-bucket&precision=ns', strval($request->getUri()) @@ -243,7 +251,7 @@ public function testRetryIntervalMaxRetries(): void public function testRetryCount(): void { $this->mockHandler->append( - // regular call + // regular call new Response(429), // retry new Response(429), @@ -350,6 +358,7 @@ public function testRetryContainsMessage(): void self::assertCount(2, $this->requests); $message = file_get_contents("log_test.txt"); + self::assertIsString($message); self::assertStringContainsString("The retryable error occurred during writing of data. Reason: 'org 04014de4ed590000 has exceeded limited_write plan limit'. Retry in: 3s.", $message); } } diff --git a/tests/WriteApiIntegrationTest.php b/tests/WriteApiIntegrationTest.php index dc935f37..4d066d2e 100644 --- a/tests/WriteApiIntegrationTest.php +++ b/tests/WriteApiIntegrationTest.php @@ -14,10 +14,8 @@ */ class WriteApiIntegrationTest extends TestCase { - /** @var Client */ - private $client; - /** @var WriteApi */ - private $writeApi; + private Client $client; + private WriteApi $writeApi; /** * @before @@ -35,16 +33,11 @@ public function setUp(): void $this->writeApi = $this->client->createWriteApi(); } - public function testExistsWriteApi(): void - { - self::assertNotNull($this->writeApi); - } - public function testWriteApiWriteRaw(): void { $payload = 'h2o_feet,location=coyote_creek water_level=2.0 2'; - $response = $this->writeApi->writeRaw($payload); - self::assertNull($response); + $this->writeApi->writeRaw($payload); + self::expectNotToPerformAssertions(); } public function testWriteArray(): void @@ -60,14 +53,14 @@ public function testWriteArray(): void 'time' => 123 ]; - $response = $this->writeApi->write($data, WritePrecision::S, "my-bucket", "my-org"); - self::assertNull($response); + $this->writeApi->write($data, WritePrecision::S, "my-bucket", "my-org"); + self::expectNotToPerformAssertions(); } public function testBatchingWrite(): void { $writeApi = $this->client->createWriteApi( - ["writeType"=>WriteType::BATCHING, 'batchSize'=>3] + ["writeType" => WriteType::BATCHING, 'batchSize' => 3] ); $data = ['name' => 'cpu', @@ -91,9 +84,8 @@ public function testBatchingWrite(): void $writeApi->write($p5); $writeApi->write($p6); - self::assertNotNull($writeApi); - $this->client->close(); + self::expectNotToPerformAssertions(); } public function testWriteArrayOfPoint(): void @@ -109,8 +101,8 @@ public function testWriteArrayOfPoint(): void $data = array($point1, $point2); - $response = $this->writeApi->write($data, WritePrecision::S, "my-bucket", "my-org"); - self::assertNull($response); + $this->writeApi->write($data, WritePrecision::S, "my-bucket", "my-org"); + self::expectNotToPerformAssertions(); } public function testWriteArrayOfArray(): void @@ -139,7 +131,7 @@ public function testWriteArrayOfArray(): void $data = array($data1, $data2); - $response = $this->writeApi->write($data, WritePrecision::S, "my-bucket", "my-org"); - self::assertNull($response); + $this->writeApi->write($data, WritePrecision::S, "my-bucket", "my-org"); + self::expectNotToPerformAssertions(); } } diff --git a/tests/WriteApiTest.php b/tests/WriteApiTest.php index 5400e3e6..481e02af 100644 --- a/tests/WriteApiTest.php +++ b/tests/WriteApiTest.php @@ -10,6 +10,7 @@ use InfluxDB2\Model\WritePrecision; use InfluxDB2\Point; use InfluxDB2\WriteRetry; +use Psr\Http\Message\RequestInterface; require_once('BasicTest.php'); @@ -36,6 +37,7 @@ public function testWriteLineProtocol(): void $request = $this->mockHandler->getLastRequest(); + self::assertInstanceOf(RequestInterface::class, $request); self::assertEquals( 'http://localhost:8086/api/v2/write?org=my-org&bucket=my-bucket&precision=ns', strval($request->getUri()) @@ -55,6 +57,7 @@ public function testWritePoint(): void $request = $this->mockHandler->getLastRequest(); + self::assertInstanceOf(RequestInterface::class, $request); self::assertEquals( 'http://localhost:8086/api/v2/write?org=my-org&bucket=my-bucket&precision=ns', strval($request->getUri()) @@ -75,6 +78,7 @@ public function testWriteArray(): void $request = $this->mockHandler->getLastRequest(); + self::assertInstanceOf(RequestInterface::class, $request); self::assertEquals( 'http://localhost:8086/api/v2/write?org=my-org&bucket=my-bucket&precision=ns', strval($request->getUri()) @@ -103,6 +107,7 @@ public function testWriteCollection(): void . "h2o,location=europe level=2i\n" . "h2o,host=aws,region=us level=5i,saturation=\"99%\" 123"; + self::assertInstanceOf(RequestInterface::class, $request); self::assertEquals( 'http://localhost:8086/api/v2/write?org=my-org&bucket=my-bucket&precision=ns', strval($request->getUri()) @@ -117,11 +122,15 @@ public function testAuthorizationHeader(): void $request = $this->mockHandler->getLastRequest(); + self::assertInstanceOf(RequestInterface::class, $request); self::assertEquals( 'http://localhost:8086/api/v2/write?org=my-org&bucket=my-bucket&precision=ns', strval($request->getUri()) ); - self::assertEquals('Token my-token', implode(' ', $request->getHeaders()['Authorization'])); + $requestHeaders = $request->getHeaders(); + self::assertArrayHasKey('Authorization', $requestHeaders); + self::assertCount(1, $requestHeaders['Authorization']); + self::assertEquals('Token my-token', implode(' ', $requestHeaders['Authorization'])); } public function testWithoutData(): void @@ -168,6 +177,7 @@ public function testWritePointWithDefaultTags(): void $request = $this->mockHandler->getLastRequest(); + self::assertInstanceOf(RequestInterface::class, $request); self::assertEquals( 'http://localhost:8086/api/v2/write?org=my-org&bucket=my-bucket&precision=ns', strval($request->getUri()) @@ -195,6 +205,7 @@ public function testWriteArrayWithDefaultTags(): void $request = $this->mockHandler->getLastRequest(); + self::assertInstanceOf(RequestInterface::class, $request); self::assertEquals( 'http://localhost:8086/api/v2/write?org=my-org&bucket=my-bucket&precision=ns', strval($request->getUri()) @@ -230,6 +241,7 @@ public function testWriteCollectionWithDefaultTags(): void . "h2o,customer=California\ Miner,data_center=LA,id=132-987-655,location=europe level=2i\n" . "h2o,customer=California\ Miner,data_center=LA,host=aws,id=132-987-655,region=us level=5i,saturation=\"99%\" 123"; + self::assertInstanceOf(RequestInterface::class, $request); self::assertEquals( 'http://localhost:8086/api/v2/write?org=my-org&bucket=my-bucket&precision=ns', strval($request->getUri()) @@ -253,6 +265,7 @@ public function testWriteArrayWithoutTagsWithDefaultTags(): void $request = $this->mockHandler->getLastRequest(); + self::assertInstanceOf(RequestInterface::class, $request); self::assertEquals( 'http://localhost:8086/api/v2/write?org=my-org&bucket=my-bucket&precision=ns', strval($request->getUri()) @@ -266,7 +279,7 @@ public function testWriteArrayWithoutTagsWithDefaultTags(): void public function testRetryCount(): void { $this->mockHandler->append( - // regular call + // regular call new Response(429), // retry new Response(429), @@ -298,7 +311,7 @@ public function testRetryCount(): void public function testRetryMaxTime(): void { $this->mockHandler->append( - // regular call + // regular call new Response(429), // retry new Response(429), @@ -377,7 +390,7 @@ public function testConnectExceptionRetry(): void try { $writeApi->write($point); } catch (ApiException $e) { - self::assertEquals(ConnectException::class, get_class($e->getPrevious())); + self::assertInstanceOf(ConnectException::class, $e->getPrevious()); throw $e; } } diff --git a/tests/WriteUdpTest.php b/tests/WriteUdpTest.php index e392c3b0..b8e030e7 100644 --- a/tests/WriteUdpTest.php +++ b/tests/WriteUdpTest.php @@ -3,6 +3,7 @@ namespace InfluxDB2Test; use InfluxDB2\Client; +use InfluxDB2\ClientOptions; use InfluxDB2\Model\WritePrecision; use InfluxDB2\Point; use InfluxDB2\UdpWriter; @@ -53,7 +54,9 @@ protected function getWriterMock() } return $this->getMockBuilder(UdpWriter::class) ->onlyMethods(['writeSocket']) - ->setConstructorArgs([$this->baseConfig + ['udpPort' => 1000]]) + ->setConstructorArgs([ + ClientOptions::fromArray($this->baseConfig + ['udpPort' => 1000]), + ]) ->getMock(); } @@ -83,7 +86,7 @@ public function testLineProtocol(): void { $writer = $this->getWriterMock(); $buffer = ''; - $writer->method('writeSocket')->willReturnCallback(function ($data) use (&$buffer) { + $writer->method('writeSocket')->willReturnCallback(function ($data) use (&$buffer): void { $buffer = $data; }); $writer->write('h2o,location=west value=33i 15'); @@ -101,7 +104,7 @@ public function testWriteArray(): void $writer = $this->getWriterMock(); $buffer = ''; - $writer->method('writeSocket')->willReturnCallback(function ($data) use (&$buffer) { + $writer->method('writeSocket')->willReturnCallback(function ($data) use (&$buffer): void { $buffer = $data; }); $writer->write($array);