diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index d8d1050e..9d79d838 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -37,7 +37,7 @@ Feel free to propose a new feature by [opening an issue for it](https://github.c 1. Fork the repository. 1. Create a new branch. - 1. If you are **implementing new functionality**, create your branch from `development`. + 1. If you are **implementing new functionality**, create your branch from `main`. 1. If you are **fixing a bug**, create your branch from the oldest [supported](https://github.com/neo4j-php/php-cypher-dsl/blob/main/LIFECYCLE.md) branch that is affected by the bug. 1. Implement your change and add tests for it. 1. Make sure the test suite passes. @@ -50,18 +50,6 @@ Some things to keep in mind: * Keep backwards compatibility breaks to a minimum. * You are encouraged to [sign your commits](https://docs.github.com/en/authentication/managing-commit-signature-verification/signing-commits) with GPG. -## Branching model - -The branching model used by this project is [gitflow](https://nvie.com/posts/a-successful-git-branching-model/), with the following changes/additions: - -1. Feature branches must follow the naming convention `feature/*`. -1. The name of a feature branch should reflect the feature added (e.g. `feature/support-indexing-operator` instead of `feature/feature-1`). -1. Release branches must follow the naming convention `release/x.y`, where `x` and `y` are the major and minor version of the release respectively. A release branch should never be made for a patch. -1. Hotfix branches must follow the naming convention `hotfix/x.y.z`, where `x`, `y` and `z` are the major, minor and patch version of the hot respectively. -1. Hotfix branches must branch off from the oldest [supported](https://github.com/neo4j-php/php-cypher-dsl/blob/main/LIFECYCLE.md) branch that is affected by the bug. -1. Right before a new **major** version is released, a *support* branch is created from `main`. -1. Support branches must follow the naming convention `support/x.y`, where `x` and `y` are the major and minor version of the most recent release respectively. - ## Coding guidelines This project comes with a [configuration file](https://github.com/neo4j-php/php-cypher-dsl/blob/main/.php-cs-fixer.dist.php) for `php-cs-fixer` that you can use to format your code: @@ -81,7 +69,7 @@ After making your changes and adding your tests, you can check whether the minim ``` $ XDEBUG_MODE=coverage php vendor/bin/phpunit --testsuite unit $ php vendor/bin/coverage-check coverage/clover.xml 90 -$ XDEBUG_MODE=coverage php vendor/bin/infection --min-msi=80 +$ XDEBUG_MODE=coverage php vendor/bin/infection --min-msi=85 ``` ## Running test suites diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ebca4dba..c4c126ed 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -14,13 +14,13 @@ jobs: strategy: matrix: - php-version: [ "7.4", "8.0", "8.1", "8.2" ] + php-version: [ "8.1", "8.2", "8.3", "8.4", "8.5" ] env: COMPOSER_VERSION: 2 COVERAGE_DRIVER: xdebug MINIMUM_COVERAGE_PERCENTAGE: 90 - MINIMUM_MSI_PERCENTAGE: 80 + MINIMUM_MSI_PERCENTAGE: 85 steps: - name: Checkout repository diff --git a/CHANGELOG.md b/CHANGELOG.md index 53d3f7c2..a2c22c50 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,24 @@ file. A changelog has been kept from version 5.0.0 onwards. The format is based on [Keep a Changelog], and this project adheres to [Semantic Versioning]. +## 7.0.0 - T.B.D. + +### Changed + +- Changed the minimum required PHP version to 8.1. +- Changed the signature of many functions to use PHP 8 union types. +- Changed the `Relationship::DIR_*` to the `Direction` enum. + +### Removed + +- Removed unnecessary dependency for the `openssl` PHP library. +- Removed `ErrorTrait` in favor of PHP 8.0 union types. +- Removed `CastTrait` in favor of the static functions in `CastUtils`. +- Removed `NameGenerationTrait` in favor of the static functions in `NameUtils`. +- Removed `EscapeTrait` in favor of the static functions in `NameUtils`. +- Removed `Relationship::DIR_UNI`, `Relationship::DIR_LEFT` and `Relationship::DIR_RIGHT` constants + in favor of the `Direction` enum. + ## 6.0.0 - 2023-09-19 ### Changed diff --git a/LIFECYCLE.md b/LIFECYCLE.md index 041efade..81a1c43e 100644 --- a/LIFECYCLE.md +++ b/LIFECYCLE.md @@ -16,7 +16,8 @@ loss and/or corruption. ## Supported versions -| Major version | PHP version | Initial release | End of bugfix support | -|------------------|-------------|-----------------|-----------------------| -| php-cypher-dsl 5 | >=7.4 | Jan 9th, 2023 | Mar 19th, 2024 | -| php-cypher-dsl 6 | >=7.4 | Sep 19th, 2023 | To be determined | +| Major version | PHP version | Initial release | End of bugfix support | +|------------------|-------------|-------------------|-----------------------| +| php-cypher-dsl 5 | >=7.4 | Jan 9th, 2023 | Mar 19th, 2024 | +| php-cypher-dsl 6 | >=7.4 | Sep 19th, 2023 | To be determined | +| php-cypher-dsl 7 | >=8.1 | To be determined | To be determined | diff --git a/README.md b/README.md index f6afc161..1f71a1fd 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,20 @@ # php-cypher-dsl -The `php-cypher-dsl` library provides a way to construct advanced Cypher -queries in an object-oriented and type-safe manner. +The `php-cypher-dsl` library provides a way to construct Cypher queries in a type-safe manner. ## Documentation -[The documentation can be found on the wiki -here.](https://github.com/WikibaseSolutions/php-cypher-dsl/wiki) +[The documentation can be found on the wiki here.](https://github.com/WikibaseSolutions/php-cypher-dsl/wiki) ## Installation ### Requirements -`php-cypher-dsl` requires PHP 7.4 or greater; using the latest version of PHP -is highly recommended. +`php-cypher-dsl` requires PHP 8.1 or greater; using the latest version of PHP is highly recommended. ### Installation through Composer -You can install `php-cypher-dsl` through composer by running the following -command: +You can install `php-cypher-dsl` through Composer by running the following command: ``` composer require "wikibase-solutions/php-cypher-dsl" @@ -30,8 +26,7 @@ Please refer to [CONTRIBUTING.md](https://github.com/neo4j-php/php-cypher-dsl/bl ## Example -To construct a query to find all of Tom Hanks' co-actors, you can use the -following code: +To construct a query to find all of Tom Hanks' co-actors, you can use the following code: ```php use function WikibaseSolutions\CypherDSL\node; @@ -41,7 +36,13 @@ $tom = node("Person")->withProperties(["name" => "Tom Hanks"]); $coActors = node(); $statement = query() - ->match($tom->relationshipTo(Query::node(), "ACTED_IN")->relationshipFrom($coActors, "ACTED_IN")) + ->match($tom->relationshipTo(node(), "ACTED_IN")->relationshipFrom($coActors, "ACTED_IN")) ->returning($coActors->property("name")) ->build(); ``` + +This produces the following Cypher query (where `$1` is a random variable name): + +``` +MATCH (:Person {name: 'Tom Hanks'})-[:ACTED_IN]->()<-[:ACTED_IN]-($1) RETURN $1.name +``` diff --git a/composer.json b/composer.json index 9ccd27b7..b599bdb5 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,6 @@ { "name": "wikibase-solutions/php-cypher-dsl", - "description": "A query builder for the Cypher query language written in PHP", + "description": "A query builder for the Cypher query language", "type": "library", "keywords": [ "neo4j", @@ -46,18 +46,15 @@ "source": "https://github.com/WikibaseSolutions/php-cypher-dsl" }, "require": { - "php": ">=7.4", - "ext-ctype": "*", - "ext-openssl": "*", - "symfony/polyfill-php80": "^1.25", - "symfony/polyfill-php81": "^1.25" + "php": ">=8.1", + "ext-ctype": "*" }, "require-dev": { - "phpunit/phpunit": "~9.0", - "infection/infection": "^0.25.5", + "phpunit/phpunit": "^10.0", + "infection/infection": "^0.29", "friendsofphp/php-cs-fixer": "^3.0", "rregeer/phpunit-coverage-check": "^0.3.1", - "phpstan/phpstan": "^1.8" + "phpstan/phpstan": "^2.0" }, "autoload": { "files": [ diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 90f61d32..58cd7a2c 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -1,5 +1,10 @@ parameters: paths: - src - level: 7 - treatPhpDocTypesAsCertain: false \ No newline at end of file + level: 9 + treatPhpDocTypesAsCertain: false + ignoreErrors: + - "#Method [a-zA-Z0-9\\_\\\\:\\(\\)]+ has parameter \\$[a-zA-Z0-9_]+ with no value type specified in iterable type array#" + - "#Function [a-zA-Z0-9\\_\\\\:\\(\\)]+ has parameter \\$[a-zA-Z0-9_]+ with no value type specified in iterable type array#" + - "#Method [a-zA-Z0-9\\_\\\\:\\(\\)]+ has parameter \\$[a-zA-Z0-9_]+ with no value type specified in iterable type iterable#" + - "#Method [a-zA-Z0-9\\_\\\\:\\(\\)]+ return type has no value type specified in iterable type array#" diff --git a/phpunit.xml.dist b/phpunit.xml.dist index d9399d2b..4ad067c1 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,7 +1,12 @@ - @@ -15,16 +20,18 @@ tests/integration - - - - - + src src/functions.php + + + + + + \ No newline at end of file diff --git a/src/Clauses/CallClause.php b/src/Clauses/CallClause.php index cc8b11c8..3182fc77 100644 --- a/src/Clauses/CallClause.php +++ b/src/Clauses/CallClause.php @@ -12,8 +12,7 @@ use WikibaseSolutions\CypherDSL\Expressions\Variable; use WikibaseSolutions\CypherDSL\Patterns\Pattern; use WikibaseSolutions\CypherDSL\Query; -use WikibaseSolutions\CypherDSL\Traits\CastTrait; -use WikibaseSolutions\CypherDSL\Traits\ErrorTrait; +use WikibaseSolutions\CypherDSL\Utils\CastUtils; /** * This class represents a CALL {} (subquery) clause. The CALL {} clause evaluates a subquery that returns @@ -26,9 +25,6 @@ */ final class CallClause extends Clause { - use CastTrait; - use ErrorTrait; - /** * @var null|Query The sub-query to call, or NULL if no sub-query has been set yet */ @@ -56,18 +52,14 @@ public function withSubQuery(Query $subQuery): self /** * Add one or more variables to include in the WITH clause. * - * @param Pattern|string|Variable ...$variables - * - * @return $this - * * @see https://neo4j.com/docs/cypher-manual/current/clauses/call-subquery/#subquery-correlated-importing */ - public function addWithVariable(...$variables): self + public function addWithVariable(Pattern|Variable|string ...$variables): self { $res = []; foreach ($variables as $variable) { - $res[] = self::toVariable($variable); + $res[] = CastUtils::toVariable($variable); } $this->withVariables = array_merge($this->withVariables, $res); diff --git a/src/Clauses/CallProcedureClause.php b/src/Clauses/CallProcedureClause.php index 788909b5..be5ccc17 100644 --- a/src/Clauses/CallProcedureClause.php +++ b/src/Clauses/CallProcedureClause.php @@ -12,7 +12,7 @@ use WikibaseSolutions\CypherDSL\Expressions\Procedures\Procedure; use WikibaseSolutions\CypherDSL\Expressions\Variable; use WikibaseSolutions\CypherDSL\Syntax\Alias; -use WikibaseSolutions\CypherDSL\Traits\CastTrait; +use WikibaseSolutions\CypherDSL\Utils\CastUtils; /** * This class represents a CALL procedure clause. @@ -25,15 +25,13 @@ */ final class CallProcedureClause extends Clause { - use CastTrait; - /** * @var null|Procedure The procedure to call */ private ?Procedure $procedure = null; /** - * @var Alias[]|Variable[]|(Alias|Variable)[] The result fields that are yielded + * @var Alias[]|(Alias|Variable)[]|Variable[] The result fields that are yielded */ private array $yields = []; @@ -41,8 +39,6 @@ final class CallProcedureClause extends Clause * Sets the procedure to call. * * @param Procedure $procedure The procedure to call - * - * @return $this */ public function setProcedure(Procedure $procedure): self { @@ -55,15 +51,13 @@ public function setProcedure(Procedure $procedure): self * Adds a variable to yield. * * @param Alias|string|Variable $yields The variable to yield - * - * @return $this */ public function addYield(...$yields): self { $res = []; foreach ($yields as $yield) { - $res[] = $yield instanceof Alias ? $yield : self::toName($yield); + $res[] = $yield instanceof Alias ? $yield : CastUtils::toName($yield); } $this->yields = array_merge($this->yields, $res); @@ -73,8 +67,6 @@ public function addYield(...$yields): self /** * Returns the procedure to call. - * - * @return Procedure */ public function getProcedure(): ?Procedure { @@ -84,7 +76,7 @@ public function getProcedure(): ?Procedure /** * Returns the variables to yield. * - * @return Alias[]|Variable[]|(Alias|Variable)[] + * @return (Alias|Variable)[] */ public function getYields(): array { diff --git a/src/Clauses/CreateClause.php b/src/Clauses/CreateClause.php index bb4f460f..f305b4b2 100644 --- a/src/Clauses/CreateClause.php +++ b/src/Clauses/CreateClause.php @@ -11,7 +11,6 @@ use WikibaseSolutions\CypherDSL\Patterns\CompletePattern; use WikibaseSolutions\CypherDSL\Query; -use WikibaseSolutions\CypherDSL\Traits\ErrorTrait; /** * This class represents a CREATE clause. @@ -24,8 +23,6 @@ */ final class CreateClause extends Clause { - use ErrorTrait; - /** * @var CompletePattern[] The patterns to create */ diff --git a/src/Clauses/DeleteClause.php b/src/Clauses/DeleteClause.php index ecf8c759..b8aeff5b 100644 --- a/src/Clauses/DeleteClause.php +++ b/src/Clauses/DeleteClause.php @@ -11,8 +11,8 @@ use WikibaseSolutions\CypherDSL\Patterns\Pattern; use WikibaseSolutions\CypherDSL\Query; -use WikibaseSolutions\CypherDSL\Traits\CastTrait; use WikibaseSolutions\CypherDSL\Types\StructuralTypes\StructuralType; +use WikibaseSolutions\CypherDSL\Utils\CastUtils; /** * This class represents a DELETE clause. @@ -25,8 +25,6 @@ */ final class DeleteClause extends Clause { - use CastTrait; - /** * Whether the DETACH modifier is needed. */ @@ -42,8 +40,6 @@ final class DeleteClause extends Clause * all relationships connected to the nodes/paths need to be explicitly deleted. * * @param bool $detach Whether to use DETACH DELETE - * - * @return $this */ public function setDetach(bool $detach = true): self { @@ -56,15 +52,13 @@ public function setDetach(bool $detach = true): self * Add one or more structures to delete. * * @param Pattern|StructuralType $structures The structures to delete - * - * @return $this */ public function addStructure(...$structures): self { $res = []; foreach ($structures as $structure) { - $res[] = self::toStructuralType($structure); + $res[] = CastUtils::toStructuralType($structure); } $this->structures = array_merge($this->structures, $res); diff --git a/src/Clauses/LimitClause.php b/src/Clauses/LimitClause.php index 2819eda2..18b900aa 100644 --- a/src/Clauses/LimitClause.php +++ b/src/Clauses/LimitClause.php @@ -10,8 +10,8 @@ namespace WikibaseSolutions\CypherDSL\Clauses; use WikibaseSolutions\CypherDSL\Query; -use WikibaseSolutions\CypherDSL\Traits\CastTrait; use WikibaseSolutions\CypherDSL\Types\PropertyTypes\IntegerType; +use WikibaseSolutions\CypherDSL\Utils\CastUtils; /** * This class represents a LIMIT clause. @@ -24,8 +24,6 @@ */ final class LimitClause extends Clause { - use CastTrait; - /** * The expression of the LIMIT statement. */ @@ -33,14 +31,10 @@ final class LimitClause extends Clause /** * Sets the expression that returns the limit. - * - * @param int|IntegerType $limit The limit - * - * @return $this */ - public function setLimit($limit): self + public function setLimit(IntegerType|int $limit): self { - $this->limit = self::toIntegerType($limit); + $this->limit = CastUtils::toIntegerType($limit); return $this; } diff --git a/src/Clauses/MatchClause.php b/src/Clauses/MatchClause.php index 48cfc80d..8615daed 100644 --- a/src/Clauses/MatchClause.php +++ b/src/Clauses/MatchClause.php @@ -29,10 +29,6 @@ final class MatchClause extends Clause /** * Add one or more patterns to the MATCH clause. - * - * @param CompletePattern ...$pattern - * - * @return $this */ public function addPattern(CompletePattern ...$pattern): self { diff --git a/src/Clauses/MergeClause.php b/src/Clauses/MergeClause.php index 6eb4dd07..6f002ef1 100644 --- a/src/Clauses/MergeClause.php +++ b/src/Clauses/MergeClause.php @@ -55,8 +55,6 @@ public function setPattern(CompletePattern $pattern): self * The clause to execute on all nodes that need to be created. * * @see https://neo4j.com/docs/cypher-manual/current/clauses/merge/#merge-merge-with-on-create - * - * @return $this */ public function setOnCreate(?SetClause $createClause): self { @@ -69,8 +67,6 @@ public function setOnCreate(?SetClause $createClause): self * The clause to execute on all found nodes. * * @see https://neo4j.com/docs/cypher-manual/current/clauses/merge/#merge-merge-with-on-match - * - * @return $this */ public function setOnMatch(?SetClause $matchClause): self { diff --git a/src/Clauses/OptionalMatchClause.php b/src/Clauses/OptionalMatchClause.php index fb297ac9..30d473a8 100644 --- a/src/Clauses/OptionalMatchClause.php +++ b/src/Clauses/OptionalMatchClause.php @@ -29,10 +29,6 @@ final class OptionalMatchClause extends Clause /** * Add one or more patterns to the OPTIONAL MATCH clause. - * - * @param CompletePattern ...$pattern - * - * @return $this */ public function addPattern(CompletePattern ...$pattern): self { diff --git a/src/Clauses/OrderByClause.php b/src/Clauses/OrderByClause.php index d36f3c74..91f4e970 100644 --- a/src/Clauses/OrderByClause.php +++ b/src/Clauses/OrderByClause.php @@ -40,8 +40,6 @@ final class OrderByClause extends Clause * Add one or more properties to sort on. * * @param Property ...$property The additional property to sort on - * - * @return OrderByClause */ public function addProperty(Property ...$property): self { @@ -52,8 +50,6 @@ public function addProperty(Property ...$property): self /** * Set to sort in a DESCENDING order. - * - * @return OrderByClause */ public function setDescending(bool $descending = true): self { diff --git a/src/Clauses/RemoveClause.php b/src/Clauses/RemoveClause.php index af9850ab..b28665ff 100644 --- a/src/Clauses/RemoveClause.php +++ b/src/Clauses/RemoveClause.php @@ -12,7 +12,6 @@ use WikibaseSolutions\CypherDSL\Expressions\Label; use WikibaseSolutions\CypherDSL\Expressions\Property; use WikibaseSolutions\CypherDSL\QueryConvertible; -use WikibaseSolutions\CypherDSL\Traits\ErrorTrait; /** * This class represents a REMOVE clause. @@ -23,10 +22,8 @@ */ final class RemoveClause extends Clause { - use ErrorTrait; - /** - * @var Label[]|Property[]|(Label|Property)[] the expressions in this REMOVE clause + * @var (Label|Property)[] the expressions in this REMOVE clause */ private array $expressions = []; @@ -34,12 +31,9 @@ final class RemoveClause extends Clause * Add one or more expressions to the REMOVE clause. * * @param Label|Property ...$expressions The expressions to add - * - * @return RemoveClause */ - public function addExpression(...$expressions): self + public function addExpression(Property|Label ...$expressions): self { - self::assertClassArray('expressions', [Property::class, Label::class], $expressions); $this->expressions = array_merge($this->expressions, $expressions); return $this; @@ -48,7 +42,7 @@ public function addExpression(...$expressions): self /** * Returns the expressions in the REMOVE clause. * - * @return Label[]|Property[]|(Label|Property)[] + * @return (Label|Property)[] */ public function getExpressions(): array { diff --git a/src/Clauses/ReturnClause.php b/src/Clauses/ReturnClause.php index aec1ce24..76986a33 100644 --- a/src/Clauses/ReturnClause.php +++ b/src/Clauses/ReturnClause.php @@ -12,9 +12,8 @@ use WikibaseSolutions\CypherDSL\Patterns\Pattern; use WikibaseSolutions\CypherDSL\QueryConvertible; use WikibaseSolutions\CypherDSL\Syntax\Alias; -use WikibaseSolutions\CypherDSL\Traits\CastTrait; -use WikibaseSolutions\CypherDSL\Traits\ErrorTrait; use WikibaseSolutions\CypherDSL\Types\AnyType; +use WikibaseSolutions\CypherDSL\Utils\CastUtils; /** * This class represents a RETURN clause. @@ -25,34 +24,29 @@ */ final class ReturnClause extends Clause { - use CastTrait; - use ErrorTrait; - /** * @var bool Whether to be a RETURN DISTINCT query */ private bool $distinct = false; /** - * @var Alias[]|AnyType[]|(Alias|AnyType)[] The expressions to return + * @var (Alias|AnyType)[] The expressions to return */ private array $columns = []; /** * Add a new column to this RETURN clause. * - * @param Alias|AnyType|bool|float|int|mixed[]|Pattern|string ...$columns The values to return - * - * @return $this + * @param Alias|AnyType|array|bool|float|int|Pattern|string ...$columns The values to return * * @see https://neo4j.com/docs/cypher-manual/current/clauses/return/#return-column-alias */ - public function addColumn(...$columns): self + public function addColumn(Alias|AnyType|bool|float|int|array|Pattern|string ...$columns): self { $res = []; foreach ($columns as $column) { - $res[] = $column instanceof Alias ? $column : self::toAnyType($column); + $res[] = $column instanceof Alias ? $column : CastUtils::toAnyType($column); } $this->columns = array_merge($this->columns, $res); @@ -63,8 +57,6 @@ public function addColumn(...$columns): self /** * Sets this query to only return unique rows. * - * @return $this - * * @see https://neo4j.com/docs/cypher-manual/current/clauses/return/#return-unique-results */ public function setDistinct(bool $distinct = true): self @@ -77,7 +69,7 @@ public function setDistinct(bool $distinct = true): self /** * Returns the columns to return. Aliased columns have string keys instead of integers. * - * @return Alias[]|AnyType[]|(Alias|AnyType)[] + * @return (Alias|AnyType)[] */ public function getColumns(): array { diff --git a/src/Clauses/SetClause.php b/src/Clauses/SetClause.php index 6c88d014..19be1ca7 100644 --- a/src/Clauses/SetClause.php +++ b/src/Clauses/SetClause.php @@ -12,7 +12,6 @@ use WikibaseSolutions\CypherDSL\Expressions\Label; use WikibaseSolutions\CypherDSL\QueryConvertible; use WikibaseSolutions\CypherDSL\Syntax\PropertyReplacement; -use WikibaseSolutions\CypherDSL\Traits\ErrorTrait; /** * This class represents a SET clause. @@ -23,23 +22,18 @@ */ final class SetClause extends Clause { - use ErrorTrait; - /** - * @var Label[]|PropertyReplacement[]|(Label|PropertyReplacement)[] The expressions to set + * @var (Label|PropertyReplacement)[] The expressions to set */ private array $expressions = []; /** * Add one or more expressions to this SET clause. * - * @param Label|PropertyReplacement $expressions The expressions to add to this set clause - * - * @return $this + * @param Label|PropertyReplacement ...$expressions The expressions to add to this set clause */ - public function add(...$expressions): self + public function add(Label|PropertyReplacement ...$expressions): self { - $this->assertClassArray('expression', [PropertyReplacement::class, Label::class], $expressions); $this->expressions = array_merge($this->expressions, $expressions); return $this; @@ -48,7 +42,7 @@ public function add(...$expressions): self /** * Returns the expressions to SET. * - * @return Label[]|PropertyReplacement[]|(Label|PropertyReplacement)[] + * @return (Label|PropertyReplacement)[] */ public function getExpressions(): array { diff --git a/src/Clauses/SkipClause.php b/src/Clauses/SkipClause.php index 4e544fe7..3a7ae7b9 100644 --- a/src/Clauses/SkipClause.php +++ b/src/Clauses/SkipClause.php @@ -9,8 +9,8 @@ */ namespace WikibaseSolutions\CypherDSL\Clauses; -use WikibaseSolutions\CypherDSL\Traits\CastTrait; use WikibaseSolutions\CypherDSL\Types\PropertyTypes\IntegerType; +use WikibaseSolutions\CypherDSL\Utils\CastUtils; /** * This class represents a SKIP clause. @@ -21,8 +21,6 @@ */ final class SkipClause extends Clause { - use CastTrait; - /** * The expression of the SKIP statement. */ @@ -32,12 +30,10 @@ final class SkipClause extends Clause * Sets the expression that returns the skip. * * @param int|IntegerType $skip The amount to skip - * - * @return SkipClause */ - public function setSkip($skip): self + public function setSkip(IntegerType|int $skip): self { - $this->skip = self::toIntegerType($skip); + $this->skip = CastUtils::toIntegerType($skip); return $this; } diff --git a/src/Clauses/UnionClause.php b/src/Clauses/UnionClause.php index 79b99317..aaed2301 100644 --- a/src/Clauses/UnionClause.php +++ b/src/Clauses/UnionClause.php @@ -31,8 +31,6 @@ final class UnionClause extends Clause * Sets that the union should include all results, instead of removing duplicates. * * @param bool $all Whether the union should include all results or remove the duplicates instead - * - * @return static */ public function setAll(bool $all = true): self { diff --git a/src/Clauses/WhereClause.php b/src/Clauses/WhereClause.php index 818d7a76..c634e27c 100644 --- a/src/Clauses/WhereClause.php +++ b/src/Clauses/WhereClause.php @@ -10,8 +10,8 @@ namespace WikibaseSolutions\CypherDSL\Clauses; use InvalidArgumentException; -use WikibaseSolutions\CypherDSL\Traits\CastTrait; use WikibaseSolutions\CypherDSL\Types\PropertyTypes\BooleanType; +use WikibaseSolutions\CypherDSL\Utils\CastUtils; /** * This class represents a WHERE clause. @@ -24,8 +24,6 @@ */ final class WhereClause extends Clause { - use CastTrait; - public const AND = 'and'; public const OR = 'or'; @@ -46,9 +44,9 @@ final class WhereClause extends Clause * * @return $this */ - public function addExpression($expression, string $operator = self::AND): self + public function addExpression(BooleanType|bool $expression, string $operator = self::AND): self { - $expression = self::toBooleanType($expression); + $expression = CastUtils::toBooleanType($expression); if ($operator !== self::AND && $operator !== self::OR && $operator !== self::XOR) { throw new InvalidArgumentException('$operator must either be "and", "xor" or "or"'); diff --git a/src/Clauses/WithClause.php b/src/Clauses/WithClause.php index 5783c91d..7332e4a2 100644 --- a/src/Clauses/WithClause.php +++ b/src/Clauses/WithClause.php @@ -14,7 +14,7 @@ use WikibaseSolutions\CypherDSL\Query; use WikibaseSolutions\CypherDSL\QueryConvertible; use WikibaseSolutions\CypherDSL\Syntax\Alias; -use WikibaseSolutions\CypherDSL\Traits\CastTrait; +use WikibaseSolutions\CypherDSL\Utils\CastUtils; /** * This class represents a WITH clause. @@ -28,26 +28,20 @@ */ final class WithClause extends Clause { - use CastTrait; - /** - * @var Alias[]|Variable[]|(Alias|Variable)[] The variables to include in the clause + * @var (Alias|Variable)[] The variables to include in the clause */ private array $entries = []; /** * Add one or more new entries to the WITH clause. - * - * @param Alias|Pattern|string|Variable ...$entries The entries to add - * - * @return $this */ - public function addEntry(...$entries): self + public function addEntry(Alias|Pattern|string|Variable ...$entries): self { $res = []; foreach ($entries as $entry) { - $res[] = $entry instanceof Alias ? $entry : self::toVariable($entry); + $res[] = $entry instanceof Alias ? $entry : CastUtils::toVariable($entry); } $this->entries = array_merge($this->entries, $res); @@ -58,7 +52,7 @@ public function addEntry(...$entries): self /** * Returns the expression to include in the clause. * - * @return Alias[]|Variable[]|(Alias|Variable)[] + * @return (Alias|Variable)[] */ public function getEntries(): array { diff --git a/src/Expressions/Exists.php b/src/Expressions/Exists.php index 72153975..1249d7e7 100644 --- a/src/Expressions/Exists.php +++ b/src/Expressions/Exists.php @@ -11,7 +11,6 @@ use WikibaseSolutions\CypherDSL\Clauses\MatchClause; use WikibaseSolutions\CypherDSL\Clauses\WhereClause; -use WikibaseSolutions\CypherDSL\Traits\ErrorTrait; use WikibaseSolutions\CypherDSL\Traits\TypeTraits\PropertyTypeTraits\BooleanTypeTrait; use WikibaseSolutions\CypherDSL\Types\PropertyTypes\BooleanType; @@ -23,7 +22,6 @@ final class Exists implements BooleanType { use BooleanTypeTrait; - use ErrorTrait; /** * @var MatchClause The MATCH part of the EXISTS expression diff --git a/src/Expressions/Label.php b/src/Expressions/Label.php index d3d11d92..d85bb462 100644 --- a/src/Expressions/Label.php +++ b/src/Expressions/Label.php @@ -9,9 +9,9 @@ */ namespace WikibaseSolutions\CypherDSL\Expressions; -use WikibaseSolutions\CypherDSL\Traits\EscapeTrait; use WikibaseSolutions\CypherDSL\Traits\TypeTraits\PropertyTypeTraits\BooleanTypeTrait; use WikibaseSolutions\CypherDSL\Types\PropertyTypes\BooleanType; +use WikibaseSolutions\CypherDSL\Utils\NameUtils; /** * Represents a label. A label in Cypher would be something like "n:German" or "n:German:Swedish". Label implements @@ -23,8 +23,6 @@ final class Label implements BooleanType { use BooleanTypeTrait; - use EscapeTrait; - /** * @var Variable The variable to which this label belongs */ @@ -44,7 +42,7 @@ final class Label implements BooleanType public function __construct(Variable $variable, string ...$labels) { $this->variable = $variable; - $this->labels = array_map([self::class, 'escape'], $labels); + $this->labels = array_map(NameUtils::escape(...), $labels); } /** @@ -56,7 +54,7 @@ public function __construct(Variable $variable, string ...$labels) */ public function addLabels(string ...$labels): self { - $this->labels = array_merge($this->labels, array_map([self::class, 'escape'], $labels)); + $this->labels = array_merge($this->labels, array_map(NameUtils::escape(...), $labels)); return $this; } diff --git a/src/Expressions/Literals/Integer.php b/src/Expressions/Literals/Integer.php index f8f8ad37..ad9d8e4b 100644 --- a/src/Expressions/Literals/Integer.php +++ b/src/Expressions/Literals/Integer.php @@ -30,12 +30,8 @@ final class Integer implements IntegerType * * @internal This function is not covered by the backwards compatibility guarantee of php-cypher-dsl */ - public function __construct($value) + public function __construct(int|string $value) { - if (!is_int($value) && !is_string($value)) { - throw new TypeError('An integer should be given as a string or integer, ' . gettype($value) . ' received.'); - } - $parsedValue = filter_var($value, FILTER_SANITIZE_NUMBER_INT); if ($parsedValue === false) { diff --git a/src/Expressions/Literals/List_.php b/src/Expressions/Literals/List_.php index 949bb9dc..63c91262 100644 --- a/src/Expressions/Literals/List_.php +++ b/src/Expressions/Literals/List_.php @@ -10,10 +10,10 @@ namespace WikibaseSolutions\CypherDSL\Expressions\Literals; use WikibaseSolutions\CypherDSL\Patterns\Pattern; -use WikibaseSolutions\CypherDSL\Traits\CastTrait; use WikibaseSolutions\CypherDSL\Traits\TypeTraits\CompositeTypeTraits\ListTypeTrait; use WikibaseSolutions\CypherDSL\Types\AnyType; use WikibaseSolutions\CypherDSL\Types\CompositeTypes\ListType; +use WikibaseSolutions\CypherDSL\Utils\CastUtils; /** * This class represents a list of expressions. For example, this class can represent the following @@ -25,7 +25,6 @@ */ final class List_ implements ListType { - use CastTrait; use ListTypeTrait; /** @@ -34,25 +33,23 @@ final class List_ implements ListType private array $expressions; /** - * @param mixed[] $expressions The list of expressions + * @param array $expressions The list of expressions * * @internal This method is not covered by the backwards compatibility promise of php-cypher-dsl */ public function __construct(array $expressions = []) { - $this->expressions = array_map([self::class, 'toAnyType'], $expressions); + $this->expressions = array_map(CastUtils::toAnyType(...), $expressions); } /** * Add one or more expressions to the list. * - * @param AnyType|bool|float|int|mixed[]|Pattern|string ...$expressions - * * @return $this */ - public function addExpression(...$expressions): self + public function addExpression(AnyType|bool|float|int|array|Pattern|string ...$expressions): self { - $this->expressions = array_merge($this->expressions, array_map([self::class, 'toAnyType'], $expressions)); + $this->expressions = array_merge($this->expressions, array_map(CastUtils::toAnyType(...), $expressions)); return $this; } diff --git a/src/Expressions/Literals/Literal.php b/src/Expressions/Literals/Literal.php index bea5576d..94f87463 100644 --- a/src/Expressions/Literals/Literal.php +++ b/src/Expressions/Literals/Literal.php @@ -10,6 +10,7 @@ namespace WikibaseSolutions\CypherDSL\Expressions\Literals; use LogicException; +use Stringable; use Traversable; use TypeError; use WikibaseSolutions\CypherDSL\Expressions\Procedures\Date; @@ -19,30 +20,27 @@ use WikibaseSolutions\CypherDSL\Expressions\Procedures\Point; use WikibaseSolutions\CypherDSL\Expressions\Procedures\Procedure; use WikibaseSolutions\CypherDSL\Expressions\Procedures\Time; -use WikibaseSolutions\CypherDSL\Traits\ErrorTrait; +use WikibaseSolutions\CypherDSL\Patterns\Pattern; +use WikibaseSolutions\CypherDSL\Types\AnyType; use WikibaseSolutions\CypherDSL\Types\PropertyTypes\NumeralType; use WikibaseSolutions\CypherDSL\Types\PropertyTypes\StringType; /** * Helper class to construct literals. * - * @note This class should only contain static methods + * @note This class should only contain static methods. */ final class Literal { - use ErrorTrait; - /** * Creates a new literal from the given value. This function automatically constructs the appropriate * class based on the type of the value given. * - * @param mixed $literal The literal to construct + * @param array|bool|float|int|string|Stringable $literal The literal to construct * * @throws TypeError when the type could not be deduced - * - * @return Boolean|Float_|Integer|List_|Map|String_ */ - public static function literal($literal) + public static function literal(string|bool|int|float|array|Stringable $literal): Boolean|Float_|Integer|List_|Map|String_ { if (is_string($literal)) { return self::string($literal); @@ -53,7 +51,6 @@ public static function literal($literal) } if (is_int($literal)) { - // @phpstan-ignore-next-line return self::integer($literal); } @@ -65,40 +62,25 @@ public static function literal($literal) return array_is_list($literal) ? self::list($literal) : self::map($literal); } - if (is_object($literal) && method_exists($literal, '__toString')) { - return self::string($literal->__toString()); - } - - throw new TypeError("The literal type " . get_debug_type($literal) . " is not supported by Cypher"); + return self::string($literal->__toString()); } /** * Creates a new numeral literal. * - * @param float|int $value - * - * @return Float_|Integer - * * @see Literal::number() * @deprecated */ - public static function decimal($value) + public static function decimal(float|int $value): Float_|Integer { return self::number($value); } /** * Creates a new numeral literal. - * - * @param float|int $value - * - * @return Float_|Integer */ - public static function number($value) + public static function number(float|int $value): Float_|Integer { - self::assertClass('value', ['int', 'float'], $value); - - // @phpstan-ignore-next-line PHPStan does not work well with classes named "Integer" return is_int($value) ? self::integer($value) : self::float($value); } @@ -140,8 +122,6 @@ public static function float(float $value): Float_ /** * Creates a new list literal. - * - * @param mixed[] $value */ public static function list(iterable $value): List_ { @@ -154,8 +134,6 @@ public static function list(iterable $value): List_ /** * Creates a new map literal. - * - * @param mixed[] $value */ public static function map(array $value): Map { @@ -166,11 +144,9 @@ public static function map(array $value): Map * Retrieves the current Date value, optionally for a different time zone. In reality, this function just returns * a call to the "date()" function. * - * @param null|string|StringType $timezone - * * @see https://neo4j.com/docs/cypher-manual/current/functions/temporal/#functions-date-current Corresponding documentation on Neo4j.com */ - public static function date($timezone = null): Date + public static function date(StringType|string|null $timezone = null): Date { if ($timezone === null) { return Procedure::date(); @@ -182,13 +158,9 @@ public static function date($timezone = null): Date /** * Creates a date from the given year, month and day. * - * @param int|NumeralType $year - * @param null|int|NumeralType $month - * @param null|int|NumeralType $day - * * @see https://neo4j.com/docs/cypher-manual/current/functions/temporal/#functions-date-calendar Corresponding documentation on Neo4j.com */ - public static function dateYMD($year, $month = null, $day = null): Date + public static function dateYMD(NumeralType|int $year, NumeralType|int|null $month = null, NumeralType|int|null $day = null): Date { return Procedure::date( self::makeTemporalMap( @@ -204,13 +176,9 @@ public static function dateYMD($year, $month = null, $day = null): Date /** * Creates a date from the given year, week and weekday. * - * @param int|NumeralType $year - * @param null|int|NumeralType $week - * @param null|int|NumeralType $weekday - * * @see https://neo4j.com/docs/cypher-manual/current/functions/temporal/#functions-date-week Corresponding documentation on Neo4j.com */ - public static function dateYWD($year, $week = null, $weekday = null): Date + public static function dateYWD(NumeralType|int $year, NumeralType|int|null $week = null, NumeralType|int|null $weekday = null): Date { return Procedure::date( self::makeTemporalMap( @@ -226,11 +194,9 @@ public static function dateYWD($year, $week = null, $weekday = null): Date /** * Creates a date from the given string. * - * @param string|StringType $date - * * @see https://neo4j.com/docs/cypher-manual/current/functions/temporal/#functions-date-create-string Corresponding documentation on Neo4j.com */ - public static function dateString($date): Date + public static function dateString(StringType|string $date): Date { return Procedure::date($date); } @@ -239,11 +205,9 @@ public static function dateString($date): Date * Retrieves the current DateTime value, optionally for a different time zone. In reality, this * function just returns a call to the "datetime()" function. * - * @param string|StringType $timezone - * * @see https://neo4j.com/docs/cypher-manual/current/functions/temporal/#functions-datetime-current Corresponding documentation on Neo4j.com */ - public static function dateTime($timezone = null): DateTime + public static function dateTime(StringType|string|null $timezone = null): DateTime { if ($timezone === null) { return Procedure::datetime(); @@ -255,30 +219,19 @@ public static function dateTime($timezone = null): DateTime /** * Creates a date from the given year, month, day and time values. * - * @param int|NumeralType $year - * @param null|int|NumeralType $month - * @param null|int|NumeralType $day - * @param null|int|NumeralType $hour - * @param null|int|NumeralType $minute - * @param null|int|NumeralType $second - * @param null|int|NumeralType $millisecond - * @param null|int|NumeralType $microsecond - * @param null|int|NumeralType $nanosecond - * @param null|string|StringType $timezone - * * @see https://neo4j.com/docs/cypher-manual/current/functions/temporal/#functions-datetime-calendar Corresponding documentation on Neo4j.com */ public static function dateTimeYMD( - $year, - $month = null, - $day = null, - $hour = null, - $minute = null, - $second = null, - $millisecond = null, - $microsecond = null, - $nanosecond = null, - $timezone = null + NumeralType|int $year, + NumeralType|int|null $month = null, + NumeralType|int|null $day = null, + NumeralType|int|null $hour = null, + NumeralType|int|null $minute = null, + NumeralType|int|null $second = null, + NumeralType|int|null $millisecond = null, + NumeralType|int|null $microsecond = null, + NumeralType|int|null $nanosecond = null, + StringType|string|null $timezone = null ): DateTime { return Procedure::datetime( self::makeTemporalMap( @@ -301,30 +254,19 @@ public static function dateTimeYMD( /** * Creates a datetime with the specified year, week, dayOfWeek, hour, minute, second, millisecond, microsecond, nanosecond and timezone component values. * - * @param int|NumeralType $year - * @param null|int|NumeralType $week - * @param null|int|NumeralType $dayOfWeek - * @param null|int|NumeralType $hour - * @param null|int|NumeralType $minute - * @param null|int|NumeralType $second - * @param null|int|NumeralType $millisecond - * @param null|int|NumeralType $microsecond - * @param null|int|NumeralType $nanosecond - * @param null|string|StringType $timezone - * * @see https://neo4j.com/docs/cypher-manual/current/functions/temporal/#functions-datetime-week Corresponding documentation on Neo4j.com */ public static function dateTimeYWD( - $year, - $week = null, - $dayOfWeek = null, - $hour = null, - $minute = null, - $second = null, - $millisecond = null, - $microsecond = null, - $nanosecond = null, - $timezone = null + NumeralType|int $year, + NumeralType|int|null $week = null, + NumeralType|int|null $dayOfWeek = null, + NumeralType|int|null $hour = null, + NumeralType|int|null $minute = null, + NumeralType|int|null $second = null, + NumeralType|int|null $millisecond = null, + NumeralType|int|null $microsecond = null, + NumeralType|int|null $nanosecond = null, + StringType|string|null $timezone = null ): DateTime { return Procedure::datetime( self::makeTemporalMap( @@ -347,30 +289,19 @@ public static function dateTimeYWD( /** * Creates a datetime with the specified year, quarter, dayOfQuarter, hour, minute, second, millisecond, microsecond, nanosecond and timezone component values. * - * @param int|NumeralType $year - * @param null|int|NumeralType $quarter - * @param null|int|NumeralType $dayOfQuarter - * @param null|int|NumeralType $hour - * @param null|int|NumeralType $minute - * @param null|int|NumeralType $second - * @param null|int|NumeralType $millisecond - * @param null|int|NumeralType $microsecond - * @param null|int|NumeralType $nanosecond - * @param null|string|StringType $timezone - * * @see https://neo4j.com/docs/cypher-manual/current/functions/temporal/#functions-datetime-quarter Corresponding documentation on Neo4j.com */ public static function dateTimeYQD( - $year, - $quarter = null, - $dayOfQuarter = null, - $hour = null, - $minute = null, - $second = null, - $millisecond = null, - $microsecond = null, - $nanosecond = null, - $timezone = null + NumeralType|int $year, + NumeralType|int|null $quarter = null, + NumeralType|int|null $dayOfQuarter = null, + NumeralType|int|null $hour = null, + NumeralType|int|null $minute = null, + NumeralType|int|null $second = null, + NumeralType|int|null $millisecond = null, + NumeralType|int|null $microsecond = null, + NumeralType|int|null $nanosecond = null, + StringType|string|null $timezone = null ): DateTime { return Procedure::datetime( self::makeTemporalMap( @@ -393,28 +324,18 @@ public static function dateTimeYQD( /** * Creates a datetime with the specified year, ordinalDay, hour, minute, second, millisecond, microsecond, nanosecond and timezone component values. * - * @param int|NumeralType $year - * @param null|int|NumeralType $ordinalDay - * @param null|int|NumeralType $hour - * @param null|int|NumeralType $minute - * @param null|int|NumeralType $second - * @param null|int|NumeralType $millisecond - * @param null|int|NumeralType $microsecond - * @param null|int|NumeralType $nanosecond - * @param null|string|StringType $timezone - * * @see https://neo4j.com/docs/cypher-manual/current/functions/temporal/#functions-datetime-ordinal Corresponding documentation on Neo4j.com */ public static function dateTimeYD( - $year, - $ordinalDay = null, - $hour = null, - $minute = null, - $second = null, - $millisecond = null, - $microsecond = null, - $nanosecond = null, - $timezone = null + NumeralType|int $year, + NumeralType|int|null $ordinalDay = null, + NumeralType|int|null $hour = null, + NumeralType|int|null $minute = null, + NumeralType|int|null $second = null, + NumeralType|int|null $millisecond = null, + NumeralType|int|null $microsecond = null, + NumeralType|int|null $nanosecond = null, + StringType|string|null $timezone = null ): DateTime { return Procedure::datetime( self::makeTemporalMap( @@ -435,10 +356,8 @@ public static function dateTimeYD( /** * Creates a datetime by parsing a string representation of a temporal value. - * - * @param string|StringType $dateString */ - public static function dateTimeString($dateString): DateTime + public static function dateTimeString(StringType|string $dateString): DateTime { return Procedure::datetime($dateString); } @@ -446,11 +365,9 @@ public static function dateTimeString($dateString): DateTime /** * Creates the current localDateTime value. * - * @param null|string|StringType $timezone - * * @see https://neo4j.com/docs/cypher-manual/current/functions/temporal/#functions-localdatetime-current Corresponding documentation on Neo4j.com */ - public static function localDateTime($timezone = null): LocalDateTime + public static function localDateTime(StringType|string|null $timezone = null): LocalDateTime { if ($timezone === null) { return Procedure::localdatetime(); @@ -462,28 +379,18 @@ public static function localDateTime($timezone = null): LocalDateTime /** * Creates a LocalDateTime value with specified year, month, day and time props. * - * @param int|NumeralType $year - * @param null|int|NumeralType $month - * @param null|int|NumeralType $day - * @param null|int|NumeralType $hour - * @param null|int|NumeralType $minute - * @param null|int|NumeralType $second - * @param null|int|NumeralType $millisecond - * @param null|int|NumeralType $microsecond - * @param null|int|NumeralType $nanosecond - * * @see https://neo4j.com/docs/cypher-manual/current/functions/temporal/#functions-localdatetime-calendar Corresponding documentation on Neo4j.com */ public static function localDateTimeYMD( - $year, - $month = null, - $day = null, - $hour = null, - $minute = null, - $second = null, - $millisecond = null, - $microsecond = null, - $nanosecond = null + NumeralType|int $year, + NumeralType|int|null $month = null, + NumeralType|int|null $day = null, + NumeralType|int|null $hour = null, + NumeralType|int|null $minute = null, + NumeralType|int|null $second = null, + NumeralType|int|null $millisecond = null, + NumeralType|int|null $microsecond = null, + NumeralType|int|null $nanosecond = null ): LocalDateTime { return Procedure::localdatetime( self::makeTemporalMap( @@ -506,28 +413,18 @@ public static function localDateTimeYMD( * Creates a LocalDateTime value with the specified year, week, dayOfWeek, hour, minute, * second, millisecond, microsecond and nanosecond component value. * - * @param int|NumeralType $year - * @param null|int|NumeralType $week - * @param null|int|NumeralType $dayOfWeek - * @param null|int|NumeralType $hour - * @param null|int|NumeralType $minute - * @param null|int|NumeralType $second - * @param null|int|NumeralType $millisecond - * @param null|int|NumeralType $microsecond - * @param null|int|NumeralType $nanosecond - * * @see https://neo4j.com/docs/cypher-manual/current/functions/temporal/#functions-localdatetime-week Corresponding documentation on Neo4j.com */ public static function localDateTimeYWD( - $year, - $week = null, - $dayOfWeek = null, - $hour = null, - $minute = null, - $second = null, - $millisecond = null, - $microsecond = null, - $nanosecond = null + NumeralType|int $year, + NumeralType|int|null $week = null, + NumeralType|int|null $dayOfWeek = null, + NumeralType|int|null $hour = null, + NumeralType|int|null $minute = null, + NumeralType|int|null $second = null, + NumeralType|int|null $millisecond = null, + NumeralType|int|null $microsecond = null, + NumeralType|int|null $nanosecond = null ): LocalDateTime { return Procedure::localdatetime( self::makeTemporalMap( @@ -549,28 +446,18 @@ public static function localDateTimeYWD( /** * Creates a LocalDateTime value with the specified year, quarter, dayOfQuarter, hour, minute, second, millisecond, microsecond and nanosecond component values. * - * @param int|NumeralType $year - * @param null|int|NumeralType $quarter - * @param null|int|NumeralType $dayOfQuarter - * @param null|int|NumeralType $hour - * @param null|int|NumeralType $minute - * @param null|int|NumeralType $second - * @param null|int|NumeralType $millisecond - * @param null|int|NumeralType $microsecond - * @param null|int|NumeralType $nanosecond - * * @see https://neo4j.com/docs/cypher-manual/current/functions/temporal/#functions-localdatetime-quarter Corresponding documentation on Neo4j.com */ public static function localDateTimeYQD( - $year, - $quarter = null, - $dayOfQuarter = null, - $hour = null, - $minute = null, - $second = null, - $millisecond = null, - $microsecond = null, - $nanosecond = null + NumeralType|int $year, + NumeralType|int|null $quarter = null, + NumeralType|int|null $dayOfQuarter = null, + NumeralType|int|null $hour = null, + NumeralType|int|null $minute = null, + NumeralType|int|null $second = null, + NumeralType|int|null $millisecond = null, + NumeralType|int|null $microsecond = null, + NumeralType|int|null $nanosecond = null ): LocalDateTime { return Procedure::localdatetime( self::MakeTemporalMap( @@ -592,26 +479,17 @@ public static function localDateTimeYQD( /** * Creates a LocalDateTime value with the specified year, ordinalDay, hour, minute, second, millisecond, microsecond and nanosecond component values. * - * @param int|NumeralType $year - * @param null|int|NumeralType $ordinalDay - * @param null|int|NumeralType $hour - * @param null|int|NumeralType $minute - * @param null|int|NumeralType $second - * @param null|int|NumeralType $millisecond - * @param null|int|NumeralType $microsecond - * @param null|int|NumeralType $nanosecond - * * @see https://neo4j.com/docs/cypher-manual/current/functions/temporal/#functions-localdatetime-ordinal Corresponding documentation on Neo4j.com */ public static function localDateTimeYD( - $year, - $ordinalDay = null, - $hour = null, - $minute = null, - $second = null, - $millisecond = null, - $microsecond = null, - $nanosecond = null + NumeralType|int $year, + NumeralType|int|null $ordinalDay = null, + NumeralType|int|null $hour = null, + NumeralType|int|null $minute = null, + NumeralType|int|null $second = null, + NumeralType|int|null $millisecond = null, + NumeralType|int|null $microsecond = null, + NumeralType|int|null $nanosecond = null ): LocalDateTime { return Procedure::localdatetime( self::makeTemporalMap( @@ -632,11 +510,9 @@ public static function localDateTimeYD( /** * Creates the LocalDateTime value obtained by parsing a string representation of a temporal value. * - * @param string|StringType $localDateTimeString - * * @see https://neo4j.com/docs/cypher-manual/current/functions/temporal/#functions-localdatetime-create-string Corresponding documentation on Neo4j.com */ - public static function localDateTimeString($localDateTimeString): LocalDateTime + public static function localDateTimeString(StringType|string $localDateTimeString): LocalDateTime { return Procedure::localdatetime($localDateTimeString); } @@ -644,11 +520,9 @@ public static function localDateTimeString($localDateTimeString): LocalDateTime /** * Creates the current LocalTime value. * - * @param null|string|StringType $timezone - * * @see https://neo4j.com/docs/cypher-manual/current/functions/temporal/#functions-localtime-current Corresponding documentation on Neo4j.com */ - public static function localTimeCurrent($timezone = null): LocalTime + public static function localTimeCurrent(StringType|string|null $timezone = null): LocalTime { if ($timezone === null) { return Procedure::localtime(); @@ -660,22 +534,15 @@ public static function localTimeCurrent($timezone = null): LocalTime /** * Creates a LocalTime value with the specified hour, minute, second, millisecond, microsecond and nanosecond component values. * - * @param int|NumeralType $hour - * @param null|int|NumeralType $minute - * @param null|int|NumeralType $second - * @param null|int|NumeralType $millisecond - * @param null|int|NumeralType $microsecond - * @param null|int|NumeralType $nanosecond - * * @see https://neo4j.com/docs/cypher-manual/current/functions/temporal/#functions-localtime-create Corresponding documentation on Neo4j.com */ public static function localTime( - $hour, - $minute = null, - $second = null, - $millisecond = null, - $microsecond = null, - $nanosecond = null + NumeralType|int $hour, + NumeralType|int|null $minute = null, + NumeralType|int|null $second = null, + NumeralType|int|null $millisecond = null, + NumeralType|int|null $microsecond = null, + NumeralType|int|null $nanosecond = null ): LocalTime { return Procedure::localtime( self::makeTemporalMap( @@ -693,10 +560,8 @@ public static function localTime( /** * Creates the LocalTime value obtained by parsing a string representation of a temporal value. - * - * @param string|StringType $localTimeString */ - public static function localTimeString($localTimeString): LocalTime + public static function localTimeString(StringType|string $localTimeString): LocalTime { return Procedure::localtime($localTimeString); } @@ -704,11 +569,9 @@ public static function localTimeString($localTimeString): LocalTime /** * Creates the current Time value. * - * @param null|string|StringType $timezone - * * @see https://neo4j.com/docs/cypher-manual/current/functions/temporal/#functions-time-current Corresponding documentation on Neo4j.com */ - public static function time($timezone = null): Time + public static function time(StringType|string|null $timezone = null): Time { if ($timezone === null) { return Procedure::time(); @@ -720,24 +583,16 @@ public static function time($timezone = null): Time /** * Creates a Time value with the specified hour, minute, second, millisecond, microsecond, nanosecond and timezone component values. * - * @param int|NumeralType $hour - * @param null|int|NumeralType $minute - * @param null|int|NumeralType $second - * @param null|int|NumeralType $millisecond - * @param null|int|NumeralType $microsecond - * @param null|int|NumeralType $nanosecond - * @param null|string|StringType $timezone - * * @see https://neo4j.com/docs/cypher-manual/current/functions/temporal/#functions-time-create Corresponding documentation on Neo4j.com */ public static function timeHMS( - $hour, - $minute = null, - $second = null, - $millisecond = null, - $microsecond = null, - $nanosecond = null, - $timezone = null + NumeralType|int $hour, + NumeralType|int|null $minute = null, + NumeralType|int|null $second = null, + NumeralType|int|null $millisecond = null, + NumeralType|int|null $microsecond = null, + NumeralType|int|null $nanosecond = null, + StringType|string|null $timezone = null ): Time { return Procedure::time( self::makeTemporalMap( @@ -757,11 +612,9 @@ public static function timeHMS( /** * Creates the Time value obtained by parsing a string representation of a temporal value. * - * @param string|StringType $timeString - * * @see https://neo4j.com/docs/cypher-manual/current/functions/temporal/#functions-time-create-string Corresponding documentation on Neo4j.com */ - public static function timeString($timeString): Time + public static function timeString(StringType|string $timeString): Time { return Procedure::time($timeString); } @@ -769,12 +622,9 @@ public static function timeString($timeString): Time /** * Creates a 2d cartesian point. * - * @param float|int|NumeralType $x - * @param float|int|NumeralType $y - * * @see https://neo4j.com/docs/cypher-manual/current/functions/spatial/#functions-point-cartesian-2d Corresponding documentation on Neo4j.com */ - public static function point2d($x, $y): Point + public static function point2d(NumeralType|int|float $x, NumeralType|int|float $y): Point { return Procedure::point([ "x" => $x, @@ -786,13 +636,9 @@ public static function point2d($x, $y): Point /** * Creates a 3d cartesian point. * - * @param float|int|NumeralType $x - * @param float|int|NumeralType $y - * @param float|int|NumeralType $z - * * @see https://neo4j.com/docs/cypher-manual/current/functions/spatial/#functions-point-cartesian-3d Corresponding documentation on Neo4j.com */ - public static function point3d($x, $y, $z): Point + public static function point3d(NumeralType|int|float $x, NumeralType|int|float $y, NumeralType|int|float $z): Point { return Procedure::point([ "x" => $x, @@ -805,12 +651,9 @@ public static function point3d($x, $y, $z): Point /** * Creates a WGS 84 2D point. * - * @param float|int|NumeralType $longitude - * @param float|int|NumeralType $latitude - * * @see https://neo4j.com/docs/cypher-manual/current/functions/spatial/#functions-point-wgs84-2d Corresponding documentation on Neo4j.com */ - public static function point2dWGS84($longitude, $latitude): Point + public static function point2dWGS84(NumeralType|int|float $longitude, NumeralType|int|float $latitude): Point { return Procedure::point([ "longitude" => $longitude, @@ -822,13 +665,9 @@ public static function point2dWGS84($longitude, $latitude): Point /** * Creates a WGS 84 2D point. * - * @param float|int|NumeralType $longitude - * @param float|int|NumeralType $latitude - * @param float|int|NumeralType $height - * * @see https://neo4j.com/docs/cypher-manual/current/functions/spatial/#functions-point-wgs84-2d Corresponding documentation on Neo4j.com */ - public static function point3dWGS84($longitude, $latitude, $height): Point + public static function point3dWGS84(NumeralType|int|float $longitude, NumeralType|int|float $latitude, NumeralType|int|float $height): Point { return Procedure::point([ "longitude" => $longitude, @@ -848,9 +687,7 @@ private function __construct() /** * Prepares the variables to be used by temporal (i.e. time-like) CYPHER-functions. * - * @param mixed[] $variables - * - * @return mixed[] + * @return (AnyType|array|bool|float|int|Pattern|string)[] */ private static function makeTemporalMap(array $variables): array { diff --git a/src/Expressions/Literals/Map.php b/src/Expressions/Literals/Map.php index 4966ce94..6b1c0382 100644 --- a/src/Expressions/Literals/Map.php +++ b/src/Expressions/Literals/Map.php @@ -9,14 +9,16 @@ */ namespace WikibaseSolutions\CypherDSL\Expressions\Literals; -use WikibaseSolutions\CypherDSL\Traits\CastTrait; -use WikibaseSolutions\CypherDSL\Traits\EscapeTrait; +use Stringable; +use WikibaseSolutions\CypherDSL\Patterns\Pattern; use WikibaseSolutions\CypherDSL\Traits\TypeTraits\CompositeTypeTraits\MapTypeTrait; use WikibaseSolutions\CypherDSL\Types\AnyType; use WikibaseSolutions\CypherDSL\Types\CompositeTypes\MapType; +use WikibaseSolutions\CypherDSL\Utils\CastUtils; +use WikibaseSolutions\CypherDSL\Utils\NameUtils; /** - * This class represents a CYPHER map. For example, this class can represent the following + * This class represents a Cypher map. For example, this class can represent the following * construct:. * * {name: 'Andy', sport: 'Brazilian Ju-Jitsu'} @@ -26,8 +28,6 @@ */ final class Map implements MapType { - use CastTrait; - use EscapeTrait; use MapTypeTrait; /** @@ -36,26 +36,26 @@ final class Map implements MapType private array $elements; /** - * @param mixed[] $elements Associative array of the elements that this map should have + * @param array $elements Associative array of the elements that this map should have * * @internal This method is not covered by the backwards compatibility promise of php-cypher-dsl */ public function __construct(array $elements = []) { - $this->elements = array_map([self::class, 'toAnyType'], $elements); + $this->elements = array_map(CastUtils::toAnyType(...), $elements); } /** * Adds an element for the given name with the given value. Overrides the element if the $key already exists. * - * @param string $key The name/label for the element - * @param mixed $value The value of the element + * @param string $key The name/label for the element + * @param AnyType|array|bool|float|int|Pattern|string|Stringable $value The value of the element * * @return $this */ - public function add(string $key, $value): self + public function add(string $key, AnyType|Pattern|Stringable|bool|float|int|array|string $value): self { - $this->elements[$key] = self::toAnyType($value); + $this->elements[$key] = CastUtils::toAnyType($value); return $this; } @@ -100,7 +100,7 @@ public function toQuery(): string $pairs = []; foreach ($this->elements as $key => $value) { - $pairs[] = sprintf("%s: %s", self::escape((string) $key), $value->toQuery()); + $pairs[] = sprintf("%s: %s", NameUtils::escape((string) $key), $value->toQuery()); } return sprintf("{%s}", implode(", ", $pairs)); diff --git a/src/Expressions/Parameter.php b/src/Expressions/Parameter.php index cbeb4bf9..2ab2789b 100644 --- a/src/Expressions/Parameter.php +++ b/src/Expressions/Parameter.php @@ -9,9 +9,6 @@ */ namespace WikibaseSolutions\CypherDSL\Expressions; -use WikibaseSolutions\CypherDSL\Traits\ErrorTrait; -use WikibaseSolutions\CypherDSL\Traits\EscapeTrait; -use WikibaseSolutions\CypherDSL\Traits\NameGenerationTrait; use WikibaseSolutions\CypherDSL\Traits\TypeTraits\CompositeTypeTraits\ListTypeTrait; use WikibaseSolutions\CypherDSL\Traits\TypeTraits\CompositeTypeTraits\MapTypeTrait; use WikibaseSolutions\CypherDSL\Traits\TypeTraits\PropertyTypeTraits\BooleanTypeTrait; @@ -36,6 +33,7 @@ use WikibaseSolutions\CypherDSL\Types\PropertyTypes\PointType; use WikibaseSolutions\CypherDSL\Types\PropertyTypes\StringType; use WikibaseSolutions\CypherDSL\Types\PropertyTypes\TimeType; +use WikibaseSolutions\CypherDSL\Utils\NameUtils; /** * Represents a parameter. @@ -68,10 +66,6 @@ final class Parameter implements PointTypeTrait, StringTypeTrait, TimeTypeTrait; - - use ErrorTrait; - use EscapeTrait; - use NameGenerationTrait; private string $parameter; /** @@ -83,10 +77,10 @@ final class Parameter implements public function __construct(?string $parameter = null) { if (!isset($parameter)) { - $parameter = self::generateIdentifier('param'); + $parameter = NameUtils::generateIdentifier('param'); } - $this->parameter = self::escape($parameter); + $this->parameter = NameUtils::escape($parameter); } /** diff --git a/src/Expressions/Procedures/IsEmpty.php b/src/Expressions/Procedures/IsEmpty.php index 264492a3..7cf7505f 100644 --- a/src/Expressions/Procedures/IsEmpty.php +++ b/src/Expressions/Procedures/IsEmpty.php @@ -9,9 +9,7 @@ */ namespace WikibaseSolutions\CypherDSL\Expressions\Procedures; -use WikibaseSolutions\CypherDSL\Traits\ErrorTrait; use WikibaseSolutions\CypherDSL\Traits\TypeTraits\PropertyTypeTraits\BooleanTypeTrait; -use WikibaseSolutions\CypherDSL\Types\AnyType; use WikibaseSolutions\CypherDSL\Types\CompositeTypes\ListType; use WikibaseSolutions\CypherDSL\Types\CompositeTypes\MapType; use WikibaseSolutions\CypherDSL\Types\PropertyTypes\BooleanType; @@ -26,12 +24,11 @@ final class IsEmpty extends Procedure implements BooleanType { use BooleanTypeTrait; - use ErrorTrait; /** * @var ListType|MapType|StringType An expression that returns a list */ - private AnyType $list; + private ListType|MapType|StringType $list; /** * The signatures of the "isEmpty()" function are: @@ -43,10 +40,8 @@ final class IsEmpty extends Procedure implements BooleanType * * @internal This method is not covered by the backwards compatibility promise of php-cypher-dsl */ - public function __construct(AnyType $list) + public function __construct(ListType|MapType|StringType $list) { - self::assertClass('list', [ListType::class, MapType::class, StringType::class], $list); - $this->list = $list; } diff --git a/src/Expressions/Procedures/Procedure.php b/src/Expressions/Procedures/Procedure.php index c858e20e..8d12b4da 100644 --- a/src/Expressions/Procedures/Procedure.php +++ b/src/Expressions/Procedures/Procedure.php @@ -13,13 +13,11 @@ use WikibaseSolutions\CypherDSL\Expressions\Variable; use WikibaseSolutions\CypherDSL\Patterns\Pattern; use WikibaseSolutions\CypherDSL\QueryConvertible; -use WikibaseSolutions\CypherDSL\Traits\CastTrait; -use WikibaseSolutions\CypherDSL\Traits\ErrorTrait; use WikibaseSolutions\CypherDSL\Types\AnyType; -use WikibaseSolutions\CypherDSL\Types\CompositeTypes\CompositeType; use WikibaseSolutions\CypherDSL\Types\CompositeTypes\ListType; use WikibaseSolutions\CypherDSL\Types\CompositeTypes\MapType; use WikibaseSolutions\CypherDSL\Types\PropertyTypes\StringType; +use WikibaseSolutions\CypherDSL\Utils\CastUtils; /** * This class represents any procedure. @@ -28,63 +26,50 @@ */ abstract class Procedure implements QueryConvertible { - use CastTrait; - use ErrorTrait; - /** * Produces a raw function call. This enables the usage of unimplemented functions in your * Cypher queries. The parameters of this function are not type-checked. * * @param string $functionName The name of the function to call - * @param AnyType|AnyType[]|bool|bool[]|float|float[]|int|int[]|mixed[][]|Pattern|Pattern[]|string|string[]|(AnyType|bool|float|int|mixed[]|Pattern|string)[] $parameters The parameters to pass to the function call + * @param array $parameters The parameters to pass to the function call */ - public static function raw(string $functionName, $parameters = []): Raw + public static function raw(string $functionName, array $parameters = []): Raw { - if (!is_array($parameters)) { - $parameters = [$parameters]; - } - - $res = []; - - foreach ($parameters as $parameter) { - $res[] = self::toAnyType($parameter); - } - - return new Raw($functionName, $res); + return new Raw($functionName, array_map(CastUtils::toAnyType(...), $parameters)); } /** * Calls the "all()" function. The signature of the "all()" function is "all(variable :: VARIABLE IN list :: LIST OF ANY? WHERE predicate :: ANY?) :: (BOOLEAN?)". * - * @param string|Variable $variable A variable that can be used from within the predicate - * @param ListType|mixed[] $list A list - * @param AnyType|bool|float|int|mixed[]|Pattern|string $predicate A predicate that is tested against all items in the list + * @param string|Variable $variable A variable that can be used from within the predicate + * @param array|ListType $list A list + * @param AnyType|array|bool|float|int|Pattern|string $predicate A predicate that is tested against all items in the list */ - public static function all($variable, $list, $predicate): All + public static function all(Variable|string $variable, ListType|array $list, AnyType|bool|float|int|array|Pattern|string $predicate): All { - return new All(self::toName($variable), self::toListType($list), self::toAnyType($predicate)); + return new All(CastUtils::toName($variable), CastUtils::toListType($list), CastUtils::toAnyType($predicate)); } /** * Calls the "any()" function. The signature of the "any()" function is "any(variable :: VARIABLE IN list :: LIST OF ANY? WHERE predicate :: ANY?) :: (BOOLEAN?)". * - * @param string|Variable $variable A variable that can be used from within the predicate - * @param ListType|mixed[] $list A list - * @param AnyType|bool|float|int|mixed[]|Pattern|string $predicate A predicate that is tested against all items in the list + * @param string|Variable $variable A variable that can be used from within the predicate + * @param array|ListType $list A list + * @param AnyType|array|bool|float|int|Pattern|string $predicate A predicate that is tested against all items in the list */ - public static function any($variable, $list, $predicate): Any + public static function any(Variable|string $variable, ListType|array $list, AnyType|bool|float|int|array|Pattern|string $predicate): Any { - return new Any(self::toName($variable), self::toListType($list), self::toAnyType($predicate)); + return new Any(CastUtils::toName($variable), CastUtils::toListType($list), CastUtils::toAnyType($predicate)); } /** * Calls the "exists()" function. The signature of the "exists()" function is "exists(input :: ANY?) :: (BOOLEAN?)". * - * @param AnyType|bool|float|int|mixed[]|Pattern|string $expression A pattern or property + * @param AnyType|array|bool|float|int|Pattern|string $expression A pattern or property */ - public static function exists($expression): Exists + public static function exists(AnyType|bool|float|int|array|Pattern|string $expression): Exists { - return new Exists(self::toAnyType($expression)); + return new Exists(CastUtils::toAnyType($expression)); } /** @@ -93,12 +78,10 @@ public static function exists($expression): Exists * - isEmpty(input :: MAP?) :: (BOOLEAN?) - to check whether a map is empty * - isEmpty(input :: STRING?) :: (BOOLEAN?) - to check whether a string is empty. * - * @param ListType|MapType|StringType $list An expression that returns a list + * @param array|ListType|MapType|string|StringType $list An expression that returns a list */ - public static function isEmpty($list): IsEmpty + public static function isEmpty(ListType|MapType|StringType|string|array $list): IsEmpty { - self::assertClass('list', [CompositeType::class, StringType::class, 'string', 'array'], $list); - if (!$list instanceof AnyType) { $list = Literal::literal($list); } @@ -110,61 +93,61 @@ public static function isEmpty($list): IsEmpty /** * Calls the "none()" function. The signature of the "none()" function is "none(variable :: VARIABLE IN list :: LIST OF ANY? WHERE predicate :: ANY?) :: (BOOLEAN?)". * - * @param string|Variable $variable A variable that can be used from within the predicate - * @param ListType|mixed[] $list A list - * @param AnyType|bool|float|int|mixed[]|Pattern|string $predicate A predicate that is tested against all items in the list + * @param string|Variable $variable A variable that can be used from within the predicate + * @param array|ListType $list A list + * @param AnyType|array|bool|float|int|Pattern|string $predicate A predicate that is tested against all items in the list */ - public static function none($variable, $list, $predicate): None + public static function none(Variable|string $variable, ListType|array $list, AnyType|bool|float|int|array|Pattern|string $predicate): None { - return new None(self::toName($variable), self::toListType($list), self::toAnyType($predicate)); + return new None(CastUtils::toName($variable), CastUtils::toListType($list), CastUtils::toAnyType($predicate)); } /** * Calls the "single()" function. The signature of the "single()" function is "single(variable :: VARIABLE IN list :: LIST OF ANY? WHERE predicate :: ANY?) :: (BOOLEAN?)". * - * @param string|Variable $variable A variable that can be used from within the predicate - * @param ListType|mixed[] $list A list - * @param AnyType|bool|float|int|mixed[]|Pattern|string $predicate A predicate that is tested against all items in the list + * @param string|Variable $variable A variable that can be used from within the predicate + * @param array|ListType $list A list + * @param AnyType|array|bool|float|int|Pattern|string $predicate A predicate that is tested against all items in the list */ - public static function single($variable, $list, $predicate): Single + public static function single(Variable|string $variable, ListType|array $list, AnyType|bool|float|int|array|Pattern|string $predicate): Single { - return new Single(self::toName($variable), self::toListType($list), self::toAnyType($predicate)); + return new Single(CastUtils::toName($variable), CastUtils::toListType($list), CastUtils::toAnyType($predicate)); } /** * Calls the "point()" function. The signature of the "point()" function is "point(input :: MAP?) :: (POINT?)". * - * @param MapType|mixed[] $map The map to use for constructing the point + * @param array|MapType $map The map to use for constructing the point * * @see Literal::point2d() * @see Literal::point2dWGS84() * @see Literal::point3d() * @see Literal::point3dWGS84() */ - public static function point($map): Point + public static function point(MapType|array $map): Point { - return new Point(self::toMapType($map)); + return new Point(CastUtils::toMapType($map)); } /** * Calls the "date()" function. The signature of the "date()" function is "date(input = DEFAULT_TEMPORAL_ARGUMENT :: ANY?) :: (DATE?)". * - * @param null|AnyType|bool|float|int|mixed[]|Pattern|string $value The input to the date function, from which to construct the date + * @param null|AnyType|array|bool|float|int|Pattern|string $value The input to the date function, from which to construct the date * * @see Literal::date() * @see Literal::dateString() * @see Literal::dateYWD() * @see Literal::dateYMD() */ - public static function date($value = null): Date + public static function date(AnyType|bool|float|int|array|Pattern|string|null $value = null): Date { - return new Date($value === null ? $value : self::toAnyType($value)); + return new Date($value === null ? null : CastUtils::toAnyType($value)); } /** * Calls the "datetime()" function. The signature of the "datetime()" function is "datetime(input = DEFAULT_TEMPORAL_ARGUMENT :: ANY?) :: (DATETIME?)". * - * @param null|AnyType|bool|float|int|mixed[]|Pattern|string $value The input to the datetime function, from which to construct the datetime + * @param null|AnyType|array|bool|float|int|Pattern|string $value The input to the datetime function, from which to construct the datetime * * @see Literal::dateTime() * @see Literal::dateTimeString() @@ -173,15 +156,15 @@ public static function date($value = null): Date * @see Literal::dateTimeYMD() * @see Literal::dateTimeYQD() */ - public static function datetime($value = null): DateTime + public static function datetime(AnyType|bool|float|int|array|Pattern|string|null $value = null): DateTime { - return new DateTime($value === null ? $value : self::toAnyType($value)); + return new DateTime($value === null ? null : CastUtils::toAnyType($value)); } /** * Calls the "localdatetime()" function. The signature of the "localdatetime()" function is "datetime(input = DEFAULT_TEMPORAL_ARGUMENT :: ANY?) :: (LOCALDATETIME?)". * - * @param null|AnyType|bool|float|int|mixed[]|Pattern|string $value The input to the localdatetime function, from which to construct the localdatetime + * @param null|AnyType|array|bool|float|int|Pattern|string $value The input to the localdatetime function, from which to construct the localdatetime * * @see Literal::localDateTime() * @see Literal::localDateTimeString() @@ -190,37 +173,37 @@ public static function datetime($value = null): DateTime * @see Literal::localDateTimeYMD() * @see Literal::localDateTimeYQD() */ - public static function localdatetime($value = null): LocalDateTime + public static function localdatetime(AnyType|bool|float|int|array|Pattern|string|null $value = null): LocalDateTime { - return new LocalDateTime($value === null ? $value : self::toAnyType($value)); + return new LocalDateTime($value === null ? null : CastUtils::toAnyType($value)); } /** * Calls the "localtime()" function. The signature of the "localtime()" function is "localtime(input = DEFAULT_TEMPORAL_ARGUMENT :: ANY?) :: (LOCALTIME?)". * - * @param null|AnyType|bool|float|int|mixed[]|Pattern|string $value The input to the localtime function, from which to construct the localtime + * @param null|AnyType|array|bool|float|int|Pattern|string $value The input to the localtime function, from which to construct the localtime * * @see Literal::localTime() * @see Literal::localTimeCurrent() * @see Literal::localTimeString() */ - public static function localtime($value = null): LocalTime + public static function localtime(AnyType|bool|float|int|array|Pattern|string|null $value = null): LocalTime { - return new LocalTime($value === null ? $value : self::toAnyType($value)); + return new LocalTime($value === null ? null : CastUtils::toAnyType($value)); } /** * Calls the "time()" function. The signature of the "time()" function is "time(input = DEFAULT_TEMPORAL_ARGUMENT :: ANY?) :: (TIME?)". * - * @param null|AnyType|bool|float|int|mixed[]|Pattern|string $value The input to the localtime function, from which to construct the time + * @param null|AnyType|array|bool|float|int|Pattern|string $value The input to the localtime function, from which to construct the time * * @see Literal::time() * @see Literal::timeHMS() * @see Literal::timeString() */ - public static function time($value = null): Time + public static function time(AnyType|bool|float|int|array|Pattern|string|null $value = null): Time { - return new Time($value === null ? $value : self::toAnyType($value)); + return new Time($value === null ? null : CastUtils::toAnyType($value)); } /** diff --git a/src/Expressions/Procedures/Raw.php b/src/Expressions/Procedures/Raw.php index a04744c4..f3f9a859 100644 --- a/src/Expressions/Procedures/Raw.php +++ b/src/Expressions/Procedures/Raw.php @@ -9,8 +9,6 @@ */ namespace WikibaseSolutions\CypherDSL\Expressions\Procedures; -use WikibaseSolutions\CypherDSL\Traits\ErrorTrait; -use WikibaseSolutions\CypherDSL\Traits\EscapeTrait; use WikibaseSolutions\CypherDSL\Traits\TypeTraits\CompositeTypeTraits\ListTypeTrait; use WikibaseSolutions\CypherDSL\Traits\TypeTraits\CompositeTypeTraits\MapTypeTrait; use WikibaseSolutions\CypherDSL\Traits\TypeTraits\PropertyTypeTraits\BooleanTypeTrait; @@ -37,6 +35,7 @@ use WikibaseSolutions\CypherDSL\Types\PropertyTypes\PointType; use WikibaseSolutions\CypherDSL\Types\PropertyTypes\StringType; use WikibaseSolutions\CypherDSL\Types\PropertyTypes\TimeType; +use WikibaseSolutions\CypherDSL\Utils\NameUtils; /** * This class represents any function call. @@ -71,9 +70,6 @@ final class Raw extends Procedure implements StringTypeTrait, TimeTypeTrait; - use ErrorTrait; - use EscapeTrait; - /** * @var string The name of the function to call */ @@ -92,9 +88,7 @@ final class Raw extends Procedure implements */ public function __construct(string $functionName, array $parameters) { - self::assertClassArray('parameters', AnyType::class, $parameters); - - $this->functionName = self::escape($functionName); + $this->functionName = NameUtils::escape($functionName); $this->parameters = $parameters; } @@ -103,7 +97,7 @@ public function __construct(string $functionName, array $parameters) */ protected function getSignature(): string { - // A string of the form '%s, %s, %s' with count($this->parameters) occurences of '%s' + // A string of the form '%s, %s, %s' with count($this->parameters) occurrences of '%s' $percentSString = count($this->parameters) === 0 ? '' : diff --git a/src/Expressions/Property.php b/src/Expressions/Property.php index 32c50735..b97fdf82 100644 --- a/src/Expressions/Property.php +++ b/src/Expressions/Property.php @@ -10,8 +10,6 @@ namespace WikibaseSolutions\CypherDSL\Expressions; use WikibaseSolutions\CypherDSL\Syntax\PropertyReplacement; -use WikibaseSolutions\CypherDSL\Traits\CastTrait; -use WikibaseSolutions\CypherDSL\Traits\EscapeTrait; use WikibaseSolutions\CypherDSL\Traits\TypeTraits\CompositeTypeTraits\ListTypeTrait; use WikibaseSolutions\CypherDSL\Traits\TypeTraits\CompositeTypeTraits\MapTypeTrait; use WikibaseSolutions\CypherDSL\Traits\TypeTraits\PropertyTypeTraits\BooleanTypeTrait; @@ -24,7 +22,6 @@ use WikibaseSolutions\CypherDSL\Traits\TypeTraits\PropertyTypeTraits\PointTypeTrait; use WikibaseSolutions\CypherDSL\Traits\TypeTraits\PropertyTypeTraits\StringTypeTrait; use WikibaseSolutions\CypherDSL\Traits\TypeTraits\PropertyTypeTraits\TimeTypeTrait; -use WikibaseSolutions\CypherDSL\Types\AnyType; use WikibaseSolutions\CypherDSL\Types\CompositeTypes\ListType; use WikibaseSolutions\CypherDSL\Types\CompositeTypes\MapType; use WikibaseSolutions\CypherDSL\Types\PropertyTypes\BooleanType; @@ -40,6 +37,8 @@ use WikibaseSolutions\CypherDSL\Types\PropertyTypes\TimeType; use WikibaseSolutions\CypherDSL\Types\StructuralTypes\NodeType; use WikibaseSolutions\CypherDSL\Types\StructuralTypes\RelationshipType; +use WikibaseSolutions\CypherDSL\Utils\CastUtils; +use WikibaseSolutions\CypherDSL\Utils\NameUtils; /** * Represents a property. A property in Cypher would be something like "n.prop" or "n.a". @@ -61,7 +60,6 @@ final class Property implements use BooleanTypeTrait, DateTimeTypeTrait, DateTypeTrait, - EscapeTrait, FloatTypeTrait, IntegerTypeTrait, ListTypeTrait, @@ -72,12 +70,10 @@ final class Property implements StringTypeTrait, TimeTypeTrait; - use CastTrait; - /** * @var MapType|NodeType|RelationshipType The expression to which this property belongs */ - private AnyType $expression; + private MapType|NodeType|RelationshipType $expression; /** * @var string The name of the property @@ -92,10 +88,8 @@ final class Property implements * * @internal This function is not covered by the backwards compatibility guarantee of php-cypher-dsl */ - public function __construct($expression, string $property) + public function __construct(MapType|NodeType|RelationshipType $expression, string $property) { - self::assertClass('expression', [MapType::class, NodeType::class, RelationshipType::class], $expression); - $this->expression = $expression; $this->property = $property; } @@ -113,9 +107,9 @@ public function __construct($expression, string $property) * * TODO: Allow this function to take arrays of property types */ - public function replaceWith($value): PropertyReplacement + public function replaceWith(PropertyType|string|bool|float|int $value): PropertyReplacement { - return new PropertyReplacement($this, self::toPropertyType($value)); + return new PropertyReplacement($this, CastUtils::toPropertyType($value)); } /** @@ -128,10 +122,8 @@ public function getProperty(): string /** * Returns the expression to which the property belongs. - * - * @return MapType|NodeType|RelationshipType */ - public function getExpression(): AnyType + public function getExpression(): MapType|NodeType|RelationshipType { return $this->expression; } @@ -141,6 +133,6 @@ public function getExpression(): AnyType */ public function toQuery(): string { - return sprintf("%s.%s", $this->expression->toQuery(), self::escape($this->property)); + return sprintf("%s.%s", $this->expression->toQuery(), NameUtils::escape($this->property)); } } diff --git a/src/Expressions/Variable.php b/src/Expressions/Variable.php index 28bc200f..4eaac110 100644 --- a/src/Expressions/Variable.php +++ b/src/Expressions/Variable.php @@ -11,9 +11,6 @@ use WikibaseSolutions\CypherDSL\Expressions\Literals\Map; use WikibaseSolutions\CypherDSL\Syntax\PropertyReplacement; -use WikibaseSolutions\CypherDSL\Traits\ErrorTrait; -use WikibaseSolutions\CypherDSL\Traits\EscapeTrait; -use WikibaseSolutions\CypherDSL\Traits\NameGenerationTrait; use WikibaseSolutions\CypherDSL\Traits\TypeTraits\CompositeTypeTraits\ListTypeTrait; use WikibaseSolutions\CypherDSL\Traits\TypeTraits\CompositeTypeTraits\MapTypeTrait; use WikibaseSolutions\CypherDSL\Traits\TypeTraits\PropertyTypeTraits\BooleanTypeTrait; @@ -45,6 +42,8 @@ use WikibaseSolutions\CypherDSL\Types\StructuralTypes\NodeType; use WikibaseSolutions\CypherDSL\Types\StructuralTypes\PathType; use WikibaseSolutions\CypherDSL\Types\StructuralTypes\RelationshipType; +use WikibaseSolutions\CypherDSL\Utils\CastUtils; +use WikibaseSolutions\CypherDSL\Utils\NameUtils; /** * Represents a variable. @@ -85,10 +84,6 @@ final class Variable implements StringTypeTrait, TimeTypeTrait; - use ErrorTrait; - use EscapeTrait; - use NameGenerationTrait; - /** * @var string The name of this variable */ @@ -102,10 +97,10 @@ final class Variable implements public function __construct(?string $name = null) { if ($name === null) { - $name = self::generateIdentifier(); + $name = NameUtils::generateIdentifier(); } - $this->name = self::escape($name); + $this->name = NameUtils::escape($name); } /** @@ -121,11 +116,11 @@ public function labeled(string ...$labels): Label /** * Assign a value to this property. * - * @param Map|mixed[] $value The value to assign + * @param array|Map $value The value to assign */ - public function assign($value): PropertyReplacement + public function assign(MapType|array $value): PropertyReplacement { - return new PropertyReplacement($this, self::toMapType($value)); + return new PropertyReplacement($this, CastUtils::toMapType($value)); } /** diff --git a/src/Patterns/Direction.php b/src/Patterns/Direction.php new file mode 100644 index 00000000..6b7bf958 --- /dev/null +++ b/src/Patterns/Direction.php @@ -0,0 +1,33 @@ +(b). + */ + case RIGHT; + + /* + * For the relation (a)<--(b). + */ + case LEFT; + + /* + * For the relation (a)--(b). + */ + case UNI; +} diff --git a/src/Patterns/Node.php b/src/Patterns/Node.php index 6ab73df5..cb8538d7 100644 --- a/src/Patterns/Node.php +++ b/src/Patterns/Node.php @@ -11,9 +11,8 @@ use WikibaseSolutions\CypherDSL\Expressions\Label; use WikibaseSolutions\CypherDSL\Expressions\Literals\Map; -use WikibaseSolutions\CypherDSL\Traits\ErrorTrait; -use WikibaseSolutions\CypherDSL\Traits\EscapeTrait; use WikibaseSolutions\CypherDSL\Traits\PatternTraits\PropertyPatternTrait; +use WikibaseSolutions\CypherDSL\Utils\NameUtils; /** * This class represents a node. @@ -22,9 +21,6 @@ */ final class Node implements CompletePattern, PropertyPattern, RelatablePattern { - use ErrorTrait; - use EscapeTrait; - use PropertyPatternTrait; /** @@ -61,8 +57,6 @@ public function withLabels(array $labels): self /** * Adds one or more labels to this node. * - * @param string ...$label - * * @return $this */ public function addLabel(string ...$label): self @@ -146,7 +140,7 @@ private function nodeInnerToString(): string if ($this->labels !== []) { foreach ($this->labels as $label) { - $nodeInner .= ":" . self::escape($label); + $nodeInner .= ":" . NameUtils::escape($label); } } diff --git a/src/Patterns/Path.php b/src/Patterns/Path.php index ca838e30..36c1714a 100644 --- a/src/Patterns/Path.php +++ b/src/Patterns/Path.php @@ -10,7 +10,6 @@ namespace WikibaseSolutions\CypherDSL\Patterns; use WikibaseSolutions\CypherDSL\Expressions\Variable; -use WikibaseSolutions\CypherDSL\Traits\ErrorTrait; use WikibaseSolutions\CypherDSL\Traits\PatternTraits\PatternTrait; use WikibaseSolutions\CypherDSL\Traits\TypeTraits\PropertyTypeTraits\BooleanTypeTrait; use WikibaseSolutions\CypherDSL\Types\CompositeTypes\MapType; @@ -24,8 +23,6 @@ final class Path implements BooleanType, CompletePattern, RelatablePattern { use BooleanTypeTrait; - use ErrorTrait; - use PatternTrait; /** @@ -44,14 +41,11 @@ final class Path implements BooleanType, CompletePattern, RelatablePattern * * @internal This method is not covered by the backwards compatibility guarantee of php-cypher-dsl */ - public function __construct($nodes = [], $relationships = []) + public function __construct(Node|array $nodes = [], Relationship|array $relationships = []) { $nodes = is_array($nodes) ? $nodes : [$nodes]; $relationships = is_array($relationships) ? $relationships : [$relationships]; - self::assertClassArray('nodes', Node::class, $nodes); - self::assertClassArray('relationships', Relationship::class, $relationships); - $this->nodes = $nodes; $this->relationships = $relationships; } @@ -100,10 +94,10 @@ public function relationship(Relationship $relationship, Pattern $pattern): self /** * @inheritDoc */ - public function relationshipTo(Pattern $pattern, ?string $type = null, $properties = null, $name = null): self + public function relationshipTo(Pattern $pattern, ?string $type = null, MapType|array|null $properties = null, Variable|string|null $name = null): self { return $this->relationship( - self::buildRelationship(Relationship::DIR_RIGHT, $type, $properties, $name), + self::buildRelationship(Direction::RIGHT, $type, $properties, $name), $pattern ); } @@ -111,10 +105,10 @@ public function relationshipTo(Pattern $pattern, ?string $type = null, $properti /** * @inheritDoc */ - public function relationshipFrom(Pattern $pattern, ?string $type = null, $properties = null, $name = null): self + public function relationshipFrom(Pattern $pattern, ?string $type = null, MapType|array|null $properties = null, Variable|string|null $name = null): self { return $this->relationship( - self::buildRelationship(Relationship::DIR_LEFT, $type, $properties, $name), + self::buildRelationship(Direction::LEFT, $type, $properties, $name), $pattern ); } @@ -122,10 +116,10 @@ public function relationshipFrom(Pattern $pattern, ?string $type = null, $proper /** * @inheritDoc */ - public function relationshipUni(Pattern $pattern, ?string $type = null, $properties = null, $name = null): self + public function relationshipUni(Pattern $pattern, ?string $type = null, MapType|array|null $properties = null, Variable|string|null $name = null): self { return $this->relationship( - self::buildRelationship(Relationship::DIR_UNI, $type, $properties, $name), + self::buildRelationship(Direction::UNI, $type, $properties, $name), $pattern ); } @@ -179,12 +173,12 @@ public function toQuery(): string /** * Construct a new relationship from the given parameters. * - * @param string[] $direction The direction of the relationship (should be a Relationship::DIR_* constant) + * @param Direction $direction The direction of the relationship * @param null|string $type The type of the relationship - * @param null|MapType|mixed[] $properties The properties to add to the relationship + * @param null|array|MapType $properties The properties to add to the relationship * @param null|string|Variable $name The name of the variable to which to assign this relationship */ - private static function buildRelationship(array $direction, ?string $type = null, $properties = null, $name = null): Relationship + private static function buildRelationship(Direction $direction, ?string $type = null, MapType|array|null $properties = null, Variable|string|null $name = null): Relationship { $relationship = new Relationship($direction); diff --git a/src/Patterns/Pattern.php b/src/Patterns/Pattern.php index a3daba2e..0fe27291 100644 --- a/src/Patterns/Pattern.php +++ b/src/Patterns/Pattern.php @@ -43,11 +43,9 @@ public function hasVariableSet(): bool; /** * Explicitly assign a named variable to this pattern. * - * @param null|string|Variable $variable - * * @return $this */ - public function withVariable($variable): self; + public function withVariable(Variable|string|null $variable): self; /** * Returns the variable of this pattern. This function generates a variable if none has been set. It will implicitly set the variable of the pattern as well. diff --git a/src/Patterns/PropertyPattern.php b/src/Patterns/PropertyPattern.php index 59e1e278..55fbf6be 100644 --- a/src/Patterns/PropertyPattern.php +++ b/src/Patterns/PropertyPattern.php @@ -9,9 +9,11 @@ */ namespace WikibaseSolutions\CypherDSL\Patterns; +use Stringable; use WikibaseSolutions\CypherDSL\Expressions\Literals\Map; use WikibaseSolutions\CypherDSL\Expressions\Property; use WikibaseSolutions\CypherDSL\Traits\PatternTraits\PropertyPatternTrait; +use WikibaseSolutions\CypherDSL\Types\AnyType; use WikibaseSolutions\CypherDSL\Types\CompositeTypes\MapType; /** @@ -32,33 +34,27 @@ public function property(string $property): Property; /** * Set the properties of this pattern. * - * @param MapType|mixed[] $properties - * * @return $this */ - public function withProperties($properties): self; + public function withProperties(MapType|array $properties): self; /** * Add a property to the properties in this pattern. This is only possible if the properties in this pattern are * a map. An exception will be thrown if they are anything else (such as a variable). If the pattern does not yet * contain any properties, a new map will be created. * - * @param mixed $property - * * @return $this */ - public function addProperty(string $key, $property): self; + public function addProperty(string $key, AnyType|Pattern|Stringable|bool|float|int|array|string $property): self; /** * Add the given properties to this pattern. This is only possible if the properties in this pattern are a map. - * An exception will be thrown if they are anything else (such as a variable). If the pattern does not yet contain + * An exception will be thrown if they are anything else (such as a variable). If the pattern does not yet contain * any properties, a new map will be created. * - * @param Map|mixed[] $properties - * * @return $this */ - public function addProperties($properties): self; + public function addProperties(Map|array $properties): self; /** * Returns the properties of this object. diff --git a/src/Patterns/RelatablePattern.php b/src/Patterns/RelatablePattern.php index 3247319d..b61ec3ae 100644 --- a/src/Patterns/RelatablePattern.php +++ b/src/Patterns/RelatablePattern.php @@ -35,10 +35,10 @@ public function relationship(Relationship $relationship, self $pattern): Path; * * @param RelatablePattern $pattern The pattern to attach to the end of this pattern * @param null|string $type The type of the relationship - * @param null|MapType|mixed[] $properties The properties to attach to the relationship + * @param null|array|MapType $properties The properties to attach to the relationship * @param null|string|Variable $name The name fo the relationship */ - public function relationshipTo(self $pattern, ?string $type = null, $properties = null, $name = null): Path; + public function relationshipTo(self $pattern, ?string $type = null, MapType|array|null $properties = null, Variable|string|null $name = null): Path; /** * Forms a new path by adding the given relatable pattern to the end of this pattern using a left (<--) @@ -46,10 +46,10 @@ public function relationshipTo(self $pattern, ?string $type = null, $properties * * @param RelatablePattern $pattern The pattern to attach to the end of this pattern * @param null|string $type The type of the relationship - * @param null|MapType|mixed[] $properties The properties to attach to the relationship + * @param null|array|MapType $properties The properties to attach to the relationship * @param null|string|Variable $name The name fo the relationship */ - public function relationshipFrom(self $pattern, ?string $type = null, $properties = null, $name = null): Path; + public function relationshipFrom(self $pattern, ?string $type = null, MapType|array|null $properties = null, Variable|string|null $name = null): Path; /** * Forms a new path by adding the given relatable pattern to the end of this pattern using a unidirectional @@ -57,8 +57,8 @@ public function relationshipFrom(self $pattern, ?string $type = null, $propertie * * @param RelatablePattern $pattern The pattern to attach to the end of this pattern * @param null|string $type The type of the relationship - * @param null|MapType|mixed[] $properties The properties to attach to the relationship + * @param null|array|MapType $properties The properties to attach to the relationship * @param null|string|Variable $name The name fo the relationship */ - public function relationshipUni(self $pattern, ?string $type = null, $properties = null, $name = null): Path; + public function relationshipUni(self $pattern, ?string $type = null, MapType|array|null $properties = null, Variable|string|null $name = null): Path; } diff --git a/src/Patterns/Relationship.php b/src/Patterns/Relationship.php index 2d0ee726..13a49be5 100644 --- a/src/Patterns/Relationship.php +++ b/src/Patterns/Relationship.php @@ -10,11 +10,10 @@ namespace WikibaseSolutions\CypherDSL\Patterns; use DomainException; -use InvalidArgumentException; use LogicException; use WikibaseSolutions\CypherDSL\Expressions\Literals\Map; -use WikibaseSolutions\CypherDSL\Traits\EscapeTrait; use WikibaseSolutions\CypherDSL\Traits\PatternTraits\PropertyPatternTrait; +use WikibaseSolutions\CypherDSL\Utils\NameUtils; /** * This class represents an arbitrary relationship. @@ -23,20 +22,12 @@ */ final class Relationship implements PropertyPattern { - use EscapeTrait; - use PropertyPatternTrait; - public const DIR_RIGHT = ["-", "->"]; - - public const DIR_LEFT = ["<-", "-"]; - - public const DIR_UNI = ["-", "-"]; - /** - * @var string[] The direction of the relationship (one of the DIR_* constants) + * @var Direction The direction of the relationship */ - private array $direction; + private Direction $direction; /** * @var string[] A list of relationship condition types @@ -64,19 +55,12 @@ final class Relationship implements PropertyPattern private bool $arbitraryHops = false; /** - * @param string[] $direction The direction of the relationship, should be either: - * - Relationship::DIR_RIGHT (for a relation of (a)-->(b)) - * - Relationship::DIR_LEFT (for a relation of (a)<--(b)) - * - Relationship::DIR_UNI (for a relation of (a)--(b)) + * @param Direction $direction The direction of the relationship * * @internal This method is not covered by the backwards compatibility guarantee of php-cypher-dsl */ - public function __construct(array $direction) + public function __construct(Direction $direction) { - if ($direction !== self::DIR_RIGHT && $direction !== self::DIR_LEFT && $direction !== self::DIR_UNI) { - throw new InvalidArgumentException("The direction must be either 'DIR_LEFT', 'DIR_RIGHT' or 'RELATED_TO'"); - } - $this->direction = $direction; } @@ -187,8 +171,6 @@ public function withTypes(array $types): self /** * Add one or more types to require for this relationship. * - * @param string ...$type - * * @return $this */ public function addType(string ...$type): self @@ -200,10 +182,8 @@ public function addType(string ...$type): self /** * Returns the direction of this relationship (one of the Relationship::DIR_* constants). - * - * @return string[] */ - public function getDirection(): array + public function getDirection(): Direction { return $this->direction; } @@ -248,7 +228,13 @@ public function getTypes(): array */ public function toQuery(): string { - return $this->direction[0] . $this->relationshipDetailToString() . $this->direction[1]; + $directionParts = match ($this->direction) { + Direction::UNI => ['-', '-'], + Direction::LEFT => ['<-', '-'], + Direction::RIGHT => ['-', '->'], + }; + + return $directionParts[0] . $this->relationshipDetailToString() . $directionParts[1]; } /** @@ -266,7 +252,7 @@ private function relationshipDetailToString(): string if (count($types) !== 0) { // If we have at least one condition type, escape them and insert them into the query - $escapedTypes = array_map(static fn (string $type): string => self::escape($type), $types); + $escapedTypes = array_map(static fn (string $type): string => NameUtils::escape($type), $types); $conditionInner .= sprintf(":%s", implode("|", $escapedTypes)); } diff --git a/src/Query.php b/src/Query.php index 6e43318b..309bed2e 100644 --- a/src/Query.php +++ b/src/Query.php @@ -9,7 +9,7 @@ */ namespace WikibaseSolutions\CypherDSL; -use Closure; +use Stringable; use WikibaseSolutions\CypherDSL\Clauses\CallClause; use WikibaseSolutions\CypherDSL\Clauses\CallProcedureClause; use WikibaseSolutions\CypherDSL\Clauses\Clause; @@ -43,26 +43,23 @@ use WikibaseSolutions\CypherDSL\Expressions\RawExpression; use WikibaseSolutions\CypherDSL\Expressions\Variable; use WikibaseSolutions\CypherDSL\Patterns\CompletePattern; +use WikibaseSolutions\CypherDSL\Patterns\Direction; use WikibaseSolutions\CypherDSL\Patterns\Node; use WikibaseSolutions\CypherDSL\Patterns\Pattern; use WikibaseSolutions\CypherDSL\Patterns\Relationship; use WikibaseSolutions\CypherDSL\Syntax\Alias; use WikibaseSolutions\CypherDSL\Syntax\PropertyReplacement; -use WikibaseSolutions\CypherDSL\Traits\CastTrait; -use WikibaseSolutions\CypherDSL\Traits\ErrorTrait; use WikibaseSolutions\CypherDSL\Types\AnyType; use WikibaseSolutions\CypherDSL\Types\PropertyTypes\BooleanType; use WikibaseSolutions\CypherDSL\Types\PropertyTypes\IntegerType; use WikibaseSolutions\CypherDSL\Types\StructuralTypes\StructuralType; +use WikibaseSolutions\CypherDSL\Utils\CastUtils; /** * Builder class for building complex Cypher queries. */ final class Query implements QueryConvertible { - use CastTrait; - use ErrorTrait; - // A reference to the Literal class public const literal = Literal::class; @@ -80,8 +77,6 @@ final class Query implements QueryConvertible /** * Construct a new Query instance. - * - * @return Query */ public static function new(): self { @@ -103,14 +98,11 @@ public static function node(?string $label = null): Node /** * Creates a relationship. * - * @param string[] $direction The direction of the relationship (optional, default: unidirectional), should be either: - * - Relationship::DIR_RIGHT (for a relation of (a)-->(b)) - * - Relationship::DIR_LEFT (for a relation of (a)<--(b)) - * - Relationship::DIR_UNI (for a relation of (a)--(b)) + * @param Direction $direction The direction of the relationship (optional, default: unidirectional) * * @see https://neo4j.com/docs/cypher-manual/current/syntax/patterns/#cypher-pattern-relationship Corresponding documentation on Neo4j.com */ - public static function relationship(array $direction = Relationship::DIR_UNI): Relationship + public static function relationship(Direction $direction = Direction::UNI): Relationship { return new Relationship($direction); } @@ -122,7 +114,7 @@ public static function relationship(array $direction = Relationship::DIR_UNI): R */ public static function relationshipUni(): Relationship { - return new Relationship(Relationship::DIR_UNI); + return new Relationship(Direction::UNI); } /** @@ -132,7 +124,7 @@ public static function relationshipUni(): Relationship */ public static function relationshipTo(): Relationship { - return new Relationship(Relationship::DIR_RIGHT); + return new Relationship(Direction::RIGHT); } /** @@ -142,7 +134,7 @@ public static function relationshipTo(): Relationship */ public static function relationshipFrom(): Relationship { - return new Relationship(Relationship::DIR_LEFT); + return new Relationship(Direction::LEFT); } /** @@ -205,11 +197,12 @@ public static function variable(?string $variable = null): Variable * - Query::list() - For a list * - Query::map() - For a map * - * @param null|bool|float|int|mixed[]|string $literal The literal to construct + * @param null|array|bool|float|int|string|Stringable $literal The literal to construct * * @return Boolean|class-string|Float_|Integer|List_|Map|String_ */ - public static function literal($literal = null) + // @phpstan-ignore-next-line + public static function literal(null|bool|float|int|array|string|Stringable $literal = null): Boolean|Float_|Integer|List_|Map|String_|string { if ($literal === null) { return self::literal; @@ -320,11 +313,8 @@ public static function rawExpression(string $expression): RawExpression /** * Creates an EXISTS expression. - * - * @param CompletePattern|CompletePattern[]|MatchClause $match - * @param null|BooleanType|WhereClause $where */ - public static function exists($match, $where = null, bool $insertParentheses = false): Exists + public static function exists(CompletePattern|MatchClause|array $match, WhereClause|BooleanType|bool|null $where = null, bool $insertParentheses = false): Exists { if (!$match instanceof MatchClause) { $match = is_array($match) ? $match : [$match]; @@ -362,16 +352,18 @@ public function __toString(): string * * @note This feature is not part of the openCypher standard. * - * @param callable|Query $query A callable decorating a Query, or an instance of Query - * @param Pattern|Pattern[]|string|string[]|Variable|Variable[]|(Pattern|string|Variable)[] $variables The variables to include in the WITH clause for correlation (optional) + * @param callable|Query $query A callable decorating a Query, or an instance of Query + * @param Pattern|(Pattern|string|Variable)[]|string|Variable $variables The variables to include in the WITH clause for correlation (optional) * * @return $this * * @see https://neo4j.com/docs/cypher-manual/current/clauses/call-subquery/ Corresponding documentation on Neo4j.com */ - public function call($query, $variables = []): self + public function call(self|callable $query, Pattern|Variable|string|array $variables = []): self { - $this->assertClass('query', [self::class, Closure::class, 'callable'], $query); + if (!is_array($variables)) { + $variables = [$variables]; + } if (is_callable($query)) { $subQuery = self::new(); @@ -380,10 +372,6 @@ public function call($query, $variables = []): self $subQuery = $query; } - if (!is_array($variables)) { - $variables = [$variables]; - } - $callClause = new CallClause(); $callClause->withSubQuery($subQuery); $callClause->addWithVariable(...$variables); @@ -397,13 +385,13 @@ public function call($query, $variables = []): self * Creates the CALL procedure clause. * * @param Procedure|string $procedure The procedure to call - * @param AnyType|AnyType[]|bool|bool[]|float|float[]|int|int[]|mixed[]|mixed[][]|Pattern|Pattern[]|string|string[]|(AnyType|bool|float|int|mixed[]|Pattern|string)[] $yields The result fields that should be returned (optional) + * @param mixed $yields The result fields that should be returned (optional) * * @return $this * * @see https://neo4j.com/docs/cypher-manual/current/clauses/call/ Corresponding documentation on Neo4j.com */ - public function callProcedure($procedure, $yields = []): self + public function callProcedure(Procedure|string $procedure, mixed $yields = []): self { if (is_string($procedure)) { $procedure = Procedure::raw($procedure); @@ -413,7 +401,7 @@ public function callProcedure($procedure, $yields = []): self $yields = [$yields]; } - $yields = $this->makeAliasArray($yields, fn ($value) => $this->toName($value)); + $yields = $this->makeAliasArray($yields, static fn ($value) => CastUtils::toName($value)); $callProcedureClause = new CallProcedureClause(); $callProcedureClause->setProcedure($procedure); @@ -433,7 +421,7 @@ public function callProcedure($procedure, $yields = []): self * * @see https://neo4j.com/docs/cypher-manual/current/clauses/match/ Corresponding documentation on Neo4j.com */ - public function match($patterns): self + public function match(CompletePattern|array $patterns): self { if (!is_array($patterns)) { $patterns = [$patterns]; @@ -450,20 +438,20 @@ public function match($patterns): self /** * Creates the RETURN clause. * - * @param Alias|Alias[]|AnyType|AnyType[]|bool|bool[]|float|float[]|int|int[]|Pattern|Pattern[]|string|string[]|(Alias|AnyType|mixed[]|bool|float|int|Pattern|string)[] $expressions A single expression to return, or a non-empty list of expressions to return - * @param bool $distinct Whether to be a RETURN DISTINCT clause (optional, default: false) + * @param mixed $expressions A single expression to return, or a non-empty list of expressions to return + * @param bool $distinct Whether to be a RETURN DISTINCT clause (optional, default: false) * * @return $this * * @see https://neo4j.com/docs/cypher-manual/current/clauses/return/ Corresponding documentation on Neo4j.com */ - public function returning($expressions, bool $distinct = false): self + public function returning(mixed $expressions, bool $distinct = false): self { if (!is_array($expressions)) { $expressions = [$expressions]; } - $expressions = $this->makeAliasArray($expressions, fn ($value) => $this->toAnyType($value)); + $expressions = $this->makeAliasArray($expressions, static fn ($value) => CastUtils::toAnyType($value)); $returnClause = new ReturnClause(); $returnClause->addColumn(...$expressions); @@ -483,7 +471,7 @@ public function returning($expressions, bool $distinct = false): self * * @see https://neo4j.com/docs/cypher-manual/current/clauses/create/ Corresponding documentation on Neo4j.com */ - public function create($patterns): self + public function create(CompletePattern|array $patterns): self { if (!is_array($patterns)) { $patterns = [$patterns]; @@ -500,14 +488,14 @@ public function create($patterns): self /** * Creates the DELETE clause. * - * @param Pattern|Pattern[]|StructuralType|StructuralType[]|(Pattern|StructuralType)[] $structures A single structure to delete, or a non-empty list of structures to delete - * @param bool $detach Whether to DETACH DELETE (optional, default: false) + * @param Pattern|(Pattern|StructuralType)[]|StructuralType $structures A single structure to delete, or a non-empty list of structures to delete + * @param bool $detach Whether to DETACH DELETE (optional, default: false) * * @return $this * * @see https://neo4j.com/docs/cypher-manual/current/clauses/delete/ Corresponding documentation on Neo4j.com */ - public function delete($structures, bool $detach = false): self + public function delete(Pattern|StructuralType|array $structures, bool $detach = false): self { if (!is_array($structures)) { $structures = [$structures]; @@ -525,13 +513,13 @@ public function delete($structures, bool $detach = false): self /** * Creates the DETACH DELETE clause. * - * @param Pattern|Pattern[]|StructuralType|StructuralType[]|(Pattern|StructuralType)[] $structures A single structure to delete, or a non-empty list of structures to delete + * @param Pattern|(Pattern|StructuralType)[]|StructuralType $structures A single structure to delete, or a non-empty list of structures to delete * * @return $this * * @see https://neo4j.com/docs/cypher-manual/current/clauses/delete/ Corresponding documentation on Neo4j.com */ - public function detachDelete($structures): self + public function detachDelete(Pattern|StructuralType|array $structures): self { return $this->delete($structures, true); } @@ -545,7 +533,7 @@ public function detachDelete($structures): self * * @see https://neo4j.com/docs/cypher-manual/current/clauses/limit/ Corresponding documentation on Neo4j.com */ - public function limit($limit): self + public function limit(IntegerType|int $limit): self { $limitClause = new LimitClause(); $limitClause->setLimit($limit); @@ -564,7 +552,7 @@ public function limit($limit): self * * @see https://neo4j.com/docs/cypher-manual/current/clauses/skip/ Corresponding documentation on Neo4j.com */ - public function skip($amount): self + public function skip(IntegerType|int $amount): self { $skipClause = new SkipClause(); $skipClause->setSkip($amount); @@ -606,7 +594,7 @@ public function merge(CompletePattern $pattern, ?SetClause $createClause = null, * * @see https://neo4j.com/docs/cypher-manual/current/clauses/optional-match/ Corresponding documentation on Neo4j.com */ - public function optionalMatch($patterns): self + public function optionalMatch(CompletePattern|array $patterns): self { if (!is_array($patterns)) { $patterns = [$patterns]; @@ -630,7 +618,7 @@ public function optionalMatch($patterns): self * * @see https://neo4j.com/docs/cypher-manual/current/clauses/order-by/ Corresponding documentation on Neo4j.com */ - public function orderBy($properties, bool $descending = false): self + public function orderBy(Property|array $properties, bool $descending = false): self { if (!is_array($properties)) { $properties = [$properties]; @@ -648,13 +636,13 @@ public function orderBy($properties, bool $descending = false): self /** * Creates the REMOVE clause. * - * @param Label|Label[]|Property|Property[]|(Label|Property)[] $expressions A single expression to remove, or a non-empty list of expressions to remove + * @param Label|(Label|Property)[]|Property $expressions A single expression to remove, or a non-empty list of expressions to remove * * @return $this * * @see https://neo4j.com/docs/cypher-manual/current/clauses/remove/ Corresponding documentation on Neo4j.com */ - public function remove($expressions): self + public function remove(Label|Property|array $expressions): self { if (!is_array($expressions)) { $expressions = [$expressions]; @@ -671,13 +659,13 @@ public function remove($expressions): self /** * Create the SET clause. * - * @param Label|Label[]|PropertyReplacement|PropertyReplacement[]|(Label|PropertyReplacement)[] $expressions A single expression to set, or a non-empty list of expressions to set + * @param Label|(Label|PropertyReplacement)[]|PropertyReplacement $expressions A single expression to set, or a non-empty list of expressions to set * * @return $this * * @see https://neo4j.com/docs/cypher-manual/current/clauses/set/ Corresponding documentation on Neo4j.com */ - public function set($expressions): self + public function set(Label|PropertyReplacement|array $expressions): self { if (!is_array($expressions)) { $expressions = [$expressions]; @@ -694,15 +682,15 @@ public function set($expressions): self /** * Creates the WHERE clause. * - * @param bool|bool[]|BooleanType|BooleanType[]|(bool|BooleanType)[] $expressions A boolean expression to evaluate, or a non-empty list of boolean expression to evaluate - * @param string $operator The operator with which to unify the given expressions, should be either WhereClause::OR, - * WhereClause::AND or WhereClause::XOR (optional, default: 'and') + * @param bool|BooleanType|(bool|BooleanType)[] $expressions A boolean expression to evaluate, or a non-empty list of boolean expression to evaluate + * @param string $operator The operator with which to unify the given expressions, should be either WhereClause::OR, + * WhereClause::AND or WhereClause::XOR (optional, default: 'and') * * @return $this * * @see https://neo4j.com/docs/cypher-manual/current/clauses/where/ Corresponding documentation on Neo4j.com */ - public function where($expressions, string $operator = WhereClause::AND): self + public function where(BooleanType|bool|array $expressions, string $operator = WhereClause::AND): self { if (!is_array($expressions)) { $expressions = [$expressions]; @@ -722,19 +710,19 @@ public function where($expressions, string $operator = WhereClause::AND): self /** * Creates the WITH clause. * - * @param Alias|Alias[]|AnyType|AnyType[]|bool|bool[]|float|float[]|int|int[]|mixed[][]|Pattern|Pattern[]|string|string[]|(Alias|AnyType|bool|float|int|mixed[]|Pattern|string)[] $expressions An entry to add, or a non-empty list of entries to add; if the array-key is non-numerical, it is used as the alias + * @param mixed $expressions An entry to add, or a non-empty list of entries to add; if the array-key is non-numerical, it is used as the alias * * @return $this * * @see https://neo4j.com/docs/cypher-manual/current/clauses/with/ Corresponding documentation on Neo4j.com */ - public function with($expressions): self + public function with(mixed $expressions): self { if (!is_array($expressions)) { $expressions = [$expressions]; } - $expressions = $this->makeAliasArray($expressions, fn ($value) => $this->toAnyType($value)); + $expressions = $this->makeAliasArray($expressions, static fn ($value) => CastUtils::toAnyType($value)); $withClause = new WithClause(); $withClause->addEntry(...$expressions); @@ -771,7 +759,7 @@ public function raw(string $clause, string $subject): self * * @see https://neo4j.com/docs/cypher-manual/current/clauses/union/ Corresponding documentation on Neo4j.com */ - public function union($queryOrCallable, bool $all = false): self + public function union(self|callable $queryOrCallable, bool $all = false): self { if (is_callable($queryOrCallable)) { $query = self::new(); @@ -845,10 +833,10 @@ public function toQuery(): string /** * Changes an associative array into an array of aliases. * - * @param mixed[] $values The array to change into an array of aliases + * @param array $values The array to change into an array of aliases * @param callable $castFunc Function to use to cast the elements of $array * - * @return mixed[] A sequential array, possibly consisting of aliases + * @return array A sequential array, possibly consisting of aliases */ private static function makeAliasArray(array $values, callable $castFunc): array { diff --git a/src/Syntax/PropertyReplacement.php b/src/Syntax/PropertyReplacement.php index 7d006a29..b1085e80 100644 --- a/src/Syntax/PropertyReplacement.php +++ b/src/Syntax/PropertyReplacement.php @@ -12,7 +12,6 @@ use WikibaseSolutions\CypherDSL\Expressions\Property; use WikibaseSolutions\CypherDSL\Expressions\Variable; use WikibaseSolutions\CypherDSL\QueryConvertible; -use WikibaseSolutions\CypherDSL\Traits\ErrorTrait; use WikibaseSolutions\CypherDSL\Types\AnyType; /** @@ -23,12 +22,10 @@ */ final class PropertyReplacement implements QueryConvertible { - use ErrorTrait; - /** * @var Property|Variable The name of the property to which we assign a (new) value */ - private $property; + private Property|Variable $property; /** * @var AnyType The value to assign to the property @@ -48,10 +45,8 @@ final class PropertyReplacement implements QueryConvertible * * @internal This method is not covered by the backwards compatibility guarantee of php-cypher-dsl */ - public function __construct($property, AnyType $value) + public function __construct(Property|Variable $property, AnyType $value) { - self::assertClass('property', [Variable::class, Property::class], $property); - $this->property = $property; $this->value = $value; } @@ -79,10 +74,8 @@ public function mutates(): bool /** * Returns the name of the property to which we assign a (new) value. - * - * @return Property|Variable */ - public function getProperty() + public function getProperty(): Property|Variable { return $this->property; } diff --git a/src/Traits/ErrorTrait.php b/src/Traits/ErrorTrait.php deleted file mode 100644 index d0a94648..00000000 --- a/src/Traits/ErrorTrait.php +++ /dev/null @@ -1,188 +0,0 @@ - 65534) { - // Remark: Some versions of Neo4j support names up to 65535 characters, but we just take the lower bound - throw new InvalidArgumentException("A name cannot be longer than 65534 (2^16 - 2) characters"); - } - - if (\preg_match('/^\p{L}[\p{L}\d_]*$/u', $name)) { - // The name is already valid and does not need to be escaped - return $name; - } - - // Escape backticks that are included in $name by doubling them. - $name = \str_replace('`', '``', $name); - - return \sprintf("`%s`", $name); - } -} diff --git a/src/Traits/NameGenerationTrait.php b/src/Traits/NameGenerationTrait.php deleted file mode 100644 index 5e1ca86f..00000000 --- a/src/Traits/NameGenerationTrait.php +++ /dev/null @@ -1,43 +0,0 @@ -variable = $variable === null ? null : self::toName($variable); + $this->variable = $variable === null ? null : CastUtils::toName($variable); return $this; } diff --git a/src/Traits/PatternTraits/PropertyPatternTrait.php b/src/Traits/PatternTraits/PropertyPatternTrait.php index e3ad55b3..80dda049 100644 --- a/src/Traits/PatternTraits/PropertyPatternTrait.php +++ b/src/Traits/PatternTraits/PropertyPatternTrait.php @@ -9,20 +9,20 @@ */ namespace WikibaseSolutions\CypherDSL\Traits\PatternTraits; +use Stringable; use TypeError; use WikibaseSolutions\CypherDSL\Expressions\Literals\Map; use WikibaseSolutions\CypherDSL\Expressions\Property; -use WikibaseSolutions\CypherDSL\Traits\CastTrait; -use WikibaseSolutions\CypherDSL\Traits\ErrorTrait; +use WikibaseSolutions\CypherDSL\Patterns\Pattern; +use WikibaseSolutions\CypherDSL\Types\AnyType; use WikibaseSolutions\CypherDSL\Types\CompositeTypes\MapType; +use WikibaseSolutions\CypherDSL\Utils\CastUtils; /** * This trait provides a default implementation to satisfy the "PropertyPattern" interface. */ trait PropertyPatternTrait { - use CastTrait; - use ErrorTrait; use PatternTrait; /** @@ -41,9 +41,9 @@ public function property(string $property): Property /** * @inheritDoc */ - public function withProperties($properties): self + public function withProperties(MapType|array $properties): self { - $this->properties = self::toMapType($properties); + $this->properties = CastUtils::toMapType($properties); return $this; } @@ -51,7 +51,7 @@ public function withProperties($properties): self /** * @inheritDoc */ - public function addProperty(string $key, $property): self + public function addProperty(string $key, AnyType|Pattern|Stringable|bool|float|int|array|string $property): self { $this->makeMap()->add($key, $property); @@ -61,18 +61,15 @@ public function addProperty(string $key, $property): self /** * @inheritDoc */ - public function addProperties($properties): self + public function addProperties(Map|array $properties): self { - self::assertClass('properties', [Map::class, 'array'], $properties); - $map = $this->makeMap(); if (is_array($properties)) { - $res = []; - - foreach ($properties as $key => $property) { - $res[$key] = self::toAnyType($property); - } + $res = array_map(static function ($property) + { + return CastUtils::toAnyType($property); + }, $properties); // Cast the array to a Map $properties = new Map($res); diff --git a/src/Traits/TypeTraits/AnyTypeTrait.php b/src/Traits/TypeTraits/AnyTypeTrait.php index 94dc7946..62813a3a 100644 --- a/src/Traits/TypeTraits/AnyTypeTrait.php +++ b/src/Traits/TypeTraits/AnyTypeTrait.php @@ -17,70 +17,71 @@ use WikibaseSolutions\CypherDSL\Expressions\Operators\IsNull; use WikibaseSolutions\CypherDSL\Expressions\Operators\LessThan; use WikibaseSolutions\CypherDSL\Expressions\Operators\LessThanOrEqual; +use WikibaseSolutions\CypherDSL\Expressions\Variable; +use WikibaseSolutions\CypherDSL\Patterns\Pattern; use WikibaseSolutions\CypherDSL\Syntax\Alias; -use WikibaseSolutions\CypherDSL\Traits\CastTrait; +use WikibaseSolutions\CypherDSL\Types\AnyType; +use WikibaseSolutions\CypherDSL\Utils\CastUtils; /** * This trait provides a default implementation to satisfy the "AnyType" interface. */ trait AnyTypeTrait { - use CastTrait; - /** * @inheritDoc */ - public function alias($right): Alias + public function alias(Variable|string $right): Alias { - return new Alias($this, self::toName($right)); + return new Alias($this, CastUtils::toName($right)); } /** * @inheritDoc */ - public function equals($right, bool $insertParentheses = true): Equality + public function equals(AnyType|Pattern|string|bool|float|int|array $right, bool $insertParentheses = true): Equality { - return new Equality($this, self::toAnyType($right), $insertParentheses); + return new Equality($this, CastUtils::toAnyType($right), $insertParentheses); } /** * @inheritDoc */ - public function notEquals($right, bool $insertParentheses = true): Inequality + public function notEquals(AnyType|Pattern|string|bool|float|int|array $right, bool $insertParentheses = true): Inequality { - return new Inequality($this, self::toAnyType($right), $insertParentheses); + return new Inequality($this, CastUtils::toAnyType($right), $insertParentheses); } /** * @inheritDoc */ - public function gt($right, bool $insertParentheses = true): GreaterThan + public function gt(AnyType|Pattern|string|bool|float|int|array $right, bool $insertParentheses = true): GreaterThan { - return new GreaterThan($this, self::toAnyType($right), $insertParentheses); + return new GreaterThan($this, CastUtils::toAnyType($right), $insertParentheses); } /** * @inheritDoc */ - public function gte($right, bool $insertParentheses = true): GreaterThanOrEqual + public function gte(AnyType|Pattern|string|bool|float|int|array $right, bool $insertParentheses = true): GreaterThanOrEqual { - return new GreaterThanOrEqual($this, self::toAnyType($right), $insertParentheses); + return new GreaterThanOrEqual($this, CastUtils::toAnyType($right), $insertParentheses); } /** * @inheritDoc */ - public function lt($right, bool $insertParentheses = true): LessThan + public function lt(AnyType|Pattern|string|bool|float|int|array $right, bool $insertParentheses = true): LessThan { - return new LessThan($this, self::toAnyType($right), $insertParentheses); + return new LessThan($this, CastUtils::toAnyType($right), $insertParentheses); } /** * @inheritDoc */ - public function lte($right, bool $insertParentheses = true): LessThanOrEqual + public function lte(AnyType|Pattern|string|bool|float|int|array $right, bool $insertParentheses = true): LessThanOrEqual { - return new LessThanOrEqual($this, self::toAnyType($right), $insertParentheses); + return new LessThanOrEqual($this, CastUtils::toAnyType($right), $insertParentheses); } /** diff --git a/src/Traits/TypeTraits/CompositeTypeTraits/ListTypeTrait.php b/src/Traits/TypeTraits/CompositeTypeTraits/ListTypeTrait.php index 164d738a..762ac10d 100644 --- a/src/Traits/TypeTraits/CompositeTypeTraits/ListTypeTrait.php +++ b/src/Traits/TypeTraits/CompositeTypeTraits/ListTypeTrait.php @@ -10,21 +10,21 @@ namespace WikibaseSolutions\CypherDSL\Traits\TypeTraits\CompositeTypeTraits; use WikibaseSolutions\CypherDSL\Expressions\Operators\In; -use WikibaseSolutions\CypherDSL\Traits\CastTrait; +use WikibaseSolutions\CypherDSL\Types\PropertyTypes\PropertyType; +use WikibaseSolutions\CypherDSL\Utils\CastUtils; /** * This trait provides a default implementation to satisfy the "ListType" interface. */ trait ListTypeTrait { - use CastTrait; use CompositeTypeTrait; /** * @inheritDoc */ - public function has($left, bool $insertParentheses = true): In + public function has(PropertyType|string|int|float|bool $left, bool $insertParentheses = true): In { - return new In(self::toPropertyType($left), $this, $insertParentheses); + return new In(CastUtils::toPropertyType($left), $this, $insertParentheses); } } diff --git a/src/Traits/TypeTraits/PropertyTypeTraits/BooleanTypeTrait.php b/src/Traits/TypeTraits/PropertyTypeTraits/BooleanTypeTrait.php index ec1f821c..fff4662f 100644 --- a/src/Traits/TypeTraits/PropertyTypeTraits/BooleanTypeTrait.php +++ b/src/Traits/TypeTraits/PropertyTypeTraits/BooleanTypeTrait.php @@ -13,38 +13,38 @@ use WikibaseSolutions\CypherDSL\Expressions\Operators\Disjunction; use WikibaseSolutions\CypherDSL\Expressions\Operators\ExclusiveDisjunction; use WikibaseSolutions\CypherDSL\Expressions\Operators\Negation; -use WikibaseSolutions\CypherDSL\Traits\CastTrait; +use WikibaseSolutions\CypherDSL\Types\PropertyTypes\BooleanType; +use WikibaseSolutions\CypherDSL\Utils\CastUtils; /** * This trait provides a default implementation to satisfy the "BooleanType" interface. */ trait BooleanTypeTrait { - use CastTrait; use PropertyTypeTrait; /** * @inheritDoc */ - public function and($right, bool $insertParentheses = true): Conjunction + public function and(BooleanType|bool $right, bool $insertParentheses = true): Conjunction { - return new Conjunction($this, self::toBooleanType($right), $insertParentheses); + return new Conjunction($this, CastUtils::toBooleanType($right), $insertParentheses); } /** * @inheritDoc */ - public function or($right, bool $insertParentheses = true): Disjunction + public function or(BooleanType|bool $right, bool $insertParentheses = true): Disjunction { - return new Disjunction($this, self::toBooleanType($right), $insertParentheses); + return new Disjunction($this, CastUtils::toBooleanType($right), $insertParentheses); } /** * @inheritDoc */ - public function xor($right, bool $insertParentheses = true): ExclusiveDisjunction + public function xor(BooleanType|bool $right, bool $insertParentheses = true): ExclusiveDisjunction { - return new ExclusiveDisjunction($this, self::toBooleanType($right), $insertParentheses); + return new ExclusiveDisjunction($this, CastUtils::toBooleanType($right), $insertParentheses); } /** diff --git a/src/Traits/TypeTraits/PropertyTypeTraits/NumeralTypeTrait.php b/src/Traits/TypeTraits/PropertyTypeTraits/NumeralTypeTrait.php index 5b0339ef..012ff24f 100644 --- a/src/Traits/TypeTraits/PropertyTypeTraits/NumeralTypeTrait.php +++ b/src/Traits/TypeTraits/PropertyTypeTraits/NumeralTypeTrait.php @@ -16,6 +16,8 @@ use WikibaseSolutions\CypherDSL\Expressions\Operators\Multiplication; use WikibaseSolutions\CypherDSL\Expressions\Operators\Subtraction; use WikibaseSolutions\CypherDSL\Expressions\Operators\UnaryMinus; +use WikibaseSolutions\CypherDSL\Types\PropertyTypes\NumeralType; +use WikibaseSolutions\CypherDSL\Utils\CastUtils; /** * This trait provides a default implementation to satisfy the "NumeralType" interface. @@ -27,49 +29,49 @@ trait NumeralTypeTrait /** * @inheritDoc */ - public function plus($right, bool $insertParentheses = true): Addition + public function plus(NumeralType|float|int $right, bool $insertParentheses = true): Addition { - return new Addition($this, self::toNumeralType($right), $insertParentheses); + return new Addition($this, CastUtils::toNumeralType($right), $insertParentheses); } /** * @inheritDoc */ - public function divide($right, bool $insertParentheses = true): Division + public function divide(NumeralType|float|int $right, bool $insertParentheses = true): Division { - return new Division($this, self::toNumeralType($right), $insertParentheses); + return new Division($this, CastUtils::toNumeralType($right), $insertParentheses); } /** * @inheritDoc */ - public function exponentiate($right, bool $insertParentheses = true): Exponentiation + public function exponentiate(NumeralType|float|int $right, bool $insertParentheses = true): Exponentiation { - return new Exponentiation($this, self::toNumeralType($right), $insertParentheses); + return new Exponentiation($this, CastUtils::toNumeralType($right), $insertParentheses); } /** * @inheritDoc */ - public function mod($right, bool $insertParentheses = true): ModuloDivision + public function mod(NumeralType|float|int $right, bool $insertParentheses = true): ModuloDivision { - return new ModuloDivision($this, self::toNumeralType($right), $insertParentheses); + return new ModuloDivision($this, CastUtils::toNumeralType($right), $insertParentheses); } /** * @inheritDoc */ - public function times($right, bool $insertParentheses = true): Multiplication + public function times(NumeralType|float|int $right, bool $insertParentheses = true): Multiplication { - return new Multiplication($this, self::toNumeralType($right), $insertParentheses); + return new Multiplication($this, CastUtils::toNumeralType($right), $insertParentheses); } /** * @inheritDoc */ - public function minus($right, bool $insertParentheses = true): Subtraction + public function minus(NumeralType|float|int $right, bool $insertParentheses = true): Subtraction { - return new Subtraction($this, self::toNumeralType($right), $insertParentheses); + return new Subtraction($this, CastUtils::toNumeralType($right), $insertParentheses); } /** diff --git a/src/Traits/TypeTraits/PropertyTypeTraits/PropertyTypeTrait.php b/src/Traits/TypeTraits/PropertyTypeTraits/PropertyTypeTrait.php index c42aa8f8..787bc2a1 100644 --- a/src/Traits/TypeTraits/PropertyTypeTraits/PropertyTypeTrait.php +++ b/src/Traits/TypeTraits/PropertyTypeTraits/PropertyTypeTrait.php @@ -10,8 +10,9 @@ namespace WikibaseSolutions\CypherDSL\Traits\TypeTraits\PropertyTypeTraits; use WikibaseSolutions\CypherDSL\Expressions\Operators\In; -use WikibaseSolutions\CypherDSL\Traits\CastTrait; use WikibaseSolutions\CypherDSL\Traits\TypeTraits\AnyTypeTrait; +use WikibaseSolutions\CypherDSL\Types\CompositeTypes\ListType; +use WikibaseSolutions\CypherDSL\Utils\CastUtils; /** * This trait provides a default implementation to satisfy the "PropertyType" interface. @@ -32,13 +33,12 @@ trait PropertyTypeTrait { use AnyTypeTrait; - use CastTrait; /** * @inheritDoc */ - public function in($right, bool $insertParentheses = true): In + public function in(ListType|array $right, bool $insertParentheses = true): In { - return new In($this, self::toListType($right), $insertParentheses); + return new In($this, CastUtils::toListType($right), $insertParentheses); } } diff --git a/src/Traits/TypeTraits/PropertyTypeTraits/StringTypeTrait.php b/src/Traits/TypeTraits/PropertyTypeTraits/StringTypeTrait.php index e5221f24..80c00e48 100644 --- a/src/Traits/TypeTraits/PropertyTypeTraits/StringTypeTrait.php +++ b/src/Traits/TypeTraits/PropertyTypeTraits/StringTypeTrait.php @@ -13,45 +13,45 @@ use WikibaseSolutions\CypherDSL\Expressions\Operators\EndsWith; use WikibaseSolutions\CypherDSL\Expressions\Operators\Regex; use WikibaseSolutions\CypherDSL\Expressions\Operators\StartsWith; -use WikibaseSolutions\CypherDSL\Traits\CastTrait; +use WikibaseSolutions\CypherDSL\Types\PropertyTypes\StringType; +use WikibaseSolutions\CypherDSL\Utils\CastUtils; /** * This trait provides a default implementation to satisfy the "StringType" interface. */ trait StringTypeTrait { - use CastTrait; use PropertyTypeTrait; /** * @inheritDoc */ - public function contains($right, bool $insertParentheses = true): Contains + public function contains(StringType|string $right, bool $insertParentheses = true): Contains { - return new Contains($this, self::toStringType($right), $insertParentheses); + return new Contains($this, CastUtils::toStringType($right), $insertParentheses); } /** * @inheritDoc */ - public function endsWith($right, bool $insertParentheses = true): EndsWith + public function endsWith(StringType|string $right, bool $insertParentheses = true): EndsWith { - return new EndsWith($this, self::toStringType($right), $insertParentheses); + return new EndsWith($this, CastUtils::toStringType($right), $insertParentheses); } /** * @inheritDoc */ - public function startsWith($right, bool $insertParentheses = true): StartsWith + public function startsWith(StringType|string $right, bool $insertParentheses = true): StartsWith { - return new StartsWith($this, self::toStringType($right), $insertParentheses); + return new StartsWith($this, CastUtils::toStringType($right), $insertParentheses); } /** * @inheritDoc */ - public function regex($right, bool $insertParentheses = true): Regex + public function regex(StringType|string $right, bool $insertParentheses = true): Regex { - return new Regex($this, self::toStringType($right), $insertParentheses); + return new Regex($this, CastUtils::toStringType($right), $insertParentheses); } } diff --git a/src/Types/AnyType.php b/src/Types/AnyType.php index fa679321..1b1b3fb3 100644 --- a/src/Types/AnyType.php +++ b/src/Types/AnyType.php @@ -28,59 +28,45 @@ * * @note This interface should not be implemented by any class directly * - * @see AnyTypeTrait for a default implementation + * @see AnyTypeTrait for a default implementation * @see https://neo4j.com/docs/cypher-manual/current/syntax/values/ Corresponding documentation on Neo4j.com */ interface AnyType extends QueryConvertible { /** * Creates an alias of the current expression. - * - * @param string|Variable $right */ - public function alias($right): Alias; + public function alias(Variable|string $right): Alias; /** * Perform an equality check with the given expression. - * - * @param AnyType|bool|float|int|mixed[]|Pattern|string $right */ - public function equals($right, bool $insertParentheses = true): Equality; + public function equals(self|Pattern|string|bool|float|int|array $right, bool $insertParentheses = true): Equality; /** * Perform an inequality comparison against the given expression. - * - * @param AnyType|bool|float|int|mixed[]|Pattern|string $right */ - public function notEquals($right, bool $insertParentheses = true): Inequality; + public function notEquals(self|Pattern|string|bool|float|int|array $right, bool $insertParentheses = true): Inequality; /** * Perform a greater than comparison against the given expression. - * - * @param AnyType|bool|float|int|mixed[]|Pattern|string $right */ - public function gt($right, bool $insertParentheses = true): GreaterThan; + public function gt(self|Pattern|string|bool|float|int|array $right, bool $insertParentheses = true): GreaterThan; /** * Perform a greater than or equal comparison against the given expression. - * - * @param AnyType|bool|float|int|mixed[]|Pattern|string $right */ - public function gte($right, bool $insertParentheses = true): GreaterThanOrEqual; + public function gte(self|Pattern|string|bool|float|int|array $right, bool $insertParentheses = true): GreaterThanOrEqual; /** * Perform a less than comparison against the given expression. - * - * @param AnyType|bool|float|int|mixed[]|Pattern|string $right */ - public function lt($right, bool $insertParentheses = true): LessThan; + public function lt(self|Pattern|string|bool|float|int|array $right, bool $insertParentheses = true): LessThan; /** * Perform a less than or equal comparison against the given expression. - * - * @param AnyType|bool|float|int|mixed[]|Pattern|string $right */ - public function lte($right, bool $insertParentheses = true): LessThanOrEqual; + public function lte(self|Pattern|string|bool|float|int|array $right, bool $insertParentheses = true): LessThanOrEqual; /** * Checks whether the element is null. diff --git a/src/Types/CompositeTypes/CompositeType.php b/src/Types/CompositeTypes/CompositeType.php index 94c24592..b0753cf8 100644 --- a/src/Types/CompositeTypes/CompositeType.php +++ b/src/Types/CompositeTypes/CompositeType.php @@ -29,7 +29,7 @@ * * @note This interface should not be implemented by any class directly * - * @see CompositeTypeTrait for a default implemenation + * @see CompositeTypeTrait for a default implemenation * @see https://neo4j.com/docs/cypher-manual/current/syntax/values/#composite-types Corresponding documentation on Neo4j.com */ interface CompositeType extends AnyType diff --git a/src/Types/CompositeTypes/ListType.php b/src/Types/CompositeTypes/ListType.php index 7dda806b..f60746c8 100644 --- a/src/Types/CompositeTypes/ListType.php +++ b/src/Types/CompositeTypes/ListType.php @@ -22,8 +22,6 @@ interface ListType extends CompositeType { /** * Checks whether the given element exists in this list. - * - * @param bool|float|int|PropertyType|string $left */ - public function has($left, bool $insertParentheses = true): In; + public function has(PropertyType|string|int|float|bool $left, bool $insertParentheses = true): In; } diff --git a/src/Types/PropertyTypes/BooleanType.php b/src/Types/PropertyTypes/BooleanType.php index e8f72def..1987a26f 100644 --- a/src/Types/PropertyTypes/BooleanType.php +++ b/src/Types/PropertyTypes/BooleanType.php @@ -24,24 +24,18 @@ interface BooleanType extends PropertyType { /** * Create a conjunction between this expression and the given expression. - * - * @param bool|BooleanType $right */ - public function and($right, bool $insertParentheses = true): Conjunction; + public function and(self|bool $right, bool $insertParentheses = true): Conjunction; /** * Create a disjunction between this expression and the given expression. - * - * @param bool|BooleanType $right */ - public function or($right, bool $insertParentheses = true): Disjunction; + public function or(self|bool $right, bool $insertParentheses = true): Disjunction; /** * Perform an XOR with the given expression. - * - * @param bool|BooleanType $right */ - public function xor($right, bool $insertParentheses = true): ExclusiveDisjunction; + public function xor(self|bool $right, bool $insertParentheses = true): ExclusiveDisjunction; /** * Negate this expression (using the NOT operator). diff --git a/src/Types/PropertyTypes/LocalDateTimeType.php b/src/Types/PropertyTypes/LocalDateTimeType.php index 8069011c..55b36317 100644 --- a/src/Types/PropertyTypes/LocalDateTimeType.php +++ b/src/Types/PropertyTypes/LocalDateTimeType.php @@ -9,10 +9,12 @@ */ namespace WikibaseSolutions\CypherDSL\Types\PropertyTypes; +use WikibaseSolutions\CypherDSL\Traits\TypeTraits\PropertyTypeTraits\LocalDateTimeTypeTrait; + /** * Represents the leaf type "localdatetime". * - * @see LocalDateTimeType for a default implementation + * @see LocalDateTimeTypeTrait for a default implementation */ interface LocalDateTimeType extends PropertyType { diff --git a/src/Types/PropertyTypes/NumeralType.php b/src/Types/PropertyTypes/NumeralType.php index 74f2493d..29490479 100644 --- a/src/Types/PropertyTypes/NumeralType.php +++ b/src/Types/PropertyTypes/NumeralType.php @@ -23,51 +23,39 @@ * * @note This interface should not be implemented by any class directly * - * @see NumeralTypeTrait for a default implementation + * @see NumeralTypeTrait for a default implementation */ interface NumeralType extends PropertyType { /** * Add this expression to the given expression. - * - * @param float|int|NumeralType $right */ - public function plus($right, bool $insertParentheses = true): Addition; + public function plus(self|float|int $right, bool $insertParentheses = true): Addition; /** * Divide this expression by the given expression. - * - * @param float|int|NumeralType $right */ - public function divide($right, bool $insertParentheses = true): Division; + public function divide(self|float|int $right, bool $insertParentheses = true): Division; /** * Perform an exponentiation with the given expression. - * - * @param float|int|NumeralType $right */ - public function exponentiate($right, bool $insertParentheses = true): Exponentiation; + public function exponentiate(self|float|int $right, bool $insertParentheses = true): Exponentiation; /** * Perform the modulo operation with the given expression. - * - * @param float|int|NumeralType $right */ - public function mod($right, bool $insertParentheses = true): ModuloDivision; + public function mod(self|float|int $right, bool $insertParentheses = true): ModuloDivision; /** * Perform a multiplication with the given expression. - * - * @param float|int|NumeralType $right */ - public function times($right, bool $insertParentheses = true): Multiplication; + public function times(self|float|int $right, bool $insertParentheses = true): Multiplication; /** * Subtract the given expression from this expression. - * - * @param float|int|NumeralType $right */ - public function minus($right, bool $insertParentheses = true): Subtraction; + public function minus(self|float|int $right, bool $insertParentheses = true): Subtraction; /** * Negate this expression (negate the numeral using "0"). diff --git a/src/Types/PropertyTypes/PropertyType.php b/src/Types/PropertyTypes/PropertyType.php index cf48d7dd..25ea859a 100644 --- a/src/Types/PropertyTypes/PropertyType.php +++ b/src/Types/PropertyTypes/PropertyType.php @@ -37,15 +37,13 @@ * * @note This interface should not be implemented by any class directly * - * @see PropertyTypeTrait for a default implementation + * @see PropertyTypeTrait for a default implementation * @see https://neo4j.com/docs/cypher-manual/current/syntax/values/#property-types Corresponding documentation on Neo4j.com */ interface PropertyType extends AnyType { /** * Checks whether the element exists in the given list. - * - * @param ListType|mixed[] $right */ - public function in($right): In; + public function in(ListType|array $right): In; } diff --git a/src/Types/PropertyTypes/StringType.php b/src/Types/PropertyTypes/StringType.php index 40818d09..4b7c415b 100644 --- a/src/Types/PropertyTypes/StringType.php +++ b/src/Types/PropertyTypes/StringType.php @@ -24,29 +24,21 @@ interface StringType extends PropertyType { /** * Check whether this expression the given expression. - * - * @param string|StringType $right */ - public function contains($right, bool $insertParentheses = true): Contains; + public function contains(self|string $right, bool $insertParentheses = true): Contains; /** * Perform a suffix string search with the given expression. - * - * @param string|StringType $right */ - public function endsWith($right, bool $insertParentheses = true): EndsWith; + public function endsWith(self|string $right, bool $insertParentheses = true): EndsWith; /** * Perform a prefix string search with the given expression. - * - * @param string|StringType $right */ - public function startsWith($right, bool $insertParentheses = true): StartsWith; + public function startsWith(self|string $right, bool $insertParentheses = true): StartsWith; /** * Perform a regex comparison with the given expression. - * - * @param string|StringType $right */ - public function regex($right, bool $insertParentheses = true): Regex; + public function regex(self|string $right, bool $insertParentheses = true): Regex; } diff --git a/src/Types/StructuralTypes/StructuralType.php b/src/Types/StructuralTypes/StructuralType.php index 691f0cd4..4540a6cd 100644 --- a/src/Types/StructuralTypes/StructuralType.php +++ b/src/Types/StructuralTypes/StructuralType.php @@ -30,7 +30,7 @@ * * @note This interface should not be implemented by any class directly * - * @see StructuralTypeTrait for a default implementation + * @see StructuralTypeTrait for a default implementation * @see https://neo4j.com/docs/cypher-manual/current/syntax/values/#structural-types Corresponding documentation on Neo4j.com */ interface StructuralType extends AnyType diff --git a/src/Traits/CastTrait.php b/src/Utils/CastUtils.php similarity index 53% rename from src/Traits/CastTrait.php rename to src/Utils/CastUtils.php index 6c664444..8e3d89e5 100644 --- a/src/Traits/CastTrait.php +++ b/src/Utils/CastUtils.php @@ -7,8 +7,9 @@ * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -namespace WikibaseSolutions\CypherDSL\Traits; +namespace WikibaseSolutions\CypherDSL\Utils; +use Stringable; use WikibaseSolutions\CypherDSL\Expressions\Literals\Literal; use WikibaseSolutions\CypherDSL\Expressions\Variable; use WikibaseSolutions\CypherDSL\Patterns\Pattern; @@ -23,123 +24,89 @@ use WikibaseSolutions\CypherDSL\Types\StructuralTypes\StructuralType; /** - * Helper trait for casting native PHP types to Cypher-DSL types. Casts are added to this class on an as-needed basis. + * Utility functions for casting native PHP types to Cypher-DSL types. Casts are added to this class on an as-needed + * basis. * - * @internal This trait is not covered by the backwards compatibility guarantee of php-cypher-dsl + * @internal This class is not covered by the backwards compatibility guarantee of php-cypher-dsl */ -trait CastTrait +class CastUtils { - use ErrorTrait; - /** * Casts the given value to a ListType. * - * @param ListType|mixed[] $list + * @param ListType|ListType[] $list */ - private static function toListType($list): ListType + public static function toListType(ListType|array $list): ListType { - self::assertClass('list', [ListType::class, 'array'], $list); - return $list instanceof ListType ? $list : Literal::list($list); } /** * Casts the given value to a MapType. * - * @param MapType|mixed[] $map + * @param MapType|MapType[] $map */ - private static function toMapType($map): MapType + public static function toMapType(MapType|array $map): MapType { - self::assertClass('map', [MapType::class, 'array'], $map); - return $map instanceof MapType ? $map : Literal::map($map); } /** * Casts the given value to a StringType. - * - * @param string|StringType $string */ - private static function toStringType($string): StringType + public static function toStringType(StringType|string $string): StringType { - self::assertClass('string', [StringType::class, 'string'], $string); - return $string instanceof StringType ? $string : Literal::string($string); } /** * Casts the given value to a NumeralType. - * - * @param float|int|NumeralType $numeral */ - private static function toNumeralType($numeral): NumeralType + public static function toNumeralType(NumeralType|float|int $numeral): NumeralType { - self::assertClass('numeral', [NumeralType::class, 'int', 'float'], $numeral); - - // @phpstan-ignore-next-line return $numeral instanceof NumeralType ? $numeral : Literal::number($numeral); } /** * Casts the given value to an IntegerType. - * - * @param int|IntegerType $integer */ - private static function toIntegerType($integer): IntegerType + public static function toIntegerType(IntegerType|int $integer): IntegerType { - self::assertClass('integer', [IntegerType::class, 'int'], $integer); - return $integer instanceof IntegerType ? $integer : Literal::integer($integer); } /** * Casts the given value to a BooleanType. - * - * @param bool|BooleanType $boolean */ - private static function toBooleanType($boolean): BooleanType + public static function toBooleanType(BooleanType|bool $boolean): BooleanType { - self::assertClass('boolean', [BooleanType::class, 'bool'], $boolean); - return $boolean instanceof BooleanType ? $boolean : Literal::boolean($boolean); } /** * Casts the given value to a PropertyType. - * - * @param bool|float|int|PropertyType|string $property */ - private static function toPropertyType($property): PropertyType + public static function toPropertyType(PropertyType|bool|int|float|string $property): PropertyType { - self::assertClass('property', [PropertyType::class, 'bool', 'int', 'float', 'string'], $property); - // @phpstan-ignore-next-line return $property instanceof PropertyType ? $property : Literal::literal($property); } /** * Casts the given value to a StructuralType. - * - * @param Pattern|StructuralType $structure */ - private static function toStructuralType($structure): StructuralType + public static function toStructuralType(StructuralType|Pattern $structure): StructuralType { - self::assertClass('structure', [Pattern::class, StructuralType::class], $structure); - return $structure instanceof StructuralType ? $structure : $structure->getVariable(); } /** * Casts the given value to a Variable. * - * @param Pattern|string|Variable $variable - * - * @see CastTrait::toName() for a function that does not accept Pattern + * @see CastUtils::toName() for a function that does not accept Pattern */ - private static function toVariable($variable): Variable + public static function toVariable(Variable|Pattern|string $variable): Variable { - self::assertClass('variable', [Variable::class, Pattern::class, 'string'], $variable); - if ($variable instanceof Variable) { return $variable; } @@ -152,28 +119,20 @@ private static function toVariable($variable): Variable } /** - * Casts the given value to a name (as a variable). + * Casts the given value to a name. * - * @param string|Variable $name - * - * @see CastTrait::toVariable() for a function that accepts Pattern + * @see CastUtils::toVariable() for a function that accepts Pattern */ - private static function toName($name): Variable + public static function toName(Variable|string $name): Variable { - self::assertClass('name', [Variable::class, 'string'], $name); - return $name instanceof Variable ? $name : new Variable($name); } /** * Casts the given value to an AnyType. - * - * @param AnyType|bool|float|int|mixed[]|Pattern|string $value */ - private static function toAnyType($value): AnyType + public static function toAnyType(AnyType|Pattern|Stringable|bool|float|int|array|string $value): AnyType { - self::assertClass('value', [AnyType::class, Pattern::class, 'int', 'float', 'string', 'bool', 'array'], $value); - if ($value instanceof Pattern) { return $value->getVariable(); } @@ -182,7 +141,6 @@ private static function toAnyType($value): AnyType return $value; } - // @phpstan-ignore-next-line return Literal::literal($value); } } diff --git a/src/Utils/NameUtils.php b/src/Utils/NameUtils.php new file mode 100644 index 00000000..bb32cf1f --- /dev/null +++ b/src/Utils/NameUtils.php @@ -0,0 +1,83 @@ + + */ + private static array $generatedIdentifiers = []; + + /** + * Generates a guaranteed unique random identifier. + * + * @note The returned string is not cryptographically secure. + * + * @param string $prefix The prefix to put before the name. Must start with a letter. + * @param int $length the length of the generated name in bytes + */ + public static function generateIdentifier(string $prefix = 'var', int $length = 32): string + { + do { + $random = $prefix; + + for ($i = 0; $i < $length; ++$i) { + $random .= dechex(mt_rand(0, 15)); + } + } while (isset(self::$generatedIdentifiers[$random])); + + self::$generatedIdentifiers[$random] = ''; + + return $random; + } + + /** + * Escapes a name. + * + * A name in Cypher is any string that should be included directly in a Cypher query, + * such as variable names, labels, property names and relation types. + * + * @see https://neo4j.com/docs/cypher-manual/4.4/syntax/naming Corresponding documentation on Neo4j.com + */ + public static function escape(string $name): string + { + if ($name === "") { + // Although some versions of Neo4j do not crash when the empty string is used as a name, + // but there is no real reason to ever use the empty string as a name, so we disallow it. + throw new InvalidArgumentException("A name cannot be the empty string"); + } + + if (\strlen($name) > 65534) { + // Remark: Some versions of Neo4j support names up to 65535 characters, but we just take + // the lower bound. The user shouldn't be using names this long anyway. + throw new InvalidArgumentException("A name cannot be longer than 65534 (2^16 - 2) characters"); + } + + if (\preg_match('/^\p{L}[\p{L}\d_]*$/u', $name)) { + // The name is already valid and does not need to be escaped. + return $name; + } + + // Escape backticks that are included in the name by doubling them. + $name = \str_replace('`', '``', $name); + + return \sprintf("`%s`", $name); + } +} diff --git a/src/functions.php b/src/functions.php index c067aabf..a38dcdee 100644 --- a/src/functions.php +++ b/src/functions.php @@ -9,17 +9,18 @@ */ namespace WikibaseSolutions\CypherDSL; +use Stringable; use WikibaseSolutions\CypherDSL\Expressions\Literals\Boolean; use WikibaseSolutions\CypherDSL\Expressions\Literals\Float_; use WikibaseSolutions\CypherDSL\Expressions\Literals\Integer; use WikibaseSolutions\CypherDSL\Expressions\Literals\List_; -use WikibaseSolutions\CypherDSL\Expressions\Literals\Literal; use WikibaseSolutions\CypherDSL\Expressions\Literals\Map; use WikibaseSolutions\CypherDSL\Expressions\Literals\String_; use WikibaseSolutions\CypherDSL\Expressions\Parameter; use WikibaseSolutions\CypherDSL\Expressions\Procedures\Procedure; use WikibaseSolutions\CypherDSL\Expressions\RawExpression; use WikibaseSolutions\CypherDSL\Expressions\Variable; +use WikibaseSolutions\CypherDSL\Patterns\Direction; use WikibaseSolutions\CypherDSL\Patterns\Node; use WikibaseSolutions\CypherDSL\Patterns\Relationship; @@ -58,14 +59,11 @@ function node(?string $label = null): Node /** * Creates a relationship. * - * @param string[] $direction The direction of the relationship (optional, default: unidirectional), should be either: - * - Relationship::DIR_RIGHT (for a relation of (a)-->(b)) - * - Relationship::DIR_LEFT (for a relation of (a)<--(b)) - * - Relationship::DIR_UNI (for a relation of (a)--(b)) + * @param Direction $direction The direction of the relationship (optional, default: unidirectional) * * @see Query::relationship() */ -function relationship(array $direction = Relationship::DIR_UNI): Relationship +function relationship(Direction $direction = Direction::UNI): Relationship { return Query::relationship($direction); } @@ -160,13 +158,11 @@ function variable(?string $variable = null): Variable * - list_() - For a list * - map() - For a map * - * @param null|bool|float|int|mixed[]|string $literal The literal to construct - * - * @return Boolean|class-string|Float_|Integer|List_|Map|String_ + * @param null|array|bool|float|int|string|Stringable $literal The literal to construct * * @see Query::literal() */ -function literal($literal = null) +function literal(bool|float|int|array|string|Stringable|null $literal = null): Boolean|Float_|List_|String_|Integer|string|Map { return Query::literal($literal); } @@ -214,8 +210,6 @@ function float(float $value): Float_ /** * Creates a new list literal. * - * @param mixed[] $value - * * @see Query::list() */ function list_(array $value): List_ @@ -226,8 +220,6 @@ function list_(array $value): List_ /** * Creates a new map literal. * - * @param mixed[] $value - * * @see Query::map() */ function map(array $value): Map diff --git a/tests/end-to-end/ExamplesTest.php b/tests/end-to-end/ExamplesTest.php index fa75a78d..095ae3e1 100644 --- a/tests/end-to-end/ExamplesTest.php +++ b/tests/end-to-end/ExamplesTest.php @@ -32,7 +32,7 @@ */ final class ExamplesTest extends TestCase { - public function testReadmeExample(): void + public function testOldReadmeExample(): void { $tom = node("Person")->withProperties(["name" => "Tom Hanks"]); $coActors = node(); diff --git a/tests/unit/Clauses/MatchClauseTest.php b/tests/unit/Clauses/MatchClauseTest.php index bd0caa0e..0a42bcb0 100644 --- a/tests/unit/Clauses/MatchClauseTest.php +++ b/tests/unit/Clauses/MatchClauseTest.php @@ -12,7 +12,7 @@ use PHPUnit\Framework\TestCase; use TypeError; use WikibaseSolutions\CypherDSL\Clauses\MatchClause; -use WikibaseSolutions\CypherDSL\Patterns\Relationship; +use WikibaseSolutions\CypherDSL\Patterns\Direction; use WikibaseSolutions\CypherDSL\Query; /** @@ -90,7 +90,7 @@ public function testAddPatternAcceptsAnyMatchablePattern(): void public function testAddPatternDoesNotAcceptRelationship(): void { - $rel = Query::relationship(Relationship::DIR_LEFT); + $rel = Query::relationship(Direction::LEFT); $match = new MatchClause(); diff --git a/tests/unit/Clauses/MergeClauseTest.php b/tests/unit/Clauses/MergeClauseTest.php index 3bb6f306..ac33129b 100644 --- a/tests/unit/Clauses/MergeClauseTest.php +++ b/tests/unit/Clauses/MergeClauseTest.php @@ -13,7 +13,7 @@ use TypeError; use WikibaseSolutions\CypherDSL\Clauses\MergeClause; use WikibaseSolutions\CypherDSL\Clauses\SetClause; -use WikibaseSolutions\CypherDSL\Patterns\Relationship; +use WikibaseSolutions\CypherDSL\Patterns\Direction; use WikibaseSolutions\CypherDSL\Query; /** @@ -108,7 +108,7 @@ public function testSetOnBoth(): void public function testSetPatternDoesNotAcceptRelationship(): void { - $relationship = Query::relationship(Relationship::DIR_RIGHT); + $relationship = Query::relationship(Direction::RIGHT); $merge = new MergeClause(); diff --git a/tests/unit/Clauses/OptionalMatchTest.php b/tests/unit/Clauses/OptionalMatchTest.php index 9656a86c..fb69502b 100644 --- a/tests/unit/Clauses/OptionalMatchTest.php +++ b/tests/unit/Clauses/OptionalMatchTest.php @@ -13,7 +13,7 @@ use TypeError; use WikibaseSolutions\CypherDSL\Clauses\MatchClause; use WikibaseSolutions\CypherDSL\Clauses\OptionalMatchClause; -use WikibaseSolutions\CypherDSL\Patterns\Relationship; +use WikibaseSolutions\CypherDSL\Patterns\Direction; use WikibaseSolutions\CypherDSL\Query; /** @@ -91,7 +91,7 @@ public function testAddPatternAcceptsAnyMatchablePattern(): void public function testAddPatternDoesNotAcceptRelationship(): void { - $rel = Query::relationship(Relationship::DIR_LEFT); + $rel = Query::relationship(Direction::LEFT); $match = new OptionalMatchClause(); diff --git a/tests/unit/Expressions/ExistsTest.php b/tests/unit/Expressions/ExistsTest.php index 5e70f891..99812c1e 100644 --- a/tests/unit/Expressions/ExistsTest.php +++ b/tests/unit/Expressions/ExistsTest.php @@ -17,6 +17,7 @@ use WikibaseSolutions\CypherDSL\Expressions\Operators\Equality; use WikibaseSolutions\CypherDSL\Expressions\Property; use WikibaseSolutions\CypherDSL\Expressions\Variable; +use WikibaseSolutions\CypherDSL\Patterns\Direction; use WikibaseSolutions\CypherDSL\Patterns\Node; use WikibaseSolutions\CypherDSL\Patterns\Path; use WikibaseSolutions\CypherDSL\Patterns\Relationship; @@ -32,7 +33,7 @@ public function testToQuery(): void (new MatchClause)->addPattern( new Path( [(new Node)->withVariable('person'), (new Node('Dog'))->withVariable('dog')], - (new Relationship(Relationship::DIR_RIGHT))->addType('HAS_DOG') + (new Relationship(Direction::RIGHT))->addType('HAS_DOG') ) ) ); @@ -43,7 +44,7 @@ public function testToQuery(): void (new MatchClause)->addPattern( new Path( [(new Node)->withVariable('person'), (new Node('Dog'))->withVariable('dog')], - [(new Relationship(Relationship::DIR_RIGHT))->addType('HAS_DOG')] + [(new Relationship(Direction::RIGHT))->addType('HAS_DOG')] ) ), (new WhereClause)->addExpression( diff --git a/tests/unit/Expressions/Literals/FloatTest.php b/tests/unit/Expressions/Literals/FloatTest.php index 202c650d..d8163ca6 100644 --- a/tests/unit/Expressions/Literals/FloatTest.php +++ b/tests/unit/Expressions/Literals/FloatTest.php @@ -18,6 +18,16 @@ */ final class FloatTest extends TestCase { + public static function provideToQueryData(): array + { + return [ + [1, '1.0'], + [1.0, '1.0'], + [111111111111111, '1.1111111111111E+14'], + [1337.1337, '1337.1337'], + ]; + } + public function testZero(): void { $float = new Float_(0); @@ -48,14 +58,4 @@ public function testInstanceOfFloatType(): void { $this->assertInstanceOf(FloatType::class, new Float_(1.0)); } - - public function provideToQueryData(): array - { - return [ - [1, '1.0'], - [1.0, '1.0'], - [111111111111111, '1.1111111111111E+14'], - [1337.1337, '1337.1337'], - ]; - } } diff --git a/tests/unit/Expressions/Literals/IntegerTest.php b/tests/unit/Expressions/Literals/IntegerTest.php index d2c2e6cc..c1364cc2 100644 --- a/tests/unit/Expressions/Literals/IntegerTest.php +++ b/tests/unit/Expressions/Literals/IntegerTest.php @@ -19,6 +19,30 @@ */ final class IntegerTest extends TestCase { + public static function provideToQueryData(): array + { + return [ + [1, "1"], + [2, "2"], + ["2147483649", "2147483649"], + ["9223372036854775816", "9223372036854775816"], + [-12, "-12"], + [69, "69"], + ["292922929312312831203129382304823043284234729847294324724982749274294729427429471230918457", "292922929312312831203129382304823043284234729847294324724982749274294729427429471230918457"], + ["-1238109438204130457284308235720483205", "-1238109438204130457284308235720483205"], + ]; + } + + public static function provideInvalidInputData(): array + { + return [ + ['nonumber'], + ['12.3E36'], + ['0x86'], + ['5.5'], + ]; + } + public function testZero(): void { $decimal = new Integer(0); @@ -48,8 +72,6 @@ public function testThrowsTypeErrorOnInvalidString(): void /** * @dataProvider provideToQueryData - * - * @param $number */ public function testToQuery($number, string $expected): void { @@ -67,28 +89,4 @@ public function testInvalidInput($input): void $this->expectException(TypeError::class); new Integer($input); } - - public function provideToQueryData(): array - { - return [ - [1, "1"], - [2, "2"], - ["2147483649", "2147483649"], - ["9223372036854775816", "9223372036854775816"], - [-12, "-12"], - [69, "69"], - ["292922929312312831203129382304823043284234729847294324724982749274294729427429471230918457", "292922929312312831203129382304823043284234729847294324724982749274294729427429471230918457"], - ["-1238109438204130457284308235720483205", "-1238109438204130457284308235720483205"], - ]; - } - - public function provideInvalidInputData(): array - { - return [ - ['nonumber'], - ['12.3E36'], - ['0x86'], - ['5.5'], - ]; - } } diff --git a/tests/unit/Expressions/Literals/ListTest.php b/tests/unit/Expressions/Literals/ListTest.php index c3440858..54802dc5 100644 --- a/tests/unit/Expressions/Literals/ListTest.php +++ b/tests/unit/Expressions/Literals/ListTest.php @@ -20,6 +20,24 @@ */ final class ListTest extends TestCase { + public static function provideOneDimensionalData(): array + { + return [ + [[Query::literal(12)], "[12]"], + [[Query::literal('12')], "['12']"], + [[Query::literal('12'), Query::literal('13')], "['12', '13']"], + ]; + } + + public static function provideMultidimensionalData(): array + { + return [ + [[new List_([Query::literal(12)])], "[[12]]"], + [[new List_([Query::literal('12')])], "[['12']]"], + [[new List_([Query::literal('12'), Query::literal('14')]), new List_([Query::literal('13')])], "[['12', '14'], ['13']]"], + ]; + } + public function testEmpty(): void { $list = new List_([]); @@ -145,22 +163,4 @@ public function testMultidimensional(array $expressions, string $expected): void $this->assertSame($expected, $list->toQuery()); } - - public function provideOneDimensionalData(): array - { - return [ - [[Query::literal(12)], "[12]"], - [[Query::literal('12')], "['12']"], - [[Query::literal('12'), Query::literal('13')], "['12', '13']"], - ]; - } - - public function provideMultidimensionalData(): array - { - return [ - [[new List_([Query::literal(12)])], "[[12]]"], - [[new List_([Query::literal('12')])], "[['12']]"], - [[new List_([Query::literal('12'), Query::literal('14')]), new List_([Query::literal('13')])], "[['12', '14'], ['13']]"], - ]; - } } diff --git a/tests/unit/Expressions/Literals/LiteralTest.php b/tests/unit/Expressions/Literals/LiteralTest.php index 916aa89c..08bfd386 100644 --- a/tests/unit/Expressions/Literals/LiteralTest.php +++ b/tests/unit/Expressions/Literals/LiteralTest.php @@ -33,108 +33,396 @@ */ final class LiteralTest extends TestCase { - public function testLiteralString(): void + public static function provideLiteralDeductionFailure(): array { - $string = Literal::literal('Testing is a virtue!'); - - $this->assertInstanceOf(String_::class, $string); + return [ + [new class() + { + }, ], + [null], + ]; } - public function testLiteralBoolean(): void + public static function provideDateYMDData(): array { - $boolean = Literal::literal(true); + return [ + [2000, null, null, new Date(Literal::map(["year" => 2000]))], + [2000, 12, null, new Date(Literal::map(["year" => 2000, "month" => 12]))], + [2000, 12, 17, new Date(Literal::map(["year" => 2000, "month" => 12, "day" => 17]))], + [new Integer(2000), null, null, new Date(Literal::map(["year" => 2000]))], + [new Integer(2000), new Integer(12), null, new Date(Literal::map(["year" => 2000, "month" => 12]))], + [new Integer(2000), new Integer(12), new Integer(17), new Date(Literal::map(["year" => 2000, "month" => 12, "day" => 17]))], - $this->assertInstanceOf(Boolean::class, $boolean); + ]; } - public function testLiteralInteger(): void + public static function provideDateYWDData(): array { - $integer = Literal::literal(1); + return [ + [2000, null, null, new Date(Literal::map(["year" => 2000]))], + [2000, 12, null, new Date(Literal::map(["year" => 2000, "week" => 12]))], + [2000, 12, 17, new Date(Literal::map(["year" => 2000, "week" => 12, "dayOfWeek" => 17]))], + [new Integer(2000), null, null, new Date(Literal::map(["year" => 2000]))], + [new Integer(2000), new Integer(12), null, new Date(Literal::map(["year" => 2000, "week" => 12]))], + [new Integer(2000), new Integer(12), new Integer(17), new Date(Literal::map(["year" => 2000, "week" => 12, "dayOfWeek" => 17]))], - $this->assertInstanceOf(Integer::class, $integer); + ]; } - public function testLiteralFloat(): void + public static function provideDatetimeYMDData(): array { - $float = Literal::literal(1.0); + // [$year, $month, $day, $hour, $minute, $second, $millisecond, $microsecond, $nanosecond, $timezone, $expected] + return [ + [2000, null, null, null, null, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000]))], + [2000, 12, null, null, null, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "month" => 12]))], + [2000, 12, 15, null, null, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "month" => 12, "day" => 15]))], + [2000, 12, 15, 8, null, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "month" => 12, "day" => 15, "hour" => 8]))], + [2000, 12, 15, 8, 25, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "month" => 12, "day" => 15, "hour" => 8, "minute" => 25]))], + [2000, 12, 15, 8, 25, 44, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "month" => 12, "day" => 15, "hour" => 8, "minute" => 25, "second" => 44]))], + [2000, 12, 15, 8, 25, 44, 18, null, null, null, new DateTime(Literal::map(["year" => 2000, "month" => 12, "day" => 15, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18]))], + [2000, 12, 15, 8, 25, 44, 18, 6, null, null, new DateTime(Literal::map(["year" => 2000, "month" => 12, "day" => 15, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6]))], + [2000, 12, 15, 8, 25, 44, 18, 6, 31, null, new DateTime(Literal::map(["year" => 2000, "month" => 12, "day" => 15, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6, "nanosecond" => 31]))], + [2000, 12, 15, 8, 25, 44, 18, 6, 31, "America/Los Angeles", new DateTime(Literal::map(["year" => 2000, "month" => 12, "day" => 15, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6, "nanosecond" => 31, "timezone" => "America/Los Angeles"]))], - $this->assertInstanceOf(Float_::class, $float); + // types + [new Integer(2000), null, null, null, null, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000]))], + [new Integer(2000), new Integer(12), null, null, null, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "month" => 12]))], + [new Integer(2000), new Integer(12), new Integer(15), null, null, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "month" => 12, "day" => 15]))], + [new Integer(2000), new Integer(12), new Integer(15), new Integer(8), null, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "month" => 12, "day" => 15, "hour" => 8]))], + [new Integer(2000), new Integer(12), new Integer(15), new Integer(8), new Integer(25), null, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "month" => 12, "day" => 15, "hour" => 8, "minute" => 25]))], + [new Integer(2000), new Integer(12), new Integer(15), new Integer(8), new Integer(25), new Integer(44), null, null, null, null, new DateTime(Literal::map(["year" => 2000, "month" => 12, "day" => 15, "hour" => 8, "minute" => 25, "second" => 44]))], + [new Integer(2000), new Integer(12), new Integer(15), new Integer(8), new Integer(25), new Integer(44), new Integer(18), null, null, null, new DateTime(Literal::map(["year" => 2000, "month" => 12, "day" => 15, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18]))], + [new Integer(2000), new Integer(12), new Integer(15), new Integer(8), new Integer(25), new Integer(44), new Integer(18), new Integer(6), null, null, new DateTime(Literal::map(["year" => 2000, "month" => 12, "day" => 15, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6]))], + [new Integer(2000), new Integer(12), new Integer(15), new Integer(8), new Integer(25), new Integer(44), new Integer(18), new Integer(6), new Integer(31), null, new DateTime(Literal::map(["year" => 2000, "month" => 12, "day" => 15, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6, "nanosecond" => 31]))], + [new Integer(2000), new Integer(12), new Integer(15), new Integer(8), new Integer(25), new Integer(44), new Integer(18), new Integer(6), new Integer(31), new String_("America/Los Angeles"), new DateTime(Literal::map(["year" => 2000, "month" => 12, "day" => 15, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6, "nanosecond" => 31, "timezone" => "America/Los Angeles"]))], + ]; } - public function testLiteralList(): void + public static function provideDatetimeYWDData(): array { - $list = Literal::literal(['a', 'b', 'c']); + // [$year, $week, $dayOfWeek, $hour, $minute, $second, $millisecond, $microsecond, $nanosecond, $timezone, $expected] + return [ + [2000, null, null, null, null, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000]))], + [2000, 9, null, null, null, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "week" => 9]))], + [2000, 9, 4, null, null, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "week" => 9, "dayOfWeek" => 4]))], + [2000, 9, 4, 8, null, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "week" => 9, "dayOfWeek" => 4, "hour" => 8]))], + [2000, 9, 4, 8, 25, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "week" => 9, "dayOfWeek" => 4, "hour" => 8, "minute" => 25]))], + [2000, 9, 4, 8, 25, 44, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "week" => 9, "dayOfWeek" => 4, "hour" => 8, "minute" => 25, "second" => 44]))], + [2000, 9, 4, 8, 25, 44, 18, null, null, null, new DateTime(Literal::map(["year" => 2000, "week" => 9, "dayOfWeek" => 4, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18]))], + [2000, 9, 4, 8, 25, 44, 18, 6, null, null, new DateTime(Literal::map(["year" => 2000, "week" => 9, "dayOfWeek" => 4, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6]))], + [2000, 9, 4, 8, 25, 44, 18, 6, 31, null, new DateTime(Literal::map(["year" => 2000, "week" => 9, "dayOfWeek" => 4, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6, "nanosecond" => 31]))], + [2000, 9, 4, 8, 25, 44, 18, 6, 31, "America/Los Angeles", new DateTime(Literal::map(["year" => 2000, "week" => 9, "dayOfWeek" => 4, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6, "nanosecond" => 31, "timezone" => "America/Los Angeles"]))], - $this->assertInstanceOf(List_::class, $list); + // types + [new Integer(2000), null, null, null, null, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000]))], + [new Integer(2000), new Integer(9), null, null, null, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "week" => 9]))], + [new Integer(2000), new Integer(9), new Integer(4), null, null, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "week" => 9, "dayOfWeek" => 4]))], + [new Integer(2000), new Integer(9), new Integer(4), new Integer(8), null, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "week" => 9, "dayOfWeek" => 4, "hour" => 8]))], + [new Integer(2000), new Integer(9), new Integer(4), new Integer(8), new Integer(25), null, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "week" => 9, "dayOfWeek" => 4, "hour" => 8, "minute" => 25]))], + [new Integer(2000), new Integer(9), new Integer(4), new Integer(8), new Integer(25), new Integer(44), null, null, null, null, new DateTime(Literal::map(["year" => 2000, "week" => 9, "dayOfWeek" => 4, "hour" => 8, "minute" => 25, "second" => 44]))], + [new Integer(2000), new Integer(9), new Integer(4), new Integer(8), new Integer(25), new Integer(44), new Integer(18), null, null, null, new DateTime(Literal::map(["year" => 2000, "week" => 9, "dayOfWeek" => 4, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18]))], + [new Integer(2000), new Integer(9), new Integer(4), new Integer(8), new Integer(25), new Integer(44), new Integer(18), new Integer(6), null, null, new DateTime(Literal::map(["year" => 2000, "week" => 9, "dayOfWeek" => 4, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6]))], + [new Integer(2000), new Integer(9), new Integer(4), new Integer(8), new Integer(25), new Integer(44), new Integer(18), new Integer(6), new Integer(31), null, new DateTime(Literal::map(["year" => 2000, "week" => 9, "dayOfWeek" => 4, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6, "nanosecond" => 31]))], + [new Integer(2000), new Integer(9), new Integer(4), new Integer(8), new Integer(25), new Integer(44), new Integer(18), new Integer(6), new Integer(31), new String_("America/Los Angeles"), new DateTime(Literal::map(["year" => 2000, "week" => 9, "dayOfWeek" => 4, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6, "nanosecond" => 31, "timezone" => "America/Los Angeles"]))], + ]; } - public function testLiteralMap(): void + public static function provideDatetimeYQDData(): array { - $map = Literal::literal(['a' => 'b']); + // [$year, $quarter, $dayOfQuarter, $hour, $minute, $second, $millisecond, $microsecond, $nanosecond, $timezone, $expected] + return [ + [2000, null, null, null, null, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000]))], + [2000, 3, null, null, null, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "quarter" => 3]))], + [2000, 3, 4, null, null, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "quarter" => 3, "dayOfQuarter" => 4]))], + [2000, 3, 4, 8, null, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "quarter" => 3, "dayOfQuarter" => 4, "hour" => 8]))], + [2000, 3, 4, 8, 25, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "quarter" => 3, "dayOfQuarter" => 4, "hour" => 8, "minute" => 25]))], + [2000, 3, 4, 8, 25, 44, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "quarter" => 3, "dayOfQuarter" => 4, "hour" => 8, "minute" => 25, "second" => 44]))], + [2000, 3, 4, 8, 25, 44, 18, null, null, null, new DateTime(Literal::map(["year" => 2000, "quarter" => 3, "dayOfQuarter" => 4, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18]))], + [2000, 3, 4, 8, 25, 44, 18, 6, null, null, new DateTime(Literal::map(["year" => 2000, "quarter" => 3, "dayOfQuarter" => 4, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6]))], + [2000, 3, 4, 8, 25, 44, 18, 6, 31, null, new DateTime(Literal::map(["year" => 2000, "quarter" => 3, "dayOfQuarter" => 4, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6, "nanosecond" => 31]))], + [2000, 3, 4, 8, 25, 44, 18, 6, 31, "America/Los Angeles", new DateTime(Literal::map(["year" => 2000, "quarter" => 3, "dayOfQuarter" => 4, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6, "nanosecond" => 31, "timezone" => "America/Los Angeles"]))], - $this->assertInstanceOf(Map::class, $map); + // types + [new Integer(2000), null, null, null, null, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000]))], + [new Integer(2000), new Integer(3), null, null, null, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "quarter" => 3]))], + [new Integer(2000), new Integer(3), new Integer(4), null, null, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "quarter" => 3, "dayOfQuarter" => 4]))], + [new Integer(2000), new Integer(3), new Integer(4), new Integer(8), null, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "quarter" => 3, "dayOfQuarter" => 4, "hour" => 8]))], + [new Integer(2000), new Integer(3), new Integer(4), new Integer(8), new Integer(25), null, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "quarter" => 3, "dayOfQuarter" => 4, "hour" => 8, "minute" => 25]))], + [new Integer(2000), new Integer(3), new Integer(4), new Integer(8), new Integer(25), new Integer(44), null, null, null, null, new DateTime(Literal::map(["year" => 2000, "quarter" => 3, "dayOfQuarter" => 4, "hour" => 8, "minute" => 25, "second" => 44]))], + [new Integer(2000), new Integer(3), new Integer(4), new Integer(8), new Integer(25), new Integer(44), new Integer(18), null, null, null, new DateTime(Literal::map(["year" => 2000, "quarter" => 3, "dayOfQuarter" => 4, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18]))], + [new Integer(2000), new Integer(3), new Integer(4), new Integer(8), new Integer(25), new Integer(44), new Integer(18), new Integer(6), null, null, new DateTime(Literal::map(["year" => 2000, "quarter" => 3, "dayOfQuarter" => 4, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6]))], + [new Integer(2000), new Integer(3), new Integer(4), new Integer(8), new Integer(25), new Integer(44), new Integer(18), new Integer(6), new Integer(31), null, new DateTime(Literal::map(["year" => 2000, "quarter" => 3, "dayOfQuarter" => 4, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6, "nanosecond" => 31]))], + [new Integer(2000), new Integer(3), new Integer(4), new Integer(8), new Integer(25), new Integer(44), new Integer(18), new Integer(6), new Integer(31), new String_("America/Los Angeles"), new DateTime(Literal::map(["year" => 2000, "quarter" => 3, "dayOfQuarter" => 4, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6, "nanosecond" => 31, "timezone" => "America/Los Angeles"]))], + ]; } - public function testInvalidTypeThrowsException(): void + public static function provideDatetimeYQData(): array { - $this->expectException(TypeError::class); + // [$year, $ordinalDay, $hour, $minute, $second, $millisecond, $microsecond, $nanosecond, $timezone, $expected] + return [ + [2000, null, null, null, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000]))], + [2000, 3, null, null, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "ordinalDay" => 3]))], + [2000, 3, 8, null, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "ordinalDay" => 3, "hour" => 8]))], + [2000, 3, 8, 25, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "ordinalDay" => 3, "hour" => 8, "minute" => 25]))], + [2000, 3, 8, 25, 44, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "ordinalDay" => 3, "hour" => 8, "minute" => 25, "second" => 44]))], + [2000, 3, 8, 25, 44, 18, null, null, null, new DateTime(Literal::map(["year" => 2000, "ordinalDay" => 3, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18]))], + [2000, 3, 8, 25, 44, 18, 6, null, null, new DateTime(Literal::map(["year" => 2000, "ordinalDay" => 3, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6]))], + [2000, 3, 8, 25, 44, 18, 6, 31, null, new DateTime(Literal::map(["year" => 2000, "ordinalDay" => 3, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6, "nanosecond" => 31]))], + [2000, 3, 8, 25, 44, 18, 6, 31, "America/Los Angeles", new DateTime(Literal::map(["year" => 2000, "ordinalDay" => 3, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6, "nanosecond" => 31, "timezone" => "America/Los Angeles"]))], - Literal::literal(new stdClass()); + // types + [new Integer(2000), null, null, null, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000]))], + [new Integer(2000), new Integer(3), null, null, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "ordinalDay" => 3]))], + [new Integer(2000), new Integer(3), new Integer(8), null, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "ordinalDay" => 3, "hour" => 8]))], + [new Integer(2000), new Integer(3), new Integer(8), new Integer(25), null, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "ordinalDay" => 3, "hour" => 8, "minute" => 25]))], + [new Integer(2000), new Integer(3), new Integer(8), new Integer(25), new Integer(44), null, null, null, null, new DateTime(Literal::map(["year" => 2000, "ordinalDay" => 3, "hour" => 8, "minute" => 25, "second" => 44]))], + [new Integer(2000), new Integer(3), new Integer(8), new Integer(25), new Integer(44), new Integer(18), null, null, null, new DateTime(Literal::map(["year" => 2000, "ordinalDay" => 3, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18]))], + [new Integer(2000), new Integer(3), new Integer(8), new Integer(25), new Integer(44), new Integer(18), new Integer(6), null, null, new DateTime(Literal::map(["year" => 2000, "ordinalDay" => 3, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6]))], + [new Integer(2000), new Integer(3), new Integer(8), new Integer(25), new Integer(44), new Integer(18), new Integer(6), new Integer(31), null, new DateTime(Literal::map(["year" => 2000, "ordinalDay" => 3, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6, "nanosecond" => 31]))], + [new Integer(2000), new Integer(3), new Integer(8), new Integer(25), new Integer(44), new Integer(18), new Integer(6), new Integer(31), new String_("America/Los Angeles"), new DateTime(Literal::map(["year" => 2000, "ordinalDay" => 3, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6, "nanosecond" => 31, "timezone" => "America/Los Angeles"]))], + ]; } - public function testStringable(): void + public static function provideLocalDatetimeYMDData(): array { - $stringable = Literal::literal(new class() - { - public function __toString() - { - return 'Testing is a virtue!'; - } - }); - - $this->assertInstanceOf(String_::class, $stringable); - } + // [$year, $month, $day, $hour, $minute, $second, $millisecond, $microsecond, $nanosecond, $expected] + return [ + [2000, null, null, null, null, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000]))], + [2000, 12, null, null, null, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "month" => 12]))], + [2000, 12, 15, null, null, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "month" => 12, "day" => 15]))], + [2000, 12, 15, 8, null, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "month" => 12, "day" => 15, "hour" => 8]))], + [2000, 12, 15, 8, 25, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "month" => 12, "day" => 15, "hour" => 8, "minute" => 25]))], + [2000, 12, 15, 8, 25, 44, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "month" => 12, "day" => 15, "hour" => 8, "minute" => 25, "second" => 44]))], + [2000, 12, 15, 8, 25, 44, 18, null, null, new LocalDateTime(Literal::map(["year" => 2000, "month" => 12, "day" => 15, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18]))], + [2000, 12, 15, 8, 25, 44, 18, 6, null, new LocalDateTime(Literal::map(["year" => 2000, "month" => 12, "day" => 15, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6]))], + [2000, 12, 15, 8, 25, 44, 18, 6, 31, new LocalDateTime(Literal::map(["year" => 2000, "month" => 12, "day" => 15, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6, "nanosecond" => 31]))], - /** - * @dataProvider literalDeductionFailureProvider - */ - public function testLiteralDeductionFailure($value): void - { - $this->expectException(TypeError::class); - Literal::literal($value); + // types + [new Integer(2000), null, null, null, null, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000]))], + [new Integer(2000), new Integer(12), null, null, null, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "month" => 12]))], + [new Integer(2000), new Integer(12), new Integer(15), null, null, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "month" => 12, "day" => 15]))], + [new Integer(2000), new Integer(12), new Integer(15), new Integer(8), null, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "month" => 12, "day" => 15, "hour" => 8]))], + [new Integer(2000), new Integer(12), new Integer(15), new Integer(8), new Integer(25), null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "month" => 12, "day" => 15, "hour" => 8, "minute" => 25]))], + [new Integer(2000), new Integer(12), new Integer(15), new Integer(8), new Integer(25), new Integer(44), null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "month" => 12, "day" => 15, "hour" => 8, "minute" => 25, "second" => 44]))], + [new Integer(2000), new Integer(12), new Integer(15), new Integer(8), new Integer(25), new Integer(44), new Integer(18), null, null, new LocalDateTime(Literal::map(["year" => 2000, "month" => 12, "day" => 15, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18]))], + [new Integer(2000), new Integer(12), new Integer(15), new Integer(8), new Integer(25), new Integer(44), new Integer(18), new Integer(6), null, new LocalDateTime(Literal::map(["year" => 2000, "month" => 12, "day" => 15, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6]))], + [new Integer(2000), new Integer(12), new Integer(15), new Integer(8), new Integer(25), new Integer(44), new Integer(18), new Integer(6), new Integer(31), new LocalDateTime(Literal::map(["year" => 2000, "month" => 12, "day" => 15, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6, "nanosecond" => 31]))], + ]; } - public function literalDeductionFailureProvider(): array + public static function provideLocalDatetimeYWDData(): array { + // [$year, $week, $dayOfWeek, $hour, $minute, $second, $millisecond, $microsecond, $nanosecond, $expected] return [ - [new class() - { - }, ], - [null], + [2000, null, null, null, null, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000]))], + [2000, 9, null, null, null, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "week" => 9]))], + [2000, 9, 4, null, null, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "week" => 9, "dayOfWeek" => 4]))], + [2000, 9, 4, 8, null, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "week" => 9, "dayOfWeek" => 4, "hour" => 8]))], + [2000, 9, 4, 8, 25, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "week" => 9, "dayOfWeek" => 4, "hour" => 8, "minute" => 25]))], + [2000, 9, 4, 8, 25, 44, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "week" => 9, "dayOfWeek" => 4, "hour" => 8, "minute" => 25, "second" => 44]))], + [2000, 9, 4, 8, 25, 44, 18, null, null, new LocalDateTime(Literal::map(["year" => 2000, "week" => 9, "dayOfWeek" => 4, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18]))], + [2000, 9, 4, 8, 25, 44, 18, 6, null, new LocalDateTime(Literal::map(["year" => 2000, "week" => 9, "dayOfWeek" => 4, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6]))], + [2000, 9, 4, 8, 25, 44, 18, 6, 31, new LocalDateTime(Literal::map(["year" => 2000, "week" => 9, "dayOfWeek" => 4, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6, "nanosecond" => 31]))], + + // types + [new Integer(2000), null, null, null, null, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000]))], + [new Integer(2000), new Integer(9), null, null, null, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "week" => 9]))], + [new Integer(2000), new Integer(9), new Integer(4), null, null, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "week" => 9, "dayOfWeek" => 4]))], + [new Integer(2000), new Integer(9), new Integer(4), new Integer(8), null, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "week" => 9, "dayOfWeek" => 4, "hour" => 8]))], + [new Integer(2000), new Integer(9), new Integer(4), new Integer(8), new Integer(25), null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "week" => 9, "dayOfWeek" => 4, "hour" => 8, "minute" => 25]))], + [new Integer(2000), new Integer(9), new Integer(4), new Integer(8), new Integer(25), new Integer(44), null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "week" => 9, "dayOfWeek" => 4, "hour" => 8, "minute" => 25, "second" => 44]))], + [new Integer(2000), new Integer(9), new Integer(4), new Integer(8), new Integer(25), new Integer(44), new Integer(18), null, null, new LocalDateTime(Literal::map(["year" => 2000, "week" => 9, "dayOfWeek" => 4, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18]))], + [new Integer(2000), new Integer(9), new Integer(4), new Integer(8), new Integer(25), new Integer(44), new Integer(18), new Integer(6), null, new LocalDateTime(Literal::map(["year" => 2000, "week" => 9, "dayOfWeek" => 4, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6]))], + [new Integer(2000), new Integer(9), new Integer(4), new Integer(8), new Integer(25), new Integer(44), new Integer(18), new Integer(6), new Integer(31), new LocalDateTime(Literal::map(["year" => 2000, "week" => 9, "dayOfWeek" => 4, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6, "nanosecond" => 31]))], ]; } - public function testNumberInteger(): void + public static function provideLocalDatetimeYQDData(): array { - $integer = Literal::number(1); + // [$year, $quarter, $dayOfQuarter, $hour, $minute, $second, $millisecond, $microsecond, $nanosecond, $expected] + return [ + [2000, null, null, null, null, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000]))], + [2000, 3, null, null, null, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "quarter" => 3]))], + [2000, 3, 4, null, null, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "quarter" => 3, "dayOfQuarter" => 4]))], + [2000, 3, 4, 8, null, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "quarter" => 3, "dayOfQuarter" => 4, "hour" => 8]))], + [2000, 3, 4, 8, 25, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "quarter" => 3, "dayOfQuarter" => 4, "hour" => 8, "minute" => 25]))], + [2000, 3, 4, 8, 25, 44, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "quarter" => 3, "dayOfQuarter" => 4, "hour" => 8, "minute" => 25, "second" => 44]))], + [2000, 3, 4, 8, 25, 44, 18, null, null, new LocalDateTime(Literal::map(["year" => 2000, "quarter" => 3, "dayOfQuarter" => 4, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18]))], + [2000, 3, 4, 8, 25, 44, 18, 6, null, new LocalDateTime(Literal::map(["year" => 2000, "quarter" => 3, "dayOfQuarter" => 4, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6]))], + [2000, 3, 4, 8, 25, 44, 18, 6, 31, new LocalDateTime(Literal::map(["year" => 2000, "quarter" => 3, "dayOfQuarter" => 4, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6, "nanosecond" => 31]))], - $this->assertInstanceOf(Integer::class, $integer); + // types + [new Integer(2000), null, null, null, null, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000]))], + [new Integer(2000), new Integer(3), null, null, null, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "quarter" => 3]))], + [new Integer(2000), new Integer(3), new Integer(4), null, null, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "quarter" => 3, "dayOfQuarter" => 4]))], + [new Integer(2000), new Integer(3), new Integer(4), new Integer(8), null, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "quarter" => 3, "dayOfQuarter" => 4, "hour" => 8]))], + [new Integer(2000), new Integer(3), new Integer(4), new Integer(8), new Integer(25), null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "quarter" => 3, "dayOfQuarter" => 4, "hour" => 8, "minute" => 25]))], + [new Integer(2000), new Integer(3), new Integer(4), new Integer(8), new Integer(25), new Integer(44), null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "quarter" => 3, "dayOfQuarter" => 4, "hour" => 8, "minute" => 25, "second" => 44]))], + [new Integer(2000), new Integer(3), new Integer(4), new Integer(8), new Integer(25), new Integer(44), new Integer(18), null, null, new LocalDateTime(Literal::map(["year" => 2000, "quarter" => 3, "dayOfQuarter" => 4, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18]))], + [new Integer(2000), new Integer(3), new Integer(4), new Integer(8), new Integer(25), new Integer(44), new Integer(18), new Integer(6), null, new LocalDateTime(Literal::map(["year" => 2000, "quarter" => 3, "dayOfQuarter" => 4, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6]))], + [new Integer(2000), new Integer(3), new Integer(4), new Integer(8), new Integer(25), new Integer(44), new Integer(18), new Integer(6), new Integer(31), new LocalDateTime(Literal::map(["year" => 2000, "quarter" => 3, "dayOfQuarter" => 4, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6, "nanosecond" => 31]))], + ]; } - public function testNumberFloat(): void + public static function provideLocalDatetimeYQData(): array { - $float = Literal::number(1.0); + // [$year, $ordinalDay, $hour, $minute, $second, $millisecond, $microsecond, $nanosecond, $expected] + return [ + [2000, null, null, null, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000]))], + [2000, 3, null, null, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "ordinalDay" => 3]))], + [2000, 3, 8, null, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "ordinalDay" => 3, "hour" => 8]))], + [2000, 3, 8, 25, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "ordinalDay" => 3, "hour" => 8, "minute" => 25]))], + [2000, 3, 8, 25, 44, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "ordinalDay" => 3, "hour" => 8, "minute" => 25, "second" => 44]))], + [2000, 3, 8, 25, 44, 18, null, null, new LocalDateTime(Literal::map(["year" => 2000, "ordinalDay" => 3, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18]))], + [2000, 3, 8, 25, 44, 18, 6, null, new LocalDateTime(Literal::map(["year" => 2000, "ordinalDay" => 3, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6]))], + [2000, 3, 8, 25, 44, 18, 6, 31, new LocalDateTime(Literal::map(["year" => 2000, "ordinalDay" => 3, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6, "nanosecond" => 31]))], - $this->assertInstanceOf(Float_::class, $float); + // types + [new Integer(2000), null, null, null, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000]))], + [new Integer(2000), new Integer(3), null, null, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "ordinalDay" => 3]))], + [new Integer(2000), new Integer(3), new Integer(8), null, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "ordinalDay" => 3, "hour" => 8]))], + [new Integer(2000), new Integer(3), new Integer(8), new Integer(25), null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "ordinalDay" => 3, "hour" => 8, "minute" => 25]))], + [new Integer(2000), new Integer(3), new Integer(8), new Integer(25), new Integer(44), null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "ordinalDay" => 3, "hour" => 8, "minute" => 25, "second" => 44]))], + [new Integer(2000), new Integer(3), new Integer(8), new Integer(25), new Integer(44), new Integer(18), null, null, new LocalDateTime(Literal::map(["year" => 2000, "ordinalDay" => 3, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18]))], + [new Integer(2000), new Integer(3), new Integer(8), new Integer(25), new Integer(44), new Integer(18), new Integer(6), null, new LocalDateTime(Literal::map(["year" => 2000, "ordinalDay" => 3, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6]))], + [new Integer(2000), new Integer(3), new Integer(8), new Integer(25), new Integer(44), new Integer(18), new Integer(6), new Integer(31), new LocalDateTime(Literal::map(["year" => 2000, "ordinalDay" => 3, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6, "nanosecond" => 31]))], + ]; } - public function testNumberNoString(): void + public static function provideLocalTimeData(): array { - $this->expectException(TypeError::class); - - Literal::number('55'); - } - + // [$hour, $minute, $second, $millisecond, $microsecond, $nanosecond, $expected] + return [ + [11, null, null, null, null, null, new LocalTime(Literal::map(["hour" => 11]))], + [11, 23, null, null, null, null, new LocalTime(Literal::map(["hour" => 11, "minute" => 23]))], + [11, 23, 2, null, null, null, new LocalTime(Literal::map(["hour" => 11, "minute" => 23, "second" => 2]))], + [11, 23, 2, 54, null, null, new LocalTime(Literal::map(["hour" => 11, "minute" => 23, "second" => 2, "millisecond" => 54]))], + [11, 23, 2, 54, 8, null, new LocalTime(Literal::map(["hour" => 11, "minute" => 23, "second" => 2, "millisecond" => 54, "microsecond" => 8]))], + [11, 23, 2, 54, 8, 29, new LocalTime(Literal::map(["hour" => 11, "minute" => 23, "second" => 2, "millisecond" => 54, "microsecond" => 8, "nanosecond" => 29]))], + + // types + [new Integer(11), null, null, null, null, null, new LocalTime(Literal::map(["hour" => 11]))], + [new Integer(11), new Integer(23), null, null, null, null, new LocalTime(Literal::map(["hour" => 11, "minute" => 23]))], + [new Integer(11), new Integer(23), new Integer(2), null, null, null, new LocalTime(Literal::map(["hour" => 11, "minute" => 23, "second" => 2]))], + [new Integer(11), new Integer(23), new Integer(2), new Integer(54), null, null, new LocalTime(Literal::map(["hour" => 11, "minute" => 23, "second" => 2, "millisecond" => 54]))], + [new Integer(11), new Integer(23), new Integer(2), new Integer(54), new Integer(8), null, new LocalTime(Literal::map(["hour" => 11, "minute" => 23, "second" => 2, "millisecond" => 54, "microsecond" => 8]))], + [new Integer(11), new Integer(23), new Integer(2), new Integer(54), new Integer(8), new Integer(29), new LocalTime(Literal::map(["hour" => 11, "minute" => 23, "second" => 2, "millisecond" => 54, "microsecond" => 8, "nanosecond" => 29]))], + ]; + } + + public static function provideTimeData(): array + { + // [$hour, $minute, $second, $millisecond, $microsecond, $nanosecond, $expected] + return [ + [11, null, null, null, null, null, new Time(Literal::map(["hour" => 11]))], + [11, 23, null, null, null, null, new Time(Literal::map(["hour" => 11, "minute" => 23]))], + [11, 23, 2, null, null, null, new Time(Literal::map(["hour" => 11, "minute" => 23, "second" => 2]))], + [11, 23, 2, 54, null, null, new Time(Literal::map(["hour" => 11, "minute" => 23, "second" => 2, "millisecond" => 54]))], + [11, 23, 2, 54, 8, null, new Time(Literal::map(["hour" => 11, "minute" => 23, "second" => 2, "millisecond" => 54, "microsecond" => 8]))], + [11, 23, 2, 54, 8, 29, new Time(Literal::map(["hour" => 11, "minute" => 23, "second" => 2, "millisecond" => 54, "microsecond" => 8, "nanosecond" => 29]))], + + // types + [new Integer(11), null, null, null, null, null, new Time(Literal::map(["hour" => 11]))], + [new Integer(11), new Integer(23), null, null, null, null, new Time(Literal::map(["hour" => 11, "minute" => 23]))], + [new Integer(11), new Integer(23), new Integer(2), null, null, null, new Time(Literal::map(["hour" => 11, "minute" => 23, "second" => 2]))], + [new Integer(11), new Integer(23), new Integer(2), new Integer(54), null, null, new Time(Literal::map(["hour" => 11, "minute" => 23, "second" => 2, "millisecond" => 54]))], + [new Integer(11), new Integer(23), new Integer(2), new Integer(54), new Integer(8), null, new Time(Literal::map(["hour" => 11, "minute" => 23, "second" => 2, "millisecond" => 54, "microsecond" => 8]))], + [new Integer(11), new Integer(23), new Integer(2), new Integer(54), new Integer(8), new Integer(29), new Time(Literal::map(["hour" => 11, "minute" => 23, "second" => 2, "millisecond" => 54, "microsecond" => 8, "nanosecond" => 29]))], + ]; + } + + public function testLiteralString(): void + { + $string = Literal::literal('Testing is a virtue!'); + + $this->assertInstanceOf(String_::class, $string); + } + + public function testLiteralBoolean(): void + { + $boolean = Literal::literal(true); + + $this->assertInstanceOf(Boolean::class, $boolean); + } + + public function testLiteralInteger(): void + { + $integer = Literal::literal(1); + + $this->assertInstanceOf(Integer::class, $integer); + } + + public function testLiteralFloat(): void + { + $float = Literal::literal(1.0); + + $this->assertInstanceOf(Float_::class, $float); + } + + public function testLiteralList(): void + { + $list = Literal::literal(['a', 'b', 'c']); + + $this->assertInstanceOf(List_::class, $list); + } + + public function testLiteralMap(): void + { + $map = Literal::literal(['a' => 'b']); + + $this->assertInstanceOf(Map::class, $map); + } + + public function testInvalidTypeThrowsException(): void + { + $this->expectException(TypeError::class); + + Literal::literal(new stdClass()); + } + + public function testStringable(): void + { + $stringable = Literal::literal(new class() + { + public function __toString() + { + return 'Testing is a virtue!'; + } + }); + + $this->assertInstanceOf(String_::class, $stringable); + } + + /** + * @dataProvider provideLiteralDeductionFailure + */ + public function testLiteralDeductionFailure($value): void + { + $this->expectException(TypeError::class); + Literal::literal($value); + } + + public function testNumberInteger(): void + { + $integer = Literal::number(1); + + $this->assertInstanceOf(Integer::class, $integer); + } + + public function testNumberFloat(): void + { + $float = Literal::number(1.0); + + $this->assertInstanceOf(Float_::class, $float); + } + + public function testNumberNoString(): void + { + $this->expectException(TypeError::class); + + Literal::number('55'); + } + public function testBoolean(): void { $boolean = Literal::boolean(true); @@ -189,21 +477,21 @@ public function testListAcceptsIterable(): void { $list = Literal::list(new class implements Iterator { - public function current() + public function current(): int { return 1; } - public function next() + public function next(): void { - return 1; } - public function key(): void + public function key(): string { + return ''; } - public function valid() + public function valid(): bool { static $i = 0; @@ -317,11 +605,6 @@ public function testDateTimezone(): void /** * @dataProvider provideDateYMDData - * - * @param $year - * @param $month - * @param $day - * @param $expected */ public function testDateYMD($year, $month, $day, $expected): void { @@ -341,11 +624,6 @@ public function testDateYMDMissingMonth(): void /** * @dataProvider provideDateYWDData - * - * @param $year - * @param $week - * @param $weekday - * @param $expected */ public function testDateYWD($year, $week, $weekday, $expected): void { @@ -386,18 +664,6 @@ public function testDateTimeWithTimeZone(): void /** * @dataProvider provideDatetimeYMDData - * - * @param $year - * @param $month - * @param $day - * @param $hour - * @param $minute - * @param $second - * @param $millisecond - * @param $microsecond - * @param $nanosecond - * @param $timezone - * @param $expected */ public function testDatetimeYMD($year, $month, $day, $hour, $minute, $second, $millisecond, $microsecond, $nanosecond, $timezone, $expected): void { @@ -417,18 +683,6 @@ public function testDatetimeYMDMissingMonth(): void /** * @dataProvider provideDatetimeYWDData - * - * @param $year - * @param $week - * @param $dayOfWeek - * @param $hour - * @param $minute - * @param $second - * @param $millisecond - * @param $microsecond - * @param $nanosecond - * @param $timezone - * @param $expected */ public function testDatetimeYWD($year, $week, $dayOfWeek, $hour, $minute, $second, $millisecond, $microsecond, $nanosecond, $timezone, $expected): void { @@ -448,18 +702,6 @@ public function testDatetimeYWDMissingWeek(): void /** * @dataProvider provideDatetimeYQDData - * - * @param $year - * @param $quarter - * @param $dayOfQuarter - * @param $hour - * @param $minute - * @param $second - * @param $millisecond - * @param $microsecond - * @param $nanosecond - * @param $timezone - * @param $expected */ public function testDatetimeYQD($year, $quarter, $dayOfQuarter, $hour, $minute, $second, $millisecond, $microsecond, $nanosecond, $timezone, $expected): void { @@ -479,17 +721,6 @@ public function testDatetimeYQDMissingQuarter(): void /** * @dataProvider provideDatetimeYQData - * - * @param $year - * @param $ordinalDay - * @param $hour - * @param $minute - * @param $second - * @param $millisecond - * @param $microsecond - * @param $nanosecond - * @param $timezone - * @param $expected */ public function testDatetimeYD($year, $ordinalDay, $hour, $minute, $second, $millisecond, $microsecond, $nanosecond, $timezone, $expected): void { @@ -530,17 +761,6 @@ public function testLocalDateTimeWithTimezone(): void /** * @dataProvider provideLocalDatetimeYMDData - * - * @param $year - * @param $month - * @param $day - * @param $hour - * @param $minute - * @param $second - * @param $millisecond - * @param $microsecond - * @param $nanosecond - * @param $expected */ public function testLocalDateTimeYMD($year, $month, $day, $hour, $minute, $second, $millisecond, $microsecond, $nanosecond, $expected): void { @@ -560,17 +780,6 @@ public function testLocalDateTimeYMDMissingMonth(): void /** * @dataProvider provideLocalDatetimeYWDData - * - * @param $year - * @param $week - * @param $dayOfWeek - * @param $hour - * @param $minute - * @param $second - * @param $millisecond - * @param $microsecond - * @param $nanosecond - * @param $expected */ public function testLocalDateTimeYWD($year, $week, $dayOfWeek, $hour, $minute, $second, $millisecond, $microsecond, $nanosecond, $expected): void { @@ -590,17 +799,6 @@ public function testLocalDateTimeYWDMissingWeek(): void /** * @dataProvider provideLocalDatetimeYQDData - * - * @param $year - * @param $quarter - * @param $dayOfQuarter - * @param $hour - * @param $minute - * @param $second - * @param $millisecond - * @param $microsecond - * @param $nanosecond - * @param $expected */ public function testLocalDatetimeYQD($year, $quarter, $dayOfQuarter, $hour, $minute, $second, $millisecond, $microsecond, $nanosecond, $expected): void { @@ -620,16 +818,6 @@ public function testLocalDateTimeYQDMissingQuarter(): void /** * @dataProvider provideLocalDatetimeYQData - * - * @param $year - * @param $ordinalDay - * @param $hour - * @param $minute - * @param $second - * @param $millisecond - * @param $microsecond - * @param $nanosecond - * @param $expected */ public function testLocalDatetimeYD($year, $ordinalDay, $hour, $minute, $second, $millisecond, $microsecond, $nanosecond, $expected): void { @@ -668,14 +856,6 @@ public function testLocalTimeCurrentWithTimezone(): void /** * @dataProvider provideLocalTimeData - * - * @param $hour - * @param $minute - * @param $second - * @param $millisecond - * @param $microsecond - * @param $nanosecond - * @param $expected */ public function testLocalTime($hour, $minute, $second, $millisecond, $microsecond, $nanosecond, $expected): void { @@ -712,14 +892,6 @@ public function testTimeCurrentWithTimezone(): void /** * @dataProvider provideTimeData - * - * @param $hour - * @param $minute - * @param $second - * @param $millisecond - * @param $microsecond - * @param $nanosecond - * @param $expected */ public function testTime($hour, $minute, $second, $millisecond, $microsecond, $nanosecond, $expected): void { @@ -741,292 +913,4 @@ public function testTimeString(): void $time = Literal::timeString("21:40:32.142+0100"); $this->assertEquals($time, new Time(new String_("21:40:32.142+0100"))); } - - public function provideDateYMDData(): array - { - return [ - [2000, null, null, new Date(Literal::map(["year" => 2000]))], - [2000, 12, null, new Date(Literal::map(["year" => 2000, "month" => 12]))], - [2000, 12, 17, new Date(Literal::map(["year" => 2000, "month" => 12, "day" => 17]))], - [new Integer(2000), null, null, new Date(Literal::map(["year" => 2000]))], - [new Integer(2000), new Integer(12), null, new Date(Literal::map(["year" => 2000, "month" => 12]))], - [new Integer(2000), new Integer(12), new Integer(17), new Date(Literal::map(["year" => 2000, "month" => 12, "day" => 17]))], - - ]; - } - - public function provideDateYWDData(): array - { - return [ - [2000, null, null, new Date(Literal::map(["year" => 2000]))], - [2000, 12, null, new Date(Literal::map(["year" => 2000, "week" => 12]))], - [2000, 12, 17, new Date(Literal::map(["year" => 2000, "week" => 12, "dayOfWeek" => 17]))], - [new Integer(2000), null, null, new Date(Literal::map(["year" => 2000]))], - [new Integer(2000), new Integer(12), null, new Date(Literal::map(["year" => 2000, "week" => 12]))], - [new Integer(2000), new Integer(12), new Integer(17), new Date(Literal::map(["year" => 2000, "week" => 12, "dayOfWeek" => 17]))], - - ]; - } - - public function provideDatetimeYMDData(): array - { - // [$year, $month, $day, $hour, $minute, $second, $millisecond, $microsecond, $nanosecond, $timezone, $expected] - return [ - [2000, null, null, null, null, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000]))], - [2000, 12, null, null, null, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "month" => 12]))], - [2000, 12, 15, null, null, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "month" => 12, "day" => 15]))], - [2000, 12, 15, 8, null, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "month" => 12, "day" => 15, "hour" => 8]))], - [2000, 12, 15, 8, 25, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "month" => 12, "day" => 15, "hour" => 8, "minute" => 25]))], - [2000, 12, 15, 8, 25, 44, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "month" => 12, "day" => 15, "hour" => 8, "minute" => 25, "second" => 44]))], - [2000, 12, 15, 8, 25, 44, 18, null, null, null, new DateTime(Literal::map(["year" => 2000, "month" => 12, "day" => 15, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18]))], - [2000, 12, 15, 8, 25, 44, 18, 6, null, null, new DateTime(Literal::map(["year" => 2000, "month" => 12, "day" => 15, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6]))], - [2000, 12, 15, 8, 25, 44, 18, 6, 31, null, new DateTime(Literal::map(["year" => 2000, "month" => 12, "day" => 15, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6, "nanosecond" => 31]))], - [2000, 12, 15, 8, 25, 44, 18, 6, 31, "America/Los Angeles", new DateTime(Literal::map(["year" => 2000, "month" => 12, "day" => 15, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6, "nanosecond" => 31, "timezone" => "America/Los Angeles"]))], - - // types - [new Integer(2000), null, null, null, null, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000]))], - [new Integer(2000), new Integer(12), null, null, null, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "month" => 12]))], - [new Integer(2000), new Integer(12), new Integer(15), null, null, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "month" => 12, "day" => 15]))], - [new Integer(2000), new Integer(12), new Integer(15), new Integer(8), null, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "month" => 12, "day" => 15, "hour" => 8]))], - [new Integer(2000), new Integer(12), new Integer(15), new Integer(8), new Integer(25), null, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "month" => 12, "day" => 15, "hour" => 8, "minute" => 25]))], - [new Integer(2000), new Integer(12), new Integer(15), new Integer(8), new Integer(25), new Integer(44), null, null, null, null, new DateTime(Literal::map(["year" => 2000, "month" => 12, "day" => 15, "hour" => 8, "minute" => 25, "second" => 44]))], - [new Integer(2000), new Integer(12), new Integer(15), new Integer(8), new Integer(25), new Integer(44), new Integer(18), null, null, null, new DateTime(Literal::map(["year" => 2000, "month" => 12, "day" => 15, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18]))], - [new Integer(2000), new Integer(12), new Integer(15), new Integer(8), new Integer(25), new Integer(44), new Integer(18), new Integer(6), null, null, new DateTime(Literal::map(["year" => 2000, "month" => 12, "day" => 15, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6]))], - [new Integer(2000), new Integer(12), new Integer(15), new Integer(8), new Integer(25), new Integer(44), new Integer(18), new Integer(6), new Integer(31), null, new DateTime(Literal::map(["year" => 2000, "month" => 12, "day" => 15, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6, "nanosecond" => 31]))], - [new Integer(2000), new Integer(12), new Integer(15), new Integer(8), new Integer(25), new Integer(44), new Integer(18), new Integer(6), new Integer(31), new String_("America/Los Angeles"), new DateTime(Literal::map(["year" => 2000, "month" => 12, "day" => 15, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6, "nanosecond" => 31, "timezone" => "America/Los Angeles"]))], - ]; - } - - public function provideDatetimeYWDData(): array - { - // [$year, $week, $dayOfWeek, $hour, $minute, $second, $millisecond, $microsecond, $nanosecond, $timezone, $expected] - return [ - [2000, null, null, null, null, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000]))], - [2000, 9, null, null, null, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "week" => 9]))], - [2000, 9, 4, null, null, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "week" => 9, "dayOfWeek" => 4]))], - [2000, 9, 4, 8, null, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "week" => 9, "dayOfWeek" => 4, "hour" => 8]))], - [2000, 9, 4, 8, 25, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "week" => 9, "dayOfWeek" => 4, "hour" => 8, "minute" => 25]))], - [2000, 9, 4, 8, 25, 44, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "week" => 9, "dayOfWeek" => 4, "hour" => 8, "minute" => 25, "second" => 44]))], - [2000, 9, 4, 8, 25, 44, 18, null, null, null, new DateTime(Literal::map(["year" => 2000, "week" => 9, "dayOfWeek" => 4, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18]))], - [2000, 9, 4, 8, 25, 44, 18, 6, null, null, new DateTime(Literal::map(["year" => 2000, "week" => 9, "dayOfWeek" => 4, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6]))], - [2000, 9, 4, 8, 25, 44, 18, 6, 31, null, new DateTime(Literal::map(["year" => 2000, "week" => 9, "dayOfWeek" => 4, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6, "nanosecond" => 31]))], - [2000, 9, 4, 8, 25, 44, 18, 6, 31, "America/Los Angeles", new DateTime(Literal::map(["year" => 2000, "week" => 9, "dayOfWeek" => 4, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6, "nanosecond" => 31, "timezone" => "America/Los Angeles"]))], - - // types - [new Integer(2000), null, null, null, null, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000]))], - [new Integer(2000), new Integer(9), null, null, null, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "week" => 9]))], - [new Integer(2000), new Integer(9), new Integer(4), null, null, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "week" => 9, "dayOfWeek" => 4]))], - [new Integer(2000), new Integer(9), new Integer(4), new Integer(8), null, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "week" => 9, "dayOfWeek" => 4, "hour" => 8]))], - [new Integer(2000), new Integer(9), new Integer(4), new Integer(8), new Integer(25), null, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "week" => 9, "dayOfWeek" => 4, "hour" => 8, "minute" => 25]))], - [new Integer(2000), new Integer(9), new Integer(4), new Integer(8), new Integer(25), new Integer(44), null, null, null, null, new DateTime(Literal::map(["year" => 2000, "week" => 9, "dayOfWeek" => 4, "hour" => 8, "minute" => 25, "second" => 44]))], - [new Integer(2000), new Integer(9), new Integer(4), new Integer(8), new Integer(25), new Integer(44), new Integer(18), null, null, null, new DateTime(Literal::map(["year" => 2000, "week" => 9, "dayOfWeek" => 4, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18]))], - [new Integer(2000), new Integer(9), new Integer(4), new Integer(8), new Integer(25), new Integer(44), new Integer(18), new Integer(6), null, null, new DateTime(Literal::map(["year" => 2000, "week" => 9, "dayOfWeek" => 4, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6]))], - [new Integer(2000), new Integer(9), new Integer(4), new Integer(8), new Integer(25), new Integer(44), new Integer(18), new Integer(6), new Integer(31), null, new DateTime(Literal::map(["year" => 2000, "week" => 9, "dayOfWeek" => 4, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6, "nanosecond" => 31]))], - [new Integer(2000), new Integer(9), new Integer(4), new Integer(8), new Integer(25), new Integer(44), new Integer(18), new Integer(6), new Integer(31), new String_("America/Los Angeles"), new DateTime(Literal::map(["year" => 2000, "week" => 9, "dayOfWeek" => 4, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6, "nanosecond" => 31, "timezone" => "America/Los Angeles"]))], - ]; - } - - public function provideDatetimeYQDData(): array - { - // [$year, $quarter, $dayOfQuarter, $hour, $minute, $second, $millisecond, $microsecond, $nanosecond, $timezone, $expected] - return [ - [2000, null, null, null, null, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000]))], - [2000, 3, null, null, null, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "quarter" => 3]))], - [2000, 3, 4, null, null, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "quarter" => 3, "dayOfQuarter" => 4]))], - [2000, 3, 4, 8, null, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "quarter" => 3, "dayOfQuarter" => 4, "hour" => 8]))], - [2000, 3, 4, 8, 25, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "quarter" => 3, "dayOfQuarter" => 4, "hour" => 8, "minute" => 25]))], - [2000, 3, 4, 8, 25, 44, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "quarter" => 3, "dayOfQuarter" => 4, "hour" => 8, "minute" => 25, "second" => 44]))], - [2000, 3, 4, 8, 25, 44, 18, null, null, null, new DateTime(Literal::map(["year" => 2000, "quarter" => 3, "dayOfQuarter" => 4, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18]))], - [2000, 3, 4, 8, 25, 44, 18, 6, null, null, new DateTime(Literal::map(["year" => 2000, "quarter" => 3, "dayOfQuarter" => 4, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6]))], - [2000, 3, 4, 8, 25, 44, 18, 6, 31, null, new DateTime(Literal::map(["year" => 2000, "quarter" => 3, "dayOfQuarter" => 4, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6, "nanosecond" => 31]))], - [2000, 3, 4, 8, 25, 44, 18, 6, 31, "America/Los Angeles", new DateTime(Literal::map(["year" => 2000, "quarter" => 3, "dayOfQuarter" => 4, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6, "nanosecond" => 31, "timezone" => "America/Los Angeles"]))], - - // types - [new Integer(2000), null, null, null, null, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000]))], - [new Integer(2000), new Integer(3), null, null, null, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "quarter" => 3]))], - [new Integer(2000), new Integer(3), new Integer(4), null, null, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "quarter" => 3, "dayOfQuarter" => 4]))], - [new Integer(2000), new Integer(3), new Integer(4), new Integer(8), null, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "quarter" => 3, "dayOfQuarter" => 4, "hour" => 8]))], - [new Integer(2000), new Integer(3), new Integer(4), new Integer(8), new Integer(25), null, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "quarter" => 3, "dayOfQuarter" => 4, "hour" => 8, "minute" => 25]))], - [new Integer(2000), new Integer(3), new Integer(4), new Integer(8), new Integer(25), new Integer(44), null, null, null, null, new DateTime(Literal::map(["year" => 2000, "quarter" => 3, "dayOfQuarter" => 4, "hour" => 8, "minute" => 25, "second" => 44]))], - [new Integer(2000), new Integer(3), new Integer(4), new Integer(8), new Integer(25), new Integer(44), new Integer(18), null, null, null, new DateTime(Literal::map(["year" => 2000, "quarter" => 3, "dayOfQuarter" => 4, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18]))], - [new Integer(2000), new Integer(3), new Integer(4), new Integer(8), new Integer(25), new Integer(44), new Integer(18), new Integer(6), null, null, new DateTime(Literal::map(["year" => 2000, "quarter" => 3, "dayOfQuarter" => 4, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6]))], - [new Integer(2000), new Integer(3), new Integer(4), new Integer(8), new Integer(25), new Integer(44), new Integer(18), new Integer(6), new Integer(31), null, new DateTime(Literal::map(["year" => 2000, "quarter" => 3, "dayOfQuarter" => 4, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6, "nanosecond" => 31]))], - [new Integer(2000), new Integer(3), new Integer(4), new Integer(8), new Integer(25), new Integer(44), new Integer(18), new Integer(6), new Integer(31), new String_("America/Los Angeles"), new DateTime(Literal::map(["year" => 2000, "quarter" => 3, "dayOfQuarter" => 4, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6, "nanosecond" => 31, "timezone" => "America/Los Angeles"]))], - ]; - } - - public function provideDatetimeYQData(): array - { - // [$year, $ordinalDay, $hour, $minute, $second, $millisecond, $microsecond, $nanosecond, $timezone, $expected] - return [ - [2000, null, null, null, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000]))], - [2000, 3, null, null, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "ordinalDay" => 3]))], - [2000, 3, 8, null, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "ordinalDay" => 3, "hour" => 8]))], - [2000, 3, 8, 25, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "ordinalDay" => 3, "hour" => 8, "minute" => 25]))], - [2000, 3, 8, 25, 44, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "ordinalDay" => 3, "hour" => 8, "minute" => 25, "second" => 44]))], - [2000, 3, 8, 25, 44, 18, null, null, null, new DateTime(Literal::map(["year" => 2000, "ordinalDay" => 3, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18]))], - [2000, 3, 8, 25, 44, 18, 6, null, null, new DateTime(Literal::map(["year" => 2000, "ordinalDay" => 3, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6]))], - [2000, 3, 8, 25, 44, 18, 6, 31, null, new DateTime(Literal::map(["year" => 2000, "ordinalDay" => 3, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6, "nanosecond" => 31]))], - [2000, 3, 8, 25, 44, 18, 6, 31, "America/Los Angeles", new DateTime(Literal::map(["year" => 2000, "ordinalDay" => 3, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6, "nanosecond" => 31, "timezone" => "America/Los Angeles"]))], - - // types - [new Integer(2000), null, null, null, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000]))], - [new Integer(2000), new Integer(3), null, null, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "ordinalDay" => 3]))], - [new Integer(2000), new Integer(3), new Integer(8), null, null, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "ordinalDay" => 3, "hour" => 8]))], - [new Integer(2000), new Integer(3), new Integer(8), new Integer(25), null, null, null, null, null, new DateTime(Literal::map(["year" => 2000, "ordinalDay" => 3, "hour" => 8, "minute" => 25]))], - [new Integer(2000), new Integer(3), new Integer(8), new Integer(25), new Integer(44), null, null, null, null, new DateTime(Literal::map(["year" => 2000, "ordinalDay" => 3, "hour" => 8, "minute" => 25, "second" => 44]))], - [new Integer(2000), new Integer(3), new Integer(8), new Integer(25), new Integer(44), new Integer(18), null, null, null, new DateTime(Literal::map(["year" => 2000, "ordinalDay" => 3, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18]))], - [new Integer(2000), new Integer(3), new Integer(8), new Integer(25), new Integer(44), new Integer(18), new Integer(6), null, null, new DateTime(Literal::map(["year" => 2000, "ordinalDay" => 3, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6]))], - [new Integer(2000), new Integer(3), new Integer(8), new Integer(25), new Integer(44), new Integer(18), new Integer(6), new Integer(31), null, new DateTime(Literal::map(["year" => 2000, "ordinalDay" => 3, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6, "nanosecond" => 31]))], - [new Integer(2000), new Integer(3), new Integer(8), new Integer(25), new Integer(44), new Integer(18), new Integer(6), new Integer(31), new String_("America/Los Angeles"), new DateTime(Literal::map(["year" => 2000, "ordinalDay" => 3, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6, "nanosecond" => 31, "timezone" => "America/Los Angeles"]))], - ]; - } - - public function provideLocalDatetimeYMDData(): array - { - // [$year, $month, $day, $hour, $minute, $second, $millisecond, $microsecond, $nanosecond, $expected] - return [ - [2000, null, null, null, null, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000]))], - [2000, 12, null, null, null, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "month" => 12]))], - [2000, 12, 15, null, null, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "month" => 12, "day" => 15]))], - [2000, 12, 15, 8, null, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "month" => 12, "day" => 15, "hour" => 8]))], - [2000, 12, 15, 8, 25, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "month" => 12, "day" => 15, "hour" => 8, "minute" => 25]))], - [2000, 12, 15, 8, 25, 44, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "month" => 12, "day" => 15, "hour" => 8, "minute" => 25, "second" => 44]))], - [2000, 12, 15, 8, 25, 44, 18, null, null, new LocalDateTime(Literal::map(["year" => 2000, "month" => 12, "day" => 15, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18]))], - [2000, 12, 15, 8, 25, 44, 18, 6, null, new LocalDateTime(Literal::map(["year" => 2000, "month" => 12, "day" => 15, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6]))], - [2000, 12, 15, 8, 25, 44, 18, 6, 31, new LocalDateTime(Literal::map(["year" => 2000, "month" => 12, "day" => 15, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6, "nanosecond" => 31]))], - - // types - [new Integer(2000), null, null, null, null, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000]))], - [new Integer(2000), new Integer(12), null, null, null, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "month" => 12]))], - [new Integer(2000), new Integer(12), new Integer(15), null, null, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "month" => 12, "day" => 15]))], - [new Integer(2000), new Integer(12), new Integer(15), new Integer(8), null, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "month" => 12, "day" => 15, "hour" => 8]))], - [new Integer(2000), new Integer(12), new Integer(15), new Integer(8), new Integer(25), null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "month" => 12, "day" => 15, "hour" => 8, "minute" => 25]))], - [new Integer(2000), new Integer(12), new Integer(15), new Integer(8), new Integer(25), new Integer(44), null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "month" => 12, "day" => 15, "hour" => 8, "minute" => 25, "second" => 44]))], - [new Integer(2000), new Integer(12), new Integer(15), new Integer(8), new Integer(25), new Integer(44), new Integer(18), null, null, new LocalDateTime(Literal::map(["year" => 2000, "month" => 12, "day" => 15, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18]))], - [new Integer(2000), new Integer(12), new Integer(15), new Integer(8), new Integer(25), new Integer(44), new Integer(18), new Integer(6), null, new LocalDateTime(Literal::map(["year" => 2000, "month" => 12, "day" => 15, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6]))], - [new Integer(2000), new Integer(12), new Integer(15), new Integer(8), new Integer(25), new Integer(44), new Integer(18), new Integer(6), new Integer(31), new LocalDateTime(Literal::map(["year" => 2000, "month" => 12, "day" => 15, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6, "nanosecond" => 31]))], - ]; - } - - public function provideLocalDatetimeYWDData(): array - { - // [$year, $week, $dayOfWeek, $hour, $minute, $second, $millisecond, $microsecond, $nanosecond, $expected] - return [ - [2000, null, null, null, null, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000]))], - [2000, 9, null, null, null, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "week" => 9]))], - [2000, 9, 4, null, null, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "week" => 9, "dayOfWeek" => 4]))], - [2000, 9, 4, 8, null, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "week" => 9, "dayOfWeek" => 4, "hour" => 8]))], - [2000, 9, 4, 8, 25, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "week" => 9, "dayOfWeek" => 4, "hour" => 8, "minute" => 25]))], - [2000, 9, 4, 8, 25, 44, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "week" => 9, "dayOfWeek" => 4, "hour" => 8, "minute" => 25, "second" => 44]))], - [2000, 9, 4, 8, 25, 44, 18, null, null, new LocalDateTime(Literal::map(["year" => 2000, "week" => 9, "dayOfWeek" => 4, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18]))], - [2000, 9, 4, 8, 25, 44, 18, 6, null, new LocalDateTime(Literal::map(["year" => 2000, "week" => 9, "dayOfWeek" => 4, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6]))], - [2000, 9, 4, 8, 25, 44, 18, 6, 31, new LocalDateTime(Literal::map(["year" => 2000, "week" => 9, "dayOfWeek" => 4, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6, "nanosecond" => 31]))], - - // types - [new Integer(2000), null, null, null, null, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000]))], - [new Integer(2000), new Integer(9), null, null, null, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "week" => 9]))], - [new Integer(2000), new Integer(9), new Integer(4), null, null, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "week" => 9, "dayOfWeek" => 4]))], - [new Integer(2000), new Integer(9), new Integer(4), new Integer(8), null, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "week" => 9, "dayOfWeek" => 4, "hour" => 8]))], - [new Integer(2000), new Integer(9), new Integer(4), new Integer(8), new Integer(25), null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "week" => 9, "dayOfWeek" => 4, "hour" => 8, "minute" => 25]))], - [new Integer(2000), new Integer(9), new Integer(4), new Integer(8), new Integer(25), new Integer(44), null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "week" => 9, "dayOfWeek" => 4, "hour" => 8, "minute" => 25, "second" => 44]))], - [new Integer(2000), new Integer(9), new Integer(4), new Integer(8), new Integer(25), new Integer(44), new Integer(18), null, null, new LocalDateTime(Literal::map(["year" => 2000, "week" => 9, "dayOfWeek" => 4, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18]))], - [new Integer(2000), new Integer(9), new Integer(4), new Integer(8), new Integer(25), new Integer(44), new Integer(18), new Integer(6), null, new LocalDateTime(Literal::map(["year" => 2000, "week" => 9, "dayOfWeek" => 4, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6]))], - [new Integer(2000), new Integer(9), new Integer(4), new Integer(8), new Integer(25), new Integer(44), new Integer(18), new Integer(6), new Integer(31), new LocalDateTime(Literal::map(["year" => 2000, "week" => 9, "dayOfWeek" => 4, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6, "nanosecond" => 31]))], - ]; - } - - public function provideLocalDatetimeYQDData(): array - { - // [$year, $quarter, $dayOfQuarter, $hour, $minute, $second, $millisecond, $microsecond, $nanosecond, $expected] - return [ - [2000, null, null, null, null, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000]))], - [2000, 3, null, null, null, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "quarter" => 3]))], - [2000, 3, 4, null, null, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "quarter" => 3, "dayOfQuarter" => 4]))], - [2000, 3, 4, 8, null, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "quarter" => 3, "dayOfQuarter" => 4, "hour" => 8]))], - [2000, 3, 4, 8, 25, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "quarter" => 3, "dayOfQuarter" => 4, "hour" => 8, "minute" => 25]))], - [2000, 3, 4, 8, 25, 44, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "quarter" => 3, "dayOfQuarter" => 4, "hour" => 8, "minute" => 25, "second" => 44]))], - [2000, 3, 4, 8, 25, 44, 18, null, null, new LocalDateTime(Literal::map(["year" => 2000, "quarter" => 3, "dayOfQuarter" => 4, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18]))], - [2000, 3, 4, 8, 25, 44, 18, 6, null, new LocalDateTime(Literal::map(["year" => 2000, "quarter" => 3, "dayOfQuarter" => 4, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6]))], - [2000, 3, 4, 8, 25, 44, 18, 6, 31, new LocalDateTime(Literal::map(["year" => 2000, "quarter" => 3, "dayOfQuarter" => 4, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6, "nanosecond" => 31]))], - - // types - [new Integer(2000), null, null, null, null, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000]))], - [new Integer(2000), new Integer(3), null, null, null, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "quarter" => 3]))], - [new Integer(2000), new Integer(3), new Integer(4), null, null, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "quarter" => 3, "dayOfQuarter" => 4]))], - [new Integer(2000), new Integer(3), new Integer(4), new Integer(8), null, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "quarter" => 3, "dayOfQuarter" => 4, "hour" => 8]))], - [new Integer(2000), new Integer(3), new Integer(4), new Integer(8), new Integer(25), null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "quarter" => 3, "dayOfQuarter" => 4, "hour" => 8, "minute" => 25]))], - [new Integer(2000), new Integer(3), new Integer(4), new Integer(8), new Integer(25), new Integer(44), null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "quarter" => 3, "dayOfQuarter" => 4, "hour" => 8, "minute" => 25, "second" => 44]))], - [new Integer(2000), new Integer(3), new Integer(4), new Integer(8), new Integer(25), new Integer(44), new Integer(18), null, null, new LocalDateTime(Literal::map(["year" => 2000, "quarter" => 3, "dayOfQuarter" => 4, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18]))], - [new Integer(2000), new Integer(3), new Integer(4), new Integer(8), new Integer(25), new Integer(44), new Integer(18), new Integer(6), null, new LocalDateTime(Literal::map(["year" => 2000, "quarter" => 3, "dayOfQuarter" => 4, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6]))], - [new Integer(2000), new Integer(3), new Integer(4), new Integer(8), new Integer(25), new Integer(44), new Integer(18), new Integer(6), new Integer(31), new LocalDateTime(Literal::map(["year" => 2000, "quarter" => 3, "dayOfQuarter" => 4, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6, "nanosecond" => 31]))], - ]; - } - - public function provideLocalDatetimeYQData(): array - { - // [$year, $ordinalDay, $hour, $minute, $second, $millisecond, $microsecond, $nanosecond, $expected] - return [ - [2000, null, null, null, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000]))], - [2000, 3, null, null, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "ordinalDay" => 3]))], - [2000, 3, 8, null, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "ordinalDay" => 3, "hour" => 8]))], - [2000, 3, 8, 25, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "ordinalDay" => 3, "hour" => 8, "minute" => 25]))], - [2000, 3, 8, 25, 44, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "ordinalDay" => 3, "hour" => 8, "minute" => 25, "second" => 44]))], - [2000, 3, 8, 25, 44, 18, null, null, new LocalDateTime(Literal::map(["year" => 2000, "ordinalDay" => 3, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18]))], - [2000, 3, 8, 25, 44, 18, 6, null, new LocalDateTime(Literal::map(["year" => 2000, "ordinalDay" => 3, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6]))], - [2000, 3, 8, 25, 44, 18, 6, 31, new LocalDateTime(Literal::map(["year" => 2000, "ordinalDay" => 3, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6, "nanosecond" => 31]))], - - // types - [new Integer(2000), null, null, null, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000]))], - [new Integer(2000), new Integer(3), null, null, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "ordinalDay" => 3]))], - [new Integer(2000), new Integer(3), new Integer(8), null, null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "ordinalDay" => 3, "hour" => 8]))], - [new Integer(2000), new Integer(3), new Integer(8), new Integer(25), null, null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "ordinalDay" => 3, "hour" => 8, "minute" => 25]))], - [new Integer(2000), new Integer(3), new Integer(8), new Integer(25), new Integer(44), null, null, null, new LocalDateTime(Literal::map(["year" => 2000, "ordinalDay" => 3, "hour" => 8, "minute" => 25, "second" => 44]))], - [new Integer(2000), new Integer(3), new Integer(8), new Integer(25), new Integer(44), new Integer(18), null, null, new LocalDateTime(Literal::map(["year" => 2000, "ordinalDay" => 3, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18]))], - [new Integer(2000), new Integer(3), new Integer(8), new Integer(25), new Integer(44), new Integer(18), new Integer(6), null, new LocalDateTime(Literal::map(["year" => 2000, "ordinalDay" => 3, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6]))], - [new Integer(2000), new Integer(3), new Integer(8), new Integer(25), new Integer(44), new Integer(18), new Integer(6), new Integer(31), new LocalDateTime(Literal::map(["year" => 2000, "ordinalDay" => 3, "hour" => 8, "minute" => 25, "second" => 44, "millisecond" => 18, "microsecond" => 6, "nanosecond" => 31]))], - ]; - } - - public function provideLocalTimeData(): array - { - // [$hour, $minute, $second, $millisecond, $microsecond, $nanosecond, $expected] - return [ - [11, null, null, null, null, null, new LocalTime(Literal::map(["hour" => 11]))], - [11, 23, null, null, null, null, new LocalTime(Literal::map(["hour" => 11, "minute" => 23]))], - [11, 23, 2, null, null, null, new LocalTime(Literal::map(["hour" => 11, "minute" => 23, "second" => 2]))], - [11, 23, 2, 54, null, null, new LocalTime(Literal::map(["hour" => 11, "minute" => 23, "second" => 2, "millisecond" => 54]))], - [11, 23, 2, 54, 8, null, new LocalTime(Literal::map(["hour" => 11, "minute" => 23, "second" => 2, "millisecond" => 54, "microsecond" => 8]))], - [11, 23, 2, 54, 8, 29, new LocalTime(Literal::map(["hour" => 11, "minute" => 23, "second" => 2, "millisecond" => 54, "microsecond" => 8, "nanosecond" => 29]))], - - // types - [new Integer(11), null, null, null, null, null, new LocalTime(Literal::map(["hour" => 11]))], - [new Integer(11), new Integer(23), null, null, null, null, new LocalTime(Literal::map(["hour" => 11, "minute" => 23]))], - [new Integer(11), new Integer(23), new Integer(2), null, null, null, new LocalTime(Literal::map(["hour" => 11, "minute" => 23, "second" => 2]))], - [new Integer(11), new Integer(23), new Integer(2), new Integer(54), null, null, new LocalTime(Literal::map(["hour" => 11, "minute" => 23, "second" => 2, "millisecond" => 54]))], - [new Integer(11), new Integer(23), new Integer(2), new Integer(54), new Integer(8), null, new LocalTime(Literal::map(["hour" => 11, "minute" => 23, "second" => 2, "millisecond" => 54, "microsecond" => 8]))], - [new Integer(11), new Integer(23), new Integer(2), new Integer(54), new Integer(8), new Integer(29), new LocalTime(Literal::map(["hour" => 11, "minute" => 23, "second" => 2, "millisecond" => 54, "microsecond" => 8, "nanosecond" => 29]))], - ]; - } - - public function provideTimeData(): array - { - // [$hour, $minute, $second, $millisecond, $microsecond, $nanosecond, $expected] - return [ - [11, null, null, null, null, null, new Time(Literal::map(["hour" => 11]))], - [11, 23, null, null, null, null, new Time(Literal::map(["hour" => 11, "minute" => 23]))], - [11, 23, 2, null, null, null, new Time(Literal::map(["hour" => 11, "minute" => 23, "second" => 2]))], - [11, 23, 2, 54, null, null, new Time(Literal::map(["hour" => 11, "minute" => 23, "second" => 2, "millisecond" => 54]))], - [11, 23, 2, 54, 8, null, new Time(Literal::map(["hour" => 11, "minute" => 23, "second" => 2, "millisecond" => 54, "microsecond" => 8]))], - [11, 23, 2, 54, 8, 29, new Time(Literal::map(["hour" => 11, "minute" => 23, "second" => 2, "millisecond" => 54, "microsecond" => 8, "nanosecond" => 29]))], - - // types - [new Integer(11), null, null, null, null, null, new Time(Literal::map(["hour" => 11]))], - [new Integer(11), new Integer(23), null, null, null, null, new Time(Literal::map(["hour" => 11, "minute" => 23]))], - [new Integer(11), new Integer(23), new Integer(2), null, null, null, new Time(Literal::map(["hour" => 11, "minute" => 23, "second" => 2]))], - [new Integer(11), new Integer(23), new Integer(2), new Integer(54), null, null, new Time(Literal::map(["hour" => 11, "minute" => 23, "second" => 2, "millisecond" => 54]))], - [new Integer(11), new Integer(23), new Integer(2), new Integer(54), new Integer(8), null, new Time(Literal::map(["hour" => 11, "minute" => 23, "second" => 2, "millisecond" => 54, "microsecond" => 8]))], - [new Integer(11), new Integer(23), new Integer(2), new Integer(54), new Integer(8), new Integer(29), new Time(Literal::map(["hour" => 11, "minute" => 23, "second" => 2, "millisecond" => 54, "microsecond" => 8, "nanosecond" => 29]))], - ]; - } } diff --git a/tests/unit/Expressions/Literals/MapTest.php b/tests/unit/Expressions/Literals/MapTest.php index 9738f440..bfee9778 100644 --- a/tests/unit/Expressions/Literals/MapTest.php +++ b/tests/unit/Expressions/Literals/MapTest.php @@ -19,6 +19,33 @@ */ final class MapTest extends TestCase { + public static function provideNumericalKeysData(): array + { + return [ + [[0 => new String_('a')], "{`0`: 'a'}"], + [[0 => new String_('a'), 1 => new String_('b')], "{`0`: 'a', `1`: 'b'}"], + ]; + } + + public static function provideStringKeysData(): array + { + return [ + [['a' => new String_('a')], "{a: 'a'}"], + [['a' => new String_('a'), 'b' => new String_('b')], "{a: 'a', b: 'b'}"], + [['a' => new String_('b')], "{a: 'b'}"], + [[':' => new String_('a')], "{`:`: 'a'}"], + ]; + } + + public static function provideNestedMapsData() + { + return [ + [['a' => new Map([])], "{a: {}}"], + [['a' => new Map(['a' => new Map(['a' => new String_('b')])])], "{a: {a: {a: 'b'}}}"], + [['a' => new Map(['b' => new String_('c')]), 'b' => new String_('d')], "{a: {b: 'c'}, b: 'd'}"], + ]; + } + public function testEmpty(): void { $map = new Map([]); @@ -101,31 +128,4 @@ public function testIsInstanceOfMapType(): void $this->assertInstanceOf(MapType::class, $map); } - - public function provideNumericalKeysData(): array - { - return [ - [[0 => new String_('a')], "{`0`: 'a'}"], - [[0 => new String_('a'), 1 => new String_('b')], "{`0`: 'a', `1`: 'b'}"], - ]; - } - - public function provideStringKeysData(): array - { - return [ - [['a' => new String_('a')], "{a: 'a'}"], - [['a' => new String_('a'), 'b' => new String_('b')], "{a: 'a', b: 'b'}"], - [['a' => new String_('b')], "{a: 'b'}"], - [[':' => new String_('a')], "{`:`: 'a'}"], - ]; - } - - public function provideNestedMapsData() - { - return [ - [['a' => new Map([])], "{a: {}}"], - [['a' => new Map(['a' => new Map(['a' => new String_('b')])])], "{a: {a: {a: 'b'}}}"], - [['a' => new Map(['b' => new String_('c')]), 'b' => new String_('d')], "{a: {b: 'c'}, b: 'd'}"], - ]; - } } diff --git a/tests/unit/Expressions/Literals/StringTest.php b/tests/unit/Expressions/Literals/StringTest.php index 1be239ae..35044717 100644 --- a/tests/unit/Expressions/Literals/StringTest.php +++ b/tests/unit/Expressions/Literals/StringTest.php @@ -18,6 +18,54 @@ */ final class StringTest extends TestCase { + public static function provideSingleQuotesData(): array + { + return [ + ["a", "'a'"], + ["b", "'b'"], + ["\t", "'\\t'"], + ["\b", "'\\\\b'"], + ["\n", "'\\n'"], + ["\r", "'\\r'"], + ["\f", "'\\f'"], + ["'", "'\\''"], + ["\"", "'\\\"'"], + ["\\\\", "'\\\\\\\\'"], + ["\u1234", "'\\\\u1234'"], + ["\U12345678", "'\\\\U12345678'"], + ["\u0000", "'\\\\u0000'"], + ["\uffff", "'\\\\uffff'"], + ["\U00000000", "'\\\\U00000000'"], + ["\Uffffffff", "'\\\\Uffffffff'"], + ["\\\\b", "'\\\\\\\\b'"], + ["\t\n\\", "'\\t\\n\\\\'"], + ]; + } + + public static function provideDoubleQuotesData(): array + { + return [ + ["a", "\"a\""], + ["b", "\"b\""], + ["\t", "\"\\t\""], + ["\b", "\"\\\\b\""], + ["\n", "\"\\n\""], + ["\r", "\"\\r\""], + ["\f", "\"\\f\""], + ["'", "\"\\'\""], + ["\"", "\"\\\"\""], + ["\\\\", "\"\\\\\\\\\""], + ["\u1234", "\"\\\\u1234\""], + ["\U12345678", "\"\\\\U12345678\""], + ["\u0000", "\"\\\\u0000\""], + ["\uffff", "\"\\\\uffff\""], + ["\U00000000", "\"\\\\U00000000\""], + ["\Uffffffff", "\"\\\\Uffffffff\""], + ["\\\\b", "\"\\\\\\\\b\""], + ["\t\n\\", "\"\\t\\n\\\\\""], + ]; + } + public function testEmptySingleQuotes(): void { $string = new String_(""); @@ -68,52 +116,4 @@ public function testDoubleQuotes(string $string, string $expected): void $this->assertEquals($string, $literal->getValue()); $this->assertTrue($literal->usesDoubleQuotes()); } - - public function provideSingleQuotesData(): array - { - return [ - ["a", "'a'"], - ["b", "'b'"], - ["\t", "'\\t'"], - ["\b", "'\\\\b'"], - ["\n", "'\\n'"], - ["\r", "'\\r'"], - ["\f", "'\\f'"], - ["'", "'\\''"], - ["\"", "'\\\"'"], - ["\\\\", "'\\\\\\\\'"], - ["\u1234", "'\\\\u1234'"], - ["\U12345678", "'\\\\U12345678'"], - ["\u0000", "'\\\\u0000'"], - ["\uffff", "'\\\\uffff'"], - ["\U00000000", "'\\\\U00000000'"], - ["\Uffffffff", "'\\\\Uffffffff'"], - ["\\\\b", "'\\\\\\\\b'"], - ["\t\n\\", "'\\t\\n\\\\'"], - ]; - } - - public function provideDoubleQuotesData(): array - { - return [ - ["a", "\"a\""], - ["b", "\"b\""], - ["\t", "\"\\t\""], - ["\b", "\"\\\\b\""], - ["\n", "\"\\n\""], - ["\r", "\"\\r\""], - ["\f", "\"\\f\""], - ["'", "\"\\'\""], - ["\"", "\"\\\"\""], - ["\\\\", "\"\\\\\\\\\""], - ["\u1234", "\"\\\\u1234\""], - ["\U12345678", "\"\\\\U12345678\""], - ["\u0000", "\"\\\\u0000\""], - ["\uffff", "\"\\\\uffff\""], - ["\U00000000", "\"\\\\U00000000\""], - ["\Uffffffff", "\"\\\\Uffffffff\""], - ["\\\\b", "\"\\\\\\\\b\""], - ["\t\n\\", "\"\\t\\n\\\\\""], - ]; - } } diff --git a/tests/unit/Expressions/ParameterTest.php b/tests/unit/Expressions/ParameterTest.php index 77f7afab..dbbb341a 100644 --- a/tests/unit/Expressions/ParameterTest.php +++ b/tests/unit/Expressions/ParameterTest.php @@ -18,6 +18,24 @@ */ final class ParameterTest extends TestCase { + public static function provideToQueryData(): array + { + return [ + ["a", '$a'], + ["b", '$b'], + ["foo_bar", '$foo_bar'], + ["A", '$A'], + ]; + } + + public static function provideThrowsExceptionOnInvalidData(): array + { + return [ + [""], + [str_repeat('a', 65535)], + ]; + } + /** * @dataProvider provideToQueryData */ @@ -38,22 +56,4 @@ public function testThrowsExceptionOnInvalid(string $parameter): void new Parameter($parameter); } - - public function provideToQueryData(): array - { - return [ - ["a", '$a'], - ["b", '$b'], - ["foo_bar", '$foo_bar'], - ["A", '$A'], - ]; - } - - public function provideThrowsExceptionOnInvalidData(): array - { - return [ - [""], - [str_repeat('a', 65535)], - ]; - } } diff --git a/tests/unit/Expressions/PropertyTest.php b/tests/unit/Expressions/PropertyTest.php index 5c3c8ce0..bc418a87 100644 --- a/tests/unit/Expressions/PropertyTest.php +++ b/tests/unit/Expressions/PropertyTest.php @@ -25,6 +25,16 @@ */ final class PropertyTest extends TestCase { + public static function provideToQueryData(): array + { + return [ + [new Variable("a"), "a", "a.a"], + [new Map(["b" => new String_("c")]), "b", "{b: 'c'}.b"], + [new Variable("b"), "a", "b.a"], + [new Map([":" => new String_("c")]), ":", "{`:`: 'c'}.`:`"], + ]; + } + /** * @dataProvider provideToQueryData */ @@ -80,14 +90,4 @@ public function testReplaceWithUsesSameProperty(): void $this->assertSame($property, $replaceWith->getProperty()); } - - public function provideToQueryData(): array - { - return [ - [new Variable("a"), "a", "a.a"], - [new Map(["b" => new String_("c")]), "b", "{b: 'c'}.b"], - [new Variable("b"), "a", "b.a"], - [new Map([":" => new String_("c")]), ":", "{`:`: 'c'}.`:`"], - ]; - } } diff --git a/tests/unit/Expressions/VariableTest.php b/tests/unit/Expressions/VariableTest.php index 08c874c2..dea06368 100644 --- a/tests/unit/Expressions/VariableTest.php +++ b/tests/unit/Expressions/VariableTest.php @@ -22,6 +22,23 @@ */ final class VariableTest extends TestCase { + public static function provideToQueryData(): array + { + return [ + ["a", "a"], + ["b", "b"], + ['$foo', '`$foo`'], + ]; + } + + public static function providePropertyData(): array + { + return [ + ["a", "a", new Property(new Variable("a"), "a")], + ["a", "b", new Property(new Variable("a"), "b")], + ]; + } + public function testEmptyConstructor(): void { $variable = new Variable(); @@ -97,21 +114,4 @@ public function testProperty(string $variable, string $property, Property $expec $this->assertEquals($expected, $property); } - - public function provideToQueryData(): array - { - return [ - ["a", "a"], - ["b", "b"], - ['$foo', '`$foo`'], - ]; - } - - public function providePropertyData(): array - { - return [ - ["a", "a", new Property(new Variable("a"), "a")], - ["a", "b", new Property(new Variable("a"), "b")], - ]; - } } diff --git a/tests/unit/FunctionsTest.php b/tests/unit/FunctionsTest.php index d6c2a7eb..849b4669 100644 --- a/tests/unit/FunctionsTest.php +++ b/tests/unit/FunctionsTest.php @@ -28,6 +28,7 @@ use function WikibaseSolutions\CypherDSL\literal; use function WikibaseSolutions\CypherDSL\map; use function WikibaseSolutions\CypherDSL\node; +use WikibaseSolutions\CypherDSL\Patterns\Direction; use WikibaseSolutions\CypherDSL\Patterns\Node; use WikibaseSolutions\CypherDSL\Patterns\Relationship; use WikibaseSolutions\CypherDSL\Query; @@ -77,7 +78,7 @@ public function testNodeOnlyAcceptsStringLabel(): void public function testRelationshipReturnsRelationship(): void { - $relationship = relationship(Relationship::DIR_RIGHT); + $relationship = relationship(Direction::RIGHT); $this->assertInstanceOf(Relationship::class, $relationship); $this->assertSame('-->', $relationship->toQuery()); diff --git a/tests/unit/Patterns/NodeTest.php b/tests/unit/Patterns/NodeTest.php index 85b71d72..8f64e3f0 100644 --- a/tests/unit/Patterns/NodeTest.php +++ b/tests/unit/Patterns/NodeTest.php @@ -18,6 +18,7 @@ use WikibaseSolutions\CypherDSL\Expressions\Literals\Map; use WikibaseSolutions\CypherDSL\Expressions\Literals\String_; use WikibaseSolutions\CypherDSL\Expressions\Variable; +use WikibaseSolutions\CypherDSL\Patterns\Direction; use WikibaseSolutions\CypherDSL\Patterns\Node; use WikibaseSolutions\CypherDSL\Patterns\Relationship; @@ -26,6 +27,79 @@ */ final class NodeTest extends TestCase { + public static function provideOnlyLabelData(): array + { + return [ + ['(:a)', 'a'], + ['(:Foo:Bar)', 'Foo', 'Bar'], + ['(:`:`)', ':'], + ]; + } + + public static function provideOnlyNameData(): array + { + return [ + ['a', '(a)'], + ['A', '(A)'], + ]; + } + + public static function provideWithNameAndLabelData(): array + { + return [ + ['a', 'a', '(a:a)'], + ['A', ':', '(A:`:`)'], + ]; + } + + public static function provideWithNameAndPropertiesData(): array + { + return [ + ['a', ['a' => new String_('b'), 'b' => new String_('c')], "(a {a: 'b', b: 'c'})"], + ['b', ['a' => new Integer(0), 'b' => new Float_(1)], "(b {a: 0, b: 1.0})"], + ['c', [':' => new List_([new Integer(1), new String_('a')])], "(c {`:`: [1, 'a']})"], + ]; + } + + public static function provideWithLabelAndPropertiesData(): array + { + return [ + ['a', ['a' => new String_('b'), 'b' => new String_('c')], "(:a {a: 'b', b: 'c'})"], + ['b', ['a' => new Integer(0), 'b' => new Float_(1)], "(:b {a: 0, b: 1.0})"], + ['c', [':' => new List_([new Integer(1), new String_('a')])], "(:c {`:`: [1, 'a']})"], + ]; + } + + public static function provideOnlyPropertiesData(): array + { + return [ + [['a' => new String_('b'), 'b' => new String_('c')], "({a: 'b', b: 'c'})"], + [['a' => new Integer(0), 'b' => new Float_(-1.0)], "({a: 0, b: -1.0})"], + [[':' => new List_([new Integer(1), new String_('a')])], "({`:`: [1, 'a']})"], + ]; + } + + public static function provideWithNameAndLabelAndPropertiesData(): array + { + return [ + ['a', 'd', ['a' => new String_('b'), 'b' => new String_('c')], "(a:d {a: 'b', b: 'c'})"], + ['b', 'e', ['a' => new Integer(0), 'b' => new Float_(1)], "(b:e {a: 0, b: 1.0})"], + ['c', 'f', [':' => new List_([new Integer(1), new String_('a')])], "(c:f {`:`: [1, 'a']})"], + ]; + } + + public static function provideMultipleLabelsData(): array + { + return [ + [['a'], '(:a)'], + [['A'], '(:A)'], + [[':'], '(:`:`)'], + [['a', 'b'], '(:a:b)'], + [['A', 'B'], '(:A:B)'], + [[':', 'a'], '(:`:`:a)'], + ]; + } + public function testEmptyNode(): void { $node = new Node(); @@ -193,7 +267,7 @@ public function testGetProperties(): void public function testRelationship(): void { $node = new Node("City"); - $relationship = new Relationship(Relationship::DIR_RIGHT); + $relationship = new Relationship(Direction::RIGHT); $relationship->addType("LIVES_IN"); $amsterdam = new Node("City"); @@ -250,77 +324,4 @@ public function testLabeledMultipleLabels(): void $this->assertEquals(new Label($node->getVariable(), 'German', 'Swedish'), $labeled); } - - public function provideOnlyLabelData(): array - { - return [ - ['(:a)', 'a'], - ['(:Foo:Bar)', 'Foo', 'Bar'], - ['(:`:`)', ':'], - ]; - } - - public function provideOnlyNameData(): array - { - return [ - ['a', '(a)'], - ['A', '(A)'], - ]; - } - - public function provideWithNameAndLabelData(): array - { - return [ - ['a', 'a', '(a:a)'], - ['A', ':', '(A:`:`)'], - ]; - } - - public function provideWithNameAndPropertiesData(): array - { - return [ - ['a', ['a' => new String_('b'), 'b' => new String_('c')], "(a {a: 'b', b: 'c'})"], - ['b', ['a' => new Integer(0), 'b' => new Float_(1)], "(b {a: 0, b: 1.0})"], - ['c', [':' => new List_([new Integer(1), new String_('a')])], "(c {`:`: [1, 'a']})"], - ]; - } - - public function provideWithLabelAndPropertiesData(): array - { - return [ - ['a', ['a' => new String_('b'), 'b' => new String_('c')], "(:a {a: 'b', b: 'c'})"], - ['b', ['a' => new Integer(0), 'b' => new Float_(1)], "(:b {a: 0, b: 1.0})"], - ['c', [':' => new List_([new Integer(1), new String_('a')])], "(:c {`:`: [1, 'a']})"], - ]; - } - - public function provideOnlyPropertiesData(): array - { - return [ - [['a' => new String_('b'), 'b' => new String_('c')], "({a: 'b', b: 'c'})"], - [['a' => new Integer(0), 'b' => new Float_(-1.0)], "({a: 0, b: -1.0})"], - [[':' => new List_([new Integer(1), new String_('a')])], "({`:`: [1, 'a']})"], - ]; - } - - public function provideWithNameAndLabelAndPropertiesData(): array - { - return [ - ['a', 'd', ['a' => new String_('b'), 'b' => new String_('c')], "(a:d {a: 'b', b: 'c'})"], - ['b', 'e', ['a' => new Integer(0), 'b' => new Float_(1)], "(b:e {a: 0, b: 1.0})"], - ['c', 'f', [':' => new List_([new Integer(1), new String_('a')])], "(c:f {`:`: [1, 'a']})"], - ]; - } - - public function provideMultipleLabelsData(): array - { - return [ - [['a'], '(:a)'], - [['A'], '(:A)'], - [[':'], '(:`:`)'], - [['a', 'b'], '(:a:b)'], - [['A', 'B'], '(:A:B)'], - [[':', 'a'], '(:`:`:a)'], - ]; - } } diff --git a/tests/unit/Patterns/PathTest.php b/tests/unit/Patterns/PathTest.php index 63989de2..0a5d59a1 100644 --- a/tests/unit/Patterns/PathTest.php +++ b/tests/unit/Patterns/PathTest.php @@ -10,6 +10,7 @@ namespace WikibaseSolutions\CypherDSL\Tests\Unit\Patterns; use PHPUnit\Framework\TestCase; +use WikibaseSolutions\CypherDSL\Patterns\Direction; use WikibaseSolutions\CypherDSL\Patterns\Node; use WikibaseSolutions\CypherDSL\Patterns\Path; use WikibaseSolutions\CypherDSL\Patterns\Relationship; @@ -22,7 +23,7 @@ public function testEmpty(): void $this->assertEquals('', (new Path())->toQuery()); $this->assertEquals('', (new Path([], []))->toQuery()); $this->assertEquals('', (new Path([], []))->toQuery()); - $this->assertEquals('', (new Path([], [new Relationship(Relationship::DIR_UNI)]))->toQuery()); + $this->assertEquals('', (new Path([], [new Relationship(Direction::UNI)]))->toQuery()); } public function testSingleNode(): void @@ -42,7 +43,7 @@ public function testSingleNodeNamed(): void public function testSingle(): void { - $path = new Path(new Node(), new Relationship(Relationship::DIR_UNI)); + $path = new Path(new Node(), new Relationship(Direction::UNI)); $this->assertEquals('()', $path->toQuery()); } @@ -56,8 +57,8 @@ public function testSingleNoRel(): void public function testPathMerge(): void { - $pathX = new Path([new Node(), new Node()], [new Relationship(Relationship::DIR_UNI)]); - $pathY = new Path([new Node(), new Node()], [new Relationship(Relationship::DIR_UNI)]); + $pathX = new Path([new Node(), new Node()], [new Relationship(Direction::UNI)]); + $pathY = new Path([new Node(), new Node()], [new Relationship(Direction::UNI)]); $pathX->withVariable('x')->relationshipTo($pathY->withVariable('y')); @@ -68,7 +69,7 @@ public function testPathFewerNodes(): void { $path = new Path( new Node, - [new Relationship(Relationship::DIR_UNI), new Relationship(Relationship::DIR_UNI)] + [new Relationship(Direction::UNI), new Relationship(Direction::UNI)] ); $this->assertSame('()', $path->toQuery()); } @@ -79,7 +80,7 @@ public function testRelationshipLong(): void $path->relationshipUni(new Node('Label')) ->relationshipTo((new Node())->withVariable('b')) ->relationshipFrom(new Node(), 'TYPE', ['x' => Query::literal('y')], 'c') - ->relationship(new Relationship(Relationship::DIR_UNI), (new Node())->withVariable('d')) + ->relationship(new Relationship(Direction::UNI), (new Node())->withVariable('d')) ->withVariable('a'); $this->assertEquals('a = ()--(:Label)-->(b)<-[c:TYPE {x: \'y\'}]-()--(d)', $path->toQuery()); @@ -93,20 +94,20 @@ public function testRelationshipLong(): void ], $path->getNodes()); $this->assertEquals([ - new Relationship(Relationship::DIR_UNI), - new Relationship(Relationship::DIR_RIGHT), - (new Relationship(Relationship::DIR_LEFT)) + new Relationship(Direction::UNI), + new Relationship(Direction::RIGHT), + (new Relationship(Direction::LEFT)) ->addType('TYPE') ->addProperties(['x' => Query::literal('y')]) ->withVariable('c'), - new Relationship(Relationship::DIR_UNI), + new Relationship(Direction::UNI), ], $path->getRelationships()); } public function testPathCanBeTreatedAsBoolean(): void { - $pathA = new Path([new Node(), new Node()], [new Relationship(Relationship::DIR_UNI)]); - $pathB = new Path([new Node(), new Node()], [new Relationship(Relationship::DIR_RIGHT)]); + $pathA = new Path([new Node(), new Node()], [new Relationship(Direction::UNI)]); + $pathB = new Path([new Node(), new Node()], [new Relationship(Direction::RIGHT)]); $this->assertSame("()--() AND ()-->()", $pathA->and($pathB, false)->toQuery()); } diff --git a/tests/unit/Patterns/RelationshipTest.php b/tests/unit/Patterns/RelationshipTest.php index ed80db63..75349e61 100644 --- a/tests/unit/Patterns/RelationshipTest.php +++ b/tests/unit/Patterns/RelationshipTest.php @@ -10,12 +10,12 @@ namespace WikibaseSolutions\CypherDSL\Tests\Unit\Patterns; use DomainException; -use InvalidArgumentException; use LogicException; use PHPUnit\Framework\TestCase; use WikibaseSolutions\CypherDSL\Expressions\Literals\Integer; use WikibaseSolutions\CypherDSL\Expressions\Literals\String_; use WikibaseSolutions\CypherDSL\Expressions\Variable; +use WikibaseSolutions\CypherDSL\Patterns\Direction; use WikibaseSolutions\CypherDSL\Patterns\Relationship; use WikibaseSolutions\CypherDSL\Query; @@ -24,29 +24,140 @@ */ final class RelationshipTest extends TestCase { - public function testExceptionIsThrownWhenInvalidDirection(): void + public static function provideVariableLengthRelationshipsWithNameData(): array { - $this->expectException(InvalidArgumentException::class); - $r = new Relationship(['--', '--']); + return [ + ['b', 0, 100, Direction::UNI, '-[b*0..100]-'], + ['b', 5, 5, Direction::RIGHT, '-[b*5..5]->'], + ['a', 10, null, Direction::UNI, '-[a*10..]-'], + ['a', null, 10, Direction::LEFT, '<-[a*..10]-'], + ]; + } + + public static function provideVariableLengthRelationshipsWithTypeData(): array + { + return [ + ['', 1, 100, Direction::LEFT, '<-[*1..100]-'], + ['a', 10, null, Direction::LEFT, '<-[:a*10..]-'], + [':', null, 10, Direction::LEFT, '<-[:`:`*..10]-'], + ]; + } + + public static function provideVariableLengthRelationshipsWithPropertiesData(): array + { + return [ + [[], 10, 100, Direction::LEFT, "<-[*10..100]-"], + [[new String_('a')], 10, null, Direction::LEFT, "<-[*10.. {`0`: 'a'}]-"], + [['a' => new String_('b')], null, 10, Direction::LEFT, "<-[*..10 {a: 'b'}]-"], + ]; + } + + public static function provideVariableLengthRelationshipsWithNameAndTypeAndPropertiesData(): array + { + return [ + ['a', 'a', [], 10, 100, Direction::LEFT, "<-[a:a*10..100]-"], + ['b', 'a', [new String_('a')], null, 10, Direction::LEFT, "<-[b:a*..10 {`0`: 'a'}]-"], + ['a', 'b', [new String_('a')], 10, 100, Direction::LEFT, "<-[a:b*10..100 {`0`: 'a'}]-"], + ['a', '', ['a' => new String_('b')], null, 10, Direction::LEFT, "<-[a*..10 {a: 'b'}]-"], + ['a', ':', ['a' => new String_('b'), new String_('c')], 10, null, Direction::LEFT, "<-[a:`:`*10.. {a: 'b', `0`: 'c'}]-"], + ]; + } + + public static function provideWithNameData(): array + { + return [ + ['a', Direction::UNI, '-[a]-'], + ['a', Direction::LEFT, '<-[a]-'], + ['a', Direction::RIGHT, '-[a]->'], + ]; + } + + public static function provideAddTypeData(): array + { + return [ + ['', Direction::LEFT, '<--'], + ['a', Direction::LEFT, '<-[:a]-'], + [':', Direction::LEFT, '<-[:`:`]-'], + ]; + } + + public static function provideWithTypesData(): array + { + return [ + [['', 'a'], Direction::LEFT, '<-[:a]-'], + [['a', 'b'], Direction::LEFT, '<-[:a|b]-'], + [['', 'a', 'b'], Direction::LEFT, '<-[:a|b]-'], + [['a', '', 'b'], Direction::LEFT, '<-[:a|b]-'], + [['a', 'b', ':'], Direction::LEFT, '<-[:a|b|`:`]-'], + ]; + } + + public static function provideWithPropertiesData(): array + { + return [ + [[], Direction::LEFT, "<--"], + [[new String_('a')], Direction::LEFT, "<-[{`0`: 'a'}]-"], + [['a' => new String_('b')], Direction::LEFT, "<-[{a: 'b'}]-"], + [['a' => new String_('b'), new String_('c')], Direction::LEFT, "<-[{a: 'b', `0`: 'c'}]-"], + [[':' => new Integer(12)], Direction::LEFT, "<-[{`:`: 12}]-"], + [['a' => 'b', 'c' => 12, 'd' => 12.38], Direction::LEFT, "<-[{a: 'b', c: 12, d: 12.38}]-"], + ]; + } + + public static function provideWithNameAndTypeData(): array + { + return [ + ['a', '', Direction::LEFT, '<-[a]-'], + ['a', 'b', Direction::LEFT, '<-[a:b]-'], + ]; + } + + public static function provideWithNameAndPropertiesData(): array + { + return [ + ['a', [], Direction::LEFT, "<-[a]-"], + ['b', [new String_('a')], Direction::LEFT, "<-[b {`0`: 'a'}]-"], + ]; + } + + public static function provideWithNameAndTypeAndPropertiesData(): array + { + return [ + ['a', 'a', [], Direction::LEFT, "<-[a:a]-"], + ['b', 'a', [new String_('a')], Direction::LEFT, "<-[b:a {`0`: 'a'}]-"], + ['a', 'b', [new String_('a')], Direction::LEFT, "<-[a:b {`0`: 'a'}]-"], + ['a', '', ['a' => new String_('b')], Direction::LEFT, "<-[a {a: 'b'}]-"], + ['a', ':', ['a' => new String_('b'), new String_('c')], Direction::LEFT, "<-[a:`:` {a: 'b', `0`: 'c'}]-"], + ]; + } + + public static function provideWithMultipleTypesData(): array + { + return [ + ['a', [], [], Direction::LEFT, "<-[a]-"], + ['b', ['a'], [new String_('a')], Direction::LEFT, "<-[b:a {`0`: 'a'}]-"], + ['a', ['a', 'b', 'c'], [new String_('a')], Direction::LEFT, "<-[a:a|b|c {`0`: 'a'}]-"], + ['a', ['a', 'b'], [], Direction::LEFT, "<-[a:a|b]-"], + ]; } public function testDirRight(): void { - $r = new Relationship(Relationship::DIR_RIGHT); + $r = new Relationship(Direction::RIGHT); $this->assertSame("-->", $r->toQuery()); } public function testDirLeft(): void { - $r = new Relationship(Relationship::DIR_LEFT); + $r = new Relationship(Direction::LEFT); $this->assertSame("<--", $r->toQuery()); } public function testDirUni(): void { - $r = new Relationship(Relationship::DIR_UNI); + $r = new Relationship(Direction::UNI); $this->assertSame("--", $r->toQuery()); } @@ -54,7 +165,7 @@ public function testDirUni(): void /** * @dataProvider provideWithNameData */ - public function testWithName(string $name, array $direction, string $expected): void + public function testWithName(string $name, Direction $direction, string $expected): void { $r = new Relationship($direction); $r->withVariable($name); @@ -65,7 +176,7 @@ public function testWithName(string $name, array $direction, string $expected): /** * @dataProvider provideAddTypeData */ - public function testAddType(string $type, array $direction, string $expected): void + public function testAddType(string $type, Direction $direction, string $expected): void { $r = new Relationship($direction); $r->addType($type); @@ -75,7 +186,7 @@ public function testAddType(string $type, array $direction, string $expected): v public function testAddTypeMultiple(): void { - $r = new Relationship(Relationship::DIR_LEFT); + $r = new Relationship(Direction::LEFT); $r->addType("a"); $r->addType("b"); $r->addType(":"); @@ -86,7 +197,7 @@ public function testAddTypeMultiple(): void /** * @dataProvider provideWithTypesData */ - public function testWithTypes(array $types, array $direction, string $expected): void + public function testWithTypes(array $types, Direction $direction, string $expected): void { $r = new Relationship($direction); $r->withTypes($types); @@ -97,7 +208,7 @@ public function testWithTypes(array $types, array $direction, string $expected): /** * @dataProvider provideWithPropertiesData */ - public function testWithProperties(array $properties, array $direction, string $expected): void + public function testWithProperties(array $properties, Direction $direction, string $expected): void { $r = new Relationship($direction); $r->withProperties($properties); @@ -108,7 +219,7 @@ public function testWithProperties(array $properties, array $direction, string $ /** * @dataProvider provideWithNameAndTypeData */ - public function testWithNameAndType(string $name, string $type, array $direction, string $expected): void + public function testWithNameAndType(string $name, string $type, Direction $direction, string $expected): void { $r = new Relationship($direction); $r->withVariable($name)->addType($type); @@ -118,7 +229,7 @@ public function testWithNameAndType(string $name, string $type, array $direction public function testWithNameAndMultipleTypes(): void { - $r = new Relationship(Relationship::DIR_LEFT); + $r = new Relationship(Direction::LEFT); $r->withVariable('a')->addType('a')->addType('b'); $this->assertSame('<-[a:a|b]-', $r->toQuery()); @@ -126,7 +237,7 @@ public function testWithNameAndMultipleTypes(): void public function testWithVariableActualVariable(): void { - $r = new Relationship(Relationship::DIR_LEFT); + $r = new Relationship(Direction::LEFT); $r->withVariable(new Variable('a')); $this->assertSame('<-[a]-', $r->toQuery()); @@ -135,7 +246,7 @@ public function testWithVariableActualVariable(): void /** * @dataProvider provideWithNameAndPropertiesData */ - public function testWithNameAndProperties(string $name, array $properties, array $direction, string $expected): void + public function testWithNameAndProperties(string $name, array $properties, Direction $direction, string $expected): void { $r = new Relationship($direction); $r->withVariable($name)->withProperties($properties); @@ -146,7 +257,7 @@ public function testWithNameAndProperties(string $name, array $properties, array /** * @dataProvider provideWithNameAndTypeAndPropertiesData */ - public function testWithNameAndTypeAndProperties(string $name, string $type, array $properties, array $direction, string $expected): void + public function testWithNameAndTypeAndProperties(string $name, string $type, array $properties, Direction $direction, string $expected): void { $r = new Relationship($direction); $r->withVariable($name)->addType($type)->withProperties($properties); @@ -157,7 +268,7 @@ public function testWithNameAndTypeAndProperties(string $name, string $type, arr /** * @dataProvider provideWithMultipleTypesData */ - public function testWithMultipleTypes(string $name, array $types, array $properties, array $direction, string $expected): void + public function testWithMultipleTypes(string $name, array $types, array $properties, Direction $direction, string $expected): void { $r = new Relationship($direction); $r->withVariable($name)->withProperties($properties); @@ -172,7 +283,7 @@ public function testWithMultipleTypes(string $name, array $types, array $propert /** * @dataProvider provideVariableLengthRelationshipsWithNameData */ - public function testVariableLengthRelationshipsWithName(string $name, ?int $minHops, ?int $maxHops, array $direction, string $expected): void + public function testVariableLengthRelationshipsWithName(string $name, ?int $minHops, ?int $maxHops, Direction $direction, string $expected): void { $r = new Relationship($direction); $r->withVariable($name); @@ -191,7 +302,7 @@ public function testVariableLengthRelationshipsWithName(string $name, ?int $minH /** * @dataProvider provideVariableLengthRelationshipsWithTypeData */ - public function testVariableLengthRelationshipsWithType(string $type, ?int $minHops, ?int $maxHops, array $direction, string $expected): void + public function testVariableLengthRelationshipsWithType(string $type, ?int $minHops, ?int $maxHops, Direction $direction, string $expected): void { $r = new Relationship($direction); $r->addType($type); @@ -210,7 +321,7 @@ public function testVariableLengthRelationshipsWithType(string $type, ?int $minH /** * @dataProvider provideVariableLengthRelationshipsWithPropertiesData */ - public function testVariableLengthRelationshipsWithProperties(array $properties, ?int $minHops, ?int $maxHops, array $direction, string $expected): void + public function testVariableLengthRelationshipsWithProperties(array $properties, ?int $minHops, ?int $maxHops, Direction $direction, string $expected): void { $r = new Relationship($direction); $r->withProperties($properties); @@ -229,7 +340,7 @@ public function testVariableLengthRelationshipsWithProperties(array $properties, /** * @dataProvider provideVariableLengthRelationshipsWithNameAndTypeAndPropertiesData */ - public function testVariableLengthRelationshipsWithNameAndTypeAndProperties(string $name, string $type, array $properties, ?int $minHops, ?int $maxHops, array $direction, string $expected): void + public function testVariableLengthRelationshipsWithNameAndTypeAndProperties(string $name, string $type, array $properties, ?int $minHops, ?int $maxHops, Direction $direction, string $expected): void { $r = new Relationship($direction); $r->withVariable($name)->addType($type)->withProperties($properties); @@ -247,7 +358,7 @@ public function testVariableLengthRelationshipsWithNameAndTypeAndProperties(stri public function testArbitraryHops(): void { - $r = new Relationship(Relationship::DIR_LEFT); + $r = new Relationship(Direction::LEFT); $r->withVariable('hello')->addType('world')->addType('testing')->withProperties(['is' => 'a virtue']); $r->withArbitraryHops(); @@ -256,7 +367,7 @@ public function testArbitraryHops(): void public function testExactLengthRelationships(): void { - $r = new Relationship(Relationship::DIR_RIGHT); + $r = new Relationship(Direction::RIGHT); $r->withVariable("tom") ->addType("Person") ->withProperties(['name' => 'Tom Hanks']); @@ -268,7 +379,7 @@ public function testExactLengthRelationships(): void public function testMinAndExactHops(): void { - $r = new Relationship(Relationship::DIR_RIGHT); + $r = new Relationship(Direction::RIGHT); $r->withMinHops(1); $this->expectException(LogicException::class); @@ -278,7 +389,7 @@ public function testMinAndExactHops(): void public function testMaxAndExactHops(): void { - $r = new Relationship(Relationship::DIR_RIGHT); + $r = new Relationship(Direction::RIGHT); $r->withMaxHops(1); $this->expectException(LogicException::class); @@ -288,7 +399,7 @@ public function testMaxAndExactHops(): void public function testMinMaxAndExactHops(): void { - $r = new Relationship(Relationship::DIR_RIGHT); + $r = new Relationship(Direction::RIGHT); $r->withMinHops(1); $r->withMaxHops(1); @@ -299,7 +410,7 @@ public function testMinMaxAndExactHops(): void public function testExactAndMinHops(): void { - $r = new Relationship(Relationship::DIR_RIGHT); + $r = new Relationship(Direction::RIGHT); $r->withExactHops(1); $this->expectException(LogicException::class); @@ -309,7 +420,7 @@ public function testExactAndMinHops(): void public function testExactAndMaxHops(): void { - $r = new Relationship(Relationship::DIR_RIGHT); + $r = new Relationship(Direction::RIGHT); $r->withExactHops(1); $this->expectException(LogicException::class); @@ -319,7 +430,7 @@ public function testExactAndMaxHops(): void public function testMaxHopsLessThanMinHops(): void { - $r = new Relationship(Relationship::DIR_RIGHT); + $r = new Relationship(Direction::RIGHT); $r->withMinHops(100); $this->expectException(DomainException::class); @@ -329,7 +440,7 @@ public function testMaxHopsLessThanMinHops(): void public function testMinHopsGreaterThanMaxHops(): void { - $r = new Relationship(Relationship::DIR_RIGHT); + $r = new Relationship(Direction::RIGHT); $r->withMaxHops(1); $this->expectException(DomainException::class); @@ -339,7 +450,7 @@ public function testMinHopsGreaterThanMaxHops(): void public function testMinHopsLessThanZero(): void { - $r = new Relationship(Relationship::DIR_RIGHT); + $r = new Relationship(Direction::RIGHT); $this->expectException(DomainException::class); @@ -348,7 +459,7 @@ public function testMinHopsLessThanZero(): void public function testMaxHopsLessThanOne(): void { - $r = new Relationship(Relationship::DIR_RIGHT); + $r = new Relationship(Direction::RIGHT); $this->expectException(DomainException::class); @@ -357,7 +468,7 @@ public function testMaxHopsLessThanOne(): void public function testMaxHopsLessThanZero(): void { - $r = new Relationship(Relationship::DIR_RIGHT); + $r = new Relationship(Direction::RIGHT); $this->expectException(DomainException::class); @@ -366,7 +477,7 @@ public function testMaxHopsLessThanZero(): void public function testExactHopsLessThanOne(): void { - $r = new Relationship(Relationship::DIR_RIGHT); + $r = new Relationship(Direction::RIGHT); $this->expectException(DomainException::class); @@ -375,7 +486,7 @@ public function testExactHopsLessThanOne(): void public function testExactHopsLessThanZero(): void { - $r = new Relationship(Relationship::DIR_RIGHT); + $r = new Relationship(Direction::RIGHT); $this->expectException(DomainException::class); @@ -384,7 +495,7 @@ public function testExactHopsLessThanZero(): void public function testExactHopsWithArbitraryHops(): void { - $r = new Relationship(Relationship::DIR_RIGHT); + $r = new Relationship(Direction::RIGHT); $r->withArbitraryHops(); $this->expectException(LogicException::class); @@ -394,7 +505,7 @@ public function testExactHopsWithArbitraryHops(): void public function testMinHopsWithArbitraryHops(): void { - $r = new Relationship(Relationship::DIR_RIGHT); + $r = new Relationship(Direction::RIGHT); $r->withArbitraryHops(); $this->expectException(LogicException::class); @@ -404,7 +515,7 @@ public function testMinHopsWithArbitraryHops(): void public function testMaxHopsWithArbitraryHops(): void { - $r = new Relationship(Relationship::DIR_RIGHT); + $r = new Relationship(Direction::RIGHT); $r->withArbitraryHops(); $this->expectException(LogicException::class); @@ -414,7 +525,7 @@ public function testMaxHopsWithArbitraryHops(): void public function testArbitraryHopsWithExactHops(): void { - $r = new Relationship(Relationship::DIR_RIGHT); + $r = new Relationship(Direction::RIGHT); $r->withExactHops(5); $this->expectException(LogicException::class); @@ -424,7 +535,7 @@ public function testArbitraryHopsWithExactHops(): void public function testArbitraryHopsWithMinHops(): void { - $r = new Relationship(Relationship::DIR_RIGHT); + $r = new Relationship(Direction::RIGHT); $r->withMinHops(5); $this->expectException(LogicException::class); @@ -434,7 +545,7 @@ public function testArbitraryHopsWithMinHops(): void public function testArbitraryHopsWithMaxHops(): void { - $r = new Relationship(Relationship::DIR_RIGHT); + $r = new Relationship(Direction::RIGHT); $r->withMaxHops(5); $this->expectException(LogicException::class); @@ -444,14 +555,14 @@ public function testArbitraryHopsWithMaxHops(): void public function testGetDirection(): void { - $r = new Relationship(Relationship::DIR_LEFT); - $this->assertSame(Relationship::DIR_LEFT, $r->getDirection()); + $r = new Relationship(Direction::LEFT); + $this->assertSame(Direction::LEFT, $r->getDirection()); } public function testGetProperties(): void { $properties = Query::map(['foo' => 'bar']); - $r = new Relationship(Relationship::DIR_LEFT); + $r = new Relationship(Direction::LEFT); $this->assertNull($r->getProperties()); $r->withProperties($properties); @@ -461,7 +572,7 @@ public function testGetProperties(): void public function testGetExactHops(): void { - $r = new Relationship(Relationship::DIR_LEFT); + $r = new Relationship(Direction::LEFT); $this->assertNull($r->getExactHops()); $r->withExactHops(12); @@ -471,7 +582,7 @@ public function testGetExactHops(): void public function testGetMaxHops(): void { - $r = new Relationship(Relationship::DIR_LEFT); + $r = new Relationship(Direction::LEFT); $this->assertNull($r->getMaxHops()); $r->withMaxHops(12); @@ -481,7 +592,7 @@ public function testGetMaxHops(): void public function testGetMinHops(): void { - $r = new Relationship(Relationship::DIR_LEFT); + $r = new Relationship(Direction::LEFT); $this->assertNull($r->getMinHops()); $r->withMinHops(12); @@ -491,128 +602,11 @@ public function testGetMinHops(): void public function testGetTypes(): void { - $r = new Relationship(Relationship::DIR_LEFT); + $r = new Relationship(Direction::LEFT); $this->assertEmpty($r->getTypes()); $r->withTypes(['a', 'b']); $this->assertSame(['a', 'b'], $r->getTypes()); } - - public function provideVariableLengthRelationshipsWithNameData(): array - { - return [ - ['b', 0, 100, Relationship::DIR_UNI, '-[b*0..100]-'], - ['b', 5, 5, Relationship::DIR_RIGHT, '-[b*5..5]->'], - ['a', 10, null, Relationship::DIR_UNI, '-[a*10..]-'], - ['a', null, 10, Relationship::DIR_LEFT, '<-[a*..10]-'], - ]; - } - - public function provideVariableLengthRelationshipsWithTypeData(): array - { - return [ - ['', 1, 100, Relationship::DIR_LEFT, '<-[*1..100]-'], - ['a', 10, null, Relationship::DIR_LEFT, '<-[:a*10..]-'], - [':', null, 10, Relationship::DIR_LEFT, '<-[:`:`*..10]-'], - ]; - } - - public function provideVariableLengthRelationshipsWithPropertiesData(): array - { - return [ - [[], 10, 100, Relationship::DIR_LEFT, "<-[*10..100]-"], - [[new String_('a')], 10, null, Relationship::DIR_LEFT, "<-[*10.. {`0`: 'a'}]-"], - [['a' => new String_('b')], null, 10, Relationship::DIR_LEFT, "<-[*..10 {a: 'b'}]-"], - ]; - } - - public function provideVariableLengthRelationshipsWithNameAndTypeAndPropertiesData(): array - { - return [ - ['a', 'a', [], 10, 100, Relationship::DIR_LEFT, "<-[a:a*10..100]-"], - ['b', 'a', [new String_('a')], null, 10, Relationship::DIR_LEFT, "<-[b:a*..10 {`0`: 'a'}]-"], - ['a', 'b', [new String_('a')], 10, 100, Relationship::DIR_LEFT, "<-[a:b*10..100 {`0`: 'a'}]-"], - ['a', '', ['a' => new String_('b')], null, 10, Relationship::DIR_LEFT, "<-[a*..10 {a: 'b'}]-"], - ['a', ':', ['a' => new String_('b'), new String_('c')], 10, null, Relationship::DIR_LEFT, "<-[a:`:`*10.. {a: 'b', `0`: 'c'}]-"], - ]; - } - - public function provideWithNameData(): array - { - return [ - ['a', Relationship::DIR_UNI, '-[a]-'], - ['a', Relationship::DIR_LEFT, '<-[a]-'], - ['a', Relationship::DIR_RIGHT, '-[a]->'], - ]; - } - - public function provideAddTypeData(): array - { - return [ - ['', Relationship::DIR_LEFT, '<--'], - ['a', Relationship::DIR_LEFT, '<-[:a]-'], - [':', Relationship::DIR_LEFT, '<-[:`:`]-'], - ]; - } - - public function provideWithTypesData(): array - { - return [ - [['', 'a'], Relationship::DIR_LEFT, '<-[:a]-'], - [['a', 'b'], Relationship::DIR_LEFT, '<-[:a|b]-'], - [['', 'a', 'b'], Relationship::DIR_LEFT, '<-[:a|b]-'], - [['a', '', 'b'], Relationship::DIR_LEFT, '<-[:a|b]-'], - [['a', 'b', ':'], Relationship::DIR_LEFT, '<-[:a|b|`:`]-'], - ]; - } - - public function provideWithPropertiesData(): array - { - return [ - [[], Relationship::DIR_LEFT, "<--"], - [[new String_('a')], Relationship::DIR_LEFT, "<-[{`0`: 'a'}]-"], - [['a' => new String_('b')], Relationship::DIR_LEFT, "<-[{a: 'b'}]-"], - [['a' => new String_('b'), new String_('c')], Relationship::DIR_LEFT, "<-[{a: 'b', `0`: 'c'}]-"], - [[':' => new Integer(12)], Relationship::DIR_LEFT, "<-[{`:`: 12}]-"], - [['a' => 'b', 'c' => 12, 'd' => 12.38], Relationship::DIR_LEFT, "<-[{a: 'b', c: 12, d: 12.38}]-"], - ]; - } - - public function provideWithNameAndTypeData(): array - { - return [ - ['a', '', Relationship::DIR_LEFT, '<-[a]-'], - ['a', 'b', Relationship::DIR_LEFT, '<-[a:b]-'], - ]; - } - - public function provideWithNameAndPropertiesData(): array - { - return [ - ['a', [], Relationship::DIR_LEFT, "<-[a]-"], - ['b', [new String_('a')], Relationship::DIR_LEFT, "<-[b {`0`: 'a'}]-"], - ]; - } - - public function provideWithNameAndTypeAndPropertiesData(): array - { - return [ - ['a', 'a', [], Relationship::DIR_LEFT, "<-[a:a]-"], - ['b', 'a', [new String_('a')], Relationship::DIR_LEFT, "<-[b:a {`0`: 'a'}]-"], - ['a', 'b', [new String_('a')], Relationship::DIR_LEFT, "<-[a:b {`0`: 'a'}]-"], - ['a', '', ['a' => new String_('b')], Relationship::DIR_LEFT, "<-[a {a: 'b'}]-"], - ['a', ':', ['a' => new String_('b'), new String_('c')], Relationship::DIR_LEFT, "<-[a:`:` {a: 'b', `0`: 'c'}]-"], - ]; - } - - public function provideWithMultipleTypesData(): array - { - return [ - ['a', [], [], Relationship::DIR_LEFT, "<-[a]-"], - ['b', ['a'], [new String_('a')], Relationship::DIR_LEFT, "<-[b:a {`0`: 'a'}]-"], - ['a', ['a', 'b', 'c'], [new String_('a')], Relationship::DIR_LEFT, "<-[a:a|b|c {`0`: 'a'}]-"], - ['a', ['a', 'b'], [], Relationship::DIR_LEFT, "<-[a:a|b]-"], - ]; - } } diff --git a/tests/unit/QueryCreateTest.php b/tests/unit/QueryCreateTest.php index c46ecb1c..b1cf08ac 100644 --- a/tests/unit/QueryCreateTest.php +++ b/tests/unit/QueryCreateTest.php @@ -11,7 +11,7 @@ use PHPUnit\Framework\TestCase; use TypeError; -use WikibaseSolutions\CypherDSL\Patterns\Relationship; +use WikibaseSolutions\CypherDSL\Patterns\Direction; use WikibaseSolutions\CypherDSL\Query; /** @@ -42,7 +42,7 @@ public function testCreateMultiplePatterns(): void public function testDoesNotAcceptRelationship(): void { - $rel = Query::relationship(Relationship::DIR_RIGHT); + $rel = Query::relationship(Direction::RIGHT); $this->expectException(TypeError::class); diff --git a/tests/unit/QueryMatchTest.php b/tests/unit/QueryMatchTest.php index 14ba6a15..b2957c27 100644 --- a/tests/unit/QueryMatchTest.php +++ b/tests/unit/QueryMatchTest.php @@ -11,7 +11,7 @@ use PHPUnit\Framework\TestCase; use TypeError; -use WikibaseSolutions\CypherDSL\Patterns\Relationship; +use WikibaseSolutions\CypherDSL\Patterns\Direction; use WikibaseSolutions\CypherDSL\Query; /** @@ -36,7 +36,7 @@ public function testClause(): void public function testDoesNotAcceptRelationship(): void { - $r = Query::relationship(Relationship::DIR_LEFT); + $r = Query::relationship(Direction::LEFT); $this->expectException(TypeError::class); @@ -46,7 +46,7 @@ public function testDoesNotAcceptRelationship(): void public function testDoesNotAcceptRelationshipWithNode(): void { - $r = Query::relationship(Relationship::DIR_LEFT); + $r = Query::relationship(Direction::LEFT); $m = Query::node(); $this->expectException(TypeError::class); diff --git a/tests/unit/QueryOptionalMatchTest.php b/tests/unit/QueryOptionalMatchTest.php index ccfa6a5c..3b0e817f 100644 --- a/tests/unit/QueryOptionalMatchTest.php +++ b/tests/unit/QueryOptionalMatchTest.php @@ -11,7 +11,7 @@ use PHPUnit\Framework\TestCase; use TypeError; -use WikibaseSolutions\CypherDSL\Patterns\Relationship; +use WikibaseSolutions\CypherDSL\Patterns\Direction; use WikibaseSolutions\CypherDSL\Query; /** @@ -36,7 +36,7 @@ public function testClause(): void public function testDoesNotAcceptRelationship(): void { - $r = Query::relationship(Relationship::DIR_LEFT); + $r = Query::relationship(Direction::LEFT); $this->expectException(TypeError::class); @@ -46,7 +46,7 @@ public function testDoesNotAcceptRelationship(): void public function testDoesNotAcceptRelationshipWithNode(): void { - $r = Query::relationship(Relationship::DIR_LEFT); + $r = Query::relationship(Direction::UNI); $m = Query::node(); $this->expectException(TypeError::class); diff --git a/tests/unit/QueryTest.php b/tests/unit/QueryTest.php index a3fec160..215373db 100644 --- a/tests/unit/QueryTest.php +++ b/tests/unit/QueryTest.php @@ -9,7 +9,6 @@ */ namespace WikibaseSolutions\CypherDSL\Tests\Unit; -use InvalidArgumentException; use Iterator; use PHPUnit\Framework\TestCase; use TypeError; @@ -30,6 +29,7 @@ use WikibaseSolutions\CypherDSL\Expressions\Property; use WikibaseSolutions\CypherDSL\Expressions\RawExpression; use WikibaseSolutions\CypherDSL\Expressions\Variable; +use WikibaseSolutions\CypherDSL\Patterns\Direction; use WikibaseSolutions\CypherDSL\Patterns\Node; use WikibaseSolutions\CypherDSL\Patterns\Path; use WikibaseSolutions\CypherDSL\Patterns\Relationship; @@ -45,6 +45,25 @@ */ final class QueryTest extends TestCase { + /** + * @return mixed[][] + */ + public static function provideLiteralData(): array + { + return [ + ['foobar', new String_('foobar')], + ['0', new String_('0')], + ['100', new String_('100')], + [0, new Integer(0)], + [100, new Integer(100)], + [10.0, new Float_(10.0)], + [69420.0, new Float_(69420)], + [10.0000000000000000000000000000001, new Float_(10.0000000000000000000000000000001)], + [false, new Boolean(false)], + [true, new Boolean(true)], + ]; + } + public function testNew(): void { $new = Query::new(); @@ -80,7 +99,7 @@ public function testNodeWithLabel(): void public function testRelationship(): void { - $directions = [Relationship::DIR_UNI, Relationship::DIR_LEFT, Relationship::DIR_RIGHT]; + $directions = [Direction::UNI, Direction::LEFT, Direction::RIGHT]; foreach ($directions as $direction) { $expected = new Relationship($direction); @@ -90,13 +109,6 @@ public function testRelationship(): void } } - public function testInvalidRelationship(): void - { - $this->expectException(InvalidArgumentException::class); - - Query::relationship(['bad', 'value']); - } - public function testVariable(): void { $variable = Query::variable("foo"); @@ -225,11 +237,9 @@ public function current(): int return 1; } - public function next(): int + public function next(): void { $this->count++; - - return 1; } public function key(): int @@ -291,7 +301,7 @@ public function testBuild(): void $variableMock = new Variable("a"); $nodeMock = (new Node)->withVariable($variableMock); - $pathMock = new Path([$nodeMock, (new Node)->withVariable('b')], [new Relationship(Relationship::DIR_RIGHT)]); + $pathMock = new Path([$nodeMock, (new Node)->withVariable('b')], [new Relationship(Direction::RIGHT)]); $numeralMock = new Integer(12); $booleanMock = new GreaterThan($variableMock, new Variable('b'), false); $propertyMock = new Property($variableMock, 'b'); @@ -420,23 +430,4 @@ public function testAutomaticIdentifierGeneration(): void $this->assertInstanceOf(Variable::class, $node->getVariable()); } - - /** - * @return mixed[][] - */ - public function provideLiteralData(): array - { - return [ - ['foobar', new String_('foobar')], - ['0', new String_('0')], - ['100', new String_('100')], - [0, new Integer(0)], - [100, new Integer(100)], - [10.0, new Float_(10.0)], - [69420.0, new Float_(69420)], - [10.0000000000000000000000000000001, new Float_(10.0000000000000000000000000000001)], - [false, new Boolean(false)], - [true, new Boolean(true)], - ]; - } } diff --git a/tests/unit/Traits/ErrorTraitTest.php b/tests/unit/Traits/ErrorTraitTest.php deleted file mode 100644 index 023ba06f..00000000 --- a/tests/unit/Traits/ErrorTraitTest.php +++ /dev/null @@ -1,139 +0,0 @@ -errorImpl = new ErrorImpl(); - } - - /** - * @doesNotPerformAssertions - * @dataProvider CorrectAssertionsProvider - */ - public function testAssertClass($classNames, $userInput): void - { - $this->errorImpl->call('assertClass', ['foo', $classNames, $userInput]); - } - - /** - * @dataProvider failingAssertionsProvider - */ - public function testAssertClassFailure($classNames, $userInput): void - { - $this->expectException(TypeError::class); - $this->errorImpl->call('assertClass', ['foo', $classNames, $userInput]); - } - - public function correctAssertionsProvider(): array - { - return [ - [ErrorHelperDummyA::class, new ErrorHelperDummyA()], - [ErrorHelperDummyA::class, new ErrorHelperDummyExtendsA()], - [[ErrorHelperDummyA::class, ErrorHelperDummyB::class], new ErrorHelperDummyB()], - [[ErrorHelperDummyA::class, ErrorHelperDummyB::class], new ErrorHelperDummyExtendsB()], - ]; - } - - public function failingAssertionsProvider(): array - { - return [ - [ErrorHelperDummyA::class, new ErrorHelperDummyB()], - [ErrorHelperDummyExtendsA::class, new ErrorHelperDummyA()], - [[ErrorHelperDummyA::class, ErrorHelperDummyExtendsB::class], new ErrorHelperDummyB()], - ]; - } - - public function testGetTypeErrorText(): void - { - $this->assertEquals( - '$foo should be a WikibaseSolutions\CypherDSL\Tests\Unit\Traits\ErrorHelperDummyA, int given.', - $this->errorImpl->call('typeError', ['foo', [ErrorHelperDummyA::class], 5])->getMessage() - ); - $this->assertEquals( - '$foo should be a ' . - 'WikibaseSolutions\CypherDSL\Tests\Unit\Traits\ErrorHelperDummyA or ' . - 'WikibaseSolutions\CypherDSL\Tests\Unit\Traits\ErrorHelperDummyB, int given.', - $this->errorImpl->call('typeError', ['foo', [ErrorHelperDummyA::class, ErrorHelperDummyB::class], 5])->getMessage() - ); - } - - /** - * @dataProvider getUserInputInfoProvider - */ - public function testGetUserInputInfo($expected, $input): void - { - $this->assertEquals( - $expected, - $this->errorImpl->call('getDebugType', [$input]) - ); - } - - public function getUserInputInfoProvider(): array - { - return [ - ['string', 'foo'], - ['int', 5], - ['float', 3.14], - ['bool', true], - ['array', ['foo', 'bar']], - ['class@anonymous', new class() - { - }, ], - [ErrorHelperDummyA::class, new ErrorHelperDummyA()], - ]; - } -} diff --git a/tests/unit/Traits/NameGenerationTraitTest.php b/tests/unit/Traits/NameGenerationTraitTest.php deleted file mode 100644 index b76c33b7..00000000 --- a/tests/unit/Traits/NameGenerationTraitTest.php +++ /dev/null @@ -1,46 +0,0 @@ -trait = new class() - { - use NameGenerationTrait { - generateIdentifier as public; - } - }; - } - - public function testGenerateIdentifierWithoutPrefix(): void - { - $this->assertMatchesRegularExpression('/^var\w{32}$/', $this->trait->generateIdentifier()); - } - - public function testGenerateIdentifierWithPrefix(): void - { - $this->assertMatchesRegularExpression('/^x\w{32}$/', $this->trait->generateIdentifier('x')); - } - - public function testGenerateIdentifierWithPrefixAndLength(): void - { - $this->assertMatchesRegularExpression('/^x\w{16}$/', $this->trait->generateIdentifier('x', 16)); - } -} diff --git a/tests/unit/Traits/CastTraitTest.php b/tests/unit/Utils/CastUtilsTest.php similarity index 58% rename from tests/unit/Traits/CastTraitTest.php rename to tests/unit/Utils/CastUtilsTest.php index cc7c54d8..5b687c2b 100644 --- a/tests/unit/Traits/CastTraitTest.php +++ b/tests/unit/Utils/CastUtilsTest.php @@ -7,14 +7,12 @@ * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -namespace WikibaseSolutions\CypherDSL\Tests\Unit\Traits; +namespace WikibaseSolutions\CypherDSL\Tests\Unit\Utils; use PHPUnit\Framework\TestCase; -use TypeError; use WikibaseSolutions\CypherDSL\Expressions\Literals\Literal; use WikibaseSolutions\CypherDSL\Expressions\Variable; use WikibaseSolutions\CypherDSL\Query; -use WikibaseSolutions\CypherDSL\Traits\CastTrait; use WikibaseSolutions\CypherDSL\Types\CompositeTypes\ListType; use WikibaseSolutions\CypherDSL\Types\CompositeTypes\MapType; use WikibaseSolutions\CypherDSL\Types\PropertyTypes\BooleanType; @@ -22,172 +20,144 @@ use WikibaseSolutions\CypherDSL\Types\PropertyTypes\IntegerType; use WikibaseSolutions\CypherDSL\Types\PropertyTypes\StringType; use WikibaseSolutions\CypherDSL\Types\StructuralTypes\StructuralType; +use WikibaseSolutions\CypherDSL\Utils\CastUtils; /** - * @covers \WikibaseSolutions\CypherDSL\Traits\CastTrait + * @covers \WikibaseSolutions\CypherDSL\Utils\CastUtils */ -final class CastTraitTest extends TestCase +class CastUtilsTest extends TestCase { - protected function setUp(): void - { - parent::setUp(); - - $this->trait = new class - { - use CastTrait { - toListType as public; - toMapType as public; - toStringType as public; - toNumeralType as public; - toIntegerType as public; - toBooleanType as public; - toPropertyType as public; - toStructuralType as public; - toVariable as public; - toName as public; - toAnyType as public; - } - }; - } - public function testToListType(): void { - $list = $this->trait->toListType(['a', 'b', 'c']); + $list = CastUtils::toListType(['a', 'b', 'c']); $this->assertInstanceOf(ListType::class, $list); $list = Literal::list(['a', 'b', 'c']); - $list = $this->trait->toListType($list); + $list = CastUtils::toListType($list); $this->assertInstanceOf(ListType::class, $list); } public function testToMapType(): void { - $map = $this->trait->toMapType(['a' => 'a', 'b' => 'b', 'c' => 'c']); + $map = CastUtils::toMapType(['a' => 'a', 'b' => 'b', 'c' => 'c']); $this->assertInstanceOf(MapType::class, $map); $map = Literal::map(['a' => 'a', 'b' => 'b', 'c' => 'c']); - $map = $this->trait->toMapType($map); + $map = CastUtils::toMapType($map); $this->assertInstanceOf(MapType::class, $map); } public function testToStringType(): void { - $string = $this->trait->toStringType('hello'); + $string = CastUtils::toStringType('hello'); $this->assertInstanceOf(StringType::class, $string); $string = Literal::string('a'); - $string = $this->trait->toStringType($string); + $string = CastUtils::toStringType($string); $this->assertInstanceOf(StringType::class, $string); } public function testToNumeralType(): void { - $numeral = $this->trait->toNumeralType(1); + $numeral = CastUtils::toNumeralType(1); $this->assertInstanceOf(IntegerType::class, $numeral); - $numeral = $this->trait->toNumeralType(1.1); + $numeral = CastUtils::toNumeralType(1.1); $this->assertInstanceOf(FloatType::class, $numeral); $numeral = Literal::number(1.1); - $numeral = $this->trait->toNumeralType($numeral); + $numeral = CastUtils::toNumeralType($numeral); $this->assertInstanceOf(FloatType::class, $numeral); $numeral = Literal::number(1); - $numeral = $this->trait->toNumeralType($numeral); + $numeral = CastUtils::toNumeralType($numeral); $this->assertInstanceOf(IntegerType::class, $numeral); } public function testToIntegerType(): void { - $integer = $this->trait->toIntegerType(10); + $integer = CastUtils::toIntegerType(10); $this->assertInstanceOf(IntegerType::class, $integer); $integer = Literal::integer(10); - $integer = $this->trait->toIntegerType($integer); + $integer = CastUtils::toIntegerType($integer); $this->assertInstanceOf(IntegerType::class, $integer); } public function testToBooleanType(): void { - $boolean = $this->trait->toBooleanType(true); + $boolean = CastUtils::toBooleanType(true); $this->assertInstanceOf(BooleanType::class, $boolean); $boolean = Literal::boolean(true); - $boolean = $this->trait->toBooleanType($boolean); + $boolean = CastUtils::toBooleanType($boolean); $this->assertInstanceOf(BooleanType::class, $boolean); } public function testToPropertyType(): void { - $property = $this->trait->toPropertyType('test'); + $property = CastUtils::toPropertyType('test'); $this->assertInstanceOf(StringType::class, $property); - $property = $this->trait->toPropertyType(true); + $property = CastUtils::toPropertyType(true); $this->assertInstanceOf(BooleanType::class, $property); $property = Literal::boolean(true); - $property = $this->trait->toBooleanType($property); + $property = CastUtils::toBooleanType($property); $this->assertInstanceOf(BooleanType::class, $property); } public function testToStructuralType(): void { - $structural = $this->trait->toStructuralType(Query::node()); + $structural = CastUtils::toStructuralType(Query::node()); $this->assertInstanceOf(StructuralType::class, $structural); - $structural = $this->trait->toStructuralType(Query::node()->getVariable()); + $structural = CastUtils::toStructuralType(Query::node()->getVariable()); $this->assertInstanceOf(StructuralType::class, $structural); } public function testToVariable(): void { - $variable = $this->trait->toVariable('a'); + $variable = CastUtils::toVariable('a'); $this->assertInstanceOf(Variable::class, $variable); - $variable = $this->trait->toVariable(Query::node()); + $variable = CastUtils::toVariable(Query::node()); $this->assertInstanceOf(Variable::class, $variable); - $variable = $this->trait->toVariable(new Variable('a')); + $variable = CastUtils::toVariable(new Variable('a')); $this->assertInstanceOf(Variable::class, $variable); } public function testToName(): void { - $name = $this->trait->toName('a'); + $name = CastUtils::toName('a'); $this->assertInstanceOf(Variable::class, $name); - $name = $this->trait->toName(new Variable('a')); + $name = CastUtils::toName(new Variable('a')); $this->assertInstanceOf(Variable::class, $name); } - - public function testToNameDoesNotAcceptPattern(): void - { - $this->expectException(TypeError::class); - - $this->trait->toName(Query::node()); - } } diff --git a/tests/unit/Traits/EscapeTraitTest.php b/tests/unit/Utils/NameUtilsTest.php similarity index 63% rename from tests/unit/Traits/EscapeTraitTest.php rename to tests/unit/Utils/NameUtilsTest.php index 15426a4a..ed770ced 100644 --- a/tests/unit/Traits/EscapeTraitTest.php +++ b/tests/unit/Utils/NameUtilsTest.php @@ -7,29 +7,60 @@ * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -namespace WikibaseSolutions\CypherDSL\Tests\Unit\Traits; +namespace WikibaseSolutions\CypherDSL\Tests\Unit\Utils; use InvalidArgumentException; use PHPUnit\Framework\TestCase; -use WikibaseSolutions\CypherDSL\Traits\EscapeTrait; +use WikibaseSolutions\CypherDSL\Utils\NameUtils; /** - * @covers \WikibaseSolutions\CypherDSL\Traits\EscapeTrait + * @covers \WikibaseSolutions\CypherDSL\Utils\NameUtils */ -final class EscapeTraitTest extends TestCase +class NameUtilsTest extends TestCase { - private $trait; + public static function provideSafeValueIsNotEscapedData(): array + { + return [ + ['foobar'], + ['fooBar'], + ['FOOBAR'], + ['foo_bar'], + ['FOO_BAR'], + ['aaa'], + ['aaa100'], + ['a0'], + ['z10'], + ['z99'], + ['ça'], + ['日'], + ]; + } - protected function setUp(): void + public static function provideUnsafeValueIsEscapedData(): array { - parent::setUp(); + return [ + ['__FooBar__'], + ['_'], + ['__'], + ['\''], + ['"'], + ['0'], + ['10'], + ['100'], + ['1'], + ['2'], + ]; + } - $this->trait = new class - { - use EscapeTrait { - escape as public; - } - }; + public static function provideValueWithBacktickIsProperlyEscapedData(): array + { + return [ + ['foo`bar', '`foo``bar`'], + ['`foo', '```foo`'], + ['foo`', '`foo```'], + ['foo``bar', '`foo````bar`'], + ['`foo`', '```foo```'], + ]; } /** @@ -37,7 +68,7 @@ protected function setUp(): void */ public function testSafeValueIsNotEscaped(string $expected): void { - $actual = $this->trait->escape($expected); + $actual = NameUtils::escape($expected); $this->assertSame($expected, $actual); } @@ -48,7 +79,7 @@ public function testSafeValueIsNotEscaped(string $expected): void public function testUnsafeValueIsEscaped(string $value): void { $expected = sprintf("`%s`", $value); - $actual = $this->trait->escape($value); + $actual = NameUtils::escape($value); $this->assertSame($expected, $actual); } @@ -58,7 +89,7 @@ public function testUnsafeValueIsEscaped(string $value): void */ public function testValueWithBacktickIsProperlyEscaped($input, $expected): void { - $this->assertSame('`foo``bar`', $this->trait->escape("foo`bar")); + $this->assertSame($expected, NameUtils::escape($input)); } public function testValueWithMoreThan65534CharactersCannotBeEscaped(): void @@ -67,51 +98,21 @@ public function testValueWithMoreThan65534CharactersCannotBeEscaped(): void $this->expectException(InvalidArgumentException::class); - $this->trait->escape($value); + NameUtils::escape($value); } - public function provideSafeValueIsNotEscapedData(): array + public function testGenerateIdentifierWithoutPrefix(): void { - return [ - ['foobar'], - ['fooBar'], - ['FOOBAR'], - ['foo_bar'], - ['FOO_BAR'], - ['aaa'], - ['aaa100'], - ['a0'], - ['z10'], - ['z99'], - ['ça'], - ['日'], - ]; + $this->assertMatchesRegularExpression('/^var\w{32}$/', NameUtils::generateIdentifier()); } - public function provideUnsafeValueIsEscapedData(): array + public function testGenerateIdentifierWithPrefix(): void { - return [ - ['__FooBar__'], - ['_'], - ['__'], - ['\''], - ['"'], - ['0'], - ['10'], - ['100'], - ['1'], - ['2'], - ]; + $this->assertMatchesRegularExpression('/^x\w{32}$/', NameUtils::generateIdentifier('x')); } - public function provideValueWithBacktickIsProperlyEscapedData(): array + public function testGenerateIdentifierWithPrefixAndLength(): void { - return [ - ['foo`bar', '`foo``bar`'], - ['`foo', '```foo`'], - ['foo`', '`foo```'], - ['foo``bar', '`foo````bar`'], - ['`foo`', '```foo```'], - ]; + $this->assertMatchesRegularExpression('/^x\w{16}$/', NameUtils::generateIdentifier('x', 16)); } }