From 6bd6e7ad96627e383ae95f82c43f3a108ecac3fd Mon Sep 17 00:00:00 2001 From: ghlen Date: Fri, 2 Dec 2022 12:56:55 +0530 Subject: [PATCH 01/15] moved types that are OGM related to separate sub namespace --- benchmark/benchmark/NodeBench.php | 4 ++-- benchmark/benchmark/RelationBench.php | 8 ++++---- docs/constraint.md | 2 +- docs/helper.md | 19 ++++++------------- docs/node.md | 4 ++-- docs/relation.md | 6 +----- docs/type.index.md | 2 +- src/Type/{ => OGM}/Node.php | 2 +- src/Type/{ => OGM}/NodeLabel.php | 2 +- src/Type/{ => OGM}/NodeLabelStorage.php | 2 +- src/Type/{ => OGM}/Relation.php | 2 +- src/Type/{ => OGM}/RelationType.php | 2 +- src/Type/{ => OGM}/WeakRelation.php | 2 +- src/Type/{ => OGM}/WeakRelationStorage.php | 2 +- tests/Helper/ToCypherHelperTest.php | 10 +++++----- tests/Type/ConstraintTest.php | 4 ++-- tests/Type/IndexTest.php | 4 ++-- tests/Type/NodeLabelStorageTest.php | 4 ++-- tests/Type/NodeLabelTest.php | 2 +- tests/Type/NodeTest.php | 14 +++++++------- tests/Type/RelationTest.php | 8 ++++---- tests/Type/RelationTypeTest.php | 2 +- tests/Type/WeakRelationStorageTest.php | 8 ++++---- tests/Type/WeakRelationTest.php | 6 +++--- 24 files changed, 55 insertions(+), 66 deletions(-) rename src/Type/{ => OGM}/Node.php (99%) rename src/Type/{ => OGM}/NodeLabel.php (95%) rename src/Type/{ => OGM}/NodeLabelStorage.php (96%) rename src/Type/{ => OGM}/Relation.php (97%) rename src/Type/{ => OGM}/RelationType.php (95%) rename src/Type/{ => OGM}/WeakRelation.php (96%) rename src/Type/{ => OGM}/WeakRelationStorage.php (97%) diff --git a/benchmark/benchmark/NodeBench.php b/benchmark/benchmark/NodeBench.php index f22e3a9..d80a63c 100644 --- a/benchmark/benchmark/NodeBench.php +++ b/benchmark/benchmark/NodeBench.php @@ -5,8 +5,8 @@ namespace Syndesi\CypherDataStructures\Benchmark; use PhpBench\Attributes as Bench; -use Syndesi\CypherDataStructures\Type\Node; -use Syndesi\CypherDataStructures\Type\NodeLabel; +use Syndesi\CypherDataStructures\Type\OGM\Node; +use Syndesi\CypherDataStructures\Type\OGM\NodeLabel; use Syndesi\CypherDataStructures\Type\PropertyName; class NodeBench diff --git a/benchmark/benchmark/RelationBench.php b/benchmark/benchmark/RelationBench.php index ab3fc62..3323447 100644 --- a/benchmark/benchmark/RelationBench.php +++ b/benchmark/benchmark/RelationBench.php @@ -5,11 +5,11 @@ namespace Syndesi\CypherDataStructures\Benchmark; use PhpBench\Attributes as Bench; -use Syndesi\CypherDataStructures\Type\Node; -use Syndesi\CypherDataStructures\Type\NodeLabel; +use Syndesi\CypherDataStructures\Type\OGM\Node; +use Syndesi\CypherDataStructures\Type\OGM\NodeLabel; +use Syndesi\CypherDataStructures\Type\OGM\Relation; +use Syndesi\CypherDataStructures\Type\OGM\RelationType; use Syndesi\CypherDataStructures\Type\PropertyName; -use Syndesi\CypherDataStructures\Type\Relation; -use Syndesi\CypherDataStructures\Type\RelationType; class RelationBench { diff --git a/docs/constraint.md b/docs/constraint.md index 88d0a3b..3720944 100644 --- a/docs/constraint.md +++ b/docs/constraint.md @@ -18,7 +18,7 @@ Constraints are entities which contain the following attributes: use Syndesi\CypherDataStructures\Type\ConstraintName; use Syndesi\CypherDataStructures\Type\Constraint; use Syndesi\CypherDataStructures\Type\ConstraintType; -use Syndesi\CypherDataStructures\Type\NodeLabel; +use Syndesi\CypherDataStructures\Type\OGM\NodeLabel; use Syndesi\CypherDataStructures\Type\PropertyName; $constraint = new Constraint(); diff --git a/docs/helper.md b/docs/helper.md index 23e1cc2..c04db16 100644 --- a/docs/helper.md +++ b/docs/helper.md @@ -30,9 +30,7 @@ Transforms objects of type `NodeLabelInterface` to a Cypher label string with so Internal labels will be sorted first. ```php -use Syndesi\CypherDataStructures\Helper\ToCypherHelper; -use Syndesi\CypherDataStructures\Type\NodeLabelStorage; -use Syndesi\CypherDataStructures\Type\NodeLabel; +use Syndesi\CypherDataStructures\Helper\ToCypherHelper;use Syndesi\CypherDataStructures\Type\OGM\NodeLabel;use Syndesi\CypherDataStructures\Type\OGM\NodeLabelStorage; $nodeLabelStorage = new NodeLabelStorage(); $nodeLabelStorage->attach(new NodeLabel('LabelA')); @@ -50,9 +48,9 @@ Transforms objects of type `NodeInterface` to a Cypher node string, optionally l ones. ```php -use Syndesi\CypherDataStructures\Type\Node; +use Syndesi\CypherDataStructures\Type\OGM\Node; use Syndesi\CypherDataStructures\Type\PropertyName; -use Syndesi\CypherDataStructures\Type\NodeLabel; +use Syndesi\CypherDataStructures\Type\OGM\NodeLabel; use Syndesi\CypherDataStructures\Helper\ToCypherHelper; $node = new Node(); @@ -85,12 +83,7 @@ identifying ones. Referenced nodes are limited to identifying properties. Both nodes can be omitted. ```php -use Syndesi\CypherDataStructures\Type\Node; -use Syndesi\CypherDataStructures\Type\NodeLabel; -use Syndesi\CypherDataStructures\Type\PropertyName; -use Syndesi\CypherDataStructures\Type\Relation; -use Syndesi\CypherDataStructures\Type\RelationType; -use Syndesi\CypherDataStructures\Helper\ToCypherHelper; +use Syndesi\CypherDataStructures\Helper\ToCypherHelper;use Syndesi\CypherDataStructures\Type\OGM\Node;use Syndesi\CypherDataStructures\Type\OGM\NodeLabel;use Syndesi\CypherDataStructures\Type\OGM\Relation;use Syndesi\CypherDataStructures\Type\OGM\RelationType;use Syndesi\CypherDataStructures\Type\PropertyName; $startNode = new Node(); $startNode->addNodeLabel(new NodeLabel('StartNode')); @@ -149,7 +142,7 @@ Transforms objects of type `ConstraintInterface` to a Cypher constraint string. use Syndesi\CypherDataStructures\Type\ConstraintName; use Syndesi\CypherDataStructures\Type\Constraint; use Syndesi\CypherDataStructures\Type\ConstraintType; -use Syndesi\CypherDataStructures\Type\NodeLabel; +use Syndesi\CypherDataStructures\Type\OGM\NodeLabel; use Syndesi\CypherDataStructures\Type\PropertyName; use Syndesi\CypherDataStructures\Helper\ToCypherHelper; @@ -172,7 +165,7 @@ Transforms objects of type `ConstraintInterface` to a Cypher constraint string. use Syndesi\CypherDataStructures\Type\IndexName; use Syndesi\CypherDataStructures\Type\Index; use Syndesi\CypherDataStructures\Type\IndexType; -use Syndesi\CypherDataStructures\Type\NodeLabel; +use Syndesi\CypherDataStructures\Type\OGM\NodeLabel; use Syndesi\CypherDataStructures\Type\PropertyName; use Syndesi\CypherDataStructures\Helper\ToCypherHelper; diff --git a/docs/node.md b/docs/node.md index aae0a69..7716949 100644 --- a/docs/node.md +++ b/docs/node.md @@ -29,8 +29,8 @@ Nodes are entities which contain the following attributes: ## Examples ```php -use Syndesi\CypherDataStructures\Type\NodeLabel; -use Syndesi\CypherDataStructures\Type\Node; +use Syndesi\CypherDataStructures\Type\OGM\NodeLabel; +use Syndesi\CypherDataStructures\Type\OGM\Node; use Syndesi\CypherDataStructures\Type\PropertyName; $node = new Node(); diff --git a/docs/relation.md b/docs/relation.md index 6f5f6e4..07fdf79 100644 --- a/docs/relation.md +++ b/docs/relation.md @@ -24,11 +24,7 @@ Relations are entities which contain the following attributes: ## Examples ```php -use Syndesi\CypherDataStructures\Type\RelationType; -use Syndesi\CypherDataStructures\Type\NodeLabel; -use Syndesi\CypherDataStructures\Type\Node; -use Syndesi\CypherDataStructures\Type\PropertyName; -use Syndesi\CypherDataStructures\Type\Relation; +use Syndesi\CypherDataStructures\Type\OGM\Node;use Syndesi\CypherDataStructures\Type\OGM\NodeLabel;use Syndesi\CypherDataStructures\Type\OGM\Relation;use Syndesi\CypherDataStructures\Type\OGM\RelationType;use Syndesi\CypherDataStructures\Type\PropertyName; $nodeA = new Node(); $nodeA diff --git a/docs/type.index.md b/docs/type.index.md index ddb104e..b6cbf3a 100644 --- a/docs/type.index.md +++ b/docs/type.index.md @@ -19,7 +19,7 @@ Indexes are entities which contain the following attributes: use Syndesi\CypherDataStructures\Type\IndexName; use Syndesi\CypherDataStructures\Type\Index; use Syndesi\CypherDataStructures\Type\IndexType; -use Syndesi\CypherDataStructures\Type\NodeLabel; +use Syndesi\CypherDataStructures\Type\OGM\NodeLabel; use Syndesi\CypherDataStructures\Type\PropertyName; $index = new Index(); diff --git a/src/Type/Node.php b/src/Type/OGM/Node.php similarity index 99% rename from src/Type/Node.php rename to src/Type/OGM/Node.php index 0f2a395..06cf1ac 100644 --- a/src/Type/Node.php +++ b/src/Type/OGM/Node.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Syndesi\CypherDataStructures\Type; +namespace Syndesi\CypherDataStructures\Type\OGM; use Syndesi\CypherDataStructures\Contract\NodeInterface; use Syndesi\CypherDataStructures\Contract\NodeLabelInterface; diff --git a/src/Type/NodeLabel.php b/src/Type/OGM/NodeLabel.php similarity index 95% rename from src/Type/NodeLabel.php rename to src/Type/OGM/NodeLabel.php index 0c05342..b3b9706 100644 --- a/src/Type/NodeLabel.php +++ b/src/Type/OGM/NodeLabel.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Syndesi\CypherDataStructures\Type; +namespace Syndesi\CypherDataStructures\Type\OGM; use Syndesi\CypherDataStructures\Contract\NodeLabelInterface; use Syndesi\CypherDataStructures\Exception\InvalidArgumentException; diff --git a/src/Type/NodeLabelStorage.php b/src/Type/OGM/NodeLabelStorage.php similarity index 96% rename from src/Type/NodeLabelStorage.php rename to src/Type/OGM/NodeLabelStorage.php index 3232c41..fc149f1 100644 --- a/src/Type/NodeLabelStorage.php +++ b/src/Type/OGM/NodeLabelStorage.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Syndesi\CypherDataStructures\Type; +namespace Syndesi\CypherDataStructures\Type\OGM; use SplObjectStorage; use Syndesi\CypherDataStructures\Contract\NodeLabelInterface; diff --git a/src/Type/Relation.php b/src/Type/OGM/Relation.php similarity index 97% rename from src/Type/Relation.php rename to src/Type/OGM/Relation.php index 5d3f636..5e6df18 100644 --- a/src/Type/Relation.php +++ b/src/Type/OGM/Relation.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Syndesi\CypherDataStructures\Type; +namespace Syndesi\CypherDataStructures\Type\OGM; use Syndesi\CypherDataStructures\Contract\NodeInterface; use Syndesi\CypherDataStructures\Contract\RelationInterface; diff --git a/src/Type/RelationType.php b/src/Type/OGM/RelationType.php similarity index 95% rename from src/Type/RelationType.php rename to src/Type/OGM/RelationType.php index 286fe65..6c86b6a 100644 --- a/src/Type/RelationType.php +++ b/src/Type/OGM/RelationType.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Syndesi\CypherDataStructures\Type; +namespace Syndesi\CypherDataStructures\Type\OGM; use Syndesi\CypherDataStructures\Contract\RelationTypeInterface; use Syndesi\CypherDataStructures\Exception\InvalidArgumentException; diff --git a/src/Type/WeakRelation.php b/src/Type/OGM/WeakRelation.php similarity index 96% rename from src/Type/WeakRelation.php rename to src/Type/OGM/WeakRelation.php index 70a277a..daab416 100644 --- a/src/Type/WeakRelation.php +++ b/src/Type/OGM/WeakRelation.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Syndesi\CypherDataStructures\Type; +namespace Syndesi\CypherDataStructures\Type\OGM; use Syndesi\CypherDataStructures\Contract\RelationInterface; use Syndesi\CypherDataStructures\Contract\WeakRelationInterface; diff --git a/src/Type/WeakRelationStorage.php b/src/Type/OGM/WeakRelationStorage.php similarity index 97% rename from src/Type/WeakRelationStorage.php rename to src/Type/OGM/WeakRelationStorage.php index 1caac9c..6e8b213 100644 --- a/src/Type/WeakRelationStorage.php +++ b/src/Type/OGM/WeakRelationStorage.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Syndesi\CypherDataStructures\Type; +namespace Syndesi\CypherDataStructures\Type\OGM; use SplObjectStorage; use Syndesi\CypherDataStructures\Contract\WeakRelationInterface; diff --git a/tests/Helper/ToCypherHelperTest.php b/tests/Helper/ToCypherHelperTest.php index 23d33db..5ae0c4e 100644 --- a/tests/Helper/ToCypherHelperTest.php +++ b/tests/Helper/ToCypherHelperTest.php @@ -14,15 +14,15 @@ use Syndesi\CypherDataStructures\Type\Index; use Syndesi\CypherDataStructures\Type\IndexName; use Syndesi\CypherDataStructures\Type\IndexType; -use Syndesi\CypherDataStructures\Type\Node; -use Syndesi\CypherDataStructures\Type\NodeLabel; -use Syndesi\CypherDataStructures\Type\NodeLabelStorage; +use Syndesi\CypherDataStructures\Type\OGM\Node; +use Syndesi\CypherDataStructures\Type\OGM\NodeLabel; +use Syndesi\CypherDataStructures\Type\OGM\NodeLabelStorage; +use Syndesi\CypherDataStructures\Type\OGM\Relation; +use Syndesi\CypherDataStructures\Type\OGM\RelationType; use Syndesi\CypherDataStructures\Type\OptionName; use Syndesi\CypherDataStructures\Type\OptionStorage; use Syndesi\CypherDataStructures\Type\PropertyName; use Syndesi\CypherDataStructures\Type\PropertyStorage; -use Syndesi\CypherDataStructures\Type\Relation; -use Syndesi\CypherDataStructures\Type\RelationType; class ToCypherHelperTest extends TestCase { diff --git a/tests/Type/ConstraintTest.php b/tests/Type/ConstraintTest.php index 7e71876..17788b1 100644 --- a/tests/Type/ConstraintTest.php +++ b/tests/Type/ConstraintTest.php @@ -9,9 +9,9 @@ use Syndesi\CypherDataStructures\Type\Constraint; use Syndesi\CypherDataStructures\Type\ConstraintName; use Syndesi\CypherDataStructures\Type\ConstraintType; -use Syndesi\CypherDataStructures\Type\NodeLabel; +use Syndesi\CypherDataStructures\Type\OGM\NodeLabel; +use Syndesi\CypherDataStructures\Type\OGM\RelationType; use Syndesi\CypherDataStructures\Type\PropertyName; -use Syndesi\CypherDataStructures\Type\RelationType; class ConstraintTest extends TestCase { diff --git a/tests/Type/IndexTest.php b/tests/Type/IndexTest.php index 7eb349f..c3c3c51 100644 --- a/tests/Type/IndexTest.php +++ b/tests/Type/IndexTest.php @@ -9,9 +9,9 @@ use Syndesi\CypherDataStructures\Type\Index; use Syndesi\CypherDataStructures\Type\IndexName; use Syndesi\CypherDataStructures\Type\IndexType; -use Syndesi\CypherDataStructures\Type\NodeLabel; +use Syndesi\CypherDataStructures\Type\OGM\NodeLabel; +use Syndesi\CypherDataStructures\Type\OGM\RelationType; use Syndesi\CypherDataStructures\Type\PropertyName; -use Syndesi\CypherDataStructures\Type\RelationType; class IndexTest extends TestCase { diff --git a/tests/Type/NodeLabelStorageTest.php b/tests/Type/NodeLabelStorageTest.php index 7ca8f86..e931f42 100644 --- a/tests/Type/NodeLabelStorageTest.php +++ b/tests/Type/NodeLabelStorageTest.php @@ -10,8 +10,8 @@ use Syndesi\CypherDataStructures\Contract\NodeLabelInterface; use Syndesi\CypherDataStructures\Exception\InvalidArgumentException; use Syndesi\CypherDataStructures\Exception\LogicException; -use Syndesi\CypherDataStructures\Type\NodeLabel; -use Syndesi\CypherDataStructures\Type\NodeLabelStorage; +use Syndesi\CypherDataStructures\Type\OGM\NodeLabel; +use Syndesi\CypherDataStructures\Type\OGM\NodeLabelStorage; class NodeLabelStorageTest extends TestCase { diff --git a/tests/Type/NodeLabelTest.php b/tests/Type/NodeLabelTest.php index 4e15af0..a80b106 100644 --- a/tests/Type/NodeLabelTest.php +++ b/tests/Type/NodeLabelTest.php @@ -6,7 +6,7 @@ use PHPUnit\Framework\TestCase; use Syndesi\CypherDataStructures\Exception\InvalidArgumentException; -use Syndesi\CypherDataStructures\Type\NodeLabel; +use Syndesi\CypherDataStructures\Type\OGM\NodeLabel; class NodeLabelTest extends TestCase { diff --git a/tests/Type/NodeTest.php b/tests/Type/NodeTest.php index c8dfaa2..91a6b36 100644 --- a/tests/Type/NodeTest.php +++ b/tests/Type/NodeTest.php @@ -7,14 +7,14 @@ use PHPUnit\Framework\TestCase; use stdClass; use Syndesi\CypherDataStructures\Exception\InvalidArgumentException; -use Syndesi\CypherDataStructures\Type\Node; -use Syndesi\CypherDataStructures\Type\NodeLabel; -use Syndesi\CypherDataStructures\Type\NodeLabelStorage; +use Syndesi\CypherDataStructures\Type\OGM\Node; +use Syndesi\CypherDataStructures\Type\OGM\NodeLabel; +use Syndesi\CypherDataStructures\Type\OGM\NodeLabelStorage; +use Syndesi\CypherDataStructures\Type\OGM\Relation; +use Syndesi\CypherDataStructures\Type\OGM\RelationType; +use Syndesi\CypherDataStructures\Type\OGM\WeakRelation; +use Syndesi\CypherDataStructures\Type\OGM\WeakRelationStorage; use Syndesi\CypherDataStructures\Type\PropertyName; -use Syndesi\CypherDataStructures\Type\Relation; -use Syndesi\CypherDataStructures\Type\RelationType; -use Syndesi\CypherDataStructures\Type\WeakRelation; -use Syndesi\CypherDataStructures\Type\WeakRelationStorage; class NodeTest extends TestCase { diff --git a/tests/Type/RelationTest.php b/tests/Type/RelationTest.php index df36ff1..1c82bfd 100644 --- a/tests/Type/RelationTest.php +++ b/tests/Type/RelationTest.php @@ -7,12 +7,12 @@ use PHPUnit\Framework\TestCase; use stdClass; use Syndesi\CypherDataStructures\Exception\InvalidArgumentException; -use Syndesi\CypherDataStructures\Type\Node; -use Syndesi\CypherDataStructures\Type\NodeLabel; +use Syndesi\CypherDataStructures\Type\OGM\Node; +use Syndesi\CypherDataStructures\Type\OGM\NodeLabel; +use Syndesi\CypherDataStructures\Type\OGM\Relation; +use Syndesi\CypherDataStructures\Type\OGM\RelationType; use Syndesi\CypherDataStructures\Type\PropertyName; use Syndesi\CypherDataStructures\Type\PropertyStorage; -use Syndesi\CypherDataStructures\Type\Relation; -use Syndesi\CypherDataStructures\Type\RelationType; class RelationTest extends TestCase { diff --git a/tests/Type/RelationTypeTest.php b/tests/Type/RelationTypeTest.php index 1bc3f20..7530b24 100644 --- a/tests/Type/RelationTypeTest.php +++ b/tests/Type/RelationTypeTest.php @@ -6,7 +6,7 @@ use PHPUnit\Framework\TestCase; use Syndesi\CypherDataStructures\Exception\InvalidArgumentException; -use Syndesi\CypherDataStructures\Type\RelationType; +use Syndesi\CypherDataStructures\Type\OGM\RelationType; class RelationTypeTest extends TestCase { diff --git a/tests/Type/WeakRelationStorageTest.php b/tests/Type/WeakRelationStorageTest.php index 8ba7a01..6b99e42 100644 --- a/tests/Type/WeakRelationStorageTest.php +++ b/tests/Type/WeakRelationStorageTest.php @@ -9,10 +9,10 @@ use stdClass; use Syndesi\CypherDataStructures\Exception\InvalidArgumentException; use Syndesi\CypherDataStructures\Exception\LogicException; -use Syndesi\CypherDataStructures\Type\Relation; -use Syndesi\CypherDataStructures\Type\RelationType; -use Syndesi\CypherDataStructures\Type\WeakRelation; -use Syndesi\CypherDataStructures\Type\WeakRelationStorage; +use Syndesi\CypherDataStructures\Type\OGM\Relation; +use Syndesi\CypherDataStructures\Type\OGM\RelationType; +use Syndesi\CypherDataStructures\Type\OGM\WeakRelation; +use Syndesi\CypherDataStructures\Type\OGM\WeakRelationStorage; class WeakRelationStorageTest extends TestCase { diff --git a/tests/Type/WeakRelationTest.php b/tests/Type/WeakRelationTest.php index ce93b25..3471945 100644 --- a/tests/Type/WeakRelationTest.php +++ b/tests/Type/WeakRelationTest.php @@ -6,10 +6,10 @@ use PHPUnit\Framework\TestCase; use stdClass; +use Syndesi\CypherDataStructures\Type\OGM\Relation; +use Syndesi\CypherDataStructures\Type\OGM\RelationType; +use Syndesi\CypherDataStructures\Type\OGM\WeakRelation; use Syndesi\CypherDataStructures\Type\PropertyName; -use Syndesi\CypherDataStructures\Type\Relation; -use Syndesi\CypherDataStructures\Type\RelationType; -use Syndesi\CypherDataStructures\Type\WeakRelation; class WeakRelationTest extends TestCase { From ef39c2d486dbd7980d79fcf537291c1dca66778b Mon Sep 17 00:00:00 2001 From: ghlen Date: Fri, 2 Dec 2022 12:57:06 +0530 Subject: [PATCH 02/15] added .idea folder to gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 19b71a4..81ba36f 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ infection.html /.php-cs-fixer.php /.php-cs-fixer.cache /tmp/ +/.idea \ No newline at end of file From d362748c14beda0d208f2111dc7b729a5f784916 Mon Sep 17 00:00:00 2001 From: ghlen Date: Fri, 2 Dec 2022 12:59:15 +0530 Subject: [PATCH 03/15] moved ogm types from client into OGM Folder --- src/Type/OGM/Abstract3DPoint.php | 64 +++ src/Type/OGM/AbstractCypherObject.php | 111 +++++ src/Type/OGM/AbstractCypherSequence.php | 556 ++++++++++++++++++++++++ src/Type/OGM/AbstractPoint.php | 83 ++++ src/Type/OGM/AbstractPropertyObject.php | 50 +++ src/Type/OGM/ArrayList.php | 255 +++++++++++ src/Type/OGM/Cartesian3DPoint.php | 42 ++ src/Type/OGM/CartesianPoint.php | 43 ++ src/Type/OGM/CypherList.php | 120 +++++ src/Type/OGM/CypherMap.php | 256 +++++++++++ src/Type/OGM/Date.php | 78 ++++ src/Type/OGM/DateTime.php | 110 +++++ src/Type/OGM/DateTimeZoneId.php | 110 +++++ src/Type/OGM/Duration.php | 112 +++++ src/Type/OGM/LocalDateTime.php | 93 ++++ src/Type/OGM/LocalTime.php | 60 +++ src/Type/OGM/Map.php | 520 ++++++++++++++++++++++ src/Type/OGM/Path.php | 90 ++++ src/Type/OGM/Relationship.php | 75 ++++ src/Type/OGM/Time.php | 64 +++ src/Type/OGM/UnboundRelationship.php | 90 ++++ src/Type/OGM/WGS843DPoint.php | 57 +++ src/Type/OGM/WGS84Point.php | 58 +++ 23 files changed, 3097 insertions(+) create mode 100644 src/Type/OGM/Abstract3DPoint.php create mode 100644 src/Type/OGM/AbstractCypherObject.php create mode 100644 src/Type/OGM/AbstractCypherSequence.php create mode 100644 src/Type/OGM/AbstractPoint.php create mode 100644 src/Type/OGM/AbstractPropertyObject.php create mode 100644 src/Type/OGM/ArrayList.php create mode 100644 src/Type/OGM/Cartesian3DPoint.php create mode 100644 src/Type/OGM/CartesianPoint.php create mode 100644 src/Type/OGM/CypherList.php create mode 100644 src/Type/OGM/CypherMap.php create mode 100644 src/Type/OGM/Date.php create mode 100644 src/Type/OGM/DateTime.php create mode 100644 src/Type/OGM/DateTimeZoneId.php create mode 100644 src/Type/OGM/Duration.php create mode 100644 src/Type/OGM/LocalDateTime.php create mode 100644 src/Type/OGM/LocalTime.php create mode 100644 src/Type/OGM/Map.php create mode 100644 src/Type/OGM/Path.php create mode 100644 src/Type/OGM/Relationship.php create mode 100644 src/Type/OGM/Time.php create mode 100644 src/Type/OGM/UnboundRelationship.php create mode 100644 src/Type/OGM/WGS843DPoint.php create mode 100644 src/Type/OGM/WGS84Point.php diff --git a/src/Type/OGM/Abstract3DPoint.php b/src/Type/OGM/Abstract3DPoint.php new file mode 100644 index 0000000..7607c12 --- /dev/null +++ b/src/Type/OGM/Abstract3DPoint.php @@ -0,0 +1,64 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Syndesi\CypherDataStructures\Type\OGM; + +use Bolt\structures\IStructure; +use Bolt\structures\Point3D; +use Laudis\Neo4j\Contracts\BoltConvertibleInterface; +use Laudis\Neo4j\Contracts\PointInterface; + +/** + * A cartesian point in three dimensional space. + * + * @see https://neo4j.com/docs/cypher-manual/current/functions/spatial/#functions-point-cartesian-3d + * + * @psalm-immutable + * + * @psalm-import-type Crs from \Laudis\Neo4j\Contracts\PointInterface + */ +abstract class Abstract3DPoint extends AbstractPoint implements PointInterface, BoltConvertibleInterface +{ + private float $z; + + public function convertToBolt(): IStructure + { + return new Point3D($this->getSrid(), $this->getX(), $this->getY(), $this->getZ()); + } + + /** + * @param Crs $crs + */ + public function __construct(float $x, float $y, float $z) + { + parent::__construct($x, $y); + $this->z = $z; + } + + public function getZ(): float + { + return $this->z; + } + + /** + * @return array{x: float, y: float, z: float, srid: int, crs: Crs} + */ + public function toArray(): array + { + $tbr = parent::toArray(); + + $tbr['z'] = $this->z; + + return $tbr; + } +} diff --git a/src/Type/OGM/AbstractCypherObject.php b/src/Type/OGM/AbstractCypherObject.php new file mode 100644 index 0000000..9885d63 --- /dev/null +++ b/src/Type/OGM/AbstractCypherObject.php @@ -0,0 +1,111 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Syndesi\CypherDataStructures\Type\OGM; + +use function array_key_exists; +use ArrayAccess; +use ArrayIterator; +use BadMethodCallException; +use const E_DEPRECATED; +use function error_reporting; +use IteratorAggregate; +use JsonSerializable; +use OutOfBoundsException; +use function sprintf; +use Traversable; + +/** + * Turn of error reporting for class definition. PHP Users of 8.1 receive a deprectation warning otherwise but + * it is not fixable from the minimum version 7.4 as it required the "mixed" keyword. + */ +$oldReporting = error_reporting(error_reporting() & ~E_DEPRECATED); + +/** + * Abstract immutable container with basic functionality to integrate easily into the driver ecosystem. + * + * @template TKey of array-key + * @template TValue + * + * @implements ArrayAccess + * @implements IteratorAggregate + * + * @psalm-immutable + */ +abstract class AbstractCypherObject implements JsonSerializable, ArrayAccess, IteratorAggregate +{ + /** + * Represents the container as an array. + * + * @return array + */ + abstract public function toArray(): array; + + public function jsonSerialize() + { + return $this->toArray(); + } + + /** + * @return Traversable + */ + public function getIterator(): Traversable + { + return new ArrayIterator($this->toArray()); + } + + /** + * @param TKey $offset + */ + public function offsetExists($offset): bool + { + return array_key_exists($offset, $this->toArray()); + } + + /** + * @param TKey $offset + * + * @return TValue + */ + public function offsetGet($offset) + { + $serialized = $this->toArray(); + if (!array_key_exists($offset, $serialized)) { + throw new OutOfBoundsException("Offset: \"$offset\" does not exists in object of instance: ".static::class); + } + + return $serialized[$offset]; + } + + /** + * @param TKey $offset + * @param TValue $value + */ + final public function offsetSet($offset, $value): void + { + throw new BadMethodCallException(sprintf('%s is immutable', static::class)); + } + + /** + * @param TKey $offset + */ + final public function offsetUnset($offset): void + { + throw new BadMethodCallException(sprintf('%s is immutable', static::class)); + } +} + +/** + * Turn back on old error reporting after class definition. + */ +error_reporting($oldReporting); diff --git a/src/Type/OGM/AbstractCypherSequence.php b/src/Type/OGM/AbstractCypherSequence.php new file mode 100644 index 0000000..61367fd --- /dev/null +++ b/src/Type/OGM/AbstractCypherSequence.php @@ -0,0 +1,556 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Syndesi\CypherDataStructures\Type\OGM; + +use function array_key_exists; +use function array_reverse; +use ArrayAccess; +use ArrayIterator; +use BadMethodCallException; +use function call_user_func; +use function count; +use Countable; +use function get_object_vars; +use function implode; +use const INF; +use function is_array; +use function is_callable; +use function is_numeric; +use function is_object; +use function is_string; +use Iterator; +use JsonSerializable; +use function method_exists; +use OutOfBoundsException; +use const PHP_INT_MAX; +use function property_exists; +use ReturnTypeWillChange; +use function sprintf; +use UnexpectedValueException; + +/** + * Abstract immutable sequence with basic functional methods. + * + * @template TValue + * @template TKey of array-key + * + * @implements ArrayAccess + * @implements Iterator + */ +abstract class AbstractCypherSequence implements Countable, JsonSerializable, ArrayAccess, Iterator +{ + /** @var list */ + protected array $keyCache = []; + /** @var array */ + protected array $cache = []; + private int $cacheLimit = PHP_INT_MAX; + protected int $currentPosition = 0; + protected int $generatorPosition = 0; + + /** + * @var (callable():(\Iterator))|\Iterator + */ + protected $generator; + + /** + * @template Value + * + * @param callable():(\Generator) $operation + * + * @return static + * + * @psalm-mutation-free + */ + abstract protected function withOperation($operation): self; + + /** + * Copies the sequence. + * + * @return static + * + * @psalm-mutation-free + */ + final public function copy(): self + { + return $this->withOperation(function () { + yield from $this; + }); + } + + /**mixed + * Returns whether the sequence is empty. + * + * @psalm-suppress UnusedForeachValue + */ + final public function isEmpty(): bool + { + /** @noinspection PhpLoopNeverIteratesInspection */ + foreach ($this as $ignored) { + return false; + } + + return true; + } + + /** + * Creates a new sequence by merging this one with the provided iterable. When the iterable is not a list, the provided values will override the existing items in case of a key collision. + * + * @template NewValue + * + * @param iterable $values + * + * @return static + * + * @psalm-mutation-free + */ + abstract public function merge(iterable $values): self; + + /** + * Checks if the sequence contains the given key. + * + * @param TKey $key + */ + final public function hasKey($key): bool + { + return $this->offsetExists($key); + } + + /** + * Checks if the sequence contains the given value. The equality check is strict. + * + * @param TValue $value + */ + final public function hasValue($value): bool + { + return $this->find($value) !== false; + } + + /** + * Creates a filtered the sequence with the provided callback. + * + * @param callable(TValue, TKey):bool $callback + * + * @return static + * + * @psalm-mutation-free + */ + final public function filter(callable $callback): self + { + return $this->withOperation(function () use ($callback) { + foreach ($this as $key => $value) { + if ($callback($value, $key)) { + yield $key => $value; + } + } + }); + } + + /** + * Maps the values of this sequence to a new one with the provided callback. + * + * @template ReturnType + * + * @param callable(TValue, TKey):ReturnType $callback + * + * @return static + * + * @psalm-mutation-free + */ + final public function map(callable $callback): self + { + return $this->withOperation(function () use ($callback) { + foreach ($this as $key => $value) { + yield $key => $callback($value, $key); + } + }); + } + + /** + * Reduces this sequence with the given callback. + * + * @template TInitial + * + * @param callable(TInitial|null, TValue, TKey):TInitial $callback + * @param TInitial|null $initial + * + * @return TInitial + */ + final public function reduce(callable $callback, $initial = null) + { + foreach ($this as $key => $value) { + $initial = $callback($initial, $value, $key); + } + + return $initial; + } + + /** + * Finds the position of the value within the sequence. + * + * @param TValue $value + * + * @return false|TKey returns the key of the value if it is found, false otherwise + */ + final public function find($value) + { + foreach ($this as $i => $x) { + if ($value === $x) { + return $i; + } + } + + return false; + } + + /** + * Creates a reversed sequence. + * + * @return static + * + * @psalm-mutation-free + */ + public function reversed(): self + { + return $this->withOperation(function () { + yield from array_reverse($this->toArray()); + }); + } + + /** + * Slices a new sequence starting from the given offset with a certain length. + * If the length is null it will slice the entire remainder starting from the offset. + * + * @return static + * + * @psalm-mutation-free + */ + public function slice(int $offset, int $length = null): self + { + return $this->withOperation(function () use ($offset, $length) { + if ($length !== 0) { + $count = -1; + $length ??= INF; + foreach ($this as $key => $value) { + ++$count; + if ($count < $offset) { + continue; + } + + yield $key => $value; + if ($count === ($offset + $length - 1)) { + break; + } + } + } + }); + } + + /** + * Creates a sorted sequence. If the comparator is null it will use natural ordering. + * + * @param (callable(TValue, TValue):int)|null $comparator + * + * @return static + * + * @psalm-mutation-free + */ + public function sorted(?callable $comparator = null): self + { + return $this->withOperation(function () use ($comparator) { + $iterable = $this->toArray(); + + if ($comparator) { + uasort($iterable, $comparator); + } else { + asort($iterable); + } + + yield from $iterable; + }); + } + + /** + * Creates a list from the arrays and objects in the sequence whose values corresponding with the provided key. + * + * @return ArrayList + * + * @psalm-mutation-free + */ + public function pluck(string $key): ArrayList + { + return new ArrayList(function () use ($key) { + foreach ($this as $value) { + if ((is_array($value) && array_key_exists($key, $value)) || ($value instanceof ArrayAccess && $value->offsetExists($key))) { + yield $value[$key]; + } elseif (is_object($value) && property_exists($value, $key)) { + yield $value->$key; + } + } + }); + } + + /** + * Uses the values found at the provided key as the key for the new Map. + * + * @return Map + * + * @psalm-mutation-free + */ + public function keyBy(string $key): Map + { + return new Map(function () use ($key) { + foreach ($this as $value) { + if (((is_array($value) && array_key_exists($key, $value)) || ($value instanceof ArrayAccess && $value->offsetExists($key))) && $this->isStringable($value[$key])) { + yield $value[$key] => $value; + } elseif (is_object($value) && property_exists($value, $key) && $this->isStringable($value->$key)) { + yield $value->$key => $value; + } else { + throw new UnexpectedValueException('Cannot convert the value to a string'); + } + } + }); + } + + /** + * Joins the values within the sequence together with the provided glue. If the glue is null, it will be an empty string. + */ + public function join(?string $glue = null): string + { + /** @psalm-suppress MixedArgumentTypeCoercion */ + return implode($glue ?? '', $this->toArray()); + } + + /** + * Iterates over the sequence and applies the callable. + * + * @param callable(TValue, TKey):void $callable + * + * @return static + */ + public function each(callable $callable): self + { + foreach ($this as $key => $value) { + $callable($value, $key); + } + + return $this; + } + + #[ReturnTypeWillChange] + public function offsetGet($offset) + { + while (!array_key_exists($offset, $this->cache) && $this->valid()) { + $this->next(); + } + + if (!array_key_exists($offset, $this->cache)) { + throw new OutOfBoundsException(sprintf('Offset: "%s" does not exists in object of instance: %s', $offset, static::class)); + } + + return $this->cache[$offset]; + } + + public function offsetSet($offset, $value): void + { + throw new BadMethodCallException(sprintf('%s is immutable', static::class)); + } + + public function offsetUnset($offset): void + { + throw new BadMethodCallException(sprintf('%s is immutable', static::class)); + } + + /** + * @param TKey $offset + * + * @psalm-suppress UnusedForeachValue + */ + public function offsetExists($offset): bool + { + while (!array_key_exists($offset, $this->cache) && $this->valid()) { + $this->next(); + } + + return array_key_exists($offset, $this->cache); + } + + #[ReturnTypeWillChange] + public function jsonSerialize() + { + return $this->toArray(); + } + + /** + * Returns the sequence as an array. + * + * @return array + */ + final public function toArray(): array + { + $this->preload(); + + return $this->cache; + } + + /** + * Returns the sequence as an array. + * + * @return array + */ + final public function toRecursiveArray(): array + { + return $this->map(static function ($x) { + if ($x instanceof self) { + return $x->toRecursiveArray(); + } + + return $x; + })->toArray(); + } + + final public function count(): int + { + return count($this->toArray()); + } + + /** + * @return TValue + */ + #[ReturnTypeWillChange] + public function current() + { + $this->setupCache(); + + return $this->cache[$this->cacheKey()]; + } + + public function valid(): bool + { + return $this->currentPosition < $this->generatorPosition || $this->getGenerator()->valid(); + } + + public function rewind(): void + { + $this->currentPosition = max( + $this->currentPosition - $this->cacheLimit - 1, + 0 + ); + } + + public function next(): void + { + $generator = $this->getGenerator(); + if ($this->cache === []) { + $this->setupCache(); + } elseif ($this->currentPosition === $this->generatorPosition && $generator->valid()) { + $generator->next(); + + if ($generator->valid()) { + $this->keyCache[] = $generator->key(); + $this->cache[$generator->key()] = $generator->current(); + } + ++$this->generatorPosition; + ++$this->currentPosition; + } else { + ++$this->currentPosition; + } + } + + /** + * @return TKey + */ + #[ReturnTypeWillChange] + public function key() + { + return $this->cacheKey(); + } + + /** + * @return TKey + */ + protected function cacheKey() + { + return $this->keyCache[$this->currentPosition % max($this->cacheLimit - 1, 1)]; + } + + /** + * @return Iterator + */ + public function getGenerator(): Iterator + { + if (is_callable($this->generator)) { + $this->generator = call_user_func($this->generator); + } + + return $this->generator; + } + + /** + * @return static + */ + public function withCacheLimit(int $cacheLimit): self + { + $tbr = $this->copy(); + $tbr->cacheLimit = $cacheLimit; + + return $tbr; + } + + private function setupCache(): void + { + $generator = $this->getGenerator(); + + if (count($this->cache) % $this->cacheLimit === 0) { + $this->cache = []; + $this->keyCache = []; + } + + if ($this->cache === [] && $generator->valid()) { + $this->cache[$generator->key()] = $generator->current(); + $this->keyCache[] = $generator->key(); + } + } + + /** + * Preload the lazy evaluation. + */ + public function preload(): void + { + while ($this->valid()) { + $this->next(); + } + } + + /** + * @param mixed $key + * + * @psalm-mutation-free + */ + protected function isStringable($key): bool + { + return is_string($key) || is_numeric($key) || (is_object($key) && method_exists($key, '__toString')); + } + + public function __serialize(): array + { + $this->preload(); + + $tbr = get_object_vars($this); + $tbr['generator'] = new ArrayIterator($this->cache); + $tbr['currentPosition'] = 0; + $tbr['generatorPosition'] = 0; + + return $tbr; + } +} diff --git a/src/Type/OGM/AbstractPoint.php b/src/Type/OGM/AbstractPoint.php new file mode 100644 index 0000000..4180a22 --- /dev/null +++ b/src/Type/OGM/AbstractPoint.php @@ -0,0 +1,83 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Syndesi\CypherDataStructures\Type\OGM; + +use Bolt\structures\IStructure; +use Bolt\structures\Point2D; +use Laudis\Neo4j\Contracts\BoltConvertibleInterface; +use Laudis\Neo4j\Contracts\PointInterface; + +/** + * A cartesian point in two dimensional space. + * + * @see https://neo4j.com/docs/cypher-manual/current/functions/spatial/#functions-point-cartesian-2d + * + * @psalm-immutable + * + * @psalm-import-type Crs from \Laudis\Neo4j\Contracts\PointInterface + */ +abstract class AbstractPoint extends AbstractPropertyObject implements PointInterface, BoltConvertibleInterface +{ + private float $x; + private float $y; + + /** + * @param Crs $crs + */ + public function __construct(float $x, float $y) + { + $this->x = $x; + $this->y = $y; + } + + abstract public function getCrs(): string; + + abstract public function getSrid(): int; + + public function convertToBolt(): IStructure + { + return new Point2D($this->getSrid(), $this->getX(), $this->getY()); + } + + public function getX(): float + { + return $this->x; + } + + public function getY(): float + { + return $this->y; + } + + public function getProperties(): CypherMap + { + /** @psalm-suppress InvalidReturnStatement False positive */ + return new CypherMap($this); + } + + /** + * @psalm-suppress ImplementedReturnTypeMismatch False positive + * + * @return array{x: float, y: float, crs: Crs, srid: int} + */ + public function toArray(): array + { + return [ + 'x' => $this->x, + 'y' => $this->y, + 'crs' => $this->getCrs(), + 'srid' => $this->getSrid(), + ]; + } +} diff --git a/src/Type/OGM/AbstractPropertyObject.php b/src/Type/OGM/AbstractPropertyObject.php new file mode 100644 index 0000000..0994f11 --- /dev/null +++ b/src/Type/OGM/AbstractPropertyObject.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Syndesi\CypherDataStructures\Type\OGM; + +use BadMethodCallException; +use function get_class; +use Laudis\Neo4j\Contracts\HasPropertiesInterface; +use function sprintf; + +/** + * @psalm-import-type OGMTypes from \Laudis\Neo4j\Formatter\OGMFormatter + * + * @template PropertyTypes + * @template ObjectTypes + * + * @extends AbstractCypherObject + * @implements HasPropertiesInterface + * + * @psalm-immutable + */ +abstract class AbstractPropertyObject extends AbstractCypherObject implements HasPropertiesInterface +{ + public function __get($name) + { + /** @psalm-suppress ImpureMethodCall */ + return $this->getProperties()->get($name); + } + + public function __set($name, $value): void + { + throw new BadMethodCallException(sprintf('%s is immutable', get_class($this))); + } + + public function __isset($name): bool + { + /** @psalm-suppress ImpureMethodCall */ + return $this->getProperties()->offsetExists($name); + } +} diff --git a/src/Type/OGM/ArrayList.php b/src/Type/OGM/ArrayList.php new file mode 100644 index 0000000..4790f0f --- /dev/null +++ b/src/Type/OGM/ArrayList.php @@ -0,0 +1,255 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Syndesi\CypherDataStructures\Type\OGM; + +use AppendIterator; +use function array_values; +use ArrayIterator; +use Generator; +use function is_array; +use function is_callable; +use function is_iterable; +use Laudis\Neo4j\Exception\RuntimeTypeException; +use Laudis\Neo4j\TypeCaster; +use OutOfBoundsException; + +/** + * An immutable ordered sequence of items. + * + * @template TValue + * + * @extends AbstractCypherSequence + */ +class ArrayList extends AbstractCypherSequence +{ + /** + * @param iterable|callable():\Generator $iterable + * + * @psalm-mutation-free + */ + public function __construct($iterable = []) + { + if (is_array($iterable)) { + /** @var array $iterable */ + $this->keyCache = count($iterable) === 0 ? [] : range(0, count($iterable) - 1); + $this->cache = array_values($iterable); + $this->generator = new ArrayIterator([]); + $this->generatorPosition = count($this->keyCache); + } else { + $this->generator = static function () use ($iterable): Generator { + $i = 0; + /** @var Generator $it */ + $it = is_callable($iterable) ? $iterable() : $iterable; + foreach ($it as $value) { + yield $i => $value; + ++$i; + } + }; + } + } + + /** + * @template Value + * + * @param callable():(\Generator) $operation + * + * @return static + * + * @psalm-mutation-free + */ + protected function withOperation($operation): AbstractCypherSequence + { + /** @psalm-suppress UnsafeInstantiation */ + return new static($operation); + } + + /** + * Returns the first element in the sequence. + * + * @return TValue + */ + public function first() + { + foreach ($this as $value) { + return $value; + } + + throw new OutOfBoundsException('Cannot grab first element of an empty list'); + } + + /** + * Returns the last element in the sequence. + * + * @return TValue + */ + public function last() + { + if ($this->isEmpty()) { + throw new OutOfBoundsException('Cannot grab last element of an empty list'); + } + + $array = $this->toArray(); + + return $array[count($array) - 1]; + } + + /** + * @template NewValue + * + * @param iterable $values + * + * @return static + * + * @psalm-mutation-free + */ + public function merge($values): ArrayList + { + return $this->withOperation(function () use ($values): Generator { + $iterator = new AppendIterator(); + + $iterator->append($this); + $iterator->append(new self($values)); + + yield from $iterator; + }); + } + + /** + * Gets the nth element in the list. + * + * @throws OutOfBoundsException + * + * @return TValue + */ + public function get(int $key) + { + return $this->offsetGet($key); + } + + public function getAsString(int $key): string + { + $value = $this->get($key); + $tbr = TypeCaster::toString($value); + if ($tbr === null) { + throw new RuntimeTypeException($value, 'string'); + } + + return $tbr; + } + + public function getAsInt(int $key): int + { + $value = $this->get($key); + $tbr = TypeCaster::toInt($value); + if ($tbr === null) { + throw new RuntimeTypeException($value, 'int'); + } + + return $tbr; + } + + public function getAsFloat(int $key): float + { + $value = $this->get($key); + $tbr = TypeCaster::toFloat($value); + if ($tbr === null) { + throw new RuntimeTypeException($value, 'float'); + } + + return $tbr; + } + + public function getAsBool(int $key): bool + { + $value = $this->get($key); + $tbr = TypeCaster::toBool($value); + if ($tbr === null) { + throw new RuntimeTypeException($value, 'bool'); + } + + return $tbr; + } + + /** + * @return null + */ + public function getAsNull(int $key) + { + /** @psalm-suppress UnusedMethodCall */ + $this->get($key); + + return TypeCaster::toNull(); + } + + /** + * @template U + * + * @param class-string $class + * + * @return U + */ + public function getAsObject(int $key, string $class): object + { + $value = $this->get($key); + $tbr = TypeCaster::toClass($value, $class); + if ($tbr === null) { + throw new RuntimeTypeException($value, $class); + } + + return $tbr; + } + + /** + * @return Map + */ + public function getAsMap(int $key): Map + { + $value = $this->get($key); + if (!is_iterable($value)) { + throw new RuntimeTypeException($value, Map::class); + } + + /** @psalm-suppress MixedArgumentTypeCoercion */ + return new Map($value); + } + + /** + * @return ArrayList + */ + public function getAsArrayList(int $key): ArrayList + { + $value = $this->get($key); + if (!is_iterable($value)) { + throw new RuntimeTypeException($value, __CLASS__); + } + + /** @psalm-suppress MixedArgumentTypeCoercion */ + return new ArrayList($value); + } + + /** + * @template Value + * + * @param iterable $iterable + * + * @return static + * + * @pure + */ + public static function fromIterable(iterable $iterable): ArrayList + { + /** @psalm-suppress UnsafeInstantiation */ + return new static($iterable); + } +} diff --git a/src/Type/OGM/Cartesian3DPoint.php b/src/Type/OGM/Cartesian3DPoint.php new file mode 100644 index 0000000..dcd53da --- /dev/null +++ b/src/Type/OGM/Cartesian3DPoint.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Syndesi\CypherDataStructures\Type\OGM; + +use Laudis\Neo4j\Contracts\BoltConvertibleInterface; +use Laudis\Neo4j\Contracts\PointInterface; + +/** + * A cartesian point in three dimensional space. + * + * @see https://neo4j.com/docs/cypher-manual/current/functions/spatial/#functions-point-cartesian-3d + * + * @psalm-immutable + * + * @psalm-import-type Crs from \Laudis\Neo4j\Contracts\PointInterface + */ +final class Cartesian3DPoint extends Abstract3DPoint implements PointInterface, BoltConvertibleInterface +{ + public const SRID = 9157; + public const CRS = 'cartesian-3d'; + + public function getSrid(): int + { + return self::SRID; + } + + public function getCrs(): string + { + return self::CRS; + } +} diff --git a/src/Type/OGM/CartesianPoint.php b/src/Type/OGM/CartesianPoint.php new file mode 100644 index 0000000..bfe5149 --- /dev/null +++ b/src/Type/OGM/CartesianPoint.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Syndesi\CypherDataStructures\Type\OGM; + +use Laudis\Neo4j\Contracts\BoltConvertibleInterface; +use Laudis\Neo4j\Contracts\PointInterface; + +/** + * A cartesian point in two dimensional space. + * + * @see https://neo4j.com/docs/cypher-manual/current/functions/spatial/#functions-point-cartesian-2d + * + * @psalm-immutable + * + * @psalm-import-type Crs from \Laudis\Neo4j\Contracts\PointInterface + */ +final class CartesianPoint extends AbstractPoint implements PointInterface, BoltConvertibleInterface +{ + /** @var Crs */ + public const CRS = 'cartesian'; + public const SRID = 7203; + + public function getCrs(): string + { + return self::CRS; + } + + public function getSrid(): int + { + return self::SRID; + } +} diff --git a/src/Type/OGM/CypherList.php b/src/Type/OGM/CypherList.php new file mode 100644 index 0000000..457adc0 --- /dev/null +++ b/src/Type/OGM/CypherList.php @@ -0,0 +1,120 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Syndesi\CypherDataStructures\Type\OGM; + +use Laudis\Neo4j\Exception\RuntimeTypeException; +use Laudis\Neo4j\TypeCaster; + +/** + * An immutable ordered sequence of items. + * + * @template TValue + * + * @extends ArrayList + */ +class CypherList extends ArrayList +{ + /** + * @return CypherMap + */ + public function getAsCypherMap(int $key): CypherMap + { + $value = $this->get($key); + $tbr = TypeCaster::toCypherMap($value); + if ($tbr === null) { + throw new RuntimeTypeException($value, CypherMap::class); + } + + return $tbr; + } + + /** + * @return CypherList + */ + public function getAsCypherList(int $key): CypherList + { + $value = $this->get($key); + $tbr = TypeCaster::toCypherList($value); + if ($tbr === null) { + throw new RuntimeTypeException($value, CypherList::class); + } + + return $tbr; + } + + public function getAsDate(int $key): Date + { + return $this->getAsObject($key, Date::class); + } + + public function getAsDateTime(int $key): DateTime + { + return $this->getAsObject($key, DateTime::class); + } + + public function getAsDuration(int $key): Duration + { + return $this->getAsObject($key, Duration::class); + } + + public function getAsLocalDateTime(int $key): LocalDateTime + { + return $this->getAsObject($key, LocalDateTime::class); + } + + public function getAsLocalTime(int $key): LocalTime + { + return $this->getAsObject($key, LocalTime::class); + } + + public function getAsTime(int $key): Time + { + return $this->getAsObject($key, Time::class); + } + + public function getAsNode(int $key): Node + { + return $this->getAsObject($key, Node::class); + } + + public function getAsRelationship(int $key): Relationship + { + return $this->getAsObject($key, Relationship::class); + } + + public function getAsPath(int $key): Path + { + return $this->getAsObject($key, Path::class); + } + + public function getAsCartesian3DPoint(int $key): Cartesian3DPoint + { + return $this->getAsObject($key, Cartesian3DPoint::class); + } + + public function getAsCartesianPoint(int $key): CartesianPoint + { + return $this->getAsObject($key, CartesianPoint::class); + } + + public function getAsWGS84Point(int $key): WGS84Point + { + return $this->getAsObject($key, WGS84Point::class); + } + + public function getAsWGS843DPoint(int $key): WGS843DPoint + { + return $this->getAsObject($key, WGS843DPoint::class); + } +} diff --git a/src/Type/OGM/CypherMap.php b/src/Type/OGM/CypherMap.php new file mode 100644 index 0000000..895eade --- /dev/null +++ b/src/Type/OGM/CypherMap.php @@ -0,0 +1,256 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Syndesi\CypherDataStructures\Type\OGM; + +use function func_num_args; +use Laudis\Neo4j\Exception\RuntimeTypeException; +use Laudis\Neo4j\TypeCaster; + +/** + * An immutable ordered map of items. + * + * @template TValue + * + * @extends Map + */ +final class CypherMap extends Map +{ + /** + * @param mixed $default + * + * @return CypherMap + */ + public function getAsCypherMap(string $key, $default = null): CypherMap + { + if (func_num_args() === 1) { + $value = $this->get($key); + } else { + /** @var mixed */ + $value = $this->get($key, $default); + } + $tbr = TypeCaster::toCypherMap($value); + if ($tbr === null) { + throw new RuntimeTypeException($value, __CLASS__); + } + + return $tbr; + } + + /** + * @param mixed $default + * + * @return CypherList + */ + public function getAsCypherList(string $key, $default = null): CypherList + { + if (func_num_args() === 1) { + $value = $this->get($key); + } else { + /** @var mixed */ + $value = $this->get($key, $default); + } + $tbr = TypeCaster::toCypherList($value); + if ($tbr === null) { + throw new RuntimeTypeException($value, CypherList::class); + } + + return $tbr; + } + + /** + * @param mixed $default + */ + public function getAsDate(string $key, $default = null): Date + { + if (func_num_args() === 1) { + return $this->getAsObject($key, Date::class); + } + + return $this->getAsObject($key, Date::class, $default); + } + + /** + * @param mixed $default + */ + public function getAsDateTime(string $key, $default = null): DateTime + { + if (func_num_args() === 1) { + return $this->getAsObject($key, DateTime::class); + } + + return $this->getAsObject($key, DateTime::class, $default); + } + + /** + * @param mixed $default + */ + public function getAsDuration(string $key, $default = null): Duration + { + if (func_num_args() === 1) { + return $this->getAsObject($key, Duration::class); + } + + return $this->getAsObject($key, Duration::class, $default); + } + + /** + * @param mixed $default + */ + public function getAsLocalDateTime(string $key, $default = null): LocalDateTime + { + if (func_num_args() === 1) { + return $this->getAsObject($key, LocalDateTime::class); + } + + return $this->getAsObject($key, LocalDateTime::class, $default); + } + + /** + * @param mixed $default + */ + public function getAsLocalTime(string $key, $default = null): LocalTime + { + if (func_num_args() === 1) { + return $this->getAsObject($key, LocalTime::class); + } + + return $this->getAsObject($key, LocalTime::class, $default); + } + + /** + * @param mixed $default + */ + public function getAsTime(string $key, $default = null): Time + { + if (func_num_args() === 1) { + return $this->getAsObject($key, Time::class); + } + + return $this->getAsObject($key, Time::class, $default); + } + + /** + * @param mixed $default + */ + public function getAsNode(string $key, $default = null): Node + { + if (func_num_args() === 1) { + return $this->getAsObject($key, Node::class); + } + + return $this->getAsObject($key, Node::class, $default); + } + + /** + * @param mixed $default + */ + public function getAsRelationship(string $key, $default = null): Relationship + { + if (func_num_args() === 1) { + return $this->getAsObject($key, Relationship::class); + } + + return $this->getAsObject($key, Relationship::class, $default); + } + + /** + * @param mixed $default + */ + public function getAsPath(string $key, $default = null): Path + { + if (func_num_args() === 1) { + return $this->getAsObject($key, Path::class); + } + + return $this->getAsObject($key, Path::class, $default); + } + + /** + * @param mixed $default + */ + public function getAsCartesian3DPoint(string $key, $default = null): Cartesian3DPoint + { + if (func_num_args() === 1) { + return $this->getAsObject($key, Cartesian3DPoint::class); + } + + return $this->getAsObject($key, Cartesian3DPoint::class, $default); + } + + /** + * @param mixed $default + */ + public function getAsCartesianPoint(string $key, $default = null): CartesianPoint + { + if (func_num_args() === 1) { + return $this->getAsObject($key, CartesianPoint::class); + } + + return $this->getAsObject($key, CartesianPoint::class, $default); + } + + /** + * @param mixed $default + */ + public function getAsWGS84Point(string $key, $default = null): WGS84Point + { + if (func_num_args() === 1) { + return $this->getAsObject($key, WGS84Point::class); + } + + return $this->getAsObject($key, WGS84Point::class, $default); + } + + /** + * @param mixed $default + */ + public function getAsWGS843DPoint(string $key, $default = null): WGS843DPoint + { + if (func_num_args() === 1) { + return $this->getAsObject($key, WGS843DPoint::class); + } + + return $this->getAsObject($key, WGS843DPoint::class, $default); + } + + /** + * @template Value + * + * @param iterable $iterable + * + * @return self + * + * @pure + */ + public static function fromIterable(iterable $iterable): CypherMap + { + return new self($iterable); + } + + /** + * @psalm-mutation-free + */ + public function pluck(string $key): CypherList + { + return CypherList::fromIterable(parent::pluck($key)); + } + + /** + * @psalm-mutation-free + */ + public function keyBy(string $key): CypherMap + { + return CypherMap::fromIterable(parent::keyBy($key)); + } +} diff --git a/src/Type/OGM/Date.php b/src/Type/OGM/Date.php new file mode 100644 index 0000000..37b5e32 --- /dev/null +++ b/src/Type/OGM/Date.php @@ -0,0 +1,78 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Syndesi\CypherDataStructures\Type\OGM; + +use Bolt\structures\IStructure; +use DateTimeImmutable; +use Exception; +use Laudis\Neo4j\Contracts\BoltConvertibleInterface; +use UnexpectedValueException; + +/** + * A date represented by days since unix epoch. + * + * @psalm-immutable + * + * @extends AbstractPropertyObject + * + * @psalm-suppress TypeDoesNotContainType + */ +final class Date extends AbstractPropertyObject implements BoltConvertibleInterface +{ + private int $days; + + public function __construct(int $days) + { + $this->days = $days; + } + + /** + * The amount of days since unix epoch. + */ + public function getDays(): int + { + return $this->days; + } + + /** + * Casts to an immutable date time. + * + * @throws Exception + */ + public function toDateTime(): DateTimeImmutable + { + $dateTimeImmutable = (new DateTimeImmutable('@0'))->modify(sprintf('+%s days', $this->days)); + + if ($dateTimeImmutable === false) { + throw new UnexpectedValueException('Expected DateTimeImmutable'); + } + + return $dateTimeImmutable; + } + + public function getProperties(): CypherMap + { + return new CypherMap($this); + } + + public function toArray(): array + { + return ['days' => $this->days]; + } + + public function convertToBolt(): IStructure + { + return new \Bolt\structures\Date($this->getDays()); + } +} diff --git a/src/Type/OGM/DateTime.php b/src/Type/OGM/DateTime.php new file mode 100644 index 0000000..764709b --- /dev/null +++ b/src/Type/OGM/DateTime.php @@ -0,0 +1,110 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Syndesi\CypherDataStructures\Type\OGM; + +use Bolt\structures\IStructure; +use DateTimeImmutable; +use DateTimeZone; +use Exception; +use Laudis\Neo4j\Contracts\BoltConvertibleInterface; +use RuntimeException; +use function sprintf; + +/** + * A date represented by seconds and nanoseconds since unix epoch, enriched with a timezone offset in seconds. + * + * @psalm-immutable + * + * @extends AbstractPropertyObject + */ +final class DateTime extends AbstractPropertyObject implements BoltConvertibleInterface +{ + private int $seconds; + private int $nanoseconds; + private int $tzOffsetSeconds; + + public function __construct(int $seconds, int $nanoseconds, int $tzOffsetSeconds) + { + $this->seconds = $seconds; + $this->nanoseconds = $nanoseconds; + $this->tzOffsetSeconds = $tzOffsetSeconds; + } + + /** + * Returns the amount of seconds since unix epoch. + */ + public function getSeconds(): int + { + return $this->seconds; + } + + /** + * Returns the amount of nanoseconds after the seconds have passed. + */ + public function getNanoseconds(): int + { + return $this->nanoseconds; + } + + /** + * Returns the timezone offset in seconds. + */ + public function getTimeZoneOffsetSeconds(): int + { + return $this->tzOffsetSeconds; + } + + /** + * Casts to an immutable date time. + * + * @throws Exception + */ + public function toDateTime(): DateTimeImmutable + { + /** @psalm-suppress all */ + foreach (DateTimeZone::listAbbreviations() as $tz) { + /** @psalm-suppress all */ + if ($tz[0]['offset'] === $this->getTimeZoneOffsetSeconds()) { + return (new DateTimeImmutable(sprintf('@%s', $this->getSeconds()))) + ->modify(sprintf('+%s microseconds', $this->nanoseconds / 1000)) + ->setTimezone(new DateTimeZone($tz[0]['timezone_id'])); + } + } + + $message = sprintf('Cannot find an timezone with %s seconds as offset.', $this->tzOffsetSeconds); + throw new RuntimeException($message); + } + + /** + * @return array{seconds: int, nanoseconds: int, tzOffsetSeconds: int} + */ + public function toArray(): array + { + return [ + 'seconds' => $this->seconds, + 'nanoseconds' => $this->nanoseconds, + 'tzOffsetSeconds' => $this->tzOffsetSeconds, + ]; + } + + public function getProperties(): CypherMap + { + return new CypherMap($this); + } + + public function convertToBolt(): IStructure + { + return new \Bolt\structures\DateTime($this->getSeconds(), $this->getNanoseconds(), $this->getTimeZoneOffsetSeconds()); + } +} diff --git a/src/Type/OGM/DateTimeZoneId.php b/src/Type/OGM/DateTimeZoneId.php new file mode 100644 index 0000000..5ebdb5d --- /dev/null +++ b/src/Type/OGM/DateTimeZoneId.php @@ -0,0 +1,110 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Syndesi\CypherDataStructures\Type\OGM; + +use Bolt\structures\IStructure; +use DateTimeImmutable; +use DateTimeZone; +use Exception; +use Laudis\Neo4j\Contracts\BoltConvertibleInterface; +use function sprintf; + +/** + * A date represented by seconds and nanoseconds since unix epoch, enriched with a timezone identifier. + * + * @psalm-immutable + * + * @extends AbstractPropertyObject + * + * @psalm-suppress TypeDoesNotContainType + */ +final class DateTimeZoneId extends AbstractPropertyObject implements BoltConvertibleInterface +{ + private int $seconds; + private int $nanoseconds; + private string $tzId; + + public function __construct(int $seconds, int $nanoseconds, string $tzId) + { + $this->seconds = $seconds; + $this->nanoseconds = $nanoseconds; + $this->tzId = $tzId; + } + + /** + * Returns the amount of seconds since unix epoch. + */ + public function getSeconds(): int + { + return $this->seconds; + } + + /** + * Returns the amount of nanoseconds after the seconds have passed. + */ + public function getNanoseconds(): int + { + return $this->nanoseconds; + } + + /** + * Returns the timezone identifier. + */ + public function getTimezoneIdentifier(): string + { + return $this->tzId; + } + + /** + * Casts to an immutable date time. + * + * @throws Exception + */ + public function toDateTime(): DateTimeImmutable + { + $dateTimeImmutable = (new DateTimeImmutable(sprintf('@%s', $this->getSeconds()))) + ->modify(sprintf('+%s microseconds', $this->nanoseconds / 1000)); + + if ($dateTimeImmutable === false) { + throw new \UnexpectedValueException('Expected DateTimeImmutable'); + } + + return $dateTimeImmutable->setTimezone(new DateTimeZone($this->tzId)); + } + + /** + * @return array{seconds: int, nanoseconds: int, tzId: string} + */ + public function toArray(): array + { + return [ + 'seconds' => $this->seconds, + 'nanoseconds' => $this->nanoseconds, + 'tzId' => $this->tzId, + ]; + } + + /** + * @return CypherMap + */ + public function getProperties(): CypherMap + { + return new CypherMap($this); + } + + public function convertToBolt(): IStructure + { + return new \Bolt\structures\DateTimeZoneId($this->getSeconds(), $this->getNanoseconds(), $this->getTimezoneIdentifier()); + } +} diff --git a/src/Type/OGM/Duration.php b/src/Type/OGM/Duration.php new file mode 100644 index 0000000..eca3032 --- /dev/null +++ b/src/Type/OGM/Duration.php @@ -0,0 +1,112 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Syndesi\CypherDataStructures\Type\OGM; + +use Bolt\structures\IStructure; +use DateInterval; +use Exception; +use Laudis\Neo4j\Contracts\BoltConvertibleInterface; + +/** + * A temporal range represented in months, days, seconds and nanoseconds. + * + * @psalm-immutable + * + * @extends AbstractPropertyObject + */ +final class Duration extends AbstractPropertyObject implements BoltConvertibleInterface +{ + private int $months; + private int $days; + private int $seconds; + private int $nanoseconds; + + public function __construct(int $months, int $days, int $seconds, int $nanoseconds) + { + $this->months = $months; + $this->days = $days; + $this->seconds = $seconds; + $this->nanoseconds = $nanoseconds; + } + + /** + * The amount of months in the duration. + */ + public function getMonths(): int + { + return $this->months; + } + + /** + * The amount of days in the duration after the months have passed. + */ + public function getDays(): int + { + return $this->days; + } + + /** + * The amount of seconds in the duration after the days have passed. + */ + public function getSeconds(): int + { + return $this->seconds; + } + + /** + * The amount of nanoseconds in the duration after the seconds have passed. + */ + public function getNanoseconds(): int + { + return $this->nanoseconds; + } + + /** + * Casts to a DateInterval object. + * + * @throws Exception + */ + public function toDateInterval(): DateInterval + { + return new DateInterval(sprintf('P%dM%dDT%dS', $this->months, $this->days, $this->seconds)); + } + + /** + * @return array{months: int, days: int, seconds: int, nanoseconds: int} + */ + public function toArray(): array + { + return [ + 'months' => $this->months, + 'days' => $this->days, + 'seconds' => $this->seconds, + 'nanoseconds' => $this->nanoseconds, + ]; + } + + public function getProperties(): CypherMap + { + return new CypherMap($this); + } + + public function convertToBolt(): IStructure + { + return new \Bolt\structures\Duration( + $this->getMonths(), + $this->getDays(), + $this->getSeconds(), + $this->getNanoseconds() + ); + } +} diff --git a/src/Type/OGM/LocalDateTime.php b/src/Type/OGM/LocalDateTime.php new file mode 100644 index 0000000..de2e3e4 --- /dev/null +++ b/src/Type/OGM/LocalDateTime.php @@ -0,0 +1,93 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Syndesi\CypherDataStructures\Type\OGM; + +use Bolt\structures\IStructure; +use DateTimeImmutable; +use Exception; +use Laudis\Neo4j\Contracts\BoltConvertibleInterface; +use function sprintf; +use UnexpectedValueException; + +/** + * A date time represented in seconds and nanoseconds since the unix epoch. + * + * @psalm-immutable + * + * @extends AbstractPropertyObject + * + * @psalm-suppress TypeDoesNotContainType + */ +final class LocalDateTime extends AbstractPropertyObject implements BoltConvertibleInterface +{ + private int $seconds; + private int $nanoseconds; + + public function __construct(int $seconds, int $nanoseconds) + { + $this->seconds = $seconds; + $this->nanoseconds = $nanoseconds; + } + + /** + * The amount of seconds since the unix epoch. + */ + public function getSeconds(): int + { + return $this->seconds; + } + + /** + * The amount of nanoseconds after the seconds have passed. + */ + public function getNanoseconds(): int + { + return $this->nanoseconds; + } + + /** + * @throws Exception + */ + public function toDateTime(): DateTimeImmutable + { + $dateTimeImmutable = (new DateTimeImmutable(sprintf('@%s', $this->getSeconds())))->modify(sprintf('+%s microseconds', $this->nanoseconds / 1000)); + + if ($dateTimeImmutable === false) { + throw new UnexpectedValueException('Expected DateTimeImmutable'); + } + + return $dateTimeImmutable; + } + + /** + * @return array{seconds: int, nanoseconds: int} + */ + public function toArray(): array + { + return [ + 'seconds' => $this->seconds, + 'nanoseconds' => $this->nanoseconds, + ]; + } + + public function getProperties(): CypherMap + { + return new CypherMap($this); + } + + public function convertToBolt(): IStructure + { + return new \Bolt\structures\LocalDateTime($this->getSeconds(), $this->getNanoseconds()); + } +} diff --git a/src/Type/OGM/LocalTime.php b/src/Type/OGM/LocalTime.php new file mode 100644 index 0000000..1d63f59 --- /dev/null +++ b/src/Type/OGM/LocalTime.php @@ -0,0 +1,60 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Syndesi\CypherDataStructures\Type\OGM; + +use Bolt\structures\IStructure; +use Laudis\Neo4j\Contracts\BoltConvertibleInterface; + +/** + * The time of day represented in nanoseconds. + * + * @psalm-immutable + * + * @extends AbstractPropertyObject + */ +final class LocalTime extends AbstractPropertyObject implements BoltConvertibleInterface +{ + private int $nanoseconds; + + public function __construct(int $nanoseconds) + { + $this->nanoseconds = $nanoseconds; + } + + /** + * The nanoseconds that have passed since midnight. + */ + public function getNanoseconds(): int + { + return $this->nanoseconds; + } + + /** + * @return array{nanoseconds: int} + */ + public function toArray(): array + { + return ['nanoseconds' => $this->nanoseconds]; + } + + public function getProperties(): CypherMap + { + return new CypherMap($this); + } + + public function convertToBolt(): IStructure + { + return new \Bolt\structures\LocalTime($this->getNanoseconds()); + } +} diff --git a/src/Type/OGM/Map.php b/src/Type/OGM/Map.php new file mode 100644 index 0000000..0535cc1 --- /dev/null +++ b/src/Type/OGM/Map.php @@ -0,0 +1,520 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Syndesi\CypherDataStructures\Type\OGM; + +use function array_key_exists; +use function array_key_last; +use ArrayIterator; +use function count; +use function func_num_args; +use Generator; +use function is_array; +use function is_callable; +use function is_iterable; +use Laudis\Neo4j\Databags\Pair; +use Laudis\Neo4j\Exception\RuntimeTypeException; +use Laudis\Neo4j\TypeCaster; +use OutOfBoundsException; +use function sprintf; +use stdClass; + +/** + * An immutable ordered map of items. + * + * @template TValue + * + * @extends AbstractCypherSequence + */ +class Map extends AbstractCypherSequence +{ + /** + * @param iterable|callable():\Generator $iterable + * + * @psalm-mutation-free + */ + public function __construct($iterable = []) + { + if (is_array($iterable)) { + $i = 0; + foreach ($iterable as $key => $value) { + if (!$this->isStringable($key)) { + $key = (string) $i; + } + /** @var string $key */ + $this->keyCache[] = $key; + /** @var TValue $value */ + $this->cache[$key] = $value; + ++$i; + } + /** @var ArrayIterator */ + $it = new ArrayIterator([]); + $this->generator = $it; + $this->generatorPosition = count($this->keyCache); + } else { + $this->generator = function () use ($iterable): Generator { + $i = 0; + /** @var Generator $it */ + $it = is_callable($iterable) ? $iterable() : $iterable; + /** @var mixed $key */ + foreach ($it as $key => $value) { + if ($this->isStringable($key)) { + yield (string) $key => $value; + } else { + yield (string) $i => $value; + } + ++$i; + } + }; + } + } + + /** + * @template Value + * + * @param callable():(\Generator) $operation + * + * @return static + * + * @psalm-mutation-free + */ + protected function withOperation($operation): Map + { + /** @psalm-suppress UnsafeInstantiation */ + return new static($operation); + } + + /** + * Returns the first pair in the map. + * + * @return Pair + */ + public function first(): Pair + { + foreach ($this as $key => $value) { + return new Pair($key, $value); + } + throw new OutOfBoundsException('Cannot grab first element of an empty map'); + } + + /** + * Returns the last pair in the map. + * + * @return Pair + */ + public function last(): Pair + { + $array = $this->toArray(); + if (count($array) === 0) { + throw new OutOfBoundsException('Cannot grab last element of an empty map'); + } + + $key = array_key_last($array); + + return new Pair($key, $array[$key]); + } + + /** + * Returns the pair at the nth position of the map. + * + * @return Pair + */ + public function skip(int $position): Pair + { + $i = 0; + foreach ($this as $key => $value) { + if ($i === $position) { + return new Pair($key, $value); + } + ++$i; + } + + throw new OutOfBoundsException(sprintf('Cannot skip to a pair at position: %s', $position)); + } + + /** + * Returns the keys in the map in order. + * + * @return ArrayList + * + * @psalm-suppress UnusedForeachValue + */ + public function keys(): ArrayList + { + return ArrayList::fromIterable((function () { + foreach ($this as $key => $value) { + yield $key; + } + })()); + } + + /** + * Returns the pairs in the map in order. + * + * @return ArrayList> + */ + public function pairs(): ArrayList + { + return ArrayList::fromIterable((function () { + foreach ($this as $key => $value) { + yield new Pair($key, $value); + } + })()); + } + + /** + * Create a new map sorted by keys. Natural ordering will be used if no comparator is provided. + * + * @param (callable(string, string):int)|null $comparator + * + * @return static + */ + public function ksorted(callable $comparator = null): Map + { + return $this->withOperation(function () use ($comparator) { + $pairs = $this->pairs()->sorted(static function (Pair $x, Pair $y) use ($comparator) { + if ($comparator) { + return $comparator($x->getKey(), $y->getKey()); + } + + return $x->getKey() <=> $y->getKey(); + }); + + foreach ($pairs as $pair) { + yield $pair->getKey() => $pair->getValue(); + } + }); + } + + /** + * Returns the values in the map in order. + * + * @return ArrayList + */ + public function values(): ArrayList + { + return ArrayList::fromIterable((function () { + yield from $this; + })()); + } + + /** + * Creates a new map using exclusive or on the keys. + * + * @param iterable $map + * + * @return static + */ + public function xor(iterable $map): Map + { + return $this->withOperation(function () use ($map) { + $map = Map::fromIterable($map); + foreach ($this as $key => $value) { + if (!$map->hasKey($key)) { + yield $key => $value; + } + } + + foreach ($map as $key => $value) { + if (!$this->hasKey($key)) { + yield $key => $value; + } + } + }); + } + + /** + * @template NewValue + * + * @param iterable $values + * + * @return static + * + * @psalm-mutation-free + */ + public function merge(iterable $values): Map + { + return $this->withOperation(function () use ($values) { + $tbr = $this->toArray(); + $values = Map::fromIterable($values); + + foreach ($values as $key => $value) { + $tbr[$key] = $value; + } + + yield from $tbr; + }); + } + + /** + * Creates a union of this and the provided map. The items in the original map take precedence. + * + * @param iterable $map + * + * @return static + */ + public function union(iterable $map): Map + { + return $this->withOperation(function () use ($map) { + $map = Map::fromIterable($map)->toArray(); + $x = $this->toArray(); + + yield from $x; + + foreach ($map as $key => $value) { + if (!array_key_exists($key, $x)) { + yield $key => $value; + } + } + }); + } + + /** + * Creates a new map from the existing one filtering the values based on the keys that don't exist in the provided map. + * + * @param iterable $map + * + * @return static + */ + public function intersect(iterable $map): Map + { + return $this->withOperation(function () use ($map) { + $map = Map::fromIterable($map)->toArray(); + foreach ($this as $key => $value) { + if (array_key_exists($key, $map)) { + yield $key => $value; + } + } + }); + } + + /** + * Creates a new map from the existing one filtering the values based on the keys that also exist in the provided map. + * + * @param iterable $map + * + * @return static + */ + public function diff(iterable $map): Map + { + return $this->withOperation(function () use ($map) { + $map = Map::fromIterable($map)->toArray(); + foreach ($this as $key => $value) { + if (!array_key_exists($key, $map)) { + yield $key => $value; + } + } + }); + } + + /** + * Gets the value with the provided key. If a default value is provided, it will return the default instead of throwing an error when the key does not exist. + * + * @template TDefault + * + * @param TDefault $default + * + * @throws OutOfBoundsException + * + * @return (func_num_args() is 1 ? TValue : TValue|TDefault) + */ + public function get(string $key, $default = null) + { + if (!$this->offsetExists($key)) { + if (func_num_args() === 1) { + throw new OutOfBoundsException(sprintf('Cannot get item in sequence with key: %s', $key)); + } + + return $default; + } + + return $this->offsetGet($key); + } + + public function jsonSerialize() + { + if ($this->isEmpty()) { + return new stdClass(); + } + + return parent::jsonSerialize(); + } + + /** + * @param mixed $default + */ + public function getAsString(string $key, $default = null): string + { + if (func_num_args() === 1) { + $value = $this->get($key); + } else { + /** @var mixed */ + $value = $this->get($key, $default); + } + $tbr = TypeCaster::toString($value); + if ($tbr === null) { + throw new RuntimeTypeException($value, 'string'); + } + + return $tbr; + } + + /** + * @param mixed $default + */ + public function getAsInt(string $key, $default = null): int + { + if (func_num_args() === 1) { + $value = $this->get($key); + } else { + /** @var mixed */ + $value = $this->get($key, $default); + } + $tbr = TypeCaster::toInt($value); + if ($tbr === null) { + throw new RuntimeTypeException($value, 'int'); + } + + return $tbr; + } + + /** + * @param mixed $default + */ + public function getAsFloat(string $key, $default = null): float + { + if (func_num_args() === 1) { + $value = $this->get($key); + } else { + /** @var mixed */ + $value = $this->get($key, $default); + } + $tbr = TypeCaster::toFloat($value); + if ($tbr === null) { + throw new RuntimeTypeException($value, 'float'); + } + + return $tbr; + } + + /** + * @param mixed $default + */ + public function getAsBool(string $key, $default = null): bool + { + if (func_num_args() === 1) { + $value = $this->get($key); + } else { + /** @var mixed */ + $value = $this->get($key, $default); + } + $tbr = TypeCaster::toBool($value); + if ($tbr === null) { + throw new RuntimeTypeException($value, 'bool'); + } + + return $tbr; + } + + /** + * @param mixed $default + * + * @return null + */ + public function getAsNull(string $key, $default = null) + { + if (func_num_args() === 1) { + /** @psalm-suppress UnusedMethodCall */ + $this->get($key); + } + + return TypeCaster::toNull(); + } + + /** + * @template U + * + * @param class-string $class + * @param mixed $default + * + * @return U + */ + public function getAsObject(string $key, string $class, $default = null): object + { + if (func_num_args() === 1) { + $value = $this->get($key); + } else { + /** @var mixed */ + $value = $this->get($key, $default); + } + $tbr = TypeCaster::toClass($value, $class); + if ($tbr === null) { + throw new RuntimeTypeException($value, $class); + } + + return $tbr; + } + + /** + * @param mixed $default + * + * @return Map + */ + public function getAsMap(string $key, $default = null): Map + { + if (func_num_args() === 1) { + $value = $this->get($key); + } else { + /** @var mixed */ + $value = $this->get($key, $default); + } + + if (!is_iterable($value)) { + throw new RuntimeTypeException($value, __CLASS__); + } + + return new Map($value); + } + + /** + * @param mixed $default + * + * @return ArrayList + */ + public function getAsArrayList(string $key, $default = null): ArrayList + { + if (func_num_args() === 1) { + $value = $this->get($key); + } else { + /** @var mixed */ + $value = $this->get($key, $default); + } + if (!is_iterable($value)) { + throw new RuntimeTypeException($value, ArrayList::class); + } + + return new ArrayList($value); + } + + /** + * @template Value + * + * @param iterable $iterable + * + * @return Map + */ + public static function fromIterable(iterable $iterable): Map + { + return new self($iterable); + } +} diff --git a/src/Type/OGM/Path.php b/src/Type/OGM/Path.php new file mode 100644 index 0000000..2a21061 --- /dev/null +++ b/src/Type/OGM/Path.php @@ -0,0 +1,90 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Syndesi\CypherDataStructures\Type\OGM; + +/** + * A Path class representing a Path in cypher. + * + * @psalm-immutable + * + * @extends AbstractPropertyObject|CypherList|CypherList, CypherList|CypherList|CypherList> + */ +final class Path extends AbstractPropertyObject +{ + /** @var CypherList */ + private CypherList $nodes; + /** @var CypherList */ + private CypherList $relationships; + /** @var CypherList */ + private CypherList $ids; + + /** + * @param CypherList $nodes + * @param CypherList $relationships + * @param CypherList $ids + */ + public function __construct(CypherList $nodes, CypherList $relationships, CypherList $ids) + { + $this->nodes = $nodes; + $this->relationships = $relationships; + $this->ids = $ids; + } + + /** + * Returns the node in the path. + * + * @return CypherList + */ + public function getNodes(): CypherList + { + return $this->nodes; + } + + /** + * Returns the relationships in the path. + * + * @return CypherList + */ + public function getRelationships(): CypherList + { + return $this->relationships; + } + + /** + * Returns the ids of the items in the path. + * + * @return CypherList + */ + public function getIds(): CypherList + { + return $this->ids; + } + + /** + * @return array{ids: CypherList, nodes: CypherList, relationships: CypherList} + */ + public function toArray(): array + { + return [ + 'ids' => $this->ids, + 'nodes' => $this->nodes, + 'relationships' => $this->relationships, + ]; + } + + public function getProperties(): CypherMap + { + return new CypherMap($this); + } +} diff --git a/src/Type/OGM/Relationship.php b/src/Type/OGM/Relationship.php new file mode 100644 index 0000000..2ab5c70 --- /dev/null +++ b/src/Type/OGM/Relationship.php @@ -0,0 +1,75 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Syndesi\CypherDataStructures\Type\OGM; + +/** + * A Relationship class representing a Relationship in cypher. + * + * @psalm-import-type OGMTypes from \Laudis\Neo4j\Formatter\OGMFormatter + * + * @psalm-immutable + */ +final class Relationship extends UnboundRelationship +{ + private int $startNodeId; + + private int $endNodeId; + + /** + * @param CypherMap $properties + */ + public function __construct(int $id, int $startNodeId, int $endNodeId, string $type, CypherMap $properties) + { + parent::__construct($id, $type, $properties); + $this->startNodeId = $startNodeId; + $this->endNodeId = $endNodeId; + } + + /** + * Returns the id of the start node. + */ + public function getStartNodeId(): int + { + return $this->startNodeId; + } + + /** + * Returns the id of the end node. + */ + public function getEndNodeId(): int + { + return $this->endNodeId; + } + + /** + * @psalm-suppress ImplementedReturnTypeMismatch False positive. + * + * @return array{ + * id: int, + * type: string, + * startNodeId: int, + * endNodeId: int, + * properties: CypherMap + * } + */ + public function toArray(): array + { + $tbr = parent::toArray(); + + $tbr['startNodeId'] = $this->getStartNodeId(); + $tbr['endNodeId'] = $this->getEndNodeId(); + + return $tbr; + } +} diff --git a/src/Type/OGM/Time.php b/src/Type/OGM/Time.php new file mode 100644 index 0000000..b7f913a --- /dev/null +++ b/src/Type/OGM/Time.php @@ -0,0 +1,64 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Syndesi\CypherDataStructures\Type\OGM; + +use Bolt\structures\IStructure; +use Laudis\Neo4j\Contracts\BoltConvertibleInterface; + +/** + * A time object represented in seconds since the unix epoch. + * + * @psalm-immutable + * + * @extends AbstractPropertyObject + */ +final class Time extends AbstractPropertyObject implements BoltConvertibleInterface +{ + private int $nanoSeconds; + private int $tzOffsetSeconds; + + public function __construct(int $nanoSeconds, int $tzOffsetSeconds) + { + $this->nanoSeconds = $nanoSeconds; + $this->tzOffsetSeconds = $tzOffsetSeconds; + } + + /** + * @return array{nanoSeconds: int, tzOffsetSeconds: int} + */ + public function toArray(): array + { + return ['nanoSeconds' => $this->nanoSeconds, 'tzOffsetSeconds' => $this->tzOffsetSeconds]; + } + + public function getTzOffsetSeconds(): int + { + return $this->tzOffsetSeconds; + } + + public function getNanoSeconds(): int + { + return $this->nanoSeconds; + } + + public function getProperties(): CypherMap + { + return new CypherMap($this); + } + + public function convertToBolt(): IStructure + { + return new \Bolt\structures\Time($this->getNanoSeconds(), $this->getTzOffsetSeconds()); + } +} diff --git a/src/Type/OGM/UnboundRelationship.php b/src/Type/OGM/UnboundRelationship.php new file mode 100644 index 0000000..f06606c --- /dev/null +++ b/src/Type/OGM/UnboundRelationship.php @@ -0,0 +1,90 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Syndesi\CypherDataStructures\Type\OGM; + +use Laudis\Neo4j\Exception\PropertyDoesNotExistException; +use function sprintf; + +/** + * A relationship without any nodes attached to it. + * + * @psalm-import-type OGMTypes from \Laudis\Neo4j\Formatter\OGMFormatter + * + * @psalm-immutable + * + * @extends AbstractPropertyObject> + */ +class UnboundRelationship extends AbstractPropertyObject +{ + private int $id; + private string $type; + /** @var CypherMap */ + private CypherMap $properties; + + /** + * @param CypherMap $properties + */ + public function __construct(int $id, string $type, CypherMap $properties) + { + $this->id = $id; + $this->type = $type; + $this->properties = $properties; + } + + public function getId(): int + { + return $this->id; + } + + public function getType(): string + { + return $this->type; + } + + public function getProperties(): CypherMap + { + /** @psalm-suppress InvalidReturnStatement false positive with type alias. */ + return $this->properties; + } + + /** + * @psalm-suppress ImplementedReturnTypeMismatch False positive. + * + * @return array{id: int, type: string, properties: CypherMap} + */ + public function toArray(): array + { + return [ + 'id' => $this->getId(), + 'type' => $this->getType(), + 'properties' => $this->getProperties(), + ]; + } + + /** + * Gets the property of the relationship by key. + * + * @return OGMTypes + */ + public function getProperty(string $key) + { + /** @psalm-suppress ImpureMethodCall */ + if (!$this->properties->hasKey($key)) { + throw new PropertyDoesNotExistException(sprintf('Property "%s" does not exist on relationship', $key)); + } + + /** @psalm-suppress ImpureMethodCall */ + return $this->properties->get($key); + } +} diff --git a/src/Type/OGM/WGS843DPoint.php b/src/Type/OGM/WGS843DPoint.php new file mode 100644 index 0000000..aaff039 --- /dev/null +++ b/src/Type/OGM/WGS843DPoint.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Syndesi\CypherDataStructures\Type\OGM; + +use Laudis\Neo4j\Contracts\BoltConvertibleInterface; +use Laudis\Neo4j\Contracts\PointInterface; + +/** + * A WGS84 Point in three dimensional space. + * + * @see https://neo4j.com/docs/cypher-manual/current/functions/spatial/#functions-point-wgs84-3d + * + * @psalm-immutable + * + * @psalm-import-type Crs from \Laudis\Neo4j\Contracts\PointInterface + */ +final class WGS843DPoint extends Abstract3DPoint implements PointInterface, BoltConvertibleInterface +{ + public const SRID = 4979; + public const CRS = 'wgs-84-3d'; + + public function getSrid(): int + { + return self::SRID; + } + + public function getLongitude(): float + { + return $this->getX(); + } + + public function getLatitude(): float + { + return $this->getY(); + } + + public function getHeight(): float + { + return $this->getZ(); + } + + public function getCrs(): string + { + return self::CRS; + } +} diff --git a/src/Type/OGM/WGS84Point.php b/src/Type/OGM/WGS84Point.php new file mode 100644 index 0000000..3d14c1a --- /dev/null +++ b/src/Type/OGM/WGS84Point.php @@ -0,0 +1,58 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Syndesi\CypherDataStructures\Type\OGM; + +use Laudis\Neo4j\Contracts\BoltConvertibleInterface; +use Laudis\Neo4j\Contracts\PointInterface; + +/** + * A WGS84 Point in two dimensional space. + * + * @psalm-immutable + * + * @see https://neo4j.com/docs/cypher-manual/current/functions/spatial/#functions-point-wgs84-2d + * + * @psalm-import-type Crs from \Laudis\Neo4j\Contracts\PointInterface + */ +final class WGS84Point extends AbstractPoint implements PointInterface, BoltConvertibleInterface +{ + public const SRID = 4326; + public const CRS = 'wgs-84'; + + public function getSrid(): int + { + return self::SRID; + } + + public function getCrs(): string + { + return self::CRS; + } + + /** + * A numeric expression that represents the longitude/x value in decimal degrees. + */ + public function getLongitude(): float + { + return $this->getX(); + } + + /** + * A numeric expression that represents the latitude/y value in decimal degrees. + */ + public function getLatitude(): float + { + return $this->getY(); + } +} From 4a4ef487f5e494e1dfc12a7bc9e03a592ea2e8c6 Mon Sep 17 00:00:00 2001 From: ghlen Date: Fri, 2 Dec 2022 13:06:18 +0530 Subject: [PATCH 04/15] removed all direct integrations with bolt --- src/Type/OGM/Abstract3DPoint.php | 8 +------- src/Type/OGM/AbstractCypherObject.php | 13 ------------- src/Type/OGM/AbstractPoint.php | 10 +--------- src/Type/OGM/Cartesian3DPoint.php | 3 +-- src/Type/OGM/CartesianPoint.php | 3 +-- src/Type/OGM/Date.php | 9 +-------- src/Type/OGM/DateTime.php | 9 +-------- src/Type/OGM/DateTimeZoneId.php | 9 +-------- src/Type/OGM/Duration.php | 14 +------------- src/Type/OGM/LocalDateTime.php | 9 +-------- src/Type/OGM/LocalTime.php | 10 +--------- src/Type/OGM/Time.php | 9 +-------- src/Type/OGM/WGS843DPoint.php | 3 +-- src/Type/OGM/WGS84Point.php | 3 +-- 14 files changed, 13 insertions(+), 99 deletions(-) diff --git a/src/Type/OGM/Abstract3DPoint.php b/src/Type/OGM/Abstract3DPoint.php index 7607c12..80f3bd9 100644 --- a/src/Type/OGM/Abstract3DPoint.php +++ b/src/Type/OGM/Abstract3DPoint.php @@ -15,7 +15,6 @@ use Bolt\structures\IStructure; use Bolt\structures\Point3D; -use Laudis\Neo4j\Contracts\BoltConvertibleInterface; use Laudis\Neo4j\Contracts\PointInterface; /** @@ -27,15 +26,10 @@ * * @psalm-import-type Crs from \Laudis\Neo4j\Contracts\PointInterface */ -abstract class Abstract3DPoint extends AbstractPoint implements PointInterface, BoltConvertibleInterface +abstract class Abstract3DPoint extends AbstractPoint implements PointInterface { private float $z; - public function convertToBolt(): IStructure - { - return new Point3D($this->getSrid(), $this->getX(), $this->getY(), $this->getZ()); - } - /** * @param Crs $crs */ diff --git a/src/Type/OGM/AbstractCypherObject.php b/src/Type/OGM/AbstractCypherObject.php index 9885d63..a8cedab 100644 --- a/src/Type/OGM/AbstractCypherObject.php +++ b/src/Type/OGM/AbstractCypherObject.php @@ -17,20 +17,12 @@ use ArrayAccess; use ArrayIterator; use BadMethodCallException; -use const E_DEPRECATED; -use function error_reporting; use IteratorAggregate; use JsonSerializable; use OutOfBoundsException; use function sprintf; use Traversable; -/** - * Turn of error reporting for class definition. PHP Users of 8.1 receive a deprectation warning otherwise but - * it is not fixable from the minimum version 7.4 as it required the "mixed" keyword. - */ -$oldReporting = error_reporting(error_reporting() & ~E_DEPRECATED); - /** * Abstract immutable container with basic functionality to integrate easily into the driver ecosystem. * @@ -104,8 +96,3 @@ final public function offsetUnset($offset): void throw new BadMethodCallException(sprintf('%s is immutable', static::class)); } } - -/** - * Turn back on old error reporting after class definition. - */ -error_reporting($oldReporting); diff --git a/src/Type/OGM/AbstractPoint.php b/src/Type/OGM/AbstractPoint.php index 4180a22..f3789ed 100644 --- a/src/Type/OGM/AbstractPoint.php +++ b/src/Type/OGM/AbstractPoint.php @@ -13,9 +13,6 @@ namespace Syndesi\CypherDataStructures\Type\OGM; -use Bolt\structures\IStructure; -use Bolt\structures\Point2D; -use Laudis\Neo4j\Contracts\BoltConvertibleInterface; use Laudis\Neo4j\Contracts\PointInterface; /** @@ -27,7 +24,7 @@ * * @psalm-import-type Crs from \Laudis\Neo4j\Contracts\PointInterface */ -abstract class AbstractPoint extends AbstractPropertyObject implements PointInterface, BoltConvertibleInterface +abstract class AbstractPoint extends AbstractPropertyObject implements PointInterface { private float $x; private float $y; @@ -45,11 +42,6 @@ abstract public function getCrs(): string; abstract public function getSrid(): int; - public function convertToBolt(): IStructure - { - return new Point2D($this->getSrid(), $this->getX(), $this->getY()); - } - public function getX(): float { return $this->x; diff --git a/src/Type/OGM/Cartesian3DPoint.php b/src/Type/OGM/Cartesian3DPoint.php index dcd53da..e8dc8af 100644 --- a/src/Type/OGM/Cartesian3DPoint.php +++ b/src/Type/OGM/Cartesian3DPoint.php @@ -13,7 +13,6 @@ namespace Syndesi\CypherDataStructures\Type\OGM; -use Laudis\Neo4j\Contracts\BoltConvertibleInterface; use Laudis\Neo4j\Contracts\PointInterface; /** @@ -25,7 +24,7 @@ * * @psalm-import-type Crs from \Laudis\Neo4j\Contracts\PointInterface */ -final class Cartesian3DPoint extends Abstract3DPoint implements PointInterface, BoltConvertibleInterface +final class Cartesian3DPoint extends Abstract3DPoint implements PointInterface { public const SRID = 9157; public const CRS = 'cartesian-3d'; diff --git a/src/Type/OGM/CartesianPoint.php b/src/Type/OGM/CartesianPoint.php index bfe5149..177eccf 100644 --- a/src/Type/OGM/CartesianPoint.php +++ b/src/Type/OGM/CartesianPoint.php @@ -13,7 +13,6 @@ namespace Syndesi\CypherDataStructures\Type\OGM; -use Laudis\Neo4j\Contracts\BoltConvertibleInterface; use Laudis\Neo4j\Contracts\PointInterface; /** @@ -25,7 +24,7 @@ * * @psalm-import-type Crs from \Laudis\Neo4j\Contracts\PointInterface */ -final class CartesianPoint extends AbstractPoint implements PointInterface, BoltConvertibleInterface +final class CartesianPoint extends AbstractPoint implements PointInterface { /** @var Crs */ public const CRS = 'cartesian'; diff --git a/src/Type/OGM/Date.php b/src/Type/OGM/Date.php index 37b5e32..aa72ade 100644 --- a/src/Type/OGM/Date.php +++ b/src/Type/OGM/Date.php @@ -13,10 +13,8 @@ namespace Syndesi\CypherDataStructures\Type\OGM; -use Bolt\structures\IStructure; use DateTimeImmutable; use Exception; -use Laudis\Neo4j\Contracts\BoltConvertibleInterface; use UnexpectedValueException; /** @@ -28,7 +26,7 @@ * * @psalm-suppress TypeDoesNotContainType */ -final class Date extends AbstractPropertyObject implements BoltConvertibleInterface +final class Date extends AbstractPropertyObject { private int $days; @@ -70,9 +68,4 @@ public function toArray(): array { return ['days' => $this->days]; } - - public function convertToBolt(): IStructure - { - return new \Bolt\structures\Date($this->getDays()); - } } diff --git a/src/Type/OGM/DateTime.php b/src/Type/OGM/DateTime.php index 764709b..f00c679 100644 --- a/src/Type/OGM/DateTime.php +++ b/src/Type/OGM/DateTime.php @@ -13,11 +13,9 @@ namespace Syndesi\CypherDataStructures\Type\OGM; -use Bolt\structures\IStructure; use DateTimeImmutable; use DateTimeZone; use Exception; -use Laudis\Neo4j\Contracts\BoltConvertibleInterface; use RuntimeException; use function sprintf; @@ -28,7 +26,7 @@ * * @extends AbstractPropertyObject */ -final class DateTime extends AbstractPropertyObject implements BoltConvertibleInterface +final class DateTime extends AbstractPropertyObject { private int $seconds; private int $nanoseconds; @@ -102,9 +100,4 @@ public function getProperties(): CypherMap { return new CypherMap($this); } - - public function convertToBolt(): IStructure - { - return new \Bolt\structures\DateTime($this->getSeconds(), $this->getNanoseconds(), $this->getTimeZoneOffsetSeconds()); - } } diff --git a/src/Type/OGM/DateTimeZoneId.php b/src/Type/OGM/DateTimeZoneId.php index 5ebdb5d..c7e65ff 100644 --- a/src/Type/OGM/DateTimeZoneId.php +++ b/src/Type/OGM/DateTimeZoneId.php @@ -13,11 +13,9 @@ namespace Syndesi\CypherDataStructures\Type\OGM; -use Bolt\structures\IStructure; use DateTimeImmutable; use DateTimeZone; use Exception; -use Laudis\Neo4j\Contracts\BoltConvertibleInterface; use function sprintf; /** @@ -29,7 +27,7 @@ * * @psalm-suppress TypeDoesNotContainType */ -final class DateTimeZoneId extends AbstractPropertyObject implements BoltConvertibleInterface +final class DateTimeZoneId extends AbstractPropertyObject { private int $seconds; private int $nanoseconds; @@ -102,9 +100,4 @@ public function getProperties(): CypherMap { return new CypherMap($this); } - - public function convertToBolt(): IStructure - { - return new \Bolt\structures\DateTimeZoneId($this->getSeconds(), $this->getNanoseconds(), $this->getTimezoneIdentifier()); - } } diff --git a/src/Type/OGM/Duration.php b/src/Type/OGM/Duration.php index eca3032..22ed670 100644 --- a/src/Type/OGM/Duration.php +++ b/src/Type/OGM/Duration.php @@ -13,10 +13,8 @@ namespace Syndesi\CypherDataStructures\Type\OGM; -use Bolt\structures\IStructure; use DateInterval; use Exception; -use Laudis\Neo4j\Contracts\BoltConvertibleInterface; /** * A temporal range represented in months, days, seconds and nanoseconds. @@ -25,7 +23,7 @@ * * @extends AbstractPropertyObject */ -final class Duration extends AbstractPropertyObject implements BoltConvertibleInterface +final class Duration extends AbstractPropertyObject { private int $months; private int $days; @@ -99,14 +97,4 @@ public function getProperties(): CypherMap { return new CypherMap($this); } - - public function convertToBolt(): IStructure - { - return new \Bolt\structures\Duration( - $this->getMonths(), - $this->getDays(), - $this->getSeconds(), - $this->getNanoseconds() - ); - } } diff --git a/src/Type/OGM/LocalDateTime.php b/src/Type/OGM/LocalDateTime.php index de2e3e4..f4f0a85 100644 --- a/src/Type/OGM/LocalDateTime.php +++ b/src/Type/OGM/LocalDateTime.php @@ -13,10 +13,8 @@ namespace Syndesi\CypherDataStructures\Type\OGM; -use Bolt\structures\IStructure; use DateTimeImmutable; use Exception; -use Laudis\Neo4j\Contracts\BoltConvertibleInterface; use function sprintf; use UnexpectedValueException; @@ -29,7 +27,7 @@ * * @psalm-suppress TypeDoesNotContainType */ -final class LocalDateTime extends AbstractPropertyObject implements BoltConvertibleInterface +final class LocalDateTime extends AbstractPropertyObject { private int $seconds; private int $nanoseconds; @@ -85,9 +83,4 @@ public function getProperties(): CypherMap { return new CypherMap($this); } - - public function convertToBolt(): IStructure - { - return new \Bolt\structures\LocalDateTime($this->getSeconds(), $this->getNanoseconds()); - } } diff --git a/src/Type/OGM/LocalTime.php b/src/Type/OGM/LocalTime.php index 1d63f59..986ae3c 100644 --- a/src/Type/OGM/LocalTime.php +++ b/src/Type/OGM/LocalTime.php @@ -13,9 +13,6 @@ namespace Syndesi\CypherDataStructures\Type\OGM; -use Bolt\structures\IStructure; -use Laudis\Neo4j\Contracts\BoltConvertibleInterface; - /** * The time of day represented in nanoseconds. * @@ -23,7 +20,7 @@ * * @extends AbstractPropertyObject */ -final class LocalTime extends AbstractPropertyObject implements BoltConvertibleInterface +final class LocalTime extends AbstractPropertyObject { private int $nanoseconds; @@ -52,9 +49,4 @@ public function getProperties(): CypherMap { return new CypherMap($this); } - - public function convertToBolt(): IStructure - { - return new \Bolt\structures\LocalTime($this->getNanoseconds()); - } } diff --git a/src/Type/OGM/Time.php b/src/Type/OGM/Time.php index b7f913a..1b3f88c 100644 --- a/src/Type/OGM/Time.php +++ b/src/Type/OGM/Time.php @@ -13,8 +13,6 @@ namespace Syndesi\CypherDataStructures\Type\OGM; -use Bolt\structures\IStructure; -use Laudis\Neo4j\Contracts\BoltConvertibleInterface; /** * A time object represented in seconds since the unix epoch. @@ -23,7 +21,7 @@ * * @extends AbstractPropertyObject */ -final class Time extends AbstractPropertyObject implements BoltConvertibleInterface +final class Time extends AbstractPropertyObject { private int $nanoSeconds; private int $tzOffsetSeconds; @@ -56,9 +54,4 @@ public function getProperties(): CypherMap { return new CypherMap($this); } - - public function convertToBolt(): IStructure - { - return new \Bolt\structures\Time($this->getNanoSeconds(), $this->getTzOffsetSeconds()); - } } diff --git a/src/Type/OGM/WGS843DPoint.php b/src/Type/OGM/WGS843DPoint.php index aaff039..d8410b2 100644 --- a/src/Type/OGM/WGS843DPoint.php +++ b/src/Type/OGM/WGS843DPoint.php @@ -13,7 +13,6 @@ namespace Syndesi\CypherDataStructures\Type\OGM; -use Laudis\Neo4j\Contracts\BoltConvertibleInterface; use Laudis\Neo4j\Contracts\PointInterface; /** @@ -25,7 +24,7 @@ * * @psalm-import-type Crs from \Laudis\Neo4j\Contracts\PointInterface */ -final class WGS843DPoint extends Abstract3DPoint implements PointInterface, BoltConvertibleInterface +final class WGS843DPoint extends Abstract3DPoint implements PointInterface { public const SRID = 4979; public const CRS = 'wgs-84-3d'; diff --git a/src/Type/OGM/WGS84Point.php b/src/Type/OGM/WGS84Point.php index 3d14c1a..9d3a1da 100644 --- a/src/Type/OGM/WGS84Point.php +++ b/src/Type/OGM/WGS84Point.php @@ -13,7 +13,6 @@ namespace Syndesi\CypherDataStructures\Type\OGM; -use Laudis\Neo4j\Contracts\BoltConvertibleInterface; use Laudis\Neo4j\Contracts\PointInterface; /** @@ -25,7 +24,7 @@ * * @psalm-import-type Crs from \Laudis\Neo4j\Contracts\PointInterface */ -final class WGS84Point extends AbstractPoint implements PointInterface, BoltConvertibleInterface +final class WGS84Point extends AbstractPoint implements PointInterface { public const SRID = 4326; public const CRS = 'wgs-84'; From 8d45a71e5203edba7982e4e9e48f2c7d2b77b370 Mon Sep 17 00:00:00 2001 From: ghlen Date: Fri, 2 Dec 2022 14:28:31 +0530 Subject: [PATCH 05/15] fixed imports --- src/Contract/OGM/HasPropertiesInterface.php | 58 ++++++ src/Contract/OGM/PointInterface.php | 50 ++++++ .../PropertyDoesNotExistException.php | 27 +++ src/Exception/RuntimeTypeException.php | 31 ++++ src/Type/OGM/Abstract3DPoint.php | 9 +- src/Type/OGM/AbstractPoint.php | 7 +- src/Type/OGM/AbstractPropertyObject.php | 6 +- src/Type/OGM/ArrayList.php | 6 +- src/Type/OGM/Cartesian3DPoint.php | 4 +- src/Type/OGM/CartesianPoint.php | 4 +- src/Type/OGM/CypherList.php | 4 +- src/Type/OGM/CypherMap.php | 8 +- src/Type/OGM/Map.php | 6 +- src/Type/OGM/NodeLabel.php | 2 +- src/Type/OGM/RelationType.php | 2 +- src/Type/OGM/WGS843DPoint.php | 4 +- src/Type/OGM/WGS84Point.php | 4 +- src/Type/Pair.php | 56 ++++++ src/TypeCaster.php | 168 ++++++++++++++++++ 19 files changed, 417 insertions(+), 39 deletions(-) create mode 100644 src/Contract/OGM/HasPropertiesInterface.php create mode 100644 src/Contract/OGM/PointInterface.php create mode 100644 src/Exception/PropertyDoesNotExistException.php create mode 100644 src/Exception/RuntimeTypeException.php create mode 100644 src/Type/Pair.php create mode 100644 src/TypeCaster.php diff --git a/src/Contract/OGM/HasPropertiesInterface.php b/src/Contract/OGM/HasPropertiesInterface.php new file mode 100644 index 0000000..0ada6ab --- /dev/null +++ b/src/Contract/OGM/HasPropertiesInterface.php @@ -0,0 +1,58 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Syndesi\CypherDataStructures\Contract\OGM; + +use BadMethodCallException; +use Syndesi\CypherDataStructures\Type\OGM\CypherMap; + +/** + * Defines how an object with properties should behave. + * + * @psalm-immutable + * + * @template T + */ +interface HasPropertiesInterface +{ + /** + * Returns the properties a map. + * + * @return CypherMap + */ + public function getProperties(): CypherMap; + + /** + * @param string $name + * + * @return T + */ + public function __get($name); + + /** + * Always throws an exception as cypher objects are immutable. + * + * @param string $name + * @param T $value + * + * @throws BadMethodCallException + */ + public function __set($name, $value): void; + + /** + * Checks to see if the property exists and is set. + * + * @param string $name + */ + public function __isset($name): bool; +} diff --git a/src/Contract/OGM/PointInterface.php b/src/Contract/OGM/PointInterface.php new file mode 100644 index 0000000..ee2c75a --- /dev/null +++ b/src/Contract/OGM/PointInterface.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Syndesi\CypherDataStructures\Contract\OGM; + +/** + * Defines a basic Point type in neo4j. + * + * @psalm-immutable + * + * @psalm-type Crs = 'wgs-84'|'wgs-84-3d'|'cartesian'|'cartesian-3d'; + */ +interface PointInterface +{ + /** + * Returns the x coordinate. + */ + public function getX(): float; + + /** + * Returns the y coordinate. + */ + public function getY(): float; + + /** + * Returns the Coordinates Reference System. + * + * @see https://en.wikipedia.org/wiki/Spatial_reference_system + * + * @return Crs + */ + public function getCrs(): string; + + /** + * Returns the spacial reference identifier. + * + * @see https://en.wikipedia.org/wiki/Spatial_reference_system + */ + public function getSrid(): int; +} diff --git a/src/Exception/PropertyDoesNotExistException.php b/src/Exception/PropertyDoesNotExistException.php new file mode 100644 index 0000000..fc69fd6 --- /dev/null +++ b/src/Exception/PropertyDoesNotExistException.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Syndesi\CypherDataStructures\Exception; + +use RuntimeException; + +/** + * Exception when accessing a property which does not exist. + * + * @psalm-immutable + * + * @psalm-suppress MutableDependency + */ +final class PropertyDoesNotExistException extends RuntimeException +{ +} diff --git a/src/Exception/RuntimeTypeException.php b/src/Exception/RuntimeTypeException.php new file mode 100644 index 0000000..18a177c --- /dev/null +++ b/src/Exception/RuntimeTypeException.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Syndesi\CypherDataStructures\Exception; + +use RuntimeException; + +use function get_debug_type; + +final class RuntimeTypeException extends RuntimeException +{ + /** + * @param mixed $value + */ + public function __construct($value, string $type) + { + $actualType = get_debug_type($value); + $message = sprintf('Cannot cast %s to type: %s', $actualType, $type); + parent::__construct($message); + } +} diff --git a/src/Type/OGM/Abstract3DPoint.php b/src/Type/OGM/Abstract3DPoint.php index 80f3bd9..f182775 100644 --- a/src/Type/OGM/Abstract3DPoint.php +++ b/src/Type/OGM/Abstract3DPoint.php @@ -13,9 +13,7 @@ namespace Syndesi\CypherDataStructures\Type\OGM; -use Bolt\structures\IStructure; -use Bolt\structures\Point3D; -use Laudis\Neo4j\Contracts\PointInterface; +use Syndesi\CypherDataStructures\Contract\OGM\PointInterface; /** * A cartesian point in three dimensional space. @@ -24,15 +22,12 @@ * * @psalm-immutable * - * @psalm-import-type Crs from \Laudis\Neo4j\Contracts\PointInterface + * @psalm-import-type Crs from PointInterface */ abstract class Abstract3DPoint extends AbstractPoint implements PointInterface { private float $z; - /** - * @param Crs $crs - */ public function __construct(float $x, float $y, float $z) { parent::__construct($x, $y); diff --git a/src/Type/OGM/AbstractPoint.php b/src/Type/OGM/AbstractPoint.php index f3789ed..c7775fa 100644 --- a/src/Type/OGM/AbstractPoint.php +++ b/src/Type/OGM/AbstractPoint.php @@ -13,7 +13,7 @@ namespace Syndesi\CypherDataStructures\Type\OGM; -use Laudis\Neo4j\Contracts\PointInterface; +use Syndesi\CypherDataStructures\Contract\OGM\PointInterface; /** * A cartesian point in two dimensional space. @@ -22,16 +22,13 @@ * * @psalm-immutable * - * @psalm-import-type Crs from \Laudis\Neo4j\Contracts\PointInterface + * @psalm-import-type Crs from PointInterface */ abstract class AbstractPoint extends AbstractPropertyObject implements PointInterface { private float $x; private float $y; - /** - * @param Crs $crs - */ public function __construct(float $x, float $y) { $this->x = $x; diff --git a/src/Type/OGM/AbstractPropertyObject.php b/src/Type/OGM/AbstractPropertyObject.php index 0994f11..df191e9 100644 --- a/src/Type/OGM/AbstractPropertyObject.php +++ b/src/Type/OGM/AbstractPropertyObject.php @@ -15,12 +15,10 @@ use BadMethodCallException; use function get_class; -use Laudis\Neo4j\Contracts\HasPropertiesInterface; +use Syndesi\CypherDataStructures\Contract\OGM\HasPropertiesInterface; use function sprintf; -/** - * @psalm-import-type OGMTypes from \Laudis\Neo4j\Formatter\OGMFormatter - * +/** * * @template PropertyTypes * @template ObjectTypes * diff --git a/src/Type/OGM/ArrayList.php b/src/Type/OGM/ArrayList.php index 4790f0f..1881a41 100644 --- a/src/Type/OGM/ArrayList.php +++ b/src/Type/OGM/ArrayList.php @@ -20,8 +20,8 @@ use function is_array; use function is_callable; use function is_iterable; -use Laudis\Neo4j\Exception\RuntimeTypeException; -use Laudis\Neo4j\TypeCaster; +use Syndesi\CypherDataStructures\TypeCaster; +use Syndesi\CypherDataStructures\Exception\RuntimeTypeException; use OutOfBoundsException; /** @@ -34,7 +34,7 @@ class ArrayList extends AbstractCypherSequence { /** - * @param iterable|callable():\Generator $iterable + * @param iterable|callable():Generator $iterable * * @psalm-mutation-free */ diff --git a/src/Type/OGM/Cartesian3DPoint.php b/src/Type/OGM/Cartesian3DPoint.php index e8dc8af..653b0d6 100644 --- a/src/Type/OGM/Cartesian3DPoint.php +++ b/src/Type/OGM/Cartesian3DPoint.php @@ -13,7 +13,7 @@ namespace Syndesi\CypherDataStructures\Type\OGM; -use Laudis\Neo4j\Contracts\PointInterface; +use Syndesi\CypherDataStructures\Contract\OGM\PointInterface; /** * A cartesian point in three dimensional space. @@ -22,7 +22,7 @@ * * @psalm-immutable * - * @psalm-import-type Crs from \Laudis\Neo4j\Contracts\PointInterface + * @psalm-import-type Crs from PointInterface */ final class Cartesian3DPoint extends Abstract3DPoint implements PointInterface { diff --git a/src/Type/OGM/CartesianPoint.php b/src/Type/OGM/CartesianPoint.php index 177eccf..1674687 100644 --- a/src/Type/OGM/CartesianPoint.php +++ b/src/Type/OGM/CartesianPoint.php @@ -13,7 +13,7 @@ namespace Syndesi\CypherDataStructures\Type\OGM; -use Laudis\Neo4j\Contracts\PointInterface; +use Syndesi\CypherDataStructures\Contract\OGM\PointInterface; /** * A cartesian point in two dimensional space. @@ -22,7 +22,7 @@ * * @psalm-immutable * - * @psalm-import-type Crs from \Laudis\Neo4j\Contracts\PointInterface + * @psalm-import-type Crs from PointInterface */ final class CartesianPoint extends AbstractPoint implements PointInterface { diff --git a/src/Type/OGM/CypherList.php b/src/Type/OGM/CypherList.php index 457adc0..ded0f40 100644 --- a/src/Type/OGM/CypherList.php +++ b/src/Type/OGM/CypherList.php @@ -13,8 +13,8 @@ namespace Syndesi\CypherDataStructures\Type\OGM; -use Laudis\Neo4j\Exception\RuntimeTypeException; -use Laudis\Neo4j\TypeCaster; +use Syndesi\CypherDataStructures\TypeCaster; +use Syndesi\CypherDataStructures\Exception\RuntimeTypeException; /** * An immutable ordered sequence of items. diff --git a/src/Type/OGM/CypherMap.php b/src/Type/OGM/CypherMap.php index 895eade..961ab59 100644 --- a/src/Type/OGM/CypherMap.php +++ b/src/Type/OGM/CypherMap.php @@ -14,8 +14,8 @@ namespace Syndesi\CypherDataStructures\Type\OGM; use function func_num_args; -use Laudis\Neo4j\Exception\RuntimeTypeException; -use Laudis\Neo4j\TypeCaster; +use Syndesi\CypherDataStructures\Exception\RuntimeTypeException; +use Syndesi\CypherDataStructures\TypeCaster; /** * An immutable ordered map of items. @@ -27,11 +27,9 @@ final class CypherMap extends Map { /** - * @param mixed $default - * * @return CypherMap */ - public function getAsCypherMap(string $key, $default = null): CypherMap + public function getAsCypherMap(string $key, mixed $default = null): CypherMap { if (func_num_args() === 1) { $value = $this->get($key); diff --git a/src/Type/OGM/Map.php b/src/Type/OGM/Map.php index 0535cc1..ca08c97 100644 --- a/src/Type/OGM/Map.php +++ b/src/Type/OGM/Map.php @@ -22,9 +22,9 @@ use function is_array; use function is_callable; use function is_iterable; -use Laudis\Neo4j\Databags\Pair; -use Laudis\Neo4j\Exception\RuntimeTypeException; -use Laudis\Neo4j\TypeCaster; +use Syndesi\CypherDataStructures\Type\Pair; +use Syndesi\CypherDataStructures\Exception\RuntimeTypeException; +use Syndesi\CypherDataStructures\TypeCaster; use OutOfBoundsException; use function sprintf; use stdClass; diff --git a/src/Type/OGM/NodeLabel.php b/src/Type/OGM/NodeLabel.php index b3b9706..1937eea 100644 --- a/src/Type/OGM/NodeLabel.php +++ b/src/Type/OGM/NodeLabel.php @@ -16,7 +16,7 @@ class NodeLabel implements NodeLabelInterface * @throws InvalidArgumentException */ public function __construct( - private readonly string $nodeLabel + private string $nodeLabel ) { if (!preg_match(self::FORMAT, $this->nodeLabel)) { throw InvalidArgumentException::createForRegexMismatch(self::FORMAT, self::FORMAT_DESCRIPTION, $this->nodeLabel); diff --git a/src/Type/OGM/RelationType.php b/src/Type/OGM/RelationType.php index 6c86b6a..3bb29aa 100644 --- a/src/Type/OGM/RelationType.php +++ b/src/Type/OGM/RelationType.php @@ -16,7 +16,7 @@ class RelationType implements RelationTypeInterface * @throws InvalidArgumentException */ public function __construct( - private readonly string $relationType + private string $relationType ) { if (!preg_match(self::FORMAT, $this->relationType)) { throw InvalidArgumentException::createForRegexMismatch(self::FORMAT, self::FORMAT_DESCRIPTION, $this->relationType); diff --git a/src/Type/OGM/WGS843DPoint.php b/src/Type/OGM/WGS843DPoint.php index d8410b2..2ccea56 100644 --- a/src/Type/OGM/WGS843DPoint.php +++ b/src/Type/OGM/WGS843DPoint.php @@ -13,7 +13,7 @@ namespace Syndesi\CypherDataStructures\Type\OGM; -use Laudis\Neo4j\Contracts\PointInterface; +use Syndesi\CypherDataStructures\Contract\OGM\PointInterface; /** * A WGS84 Point in three dimensional space. @@ -22,7 +22,7 @@ * * @psalm-immutable * - * @psalm-import-type Crs from \Laudis\Neo4j\Contracts\PointInterface + * @psalm-import-type Crs from PointInterface */ final class WGS843DPoint extends Abstract3DPoint implements PointInterface { diff --git a/src/Type/OGM/WGS84Point.php b/src/Type/OGM/WGS84Point.php index 9d3a1da..47eb07d 100644 --- a/src/Type/OGM/WGS84Point.php +++ b/src/Type/OGM/WGS84Point.php @@ -13,7 +13,7 @@ namespace Syndesi\CypherDataStructures\Type\OGM; -use Laudis\Neo4j\Contracts\PointInterface; +use Syndesi\CypherDataStructures\Contract\OGM\PointInterface; /** * A WGS84 Point in two dimensional space. @@ -22,7 +22,7 @@ * * @see https://neo4j.com/docs/cypher-manual/current/functions/spatial/#functions-point-wgs84-2d * - * @psalm-import-type Crs from \Laudis\Neo4j\Contracts\PointInterface + * @psalm-import-type Crs from PointInterface */ final class WGS84Point extends AbstractPoint implements PointInterface { diff --git a/src/Type/Pair.php b/src/Type/Pair.php new file mode 100644 index 0000000..2ffa6a8 --- /dev/null +++ b/src/Type/Pair.php @@ -0,0 +1,56 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Syndesi\CypherDataStructures\Type; + +/** + * A basic Key value Pair. + * + * @template TKey + * @template TValue + * + * @psalm-immutable + */ +final class Pair +{ + /** @var TKey */ + private $key; + /** @var TValue */ + private $value; + + /** + * @param TKey $key + * @param TValue $value + */ + public function __construct($key, $value) + { + $this->key = $key; + $this->value = $value; + } + + /** + * @return TKey + */ + public function getKey() + { + return $this->key; + } + + /** + * @return TValue + */ + public function getValue() + { + return $this->value; + } +} diff --git a/src/TypeCaster.php b/src/TypeCaster.php new file mode 100644 index 0000000..1930781 --- /dev/null +++ b/src/TypeCaster.php @@ -0,0 +1,168 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Syndesi\CypherDataStructures; + +use function is_a; +use function is_iterable; +use function is_numeric; +use function is_object; +use function is_scalar; +use Syndesi\CypherDataStructures\Type\OGM\CypherList; +use Syndesi\CypherDataStructures\Type\OGM\CypherMap; +use function method_exists; + +final class TypeCaster +{ + /** + * @param mixed $value + * + * @pure + */ + public static function toString($value): ?string + { + if ($value === null || is_scalar($value) || (is_object($value) && method_exists($value, '__toString'))) { + return (string) $value; + } + + return null; + } + + /** + * @param mixed $value + * + * @pure + */ + public static function toFloat($value): ?float + { + $value = self::toString($value); + if (is_numeric($value)) { + return (float) $value; + } + + return null; + } + + /** + * @param mixed $value + * + * @pure + */ + public static function toInt($value): ?int + { + $value = self::toFloat($value); + if ($value !== null) { + return (int) $value; + } + + return null; + } + + /** + * @return null + * + * @pure + */ + public static function toNull() + { + return null; + } + + /** + * @param mixed $value + * + * @pure + */ + public static function toBool($value): ?bool + { + $value = self::toInt($value); + if ($value !== null) { + return (bool) $value; + } + + return null; + } + + /** + * @template T + * + * @param mixed $value + * @param class-string $class + * + * @return T|null + * + * @pure + */ + public static function toClass($value, string $class): ?object + { + if (is_a($value, $class)) { + /** @var T */ + return $value; + } + + return null; + } + + /** + * @param mixed $value + * + * @return list + * + * @psalm-external-mutation-free + */ + public static function toArray($value): ?array + { + if (is_iterable($value)) { + $tbr = []; + /** @var mixed $x */ + foreach ($value as $x) { + /** @var mixed */ + $tbr[] = $x; + } + + return $tbr; + } + + return null; + } + + /** + * @param mixed $value + * + * @return CypherList|null + * + * @pure + */ + public static function toCypherList($value): ?CypherList + { + if (is_iterable($value)) { + return CypherList::fromIterable($value); + } + + return null; + } + + /** + * @param mixed $value + * + * @return CypherMap|null + */ + public static function toCypherMap($value): ?CypherMap + { + if (is_iterable($value)) { + return CypherMap::fromIterable($value); + } + + return null; + } +} From 433ffb6c87526e707f6a7483bdf2d3d42939ba00 Mon Sep 17 00:00:00 2001 From: ghlen Date: Fri, 2 Dec 2022 14:32:20 +0530 Subject: [PATCH 06/15] fixed OGMType imports --- src/Type/OGM/Relationship.php | 4 +++- src/Type/OGM/UnboundRelationship.php | 6 ++++-- src/TypeCaster.php | 16 ++++++++++++++++ 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/Type/OGM/Relationship.php b/src/Type/OGM/Relationship.php index 2ab5c70..a32b686 100644 --- a/src/Type/OGM/Relationship.php +++ b/src/Type/OGM/Relationship.php @@ -13,10 +13,12 @@ namespace Syndesi\CypherDataStructures\Type\OGM; +use Syndesi\CypherDataStructures\TypeCaster; + /** * A Relationship class representing a Relationship in cypher. * - * @psalm-import-type OGMTypes from \Laudis\Neo4j\Formatter\OGMFormatter + * @psalm-import-type OGMTypes from TypeCaster * * @psalm-immutable */ diff --git a/src/Type/OGM/UnboundRelationship.php b/src/Type/OGM/UnboundRelationship.php index f06606c..afaa2dd 100644 --- a/src/Type/OGM/UnboundRelationship.php +++ b/src/Type/OGM/UnboundRelationship.php @@ -13,13 +13,15 @@ namespace Syndesi\CypherDataStructures\Type\OGM; -use Laudis\Neo4j\Exception\PropertyDoesNotExistException; +use Syndesi\CypherDataStructures\Exception\PropertyDoesNotExistException; +use Syndesi\CypherDataStructures\TypeCaster; + use function sprintf; /** * A relationship without any nodes attached to it. * - * @psalm-import-type OGMTypes from \Laudis\Neo4j\Formatter\OGMFormatter + * @psalm-import-type OGMTypes from TypeCaster * * @psalm-immutable * diff --git a/src/TypeCaster.php b/src/TypeCaster.php index 1930781..cc2d6de 100644 --- a/src/TypeCaster.php +++ b/src/TypeCaster.php @@ -13,6 +13,19 @@ namespace Syndesi\CypherDataStructures; +use Syndesi\CypherDataStructures\Type\OGM\Cartesian3DPoint; +use Syndesi\CypherDataStructures\Type\OGM\CartesianPoint; +use Syndesi\CypherDataStructures\Type\OGM\Date; +use Syndesi\CypherDataStructures\Type\OGM\DateTime; +use Syndesi\CypherDataStructures\Type\OGM\Duration; +use Syndesi\CypherDataStructures\Type\OGM\LocalDateTime; +use Syndesi\CypherDataStructures\Type\OGM\LocalTime; +use Syndesi\CypherDataStructures\Type\OGM\Node; +use Syndesi\CypherDataStructures\Type\OGM\Path; +use Syndesi\CypherDataStructures\Type\OGM\Relationship; +use Syndesi\CypherDataStructures\Type\OGM\Time; +use Syndesi\CypherDataStructures\Type\OGM\WGS843DPoint; +use Syndesi\CypherDataStructures\Type\OGM\WGS84Point; use function is_a; use function is_iterable; use function is_numeric; @@ -22,6 +35,9 @@ use Syndesi\CypherDataStructures\Type\OGM\CypherMap; use function method_exists; +/** + * @psalm-type OGMTypes = string|int|float|bool|null|Date|DateTime|Duration|LocalDateTime|LocalTime|Time|CypherList|CypherMap|Node|Relationship|Path|Cartesian3DPoint|CartesianPoint|WGS84Point|WGS843DPoint + */ final class TypeCaster { /** From 40bdae4e95ead8fbecc6736833f06a1a09282b6d Mon Sep 17 00:00:00 2001 From: ghlen Date: Fri, 2 Dec 2022 15:16:18 +0530 Subject: [PATCH 07/15] added packstream marker implementations --- src/Contract/PackstreamConvertible.php | 18 ++++++++++++++++++ src/Type/OGM/Abstract3DPoint.php | 8 +++++++- src/Type/OGM/AbstractCypherObject.php | 3 ++- src/Type/OGM/AbstractPoint.php | 8 +++++++- src/Type/OGM/CypherList.php | 22 +++++++++++++++++++++- src/Type/OGM/CypherMap.php | 22 +++++++++++++++++++++- src/Type/OGM/Date.php | 5 +++++ src/Type/OGM/DateTime.php | 5 +++++ src/Type/OGM/DateTimeZoneId.php | 5 +++++ src/Type/OGM/Duration.php | 5 +++++ src/Type/OGM/LocalDateTime.php | 5 +++++ src/Type/OGM/LocalTime.php | 5 +++++ src/Type/OGM/Path.php | 5 +++++ src/Type/OGM/Relationship.php | 5 +++++ src/Type/OGM/Time.php | 5 +++++ src/Type/OGM/UnboundRelationship.php | 5 +++++ 16 files changed, 126 insertions(+), 5 deletions(-) create mode 100644 src/Contract/PackstreamConvertible.php diff --git a/src/Contract/PackstreamConvertible.php b/src/Contract/PackstreamConvertible.php new file mode 100644 index 0000000..22fc108 --- /dev/null +++ b/src/Contract/PackstreamConvertible.php @@ -0,0 +1,18 @@ + $this->getSrid(), ]; } + + public function getPackstreamMarker(): int + { + return 0x58; + } } diff --git a/src/Type/OGM/CypherList.php b/src/Type/OGM/CypherList.php index ded0f40..1f74271 100644 --- a/src/Type/OGM/CypherList.php +++ b/src/Type/OGM/CypherList.php @@ -13,6 +13,7 @@ namespace Syndesi\CypherDataStructures\Type\OGM; +use Syndesi\CypherDataStructures\Contract\PackstreamConvertible; use Syndesi\CypherDataStructures\TypeCaster; use Syndesi\CypherDataStructures\Exception\RuntimeTypeException; @@ -23,7 +24,7 @@ * * @extends ArrayList */ -class CypherList extends ArrayList +class CypherList extends ArrayList implements PackstreamConvertible { /** * @return CypherMap @@ -117,4 +118,23 @@ public function getAsWGS843DPoint(int $key): WGS843DPoint { return $this->getAsObject($key, WGS843DPoint::class); } + + public function getPackstreamMarker(): int + { + // @see https://neo4j.com/docs/bolt/current/packstream/#data-type-list + $count = $this->count(); + + if ($count <= 0xF) { + return 0x90 + $count; + } + if ($count <= 0xFF) { + return 0xD4; + } + + if ($count <= 0xFF) { + return 0xD5; + } + + return 0xD6; + } } diff --git a/src/Type/OGM/CypherMap.php b/src/Type/OGM/CypherMap.php index 961ab59..82a6a5e 100644 --- a/src/Type/OGM/CypherMap.php +++ b/src/Type/OGM/CypherMap.php @@ -13,6 +13,7 @@ namespace Syndesi\CypherDataStructures\Type\OGM; +use Syndesi\CypherDataStructures\Contract\PackstreamConvertible; use function func_num_args; use Syndesi\CypherDataStructures\Exception\RuntimeTypeException; use Syndesi\CypherDataStructures\TypeCaster; @@ -24,7 +25,7 @@ * * @extends Map */ -final class CypherMap extends Map +final class CypherMap extends Map implements PackstreamConvertible { /** * @return CypherMap @@ -251,4 +252,23 @@ public function keyBy(string $key): CypherMap { return CypherMap::fromIterable(parent::keyBy($key)); } + + public function getPackstreamMarker(): int + { + // @see https://neo4j.com/docs/bolt/current/packstream/#data-type-dictionary + $count = $this->count(); + + if ($count <= 0xF) { + return 0xA0 + $count; + } + if ($count <= 0xFF) { + return 0xD8; + } + + if ($count <= 0xFF) { + return 0xD9; + } + + return 0xDA; + } } diff --git a/src/Type/OGM/Date.php b/src/Type/OGM/Date.php index aa72ade..4a22393 100644 --- a/src/Type/OGM/Date.php +++ b/src/Type/OGM/Date.php @@ -68,4 +68,9 @@ public function toArray(): array { return ['days' => $this->days]; } + + public function getPackstreamMarker(): int + { + return 0x44; + } } diff --git a/src/Type/OGM/DateTime.php b/src/Type/OGM/DateTime.php index f00c679..920b4d4 100644 --- a/src/Type/OGM/DateTime.php +++ b/src/Type/OGM/DateTime.php @@ -100,4 +100,9 @@ public function getProperties(): CypherMap { return new CypherMap($this); } + + public function getPackstreamMarker(): int + { + return 0x49; + } } diff --git a/src/Type/OGM/DateTimeZoneId.php b/src/Type/OGM/DateTimeZoneId.php index c7e65ff..60a9b88 100644 --- a/src/Type/OGM/DateTimeZoneId.php +++ b/src/Type/OGM/DateTimeZoneId.php @@ -100,4 +100,9 @@ public function getProperties(): CypherMap { return new CypherMap($this); } + + public function getPackstreamMarker(): int + { + return 0x69; + } } diff --git a/src/Type/OGM/Duration.php b/src/Type/OGM/Duration.php index 22ed670..28e6612 100644 --- a/src/Type/OGM/Duration.php +++ b/src/Type/OGM/Duration.php @@ -97,4 +97,9 @@ public function getProperties(): CypherMap { return new CypherMap($this); } + + public function getPackstreamMarker(): int + { + return 0x45; + } } diff --git a/src/Type/OGM/LocalDateTime.php b/src/Type/OGM/LocalDateTime.php index f4f0a85..534b8bc 100644 --- a/src/Type/OGM/LocalDateTime.php +++ b/src/Type/OGM/LocalDateTime.php @@ -83,4 +83,9 @@ public function getProperties(): CypherMap { return new CypherMap($this); } + + public function getPackstreamMarker(): int + { + return 0x64; + } } diff --git a/src/Type/OGM/LocalTime.php b/src/Type/OGM/LocalTime.php index 986ae3c..c7afc10 100644 --- a/src/Type/OGM/LocalTime.php +++ b/src/Type/OGM/LocalTime.php @@ -49,4 +49,9 @@ public function getProperties(): CypherMap { return new CypherMap($this); } + + public function getPackstreamMarker(): int + { + return 0x74; + } } diff --git a/src/Type/OGM/Path.php b/src/Type/OGM/Path.php index 2a21061..d255f65 100644 --- a/src/Type/OGM/Path.php +++ b/src/Type/OGM/Path.php @@ -87,4 +87,9 @@ public function getProperties(): CypherMap { return new CypherMap($this); } + + public function getPackstreamMarker(): int + { + return 0x50; + } } diff --git a/src/Type/OGM/Relationship.php b/src/Type/OGM/Relationship.php index a32b686..c9802e1 100644 --- a/src/Type/OGM/Relationship.php +++ b/src/Type/OGM/Relationship.php @@ -74,4 +74,9 @@ public function toArray(): array return $tbr; } + + public function getPackstreamMarker(): int + { + return 0x52; + } } diff --git a/src/Type/OGM/Time.php b/src/Type/OGM/Time.php index 1b3f88c..041eba8 100644 --- a/src/Type/OGM/Time.php +++ b/src/Type/OGM/Time.php @@ -54,4 +54,9 @@ public function getProperties(): CypherMap { return new CypherMap($this); } + + public function getPackstreamMarker(): int + { + return 0x54; + } } diff --git a/src/Type/OGM/UnboundRelationship.php b/src/Type/OGM/UnboundRelationship.php index afaa2dd..535cefd 100644 --- a/src/Type/OGM/UnboundRelationship.php +++ b/src/Type/OGM/UnboundRelationship.php @@ -89,4 +89,9 @@ public function getProperty(string $key) /** @psalm-suppress ImpureMethodCall */ return $this->properties->get($key); } + + public function getPackstreamMarker(): int + { + return 0x72; + } } From fc28946ceaccba7f8059696f331b0f021359f332 Mon Sep 17 00:00:00 2001 From: ghlen Date: Fri, 2 Dec 2022 15:17:03 +0530 Subject: [PATCH 08/15] renamed CypherMap to Dictionary --- src/Contract/OGM/HasPropertiesInterface.php | 6 +++--- src/Type/OGM/AbstractPoint.php | 4 ++-- src/Type/OGM/CypherList.php | 6 +++--- src/Type/OGM/Date.php | 4 ++-- src/Type/OGM/DateTime.php | 4 ++-- src/Type/OGM/DateTimeZoneId.php | 6 +++--- src/Type/OGM/{CypherMap.php => Dictionary.php} | 12 ++++++------ src/Type/OGM/Duration.php | 4 ++-- src/Type/OGM/LocalDateTime.php | 4 ++-- src/Type/OGM/LocalTime.php | 4 ++-- src/Type/OGM/Path.php | 4 ++-- src/Type/OGM/Relationship.php | 6 +++--- src/Type/OGM/Time.php | 4 ++-- src/Type/OGM/UnboundRelationship.php | 14 +++++++------- src/TypeCaster.php | 10 +++++----- 15 files changed, 46 insertions(+), 46 deletions(-) rename src/Type/OGM/{CypherMap.php => Dictionary.php} (95%) diff --git a/src/Contract/OGM/HasPropertiesInterface.php b/src/Contract/OGM/HasPropertiesInterface.php index 0ada6ab..97329a4 100644 --- a/src/Contract/OGM/HasPropertiesInterface.php +++ b/src/Contract/OGM/HasPropertiesInterface.php @@ -14,7 +14,7 @@ namespace Syndesi\CypherDataStructures\Contract\OGM; use BadMethodCallException; -use Syndesi\CypherDataStructures\Type\OGM\CypherMap; +use Syndesi\CypherDataStructures\Type\OGM\Dictionary; /** * Defines how an object with properties should behave. @@ -28,9 +28,9 @@ interface HasPropertiesInterface /** * Returns the properties a map. * - * @return CypherMap + * @return Dictionary */ - public function getProperties(): CypherMap; + public function getProperties(): Dictionary; /** * @param string $name diff --git a/src/Type/OGM/AbstractPoint.php b/src/Type/OGM/AbstractPoint.php index 2c8c346..154dca0 100644 --- a/src/Type/OGM/AbstractPoint.php +++ b/src/Type/OGM/AbstractPoint.php @@ -50,10 +50,10 @@ public function getY(): float return $this->y; } - public function getProperties(): CypherMap + public function getProperties(): Dictionary { /** @psalm-suppress InvalidReturnStatement False positive */ - return new CypherMap($this); + return new Dictionary($this); } /** diff --git a/src/Type/OGM/CypherList.php b/src/Type/OGM/CypherList.php index 1f74271..62a6c4e 100644 --- a/src/Type/OGM/CypherList.php +++ b/src/Type/OGM/CypherList.php @@ -27,14 +27,14 @@ class CypherList extends ArrayList implements PackstreamConvertible { /** - * @return CypherMap + * @return Dictionary */ - public function getAsCypherMap(int $key): CypherMap + public function getAsCypherMap(int $key): Dictionary { $value = $this->get($key); $tbr = TypeCaster::toCypherMap($value); if ($tbr === null) { - throw new RuntimeTypeException($value, CypherMap::class); + throw new RuntimeTypeException($value, Dictionary::class); } return $tbr; diff --git a/src/Type/OGM/Date.php b/src/Type/OGM/Date.php index 4a22393..a357472 100644 --- a/src/Type/OGM/Date.php +++ b/src/Type/OGM/Date.php @@ -59,9 +59,9 @@ public function toDateTime(): DateTimeImmutable return $dateTimeImmutable; } - public function getProperties(): CypherMap + public function getProperties(): Dictionary { - return new CypherMap($this); + return new Dictionary($this); } public function toArray(): array diff --git a/src/Type/OGM/DateTime.php b/src/Type/OGM/DateTime.php index 920b4d4..23666a3 100644 --- a/src/Type/OGM/DateTime.php +++ b/src/Type/OGM/DateTime.php @@ -96,9 +96,9 @@ public function toArray(): array ]; } - public function getProperties(): CypherMap + public function getProperties(): Dictionary { - return new CypherMap($this); + return new Dictionary($this); } public function getPackstreamMarker(): int diff --git a/src/Type/OGM/DateTimeZoneId.php b/src/Type/OGM/DateTimeZoneId.php index 60a9b88..088c73d 100644 --- a/src/Type/OGM/DateTimeZoneId.php +++ b/src/Type/OGM/DateTimeZoneId.php @@ -94,11 +94,11 @@ public function toArray(): array } /** - * @return CypherMap + * @return Dictionary */ - public function getProperties(): CypherMap + public function getProperties(): Dictionary { - return new CypherMap($this); + return new Dictionary($this); } public function getPackstreamMarker(): int diff --git a/src/Type/OGM/CypherMap.php b/src/Type/OGM/Dictionary.php similarity index 95% rename from src/Type/OGM/CypherMap.php rename to src/Type/OGM/Dictionary.php index 82a6a5e..1f7f2dd 100644 --- a/src/Type/OGM/CypherMap.php +++ b/src/Type/OGM/Dictionary.php @@ -25,12 +25,12 @@ * * @extends Map */ -final class CypherMap extends Map implements PackstreamConvertible +final class Dictionary extends Map implements PackstreamConvertible { /** - * @return CypherMap + * @return Dictionary */ - public function getAsCypherMap(string $key, mixed $default = null): CypherMap + public function getAsCypherMap(string $key, mixed $default = null): Dictionary { if (func_num_args() === 1) { $value = $this->get($key); @@ -232,7 +232,7 @@ public function getAsWGS843DPoint(string $key, $default = null): WGS843DPoint * * @pure */ - public static function fromIterable(iterable $iterable): CypherMap + public static function fromIterable(iterable $iterable): Dictionary { return new self($iterable); } @@ -248,9 +248,9 @@ public function pluck(string $key): CypherList /** * @psalm-mutation-free */ - public function keyBy(string $key): CypherMap + public function keyBy(string $key): Dictionary { - return CypherMap::fromIterable(parent::keyBy($key)); + return Dictionary::fromIterable(parent::keyBy($key)); } public function getPackstreamMarker(): int diff --git a/src/Type/OGM/Duration.php b/src/Type/OGM/Duration.php index 28e6612..75f91d1 100644 --- a/src/Type/OGM/Duration.php +++ b/src/Type/OGM/Duration.php @@ -93,9 +93,9 @@ public function toArray(): array ]; } - public function getProperties(): CypherMap + public function getProperties(): Dictionary { - return new CypherMap($this); + return new Dictionary($this); } public function getPackstreamMarker(): int diff --git a/src/Type/OGM/LocalDateTime.php b/src/Type/OGM/LocalDateTime.php index 534b8bc..e96c8da 100644 --- a/src/Type/OGM/LocalDateTime.php +++ b/src/Type/OGM/LocalDateTime.php @@ -79,9 +79,9 @@ public function toArray(): array ]; } - public function getProperties(): CypherMap + public function getProperties(): Dictionary { - return new CypherMap($this); + return new Dictionary($this); } public function getPackstreamMarker(): int diff --git a/src/Type/OGM/LocalTime.php b/src/Type/OGM/LocalTime.php index c7afc10..1499eec 100644 --- a/src/Type/OGM/LocalTime.php +++ b/src/Type/OGM/LocalTime.php @@ -45,9 +45,9 @@ public function toArray(): array return ['nanoseconds' => $this->nanoseconds]; } - public function getProperties(): CypherMap + public function getProperties(): Dictionary { - return new CypherMap($this); + return new Dictionary($this); } public function getPackstreamMarker(): int diff --git a/src/Type/OGM/Path.php b/src/Type/OGM/Path.php index d255f65..d0dc92b 100644 --- a/src/Type/OGM/Path.php +++ b/src/Type/OGM/Path.php @@ -83,9 +83,9 @@ public function toArray(): array ]; } - public function getProperties(): CypherMap + public function getProperties(): Dictionary { - return new CypherMap($this); + return new Dictionary($this); } public function getPackstreamMarker(): int diff --git a/src/Type/OGM/Relationship.php b/src/Type/OGM/Relationship.php index c9802e1..deabe6b 100644 --- a/src/Type/OGM/Relationship.php +++ b/src/Type/OGM/Relationship.php @@ -29,9 +29,9 @@ final class Relationship extends UnboundRelationship private int $endNodeId; /** - * @param CypherMap $properties + * @param Dictionary $properties */ - public function __construct(int $id, int $startNodeId, int $endNodeId, string $type, CypherMap $properties) + public function __construct(int $id, int $startNodeId, int $endNodeId, string $type, Dictionary $properties) { parent::__construct($id, $type, $properties); $this->startNodeId = $startNodeId; @@ -62,7 +62,7 @@ public function getEndNodeId(): int * type: string, * startNodeId: int, * endNodeId: int, - * properties: CypherMap + * properties: Dictionary * } */ public function toArray(): array diff --git a/src/Type/OGM/Time.php b/src/Type/OGM/Time.php index 041eba8..b13cb4a 100644 --- a/src/Type/OGM/Time.php +++ b/src/Type/OGM/Time.php @@ -50,9 +50,9 @@ public function getNanoSeconds(): int return $this->nanoSeconds; } - public function getProperties(): CypherMap + public function getProperties(): Dictionary { - return new CypherMap($this); + return new Dictionary($this); } public function getPackstreamMarker(): int diff --git a/src/Type/OGM/UnboundRelationship.php b/src/Type/OGM/UnboundRelationship.php index 535cefd..eef7c34 100644 --- a/src/Type/OGM/UnboundRelationship.php +++ b/src/Type/OGM/UnboundRelationship.php @@ -25,19 +25,19 @@ * * @psalm-immutable * - * @extends AbstractPropertyObject> + * @extends AbstractPropertyObject> */ class UnboundRelationship extends AbstractPropertyObject { private int $id; private string $type; - /** @var CypherMap */ - private CypherMap $properties; + /** @var Dictionary */ + private Dictionary $properties; /** - * @param CypherMap $properties + * @param Dictionary $properties */ - public function __construct(int $id, string $type, CypherMap $properties) + public function __construct(int $id, string $type, Dictionary $properties) { $this->id = $id; $this->type = $type; @@ -54,7 +54,7 @@ public function getType(): string return $this->type; } - public function getProperties(): CypherMap + public function getProperties(): Dictionary { /** @psalm-suppress InvalidReturnStatement false positive with type alias. */ return $this->properties; @@ -63,7 +63,7 @@ public function getProperties(): CypherMap /** * @psalm-suppress ImplementedReturnTypeMismatch False positive. * - * @return array{id: int, type: string, properties: CypherMap} + * @return array{id: int, type: string, properties: Dictionary} */ public function toArray(): array { diff --git a/src/TypeCaster.php b/src/TypeCaster.php index cc2d6de..e92ae3b 100644 --- a/src/TypeCaster.php +++ b/src/TypeCaster.php @@ -32,11 +32,11 @@ use function is_object; use function is_scalar; use Syndesi\CypherDataStructures\Type\OGM\CypherList; -use Syndesi\CypherDataStructures\Type\OGM\CypherMap; +use Syndesi\CypherDataStructures\Type\OGM\Dictionary; use function method_exists; /** - * @psalm-type OGMTypes = string|int|float|bool|null|Date|DateTime|Duration|LocalDateTime|LocalTime|Time|CypherList|CypherMap|Node|Relationship|Path|Cartesian3DPoint|CartesianPoint|WGS84Point|WGS843DPoint + * @psalm-type OGMTypes = string|int|float|bool|null|Date|DateTime|Duration|LocalDateTime|LocalTime|Time|CypherList|Dictionary|Node|Relationship|Path|Cartesian3DPoint|CartesianPoint|WGS84Point|WGS843DPoint */ final class TypeCaster { @@ -171,12 +171,12 @@ public static function toCypherList($value): ?CypherList /** * @param mixed $value * - * @return CypherMap|null + * @return Dictionary|null */ - public static function toCypherMap($value): ?CypherMap + public static function toCypherMap($value): ?Dictionary { if (is_iterable($value)) { - return CypherMap::fromIterable($value); + return Dictionary::fromIterable($value); } return null; From 350c901ad743d7c78fd8192885c81eb1d734e642 Mon Sep 17 00:00:00 2001 From: ghlen Date: Fri, 2 Dec 2022 15:22:03 +0530 Subject: [PATCH 09/15] moved everything that is not pure OGM outside --- benchmark/benchmark/NodeBench.php | 4 +- benchmark/benchmark/RelationBench.php | 8 +- docs/constraint.md | 6 +- docs/helper.md | 23 +-- docs/node.md | 4 +- docs/relation.md | 2 +- docs/type.index.md | 6 +- src/Type/{OGM => }/ArrayList.php | 12 +- src/Type/{OGM => }/Map.php | 17 +- src/Type/Node.php | 179 +++++++++++++++++ src/Type/{OGM => }/NodeLabel.php | 2 +- src/Type/{OGM => }/NodeLabelStorage.php | 2 +- src/Type/OGM/AbstractCypherSequence.php | 24 ++- src/Type/OGM/CypherList.php | 4 +- src/Type/OGM/Dictionary.php | 5 +- src/Type/OGM/Node.php | 217 +++++++++------------ src/Type/OGM/Path.php | 2 + src/Type/{OGM => }/Relation.php | 2 +- src/Type/{OGM => }/RelationType.php | 2 +- src/Type/{OGM => }/WeakRelation.php | 2 +- src/Type/{OGM => }/WeakRelationStorage.php | 2 +- src/TypeCaster.php | 7 +- tests/Helper/ToCypherHelperTest.php | 10 +- tests/Type/ConstraintTest.php | 4 +- tests/Type/IndexTest.php | 4 +- tests/Type/NodeLabelStorageTest.php | 4 +- tests/Type/NodeLabelTest.php | 2 +- tests/Type/NodeTest.php | 14 +- tests/Type/RelationTest.php | 8 +- tests/Type/RelationTypeTest.php | 2 +- tests/Type/WeakRelationStorageTest.php | 8 +- tests/Type/WeakRelationTest.php | 6 +- 32 files changed, 363 insertions(+), 231 deletions(-) rename src/Type/{OGM => }/ArrayList.php (98%) rename src/Type/{OGM => }/Map.php (99%) create mode 100644 src/Type/Node.php rename src/Type/{OGM => }/NodeLabel.php (95%) rename src/Type/{OGM => }/NodeLabelStorage.php (96%) rename src/Type/{OGM => }/Relation.php (97%) rename src/Type/{OGM => }/RelationType.php (95%) rename src/Type/{OGM => }/WeakRelation.php (96%) rename src/Type/{OGM => }/WeakRelationStorage.php (97%) diff --git a/benchmark/benchmark/NodeBench.php b/benchmark/benchmark/NodeBench.php index d80a63c..f22e3a9 100644 --- a/benchmark/benchmark/NodeBench.php +++ b/benchmark/benchmark/NodeBench.php @@ -5,8 +5,8 @@ namespace Syndesi\CypherDataStructures\Benchmark; use PhpBench\Attributes as Bench; -use Syndesi\CypherDataStructures\Type\OGM\Node; -use Syndesi\CypherDataStructures\Type\OGM\NodeLabel; +use Syndesi\CypherDataStructures\Type\Node; +use Syndesi\CypherDataStructures\Type\NodeLabel; use Syndesi\CypherDataStructures\Type\PropertyName; class NodeBench diff --git a/benchmark/benchmark/RelationBench.php b/benchmark/benchmark/RelationBench.php index 3323447..ab3fc62 100644 --- a/benchmark/benchmark/RelationBench.php +++ b/benchmark/benchmark/RelationBench.php @@ -5,11 +5,11 @@ namespace Syndesi\CypherDataStructures\Benchmark; use PhpBench\Attributes as Bench; -use Syndesi\CypherDataStructures\Type\OGM\Node; -use Syndesi\CypherDataStructures\Type\OGM\NodeLabel; -use Syndesi\CypherDataStructures\Type\OGM\Relation; -use Syndesi\CypherDataStructures\Type\OGM\RelationType; +use Syndesi\CypherDataStructures\Type\Node; +use Syndesi\CypherDataStructures\Type\NodeLabel; use Syndesi\CypherDataStructures\Type\PropertyName; +use Syndesi\CypherDataStructures\Type\Relation; +use Syndesi\CypherDataStructures\Type\RelationType; class RelationBench { diff --git a/docs/constraint.md b/docs/constraint.md index 3720944..38dd115 100644 --- a/docs/constraint.md +++ b/docs/constraint.md @@ -15,11 +15,7 @@ Constraints are entities which contain the following attributes: ## Examples ```php -use Syndesi\CypherDataStructures\Type\ConstraintName; -use Syndesi\CypherDataStructures\Type\Constraint; -use Syndesi\CypherDataStructures\Type\ConstraintType; -use Syndesi\CypherDataStructures\Type\OGM\NodeLabel; -use Syndesi\CypherDataStructures\Type\PropertyName; +use Syndesi\CypherDataStructures\Type\Constraint;use Syndesi\CypherDataStructures\Type\ConstraintName;use Syndesi\CypherDataStructures\Type\ConstraintType;use Syndesi\CypherDataStructures\Type\NodeLabel;use Syndesi\CypherDataStructures\Type\PropertyName; $constraint = new Constraint(); $constraint diff --git a/docs/helper.md b/docs/helper.md index c04db16..a88abdb 100644 --- a/docs/helper.md +++ b/docs/helper.md @@ -30,7 +30,7 @@ Transforms objects of type `NodeLabelInterface` to a Cypher label string with so Internal labels will be sorted first. ```php -use Syndesi\CypherDataStructures\Helper\ToCypherHelper;use Syndesi\CypherDataStructures\Type\OGM\NodeLabel;use Syndesi\CypherDataStructures\Type\OGM\NodeLabelStorage; +use Syndesi\CypherDataStructures\Helper\ToCypherHelper;use Syndesi\CypherDataStructures\Type\NodeLabel;use Syndesi\CypherDataStructures\Type\NodeLabelStorage; $nodeLabelStorage = new NodeLabelStorage(); $nodeLabelStorage->attach(new NodeLabel('LabelA')); @@ -48,10 +48,7 @@ Transforms objects of type `NodeInterface` to a Cypher node string, optionally l ones. ```php -use Syndesi\CypherDataStructures\Type\OGM\Node; -use Syndesi\CypherDataStructures\Type\PropertyName; -use Syndesi\CypherDataStructures\Type\OGM\NodeLabel; -use Syndesi\CypherDataStructures\Helper\ToCypherHelper; +use Syndesi\CypherDataStructures\Helper\ToCypherHelper;use Syndesi\CypherDataStructures\Type\Node;use Syndesi\CypherDataStructures\Type\NodeLabel;use Syndesi\CypherDataStructures\Type\PropertyName; $node = new Node(); $node->addNodeLabel(new NodeLabel('Label')); @@ -83,7 +80,7 @@ identifying ones. Referenced nodes are limited to identifying properties. Both nodes can be omitted. ```php -use Syndesi\CypherDataStructures\Helper\ToCypherHelper;use Syndesi\CypherDataStructures\Type\OGM\Node;use Syndesi\CypherDataStructures\Type\OGM\NodeLabel;use Syndesi\CypherDataStructures\Type\OGM\Relation;use Syndesi\CypherDataStructures\Type\OGM\RelationType;use Syndesi\CypherDataStructures\Type\PropertyName; +use Syndesi\CypherDataStructures\Helper\ToCypherHelper;use Syndesi\CypherDataStructures\Type\Node;use Syndesi\CypherDataStructures\Type\NodeLabel;use Syndesi\CypherDataStructures\Type\PropertyName;use Syndesi\CypherDataStructures\Type\Relation;use Syndesi\CypherDataStructures\Type\RelationType; $startNode = new Node(); $startNode->addNodeLabel(new NodeLabel('StartNode')); @@ -139,12 +136,7 @@ echo(ToCypherHelper::relationToIdentifyingCypherString($relation, false)); Transforms objects of type `ConstraintInterface` to a Cypher constraint string. ```php -use Syndesi\CypherDataStructures\Type\ConstraintName; -use Syndesi\CypherDataStructures\Type\Constraint; -use Syndesi\CypherDataStructures\Type\ConstraintType; -use Syndesi\CypherDataStructures\Type\OGM\NodeLabel; -use Syndesi\CypherDataStructures\Type\PropertyName; -use Syndesi\CypherDataStructures\Helper\ToCypherHelper; +use Syndesi\CypherDataStructures\Helper\ToCypherHelper;use Syndesi\CypherDataStructures\Type\Constraint;use Syndesi\CypherDataStructures\Type\ConstraintName;use Syndesi\CypherDataStructures\Type\ConstraintType;use Syndesi\CypherDataStructures\Type\NodeLabel;use Syndesi\CypherDataStructures\Type\PropertyName; $constraint = new Constraint(); $constraint @@ -162,12 +154,7 @@ echo(ToCypherHelper::constraintToCypherString($constraint)); Transforms objects of type `ConstraintInterface` to a Cypher constraint string. ```php -use Syndesi\CypherDataStructures\Type\IndexName; -use Syndesi\CypherDataStructures\Type\Index; -use Syndesi\CypherDataStructures\Type\IndexType; -use Syndesi\CypherDataStructures\Type\OGM\NodeLabel; -use Syndesi\CypherDataStructures\Type\PropertyName; -use Syndesi\CypherDataStructures\Helper\ToCypherHelper; +use Syndesi\CypherDataStructures\Helper\ToCypherHelper;use Syndesi\CypherDataStructures\Type\Index;use Syndesi\CypherDataStructures\Type\IndexName;use Syndesi\CypherDataStructures\Type\IndexType;use Syndesi\CypherDataStructures\Type\NodeLabel;use Syndesi\CypherDataStructures\Type\PropertyName; $index = new Index(); $index diff --git a/docs/node.md b/docs/node.md index 7716949..0e77ccc 100644 --- a/docs/node.md +++ b/docs/node.md @@ -29,9 +29,7 @@ Nodes are entities which contain the following attributes: ## Examples ```php -use Syndesi\CypherDataStructures\Type\OGM\NodeLabel; -use Syndesi\CypherDataStructures\Type\OGM\Node; -use Syndesi\CypherDataStructures\Type\PropertyName; +use Syndesi\CypherDataStructures\Type\Node;use Syndesi\CypherDataStructures\Type\NodeLabel;use Syndesi\CypherDataStructures\Type\PropertyName; $node = new Node(); $node diff --git a/docs/relation.md b/docs/relation.md index 07fdf79..8d23f6e 100644 --- a/docs/relation.md +++ b/docs/relation.md @@ -24,7 +24,7 @@ Relations are entities which contain the following attributes: ## Examples ```php -use Syndesi\CypherDataStructures\Type\OGM\Node;use Syndesi\CypherDataStructures\Type\OGM\NodeLabel;use Syndesi\CypherDataStructures\Type\OGM\Relation;use Syndesi\CypherDataStructures\Type\OGM\RelationType;use Syndesi\CypherDataStructures\Type\PropertyName; +use Syndesi\CypherDataStructures\Type\Node;use Syndesi\CypherDataStructures\Type\NodeLabel;use Syndesi\CypherDataStructures\Type\PropertyName;use Syndesi\CypherDataStructures\Type\Relation;use Syndesi\CypherDataStructures\Type\RelationType; $nodeA = new Node(); $nodeA diff --git a/docs/type.index.md b/docs/type.index.md index b6cbf3a..ebab43d 100644 --- a/docs/type.index.md +++ b/docs/type.index.md @@ -16,11 +16,7 @@ Indexes are entities which contain the following attributes: ## Examples ```php -use Syndesi\CypherDataStructures\Type\IndexName; -use Syndesi\CypherDataStructures\Type\Index; -use Syndesi\CypherDataStructures\Type\IndexType; -use Syndesi\CypherDataStructures\Type\OGM\NodeLabel; -use Syndesi\CypherDataStructures\Type\PropertyName; +use Syndesi\CypherDataStructures\Type\Index;use Syndesi\CypherDataStructures\Type\IndexName;use Syndesi\CypherDataStructures\Type\IndexType;use Syndesi\CypherDataStructures\Type\NodeLabel;use Syndesi\CypherDataStructures\Type\PropertyName; $index = new Index(); $index diff --git a/src/Type/OGM/ArrayList.php b/src/Type/ArrayList.php similarity index 98% rename from src/Type/OGM/ArrayList.php rename to src/Type/ArrayList.php index 1881a41..f838e2c 100644 --- a/src/Type/OGM/ArrayList.php +++ b/src/Type/ArrayList.php @@ -11,18 +11,20 @@ * file that was distributed with this source code. */ -namespace Syndesi\CypherDataStructures\Type\OGM; +namespace Syndesi\CypherDataStructures\Type; use AppendIterator; -use function array_values; use ArrayIterator; use Generator; +use OutOfBoundsException; +use Syndesi\CypherDataStructures\Exception\RuntimeTypeException; +use Syndesi\CypherDataStructures\Type\OGM\AbstractCypherSequence; +use Syndesi\CypherDataStructures\TypeCaster; + +use function array_values; use function is_array; use function is_callable; use function is_iterable; -use Syndesi\CypherDataStructures\TypeCaster; -use Syndesi\CypherDataStructures\Exception\RuntimeTypeException; -use OutOfBoundsException; /** * An immutable ordered sequence of items. diff --git a/src/Type/OGM/Map.php b/src/Type/Map.php similarity index 99% rename from src/Type/OGM/Map.php rename to src/Type/Map.php index ca08c97..413ff78 100644 --- a/src/Type/OGM/Map.php +++ b/src/Type/Map.php @@ -11,23 +11,24 @@ * file that was distributed with this source code. */ -namespace Syndesi\CypherDataStructures\Type\OGM; +namespace Syndesi\CypherDataStructures\Type; + +use ArrayIterator; +use Generator; +use OutOfBoundsException; +use stdClass; +use Syndesi\CypherDataStructures\Exception\RuntimeTypeException; +use Syndesi\CypherDataStructures\Type\OGM\AbstractCypherSequence; +use Syndesi\CypherDataStructures\TypeCaster; use function array_key_exists; use function array_key_last; -use ArrayIterator; use function count; use function func_num_args; -use Generator; use function is_array; use function is_callable; use function is_iterable; -use Syndesi\CypherDataStructures\Type\Pair; -use Syndesi\CypherDataStructures\Exception\RuntimeTypeException; -use Syndesi\CypherDataStructures\TypeCaster; -use OutOfBoundsException; use function sprintf; -use stdClass; /** * An immutable ordered map of items. diff --git a/src/Type/Node.php b/src/Type/Node.php new file mode 100644 index 0000000..0f2a395 --- /dev/null +++ b/src/Type/Node.php @@ -0,0 +1,179 @@ +nodeLabelStorage = new NodeLabelStorage(); + $this->weakRelationStorage = new WeakRelationStorage(); + $this->initIdentifiersTrait(); + } + + public function __toString() + { + return ToCypherHelper::nodeToCypherString($this) ?? '()'; + } + + // node label + + public function addNodeLabel(NodeLabelInterface $nodeLabel): self + { + $this->nodeLabelStorage->attach($nodeLabel); + + return $this; + } + + public function addNodeLabels(NodeLabelStorageInterface $nodeLabelStorage): self + { + foreach ($nodeLabelStorage as $key) { + $this->nodeLabelStorage->attach($key); + } + + return $this; + } + + public function hasNodeLabel(NodeLabelInterface $nodeLabel): bool + { + return $this->nodeLabelStorage->contains($nodeLabel); + } + + public function getNodeLabels(): NodeLabelStorageInterface + { + return $this->nodeLabelStorage; + } + + public function removeNodeLabel(NodeLabelInterface $nodeLabel): self + { + $this->nodeLabelStorage->detach($nodeLabel); + + return $this; + } + + public function clearNodeLabels(): self + { + $this->nodeLabelStorage = new NodeLabelStorage(); + + return $this; + } + + // relations + + /** + * @throws InvalidArgumentException + */ + public function addRelation(WeakRelationInterface|RelationInterface $relation): self + { + $weakRelation = $relation; + if ($weakRelation instanceof RelationInterface) { + $weakRelation = WeakRelation::create($weakRelation); + } + if (null === $weakRelation->get()) { + throw InvalidArgumentException::createForAlreadyNullReference(WeakRelationInterface::class); + } + /** @psalm-suppress PossiblyNullReference */ + if (null === $weakRelation->get()->getStartNode()) { + throw InvalidArgumentException::createForTypeMismatch(NodeInterface::class, 'null'); + } + /** @psalm-suppress PossiblyNullReference */ + if (null === $weakRelation->get()->getEndNode()) { + throw InvalidArgumentException::createForTypeMismatch(NodeInterface::class, 'null'); + } + $ownIdentifyingString = ToCypherHelper::nodeToIdentifyingCypherString($this); + /** @psalm-suppress PossiblyNullReference */ + if (ToCypherHelper::nodeToIdentifyingCypherString($weakRelation->get()->getStartNode()) !== $ownIdentifyingString && + ToCypherHelper::nodeToIdentifyingCypherString($weakRelation->get()->getEndNode()) !== $ownIdentifyingString + ) { + throw new InvalidArgumentException("Adding a relation to a node requires that either the start node or the end node must be the same as the node itself."); + } + + $this->weakRelationStorage->attach($weakRelation); + + return $this; + } + + /** + * @throws InvalidArgumentException + */ + public function addRelations(WeakRelationStorageInterface $weakRelationStorage): self + { + foreach ($weakRelationStorage as $key) { + $this->addRelation($key); + } + + return $this; + } + + /** + * @throws InvalidArgumentException + */ + public function hasRelation(WeakRelationInterface|RelationInterface $relation): bool + { + if ($relation instanceof RelationInterface) { + $relation = WeakRelation::create($relation); + } + if (null === $relation->get()) { + throw InvalidArgumentException::createForAlreadyNullReference(WeakRelationInterface::class); + } + + return $this->weakRelationStorage->contains($relation); + } + + public function getRelations(): WeakRelationStorageInterface + { + return $this->weakRelationStorage; + } + + /** + * @throws InvalidArgumentException + */ + public function removeRelation(WeakRelationInterface|RelationInterface $relation): self + { + if ($relation instanceof RelationInterface) { + $relation = WeakRelation::create($relation); + } + if (null === $relation->get()) { + throw InvalidArgumentException::createForAlreadyNullReference(WeakRelationInterface::class); + } + $this->weakRelationStorage->detach($relation); + + return $this; + } + + public function clearRelations(): self + { + $this->weakRelationStorage = new WeakRelationStorage(); + + return $this; + } + + public function isEqualTo(mixed $element): bool + { + if (!($element instanceof NodeInterface)) { + return false; + } + + return ToCypherHelper::nodeToIdentifyingCypherString($this) === ToCypherHelper::nodeToIdentifyingCypherString($element); + } +} diff --git a/src/Type/OGM/NodeLabel.php b/src/Type/NodeLabel.php similarity index 95% rename from src/Type/OGM/NodeLabel.php rename to src/Type/NodeLabel.php index 1937eea..4565b71 100644 --- a/src/Type/OGM/NodeLabel.php +++ b/src/Type/NodeLabel.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Syndesi\CypherDataStructures\Type\OGM; +namespace Syndesi\CypherDataStructures\Type; use Syndesi\CypherDataStructures\Contract\NodeLabelInterface; use Syndesi\CypherDataStructures\Exception\InvalidArgumentException; diff --git a/src/Type/OGM/NodeLabelStorage.php b/src/Type/NodeLabelStorage.php similarity index 96% rename from src/Type/OGM/NodeLabelStorage.php rename to src/Type/NodeLabelStorage.php index fc149f1..3232c41 100644 --- a/src/Type/OGM/NodeLabelStorage.php +++ b/src/Type/NodeLabelStorage.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Syndesi\CypherDataStructures\Type\OGM; +namespace Syndesi\CypherDataStructures\Type; use SplObjectStorage; use Syndesi\CypherDataStructures\Contract\NodeLabelInterface; diff --git a/src/Type/OGM/AbstractCypherSequence.php b/src/Type/OGM/AbstractCypherSequence.php index 61367fd..2d1e01b 100644 --- a/src/Type/OGM/AbstractCypherSequence.php +++ b/src/Type/OGM/AbstractCypherSequence.php @@ -13,31 +13,35 @@ namespace Syndesi\CypherDataStructures\Type\OGM; -use function array_key_exists; -use function array_reverse; use ArrayAccess; use ArrayIterator; use BadMethodCallException; +use Countable; +use Iterator; +use JsonSerializable; +use OutOfBoundsException; +use ReturnTypeWillChange; +use Syndesi\CypherDataStructures\Type\ArrayList; +use Syndesi\CypherDataStructures\Type\Map; +use UnexpectedValueException; + +use function array_key_exists; +use function array_reverse; use function call_user_func; use function count; -use Countable; use function get_object_vars; use function implode; -use const INF; use function is_array; use function is_callable; use function is_numeric; use function is_object; use function is_string; -use Iterator; -use JsonSerializable; use function method_exists; -use OutOfBoundsException; -use const PHP_INT_MAX; use function property_exists; -use ReturnTypeWillChange; use function sprintf; -use UnexpectedValueException; + +use const INF; +use const PHP_INT_MAX; /** * Abstract immutable sequence with basic functional methods. diff --git a/src/Type/OGM/CypherList.php b/src/Type/OGM/CypherList.php index 62a6c4e..1677d5f 100644 --- a/src/Type/OGM/CypherList.php +++ b/src/Type/OGM/CypherList.php @@ -14,8 +14,10 @@ namespace Syndesi\CypherDataStructures\Type\OGM; use Syndesi\CypherDataStructures\Contract\PackstreamConvertible; -use Syndesi\CypherDataStructures\TypeCaster; use Syndesi\CypherDataStructures\Exception\RuntimeTypeException; +use Syndesi\CypherDataStructures\Type\ArrayList; +use Syndesi\CypherDataStructures\Type\Node; +use Syndesi\CypherDataStructures\TypeCaster; /** * An immutable ordered sequence of items. diff --git a/src/Type/OGM/Dictionary.php b/src/Type/OGM/Dictionary.php index 1f7f2dd..8732cfb 100644 --- a/src/Type/OGM/Dictionary.php +++ b/src/Type/OGM/Dictionary.php @@ -14,10 +14,13 @@ namespace Syndesi\CypherDataStructures\Type\OGM; use Syndesi\CypherDataStructures\Contract\PackstreamConvertible; -use function func_num_args; use Syndesi\CypherDataStructures\Exception\RuntimeTypeException; +use Syndesi\CypherDataStructures\Type\Map; +use Syndesi\CypherDataStructures\Type\Node; use Syndesi\CypherDataStructures\TypeCaster; +use function func_num_args; + /** * An immutable ordered map of items. * diff --git a/src/Type/OGM/Node.php b/src/Type/OGM/Node.php index 06cf1ac..f01eae0 100644 --- a/src/Type/OGM/Node.php +++ b/src/Type/OGM/Node.php @@ -2,178 +2,139 @@ declare(strict_types=1); -namespace Syndesi\CypherDataStructures\Type\OGM; - -use Syndesi\CypherDataStructures\Contract\NodeInterface; -use Syndesi\CypherDataStructures\Contract\NodeLabelInterface; -use Syndesi\CypherDataStructures\Contract\NodeLabelStorageInterface; -use Syndesi\CypherDataStructures\Contract\RelationInterface; -use Syndesi\CypherDataStructures\Contract\WeakRelationInterface; -use Syndesi\CypherDataStructures\Contract\WeakRelationStorageInterface; -use Syndesi\CypherDataStructures\Exception\InvalidArgumentException; -use Syndesi\CypherDataStructures\Helper\ToCypherHelper; -use Syndesi\CypherDataStructures\Trait\IdentifiersTrait; - -/** - * @psalm-suppress PropertyNotSetInConstructor +/* + * This file is part of the Neo4j PHP Client and Driver package. + * + * (c) Nagels + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. */ -class Node implements NodeInterface -{ - use IdentifiersTrait; - - private NodeLabelStorageInterface $nodeLabelStorage; - private WeakRelationStorageInterface $weakRelationStorage; - public function __construct( - ) { - $this->nodeLabelStorage = new NodeLabelStorage(); - $this->weakRelationStorage = new WeakRelationStorage(); - $this->initIdentifiersTrait(); - } - public function __toString() - { - return ToCypherHelper::nodeToCypherString($this) ?? '()'; - } - - // node label +namespace Syndesi\CypherDataStructures\Type\OGM; - public function addNodeLabel(NodeLabelInterface $nodeLabel): self - { - $this->nodeLabelStorage->attach($nodeLabel); +use Syndesi\CypherDataStructures\TypeCaster; +use Syndesi\CypherDataStructures\Exception\PropertyDoesNotExistException; - return $this; - } +use function sprintf; - public function addNodeLabels(NodeLabelStorageInterface $nodeLabelStorage): self - { - foreach ($nodeLabelStorage as $key) { - $this->nodeLabelStorage->attach($key); - } - - return $this; - } +/** + * A Node class representing a Node in cypher. + * + * @psalm-import-type OGMTypes from TypeCaster + * + * @psalm-immutable + * + * @extends AbstractPropertyObject> + * @extends AbstractPropertyObject|Dictionary> + */ +final class Node extends AbstractPropertyObject +{ + private int $id; + /** @var CypherList */ + private CypherList $labels; + /** @var Dictionary */ + private Dictionary $properties; - public function hasNodeLabel(NodeLabelInterface $nodeLabel): bool + /** + * @param CypherList $labels + * @param Dictionary $properties + */ + public function __construct(int $id, CypherList $labels, Dictionary $properties) { - return $this->nodeLabelStorage->contains($nodeLabel); + $this->id = $id; + $this->labels = $labels; + $this->properties = $properties; } - public function getNodeLabels(): NodeLabelStorageInterface + /** + * @deprecated + * @see self::getLabels + * + * @return CypherList + */ + public function labels(): CypherList { - return $this->nodeLabelStorage; + return $this->labels; } - public function removeNodeLabel(NodeLabelInterface $nodeLabel): self + /** + * The labels on the node. + * + * @return CypherList + */ + public function getLabels(): CypherList { - $this->nodeLabelStorage->detach($nodeLabel); - - return $this; + return $this->labels; } - public function clearNodeLabels(): self + /** + * @return Dictionary + * + * @deprecated + * @see self::getProperties + */ + public function properties(): Dictionary { - $this->nodeLabelStorage = new NodeLabelStorage(); - - return $this; + return $this->properties; } - // relations - /** - * @throws InvalidArgumentException + * @deprecated + * @see self::getId */ - public function addRelation(WeakRelationInterface|RelationInterface $relation): self + public function id(): int { - $weakRelation = $relation; - if ($weakRelation instanceof RelationInterface) { - $weakRelation = WeakRelation::create($weakRelation); - } - if (null === $weakRelation->get()) { - throw InvalidArgumentException::createForAlreadyNullReference(WeakRelationInterface::class); - } - /** @psalm-suppress PossiblyNullReference */ - if (null === $weakRelation->get()->getStartNode()) { - throw InvalidArgumentException::createForTypeMismatch(NodeInterface::class, 'null'); - } - /** @psalm-suppress PossiblyNullReference */ - if (null === $weakRelation->get()->getEndNode()) { - throw InvalidArgumentException::createForTypeMismatch(NodeInterface::class, 'null'); - } - $ownIdentifyingString = ToCypherHelper::nodeToIdentifyingCypherString($this); - /** @psalm-suppress PossiblyNullReference */ - if (ToCypherHelper::nodeToIdentifyingCypherString($weakRelation->get()->getStartNode()) !== $ownIdentifyingString && - ToCypherHelper::nodeToIdentifyingCypherString($weakRelation->get()->getEndNode()) !== $ownIdentifyingString - ) { - throw new InvalidArgumentException("Adding a relation to a node requires that either the start node or the end node must be the same as the node itself."); - } - - $this->weakRelationStorage->attach($weakRelation); - - return $this; + return $this->id; } /** - * @throws InvalidArgumentException + * The id of the node. */ - public function addRelations(WeakRelationStorageInterface $weakRelationStorage): self + public function getId(): int { - foreach ($weakRelationStorage as $key) { - $this->addRelation($key); - } - - return $this; + return $this->id; } /** - * @throws InvalidArgumentException + * Gets the property of the node by key. + * + * @return OGMTypes */ - public function hasRelation(WeakRelationInterface|RelationInterface $relation): bool + public function getProperty(string $key) { - if ($relation instanceof RelationInterface) { - $relation = WeakRelation::create($relation); - } - if (null === $relation->get()) { - throw InvalidArgumentException::createForAlreadyNullReference(WeakRelationInterface::class); + /** @psalm-suppress ImpureMethodCall */ + if (!$this->properties->hasKey($key)) { + throw new PropertyDoesNotExistException(sprintf('Property "%s" does not exist on node', $key)); } - return $this->weakRelationStorage->contains($relation); - } - - public function getRelations(): WeakRelationStorageInterface - { - return $this->weakRelationStorage; + /** @psalm-suppress ImpureMethodCall */ + return $this->properties->get($key); } /** - * @throws InvalidArgumentException + * @psalm-suppress ImplementedReturnTypeMismatch False positive. + * + * @return array{id: int, labels: CypherList, properties: Dictionary} */ - public function removeRelation(WeakRelationInterface|RelationInterface $relation): self + public function toArray(): array { - if ($relation instanceof RelationInterface) { - $relation = WeakRelation::create($relation); - } - if (null === $relation->get()) { - throw InvalidArgumentException::createForAlreadyNullReference(WeakRelationInterface::class); - } - $this->weakRelationStorage->detach($relation); - - return $this; + return [ + 'id' => $this->id, + 'labels' => $this->labels, + 'properties' => $this->properties, + ]; } - public function clearRelations(): self + public function getProperties(): Dictionary { - $this->weakRelationStorage = new WeakRelationStorage(); - - return $this; + /** @psalm-suppress InvalidReturnStatement false positive with type alias. */ + return $this->properties; } - public function isEqualTo(mixed $element): bool + public function getPackstreamMarker(): int { - if (!($element instanceof NodeInterface)) { - return false; - } - - return ToCypherHelper::nodeToIdentifyingCypherString($this) === ToCypherHelper::nodeToIdentifyingCypherString($element); + return 0x4E; } } diff --git a/src/Type/OGM/Path.php b/src/Type/OGM/Path.php index d0dc92b..fd97fcc 100644 --- a/src/Type/OGM/Path.php +++ b/src/Type/OGM/Path.php @@ -13,6 +13,8 @@ namespace Syndesi\CypherDataStructures\Type\OGM; +use Syndesi\CypherDataStructures\Type\OGM\Node; + /** * A Path class representing a Path in cypher. * diff --git a/src/Type/OGM/Relation.php b/src/Type/Relation.php similarity index 97% rename from src/Type/OGM/Relation.php rename to src/Type/Relation.php index 5e6df18..5d3f636 100644 --- a/src/Type/OGM/Relation.php +++ b/src/Type/Relation.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Syndesi\CypherDataStructures\Type\OGM; +namespace Syndesi\CypherDataStructures\Type; use Syndesi\CypherDataStructures\Contract\NodeInterface; use Syndesi\CypherDataStructures\Contract\RelationInterface; diff --git a/src/Type/OGM/RelationType.php b/src/Type/RelationType.php similarity index 95% rename from src/Type/OGM/RelationType.php rename to src/Type/RelationType.php index 3bb29aa..7b7dc63 100644 --- a/src/Type/OGM/RelationType.php +++ b/src/Type/RelationType.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Syndesi\CypherDataStructures\Type\OGM; +namespace Syndesi\CypherDataStructures\Type; use Syndesi\CypherDataStructures\Contract\RelationTypeInterface; use Syndesi\CypherDataStructures\Exception\InvalidArgumentException; diff --git a/src/Type/OGM/WeakRelation.php b/src/Type/WeakRelation.php similarity index 96% rename from src/Type/OGM/WeakRelation.php rename to src/Type/WeakRelation.php index daab416..70a277a 100644 --- a/src/Type/OGM/WeakRelation.php +++ b/src/Type/WeakRelation.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Syndesi\CypherDataStructures\Type\OGM; +namespace Syndesi\CypherDataStructures\Type; use Syndesi\CypherDataStructures\Contract\RelationInterface; use Syndesi\CypherDataStructures\Contract\WeakRelationInterface; diff --git a/src/Type/OGM/WeakRelationStorage.php b/src/Type/WeakRelationStorage.php similarity index 97% rename from src/Type/OGM/WeakRelationStorage.php rename to src/Type/WeakRelationStorage.php index 6e8b213..1caac9c 100644 --- a/src/Type/OGM/WeakRelationStorage.php +++ b/src/Type/WeakRelationStorage.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Syndesi\CypherDataStructures\Type\OGM; +namespace Syndesi\CypherDataStructures\Type; use SplObjectStorage; use Syndesi\CypherDataStructures\Contract\WeakRelationInterface; diff --git a/src/TypeCaster.php b/src/TypeCaster.php index e92ae3b..fc2f976 100644 --- a/src/TypeCaster.php +++ b/src/TypeCaster.php @@ -13,26 +13,27 @@ namespace Syndesi\CypherDataStructures; +use Syndesi\CypherDataStructures\Type\Node; use Syndesi\CypherDataStructures\Type\OGM\Cartesian3DPoint; use Syndesi\CypherDataStructures\Type\OGM\CartesianPoint; +use Syndesi\CypherDataStructures\Type\OGM\CypherList; use Syndesi\CypherDataStructures\Type\OGM\Date; use Syndesi\CypherDataStructures\Type\OGM\DateTime; +use Syndesi\CypherDataStructures\Type\OGM\Dictionary; use Syndesi\CypherDataStructures\Type\OGM\Duration; use Syndesi\CypherDataStructures\Type\OGM\LocalDateTime; use Syndesi\CypherDataStructures\Type\OGM\LocalTime; -use Syndesi\CypherDataStructures\Type\OGM\Node; use Syndesi\CypherDataStructures\Type\OGM\Path; use Syndesi\CypherDataStructures\Type\OGM\Relationship; use Syndesi\CypherDataStructures\Type\OGM\Time; use Syndesi\CypherDataStructures\Type\OGM\WGS843DPoint; use Syndesi\CypherDataStructures\Type\OGM\WGS84Point; + use function is_a; use function is_iterable; use function is_numeric; use function is_object; use function is_scalar; -use Syndesi\CypherDataStructures\Type\OGM\CypherList; -use Syndesi\CypherDataStructures\Type\OGM\Dictionary; use function method_exists; /** diff --git a/tests/Helper/ToCypherHelperTest.php b/tests/Helper/ToCypherHelperTest.php index 5ae0c4e..23d33db 100644 --- a/tests/Helper/ToCypherHelperTest.php +++ b/tests/Helper/ToCypherHelperTest.php @@ -14,15 +14,15 @@ use Syndesi\CypherDataStructures\Type\Index; use Syndesi\CypherDataStructures\Type\IndexName; use Syndesi\CypherDataStructures\Type\IndexType; -use Syndesi\CypherDataStructures\Type\OGM\Node; -use Syndesi\CypherDataStructures\Type\OGM\NodeLabel; -use Syndesi\CypherDataStructures\Type\OGM\NodeLabelStorage; -use Syndesi\CypherDataStructures\Type\OGM\Relation; -use Syndesi\CypherDataStructures\Type\OGM\RelationType; +use Syndesi\CypherDataStructures\Type\Node; +use Syndesi\CypherDataStructures\Type\NodeLabel; +use Syndesi\CypherDataStructures\Type\NodeLabelStorage; use Syndesi\CypherDataStructures\Type\OptionName; use Syndesi\CypherDataStructures\Type\OptionStorage; use Syndesi\CypherDataStructures\Type\PropertyName; use Syndesi\CypherDataStructures\Type\PropertyStorage; +use Syndesi\CypherDataStructures\Type\Relation; +use Syndesi\CypherDataStructures\Type\RelationType; class ToCypherHelperTest extends TestCase { diff --git a/tests/Type/ConstraintTest.php b/tests/Type/ConstraintTest.php index 17788b1..7e71876 100644 --- a/tests/Type/ConstraintTest.php +++ b/tests/Type/ConstraintTest.php @@ -9,9 +9,9 @@ use Syndesi\CypherDataStructures\Type\Constraint; use Syndesi\CypherDataStructures\Type\ConstraintName; use Syndesi\CypherDataStructures\Type\ConstraintType; -use Syndesi\CypherDataStructures\Type\OGM\NodeLabel; -use Syndesi\CypherDataStructures\Type\OGM\RelationType; +use Syndesi\CypherDataStructures\Type\NodeLabel; use Syndesi\CypherDataStructures\Type\PropertyName; +use Syndesi\CypherDataStructures\Type\RelationType; class ConstraintTest extends TestCase { diff --git a/tests/Type/IndexTest.php b/tests/Type/IndexTest.php index c3c3c51..7eb349f 100644 --- a/tests/Type/IndexTest.php +++ b/tests/Type/IndexTest.php @@ -9,9 +9,9 @@ use Syndesi\CypherDataStructures\Type\Index; use Syndesi\CypherDataStructures\Type\IndexName; use Syndesi\CypherDataStructures\Type\IndexType; -use Syndesi\CypherDataStructures\Type\OGM\NodeLabel; -use Syndesi\CypherDataStructures\Type\OGM\RelationType; +use Syndesi\CypherDataStructures\Type\NodeLabel; use Syndesi\CypherDataStructures\Type\PropertyName; +use Syndesi\CypherDataStructures\Type\RelationType; class IndexTest extends TestCase { diff --git a/tests/Type/NodeLabelStorageTest.php b/tests/Type/NodeLabelStorageTest.php index e931f42..7ca8f86 100644 --- a/tests/Type/NodeLabelStorageTest.php +++ b/tests/Type/NodeLabelStorageTest.php @@ -10,8 +10,8 @@ use Syndesi\CypherDataStructures\Contract\NodeLabelInterface; use Syndesi\CypherDataStructures\Exception\InvalidArgumentException; use Syndesi\CypherDataStructures\Exception\LogicException; -use Syndesi\CypherDataStructures\Type\OGM\NodeLabel; -use Syndesi\CypherDataStructures\Type\OGM\NodeLabelStorage; +use Syndesi\CypherDataStructures\Type\NodeLabel; +use Syndesi\CypherDataStructures\Type\NodeLabelStorage; class NodeLabelStorageTest extends TestCase { diff --git a/tests/Type/NodeLabelTest.php b/tests/Type/NodeLabelTest.php index a80b106..4e15af0 100644 --- a/tests/Type/NodeLabelTest.php +++ b/tests/Type/NodeLabelTest.php @@ -6,7 +6,7 @@ use PHPUnit\Framework\TestCase; use Syndesi\CypherDataStructures\Exception\InvalidArgumentException; -use Syndesi\CypherDataStructures\Type\OGM\NodeLabel; +use Syndesi\CypherDataStructures\Type\NodeLabel; class NodeLabelTest extends TestCase { diff --git a/tests/Type/NodeTest.php b/tests/Type/NodeTest.php index 91a6b36..c8dfaa2 100644 --- a/tests/Type/NodeTest.php +++ b/tests/Type/NodeTest.php @@ -7,14 +7,14 @@ use PHPUnit\Framework\TestCase; use stdClass; use Syndesi\CypherDataStructures\Exception\InvalidArgumentException; -use Syndesi\CypherDataStructures\Type\OGM\Node; -use Syndesi\CypherDataStructures\Type\OGM\NodeLabel; -use Syndesi\CypherDataStructures\Type\OGM\NodeLabelStorage; -use Syndesi\CypherDataStructures\Type\OGM\Relation; -use Syndesi\CypherDataStructures\Type\OGM\RelationType; -use Syndesi\CypherDataStructures\Type\OGM\WeakRelation; -use Syndesi\CypherDataStructures\Type\OGM\WeakRelationStorage; +use Syndesi\CypherDataStructures\Type\Node; +use Syndesi\CypherDataStructures\Type\NodeLabel; +use Syndesi\CypherDataStructures\Type\NodeLabelStorage; use Syndesi\CypherDataStructures\Type\PropertyName; +use Syndesi\CypherDataStructures\Type\Relation; +use Syndesi\CypherDataStructures\Type\RelationType; +use Syndesi\CypherDataStructures\Type\WeakRelation; +use Syndesi\CypherDataStructures\Type\WeakRelationStorage; class NodeTest extends TestCase { diff --git a/tests/Type/RelationTest.php b/tests/Type/RelationTest.php index 1c82bfd..df36ff1 100644 --- a/tests/Type/RelationTest.php +++ b/tests/Type/RelationTest.php @@ -7,12 +7,12 @@ use PHPUnit\Framework\TestCase; use stdClass; use Syndesi\CypherDataStructures\Exception\InvalidArgumentException; -use Syndesi\CypherDataStructures\Type\OGM\Node; -use Syndesi\CypherDataStructures\Type\OGM\NodeLabel; -use Syndesi\CypherDataStructures\Type\OGM\Relation; -use Syndesi\CypherDataStructures\Type\OGM\RelationType; +use Syndesi\CypherDataStructures\Type\Node; +use Syndesi\CypherDataStructures\Type\NodeLabel; use Syndesi\CypherDataStructures\Type\PropertyName; use Syndesi\CypherDataStructures\Type\PropertyStorage; +use Syndesi\CypherDataStructures\Type\Relation; +use Syndesi\CypherDataStructures\Type\RelationType; class RelationTest extends TestCase { diff --git a/tests/Type/RelationTypeTest.php b/tests/Type/RelationTypeTest.php index 7530b24..1bc3f20 100644 --- a/tests/Type/RelationTypeTest.php +++ b/tests/Type/RelationTypeTest.php @@ -6,7 +6,7 @@ use PHPUnit\Framework\TestCase; use Syndesi\CypherDataStructures\Exception\InvalidArgumentException; -use Syndesi\CypherDataStructures\Type\OGM\RelationType; +use Syndesi\CypherDataStructures\Type\RelationType; class RelationTypeTest extends TestCase { diff --git a/tests/Type/WeakRelationStorageTest.php b/tests/Type/WeakRelationStorageTest.php index 6b99e42..8ba7a01 100644 --- a/tests/Type/WeakRelationStorageTest.php +++ b/tests/Type/WeakRelationStorageTest.php @@ -9,10 +9,10 @@ use stdClass; use Syndesi\CypherDataStructures\Exception\InvalidArgumentException; use Syndesi\CypherDataStructures\Exception\LogicException; -use Syndesi\CypherDataStructures\Type\OGM\Relation; -use Syndesi\CypherDataStructures\Type\OGM\RelationType; -use Syndesi\CypherDataStructures\Type\OGM\WeakRelation; -use Syndesi\CypherDataStructures\Type\OGM\WeakRelationStorage; +use Syndesi\CypherDataStructures\Type\Relation; +use Syndesi\CypherDataStructures\Type\RelationType; +use Syndesi\CypherDataStructures\Type\WeakRelation; +use Syndesi\CypherDataStructures\Type\WeakRelationStorage; class WeakRelationStorageTest extends TestCase { diff --git a/tests/Type/WeakRelationTest.php b/tests/Type/WeakRelationTest.php index 3471945..ce93b25 100644 --- a/tests/Type/WeakRelationTest.php +++ b/tests/Type/WeakRelationTest.php @@ -6,10 +6,10 @@ use PHPUnit\Framework\TestCase; use stdClass; -use Syndesi\CypherDataStructures\Type\OGM\Relation; -use Syndesi\CypherDataStructures\Type\OGM\RelationType; -use Syndesi\CypherDataStructures\Type\OGM\WeakRelation; use Syndesi\CypherDataStructures\Type\PropertyName; +use Syndesi\CypherDataStructures\Type\Relation; +use Syndesi\CypherDataStructures\Type\RelationType; +use Syndesi\CypherDataStructures\Type\WeakRelation; class WeakRelationTest extends TestCase { From ed4f66a687810de3fe85833db8ab4f2f17b93967 Mon Sep 17 00:00:00 2001 From: ghlen Date: Fri, 2 Dec 2022 15:23:11 +0530 Subject: [PATCH 10/15] removed deprecated methods --- src/Type/OGM/Node.php | 31 ------------------------------- 1 file changed, 31 deletions(-) diff --git a/src/Type/OGM/Node.php b/src/Type/OGM/Node.php index f01eae0..2810f0b 100644 --- a/src/Type/OGM/Node.php +++ b/src/Type/OGM/Node.php @@ -48,17 +48,6 @@ public function __construct(int $id, CypherList $labels, Dictionary $properties) $this->properties = $properties; } - /** - * @deprecated - * @see self::getLabels - * - * @return CypherList - */ - public function labels(): CypherList - { - return $this->labels; - } - /** * The labels on the node. * @@ -69,26 +58,6 @@ public function getLabels(): CypherList return $this->labels; } - /** - * @return Dictionary - * - * @deprecated - * @see self::getProperties - */ - public function properties(): Dictionary - { - return $this->properties; - } - - /** - * @deprecated - * @see self::getId - */ - public function id(): int - { - return $this->id; - } - /** * The id of the node. */ From a2dd01d9948177639fd3b8dabb5bf026f984c786 Mon Sep 17 00:00:00 2001 From: ghlen Date: Fri, 2 Dec 2022 15:30:30 +0530 Subject: [PATCH 11/15] ran rector to upgrade to version 8.0 --- src/Exception/RuntimeTypeException.php | 5 +- src/Helper/ToCypherHelper.php | 4 +- src/Type/ArrayList.php | 2 +- src/Type/Map.php | 37 ++++--------- src/Type/NodeLabelStorage.php | 4 +- src/Type/OGM/Abstract3DPoint.php | 5 +- src/Type/OGM/AbstractCypherSequence.php | 4 +- src/Type/OGM/AbstractPoint.php | 7 +-- src/Type/OGM/AbstractPropertyObject.php | 2 +- src/Type/OGM/Date.php | 5 +- src/Type/OGM/DateTime.php | 9 +--- src/Type/OGM/DateTimeZoneId.php | 9 +--- src/Type/OGM/Dictionary.php | 71 ++++++------------------- src/Type/OGM/Duration.php | 11 +--- src/Type/OGM/LocalDateTime.php | 7 +-- src/Type/OGM/LocalTime.php | 5 +- src/Type/OGM/Node.php | 11 +--- src/Type/OGM/Path.php | 12 +---- src/Type/OGM/Relationship.php | 8 +-- src/Type/OGM/Time.php | 7 +-- src/Type/OGM/UnboundRelationship.php | 10 +--- src/Type/OptionStorage.php | 4 +- src/Type/Pair.php | 9 +--- src/Type/PropertyStorage.php | 4 +- src/Type/WeakRelation.php | 2 +- src/Type/WeakRelationStorage.php | 4 +- src/TypeCaster.php | 32 +++-------- 27 files changed, 61 insertions(+), 229 deletions(-) diff --git a/src/Exception/RuntimeTypeException.php b/src/Exception/RuntimeTypeException.php index 18a177c..9b6f16b 100644 --- a/src/Exception/RuntimeTypeException.php +++ b/src/Exception/RuntimeTypeException.php @@ -19,10 +19,7 @@ final class RuntimeTypeException extends RuntimeException { - /** - * @param mixed $value - */ - public function __construct($value, string $type) + public function __construct(mixed $value, string $type) { $actualType = get_debug_type($value); $message = sprintf('Cannot cast %s to type: %s', $actualType, $type); diff --git a/src/Helper/ToCypherHelper.php b/src/Helper/ToCypherHelper.php index ebb678d..9d34a9a 100644 --- a/src/Helper/ToCypherHelper.php +++ b/src/Helper/ToCypherHelper.php @@ -79,7 +79,7 @@ public static function nodeLabelStorageToCypherLabelString(NodeLabelStorageInter return sprintf( ":%s", - implode(':', array_merge($internalNodeLabels, $publicNodeLabels)) + implode(':', [...$internalNodeLabels, ...$publicNodeLabels]) ); } @@ -322,7 +322,7 @@ public static function valueToString(mixed $value): string } if (is_object($value)) { if (!($value instanceof Stringable)) { - throw InvalidArgumentException::createForTypeMismatch(Stringable::class, get_class($value)); + throw InvalidArgumentException::createForTypeMismatch(Stringable::class, $value::class); } return (string) $value; diff --git a/src/Type/ArrayList.php b/src/Type/ArrayList.php index f838e2c..f312a42 100644 --- a/src/Type/ArrayList.php +++ b/src/Type/ArrayList.php @@ -233,7 +233,7 @@ public function getAsArrayList(int $key): ArrayList { $value = $this->get($key); if (!is_iterable($value)) { - throw new RuntimeTypeException($value, __CLASS__); + throw new RuntimeTypeException($value, self::class); } /** @psalm-suppress MixedArgumentTypeCoercion */ diff --git a/src/Type/Map.php b/src/Type/Map.php index 413ff78..000ac57 100644 --- a/src/Type/Map.php +++ b/src/Type/Map.php @@ -351,10 +351,7 @@ public function jsonSerialize() return parent::jsonSerialize(); } - /** - * @param mixed $default - */ - public function getAsString(string $key, $default = null): string + public function getAsString(string $key, mixed $default = null): string { if (func_num_args() === 1) { $value = $this->get($key); @@ -370,10 +367,7 @@ public function getAsString(string $key, $default = null): string return $tbr; } - /** - * @param mixed $default - */ - public function getAsInt(string $key, $default = null): int + public function getAsInt(string $key, mixed $default = null): int { if (func_num_args() === 1) { $value = $this->get($key); @@ -389,10 +383,7 @@ public function getAsInt(string $key, $default = null): int return $tbr; } - /** - * @param mixed $default - */ - public function getAsFloat(string $key, $default = null): float + public function getAsFloat(string $key, mixed $default = null): float { if (func_num_args() === 1) { $value = $this->get($key); @@ -408,10 +399,7 @@ public function getAsFloat(string $key, $default = null): float return $tbr; } - /** - * @param mixed $default - */ - public function getAsBool(string $key, $default = null): bool + public function getAsBool(string $key, mixed $default = null): bool { if (func_num_args() === 1) { $value = $this->get($key); @@ -428,11 +416,9 @@ public function getAsBool(string $key, $default = null): bool } /** - * @param mixed $default - * * @return null */ - public function getAsNull(string $key, $default = null) + public function getAsNull(string $key, mixed $default = null) { if (func_num_args() === 1) { /** @psalm-suppress UnusedMethodCall */ @@ -446,11 +432,10 @@ public function getAsNull(string $key, $default = null) * @template U * * @param class-string $class - * @param mixed $default * * @return U */ - public function getAsObject(string $key, string $class, $default = null): object + public function getAsObject(string $key, string $class, mixed $default = null): object { if (func_num_args() === 1) { $value = $this->get($key); @@ -467,11 +452,9 @@ public function getAsObject(string $key, string $class, $default = null): object } /** - * @param mixed $default - * * @return Map */ - public function getAsMap(string $key, $default = null): Map + public function getAsMap(string $key, mixed $default = null): Map { if (func_num_args() === 1) { $value = $this->get($key); @@ -481,18 +464,16 @@ public function getAsMap(string $key, $default = null): Map } if (!is_iterable($value)) { - throw new RuntimeTypeException($value, __CLASS__); + throw new RuntimeTypeException($value, self::class); } return new Map($value); } /** - * @param mixed $default - * * @return ArrayList */ - public function getAsArrayList(string $key, $default = null): ArrayList + public function getAsArrayList(string $key, mixed $default = null): ArrayList { if (func_num_args() === 1) { $value = $this->get($key); diff --git a/src/Type/NodeLabelStorage.php b/src/Type/NodeLabelStorage.php index 3232c41..51cea59 100644 --- a/src/Type/NodeLabelStorage.php +++ b/src/Type/NodeLabelStorage.php @@ -19,7 +19,7 @@ class NodeLabelStorage extends SplObjectStorage implements NodeLabelStorageInter public function getHash(object $object): string { if (!($object instanceof NodeLabelInterface)) { - throw InvalidArgumentException::createForTypeMismatch(NodeLabelInterface::class, get_class($object)); + throw InvalidArgumentException::createForTypeMismatch(NodeLabelInterface::class, $object::class); } return $object->getNodeLabel(); @@ -32,7 +32,7 @@ public function current(): NodeLabelInterface { $element = parent::current(); if (!($element instanceof NodeLabelInterface)) { - throw LogicException::createForInternalTypeMismatch(NodeLabelInterface::class, get_class($element)); + throw LogicException::createForInternalTypeMismatch(NodeLabelInterface::class, $element::class); } return $element; diff --git a/src/Type/OGM/Abstract3DPoint.php b/src/Type/OGM/Abstract3DPoint.php index 15300ca..71216e5 100644 --- a/src/Type/OGM/Abstract3DPoint.php +++ b/src/Type/OGM/Abstract3DPoint.php @@ -27,12 +27,9 @@ */ abstract class Abstract3DPoint extends AbstractPoint implements PointInterface, PackstreamConvertible { - private float $z; - - public function __construct(float $x, float $y, float $z) + public function __construct(float $x, float $y, private float $z) { parent::__construct($x, $y); - $this->z = $z; } public function getZ(): float diff --git a/src/Type/OGM/AbstractCypherSequence.php b/src/Type/OGM/AbstractCypherSequence.php index 2d1e01b..11bbae0 100644 --- a/src/Type/OGM/AbstractCypherSequence.php +++ b/src/Type/OGM/AbstractCypherSequence.php @@ -537,11 +537,9 @@ public function preload(): void } /** - * @param mixed $key - * * @psalm-mutation-free */ - protected function isStringable($key): bool + protected function isStringable(mixed $key): bool { return is_string($key) || is_numeric($key) || (is_object($key) && method_exists($key, '__toString')); } diff --git a/src/Type/OGM/AbstractPoint.php b/src/Type/OGM/AbstractPoint.php index 154dca0..199b97f 100644 --- a/src/Type/OGM/AbstractPoint.php +++ b/src/Type/OGM/AbstractPoint.php @@ -27,13 +27,8 @@ */ abstract class AbstractPoint extends AbstractPropertyObject implements PointInterface, PackstreamConvertible { - private float $x; - private float $y; - - public function __construct(float $x, float $y) + public function __construct(private float $x, private float $y) { - $this->x = $x; - $this->y = $y; } abstract public function getCrs(): string; diff --git a/src/Type/OGM/AbstractPropertyObject.php b/src/Type/OGM/AbstractPropertyObject.php index df191e9..4e07896 100644 --- a/src/Type/OGM/AbstractPropertyObject.php +++ b/src/Type/OGM/AbstractPropertyObject.php @@ -37,7 +37,7 @@ public function __get($name) public function __set($name, $value): void { - throw new BadMethodCallException(sprintf('%s is immutable', get_class($this))); + throw new BadMethodCallException(sprintf('%s is immutable', $this::class)); } public function __isset($name): bool diff --git a/src/Type/OGM/Date.php b/src/Type/OGM/Date.php index a357472..c08e0d5 100644 --- a/src/Type/OGM/Date.php +++ b/src/Type/OGM/Date.php @@ -28,11 +28,8 @@ */ final class Date extends AbstractPropertyObject { - private int $days; - - public function __construct(int $days) + public function __construct(private int $days) { - $this->days = $days; } /** diff --git a/src/Type/OGM/DateTime.php b/src/Type/OGM/DateTime.php index 23666a3..9049400 100644 --- a/src/Type/OGM/DateTime.php +++ b/src/Type/OGM/DateTime.php @@ -28,15 +28,8 @@ */ final class DateTime extends AbstractPropertyObject { - private int $seconds; - private int $nanoseconds; - private int $tzOffsetSeconds; - - public function __construct(int $seconds, int $nanoseconds, int $tzOffsetSeconds) + public function __construct(private int $seconds, private int $nanoseconds, private int $tzOffsetSeconds) { - $this->seconds = $seconds; - $this->nanoseconds = $nanoseconds; - $this->tzOffsetSeconds = $tzOffsetSeconds; } /** diff --git a/src/Type/OGM/DateTimeZoneId.php b/src/Type/OGM/DateTimeZoneId.php index 088c73d..aae8194 100644 --- a/src/Type/OGM/DateTimeZoneId.php +++ b/src/Type/OGM/DateTimeZoneId.php @@ -29,15 +29,8 @@ */ final class DateTimeZoneId extends AbstractPropertyObject { - private int $seconds; - private int $nanoseconds; - private string $tzId; - - public function __construct(int $seconds, int $nanoseconds, string $tzId) + public function __construct(private int $seconds, private int $nanoseconds, private string $tzId) { - $this->seconds = $seconds; - $this->nanoseconds = $nanoseconds; - $this->tzId = $tzId; } /** diff --git a/src/Type/OGM/Dictionary.php b/src/Type/OGM/Dictionary.php index 8732cfb..133255e 100644 --- a/src/Type/OGM/Dictionary.php +++ b/src/Type/OGM/Dictionary.php @@ -43,18 +43,16 @@ public function getAsCypherMap(string $key, mixed $default = null): Dictionary } $tbr = TypeCaster::toCypherMap($value); if ($tbr === null) { - throw new RuntimeTypeException($value, __CLASS__); + throw new RuntimeTypeException($value, self::class); } return $tbr; } /** - * @param mixed $default - * * @return CypherList */ - public function getAsCypherList(string $key, $default = null): CypherList + public function getAsCypherList(string $key, mixed $default = null): CypherList { if (func_num_args() === 1) { $value = $this->get($key); @@ -70,10 +68,7 @@ public function getAsCypherList(string $key, $default = null): CypherList return $tbr; } - /** - * @param mixed $default - */ - public function getAsDate(string $key, $default = null): Date + public function getAsDate(string $key, mixed $default = null): Date { if (func_num_args() === 1) { return $this->getAsObject($key, Date::class); @@ -82,10 +77,7 @@ public function getAsDate(string $key, $default = null): Date return $this->getAsObject($key, Date::class, $default); } - /** - * @param mixed $default - */ - public function getAsDateTime(string $key, $default = null): DateTime + public function getAsDateTime(string $key, mixed $default = null): DateTime { if (func_num_args() === 1) { return $this->getAsObject($key, DateTime::class); @@ -94,10 +86,7 @@ public function getAsDateTime(string $key, $default = null): DateTime return $this->getAsObject($key, DateTime::class, $default); } - /** - * @param mixed $default - */ - public function getAsDuration(string $key, $default = null): Duration + public function getAsDuration(string $key, mixed $default = null): Duration { if (func_num_args() === 1) { return $this->getAsObject($key, Duration::class); @@ -106,10 +95,7 @@ public function getAsDuration(string $key, $default = null): Duration return $this->getAsObject($key, Duration::class, $default); } - /** - * @param mixed $default - */ - public function getAsLocalDateTime(string $key, $default = null): LocalDateTime + public function getAsLocalDateTime(string $key, mixed $default = null): LocalDateTime { if (func_num_args() === 1) { return $this->getAsObject($key, LocalDateTime::class); @@ -118,10 +104,7 @@ public function getAsLocalDateTime(string $key, $default = null): LocalDateTime return $this->getAsObject($key, LocalDateTime::class, $default); } - /** - * @param mixed $default - */ - public function getAsLocalTime(string $key, $default = null): LocalTime + public function getAsLocalTime(string $key, mixed $default = null): LocalTime { if (func_num_args() === 1) { return $this->getAsObject($key, LocalTime::class); @@ -130,10 +113,7 @@ public function getAsLocalTime(string $key, $default = null): LocalTime return $this->getAsObject($key, LocalTime::class, $default); } - /** - * @param mixed $default - */ - public function getAsTime(string $key, $default = null): Time + public function getAsTime(string $key, mixed $default = null): Time { if (func_num_args() === 1) { return $this->getAsObject($key, Time::class); @@ -142,10 +122,7 @@ public function getAsTime(string $key, $default = null): Time return $this->getAsObject($key, Time::class, $default); } - /** - * @param mixed $default - */ - public function getAsNode(string $key, $default = null): Node + public function getAsNode(string $key, mixed $default = null): Node { if (func_num_args() === 1) { return $this->getAsObject($key, Node::class); @@ -154,10 +131,7 @@ public function getAsNode(string $key, $default = null): Node return $this->getAsObject($key, Node::class, $default); } - /** - * @param mixed $default - */ - public function getAsRelationship(string $key, $default = null): Relationship + public function getAsRelationship(string $key, mixed $default = null): Relationship { if (func_num_args() === 1) { return $this->getAsObject($key, Relationship::class); @@ -166,10 +140,7 @@ public function getAsRelationship(string $key, $default = null): Relationship return $this->getAsObject($key, Relationship::class, $default); } - /** - * @param mixed $default - */ - public function getAsPath(string $key, $default = null): Path + public function getAsPath(string $key, mixed $default = null): Path { if (func_num_args() === 1) { return $this->getAsObject($key, Path::class); @@ -178,10 +149,7 @@ public function getAsPath(string $key, $default = null): Path return $this->getAsObject($key, Path::class, $default); } - /** - * @param mixed $default - */ - public function getAsCartesian3DPoint(string $key, $default = null): Cartesian3DPoint + public function getAsCartesian3DPoint(string $key, mixed $default = null): Cartesian3DPoint { if (func_num_args() === 1) { return $this->getAsObject($key, Cartesian3DPoint::class); @@ -190,10 +158,7 @@ public function getAsCartesian3DPoint(string $key, $default = null): Cartesian3D return $this->getAsObject($key, Cartesian3DPoint::class, $default); } - /** - * @param mixed $default - */ - public function getAsCartesianPoint(string $key, $default = null): CartesianPoint + public function getAsCartesianPoint(string $key, mixed $default = null): CartesianPoint { if (func_num_args() === 1) { return $this->getAsObject($key, CartesianPoint::class); @@ -202,10 +167,7 @@ public function getAsCartesianPoint(string $key, $default = null): CartesianPoin return $this->getAsObject($key, CartesianPoint::class, $default); } - /** - * @param mixed $default - */ - public function getAsWGS84Point(string $key, $default = null): WGS84Point + public function getAsWGS84Point(string $key, mixed $default = null): WGS84Point { if (func_num_args() === 1) { return $this->getAsObject($key, WGS84Point::class); @@ -214,10 +176,7 @@ public function getAsWGS84Point(string $key, $default = null): WGS84Point return $this->getAsObject($key, WGS84Point::class, $default); } - /** - * @param mixed $default - */ - public function getAsWGS843DPoint(string $key, $default = null): WGS843DPoint + public function getAsWGS843DPoint(string $key, mixed $default = null): WGS843DPoint { if (func_num_args() === 1) { return $this->getAsObject($key, WGS843DPoint::class); diff --git a/src/Type/OGM/Duration.php b/src/Type/OGM/Duration.php index 75f91d1..b1aee21 100644 --- a/src/Type/OGM/Duration.php +++ b/src/Type/OGM/Duration.php @@ -25,17 +25,8 @@ */ final class Duration extends AbstractPropertyObject { - private int $months; - private int $days; - private int $seconds; - private int $nanoseconds; - - public function __construct(int $months, int $days, int $seconds, int $nanoseconds) + public function __construct(private int $months, private int $days, private int $seconds, private int $nanoseconds) { - $this->months = $months; - $this->days = $days; - $this->seconds = $seconds; - $this->nanoseconds = $nanoseconds; } /** diff --git a/src/Type/OGM/LocalDateTime.php b/src/Type/OGM/LocalDateTime.php index e96c8da..01dd8d4 100644 --- a/src/Type/OGM/LocalDateTime.php +++ b/src/Type/OGM/LocalDateTime.php @@ -29,13 +29,8 @@ */ final class LocalDateTime extends AbstractPropertyObject { - private int $seconds; - private int $nanoseconds; - - public function __construct(int $seconds, int $nanoseconds) + public function __construct(private int $seconds, private int $nanoseconds) { - $this->seconds = $seconds; - $this->nanoseconds = $nanoseconds; } /** diff --git a/src/Type/OGM/LocalTime.php b/src/Type/OGM/LocalTime.php index 1499eec..e104b18 100644 --- a/src/Type/OGM/LocalTime.php +++ b/src/Type/OGM/LocalTime.php @@ -22,11 +22,8 @@ */ final class LocalTime extends AbstractPropertyObject { - private int $nanoseconds; - - public function __construct(int $nanoseconds) + public function __construct(private int $nanoseconds) { - $this->nanoseconds = $nanoseconds; } /** diff --git a/src/Type/OGM/Node.php b/src/Type/OGM/Node.php index 2810f0b..3342bf1 100644 --- a/src/Type/OGM/Node.php +++ b/src/Type/OGM/Node.php @@ -31,21 +31,12 @@ */ final class Node extends AbstractPropertyObject { - private int $id; - /** @var CypherList */ - private CypherList $labels; - /** @var Dictionary */ - private Dictionary $properties; - /** * @param CypherList $labels * @param Dictionary $properties */ - public function __construct(int $id, CypherList $labels, Dictionary $properties) + public function __construct(private int $id, private CypherList $labels, private Dictionary $properties) { - $this->id = $id; - $this->labels = $labels; - $this->properties = $properties; } /** diff --git a/src/Type/OGM/Path.php b/src/Type/OGM/Path.php index fd97fcc..4bd3ddc 100644 --- a/src/Type/OGM/Path.php +++ b/src/Type/OGM/Path.php @@ -24,23 +24,13 @@ */ final class Path extends AbstractPropertyObject { - /** @var CypherList */ - private CypherList $nodes; - /** @var CypherList */ - private CypherList $relationships; - /** @var CypherList */ - private CypherList $ids; - /** * @param CypherList $nodes * @param CypherList $relationships * @param CypherList $ids */ - public function __construct(CypherList $nodes, CypherList $relationships, CypherList $ids) + public function __construct(private CypherList $nodes, private CypherList $relationships, private CypherList $ids) { - $this->nodes = $nodes; - $this->relationships = $relationships; - $this->ids = $ids; } /** diff --git a/src/Type/OGM/Relationship.php b/src/Type/OGM/Relationship.php index deabe6b..561b6e3 100644 --- a/src/Type/OGM/Relationship.php +++ b/src/Type/OGM/Relationship.php @@ -24,18 +24,12 @@ */ final class Relationship extends UnboundRelationship { - private int $startNodeId; - - private int $endNodeId; - /** * @param Dictionary $properties */ - public function __construct(int $id, int $startNodeId, int $endNodeId, string $type, Dictionary $properties) + public function __construct(int $id, private int $startNodeId, private int $endNodeId, string $type, Dictionary $properties) { parent::__construct($id, $type, $properties); - $this->startNodeId = $startNodeId; - $this->endNodeId = $endNodeId; } /** diff --git a/src/Type/OGM/Time.php b/src/Type/OGM/Time.php index b13cb4a..64f7932 100644 --- a/src/Type/OGM/Time.php +++ b/src/Type/OGM/Time.php @@ -23,13 +23,8 @@ */ final class Time extends AbstractPropertyObject { - private int $nanoSeconds; - private int $tzOffsetSeconds; - - public function __construct(int $nanoSeconds, int $tzOffsetSeconds) + public function __construct(private int $nanoSeconds, private int $tzOffsetSeconds) { - $this->nanoSeconds = $nanoSeconds; - $this->tzOffsetSeconds = $tzOffsetSeconds; } /** diff --git a/src/Type/OGM/UnboundRelationship.php b/src/Type/OGM/UnboundRelationship.php index eef7c34..c58fded 100644 --- a/src/Type/OGM/UnboundRelationship.php +++ b/src/Type/OGM/UnboundRelationship.php @@ -29,19 +29,11 @@ */ class UnboundRelationship extends AbstractPropertyObject { - private int $id; - private string $type; - /** @var Dictionary */ - private Dictionary $properties; - /** * @param Dictionary $properties */ - public function __construct(int $id, string $type, Dictionary $properties) + public function __construct(private int $id, private string $type, private Dictionary $properties) { - $this->id = $id; - $this->type = $type; - $this->properties = $properties; } public function getId(): int diff --git a/src/Type/OptionStorage.php b/src/Type/OptionStorage.php index 7f33bdf..785c76f 100644 --- a/src/Type/OptionStorage.php +++ b/src/Type/OptionStorage.php @@ -19,7 +19,7 @@ class OptionStorage extends SplObjectStorage implements OptionStorageInterface public function getHash(object $object): string { if (!($object instanceof OptionNameInterface)) { - throw InvalidArgumentException::createForTypeMismatch(OptionNameInterface::class, get_class($object)); + throw InvalidArgumentException::createForTypeMismatch(OptionNameInterface::class, $object::class); } return $object->getOptionName(); @@ -32,7 +32,7 @@ public function current(): OptionNameInterface { $element = parent::current(); if (!($element instanceof OptionNameInterface)) { - throw LogicException::createForInternalTypeMismatch(OptionNameInterface::class, get_class($element)); + throw LogicException::createForInternalTypeMismatch(OptionNameInterface::class, $element::class); } return $element; diff --git a/src/Type/Pair.php b/src/Type/Pair.php index 2ffa6a8..a60b8fb 100644 --- a/src/Type/Pair.php +++ b/src/Type/Pair.php @@ -23,19 +23,12 @@ */ final class Pair { - /** @var TKey */ - private $key; - /** @var TValue */ - private $value; - /** * @param TKey $key * @param TValue $value */ - public function __construct($key, $value) + public function __construct(private $key, private $value) { - $this->key = $key; - $this->value = $value; } /** diff --git a/src/Type/PropertyStorage.php b/src/Type/PropertyStorage.php index 9f021e2..2d116da 100644 --- a/src/Type/PropertyStorage.php +++ b/src/Type/PropertyStorage.php @@ -19,7 +19,7 @@ class PropertyStorage extends SplObjectStorage implements PropertyStorageInterfa public function getHash(object $object): string { if (!($object instanceof PropertyNameInterface)) { - throw InvalidArgumentException::createForTypeMismatch(PropertyNameInterface::class, get_class($object)); + throw InvalidArgumentException::createForTypeMismatch(PropertyNameInterface::class, $object::class); } return $object->getPropertyName(); @@ -32,7 +32,7 @@ public function current(): PropertyNameInterface { $element = parent::current(); if (!($element instanceof PropertyNameInterface)) { - throw LogicException::createForInternalTypeMismatch(PropertyNameInterface::class, get_class($element)); + throw LogicException::createForInternalTypeMismatch(PropertyNameInterface::class, $element::class); } return $element; diff --git a/src/Type/WeakRelation.php b/src/Type/WeakRelation.php index 70a277a..41920e8 100644 --- a/src/Type/WeakRelation.php +++ b/src/Type/WeakRelation.php @@ -50,7 +50,7 @@ public function get(): ?RelationInterface } if (!($element instanceof RelationInterface)) { // @codeCoverageIgnoreStart - throw LogicException::createForInternalTypeMismatch(RelationInterface::class, get_class($element)); + throw LogicException::createForInternalTypeMismatch(RelationInterface::class, $element::class); // @codeCoverageIgnoreEnd } diff --git a/src/Type/WeakRelationStorage.php b/src/Type/WeakRelationStorage.php index 1caac9c..f6bb921 100644 --- a/src/Type/WeakRelationStorage.php +++ b/src/Type/WeakRelationStorage.php @@ -19,7 +19,7 @@ class WeakRelationStorage extends SplObjectStorage implements WeakRelationStorag public function getHash(object $object): string { if (!($object instanceof WeakRelationInterface)) { - throw InvalidArgumentException::createForTypeMismatch(WeakRelationInterface::class, get_class($object)); + throw InvalidArgumentException::createForTypeMismatch(WeakRelationInterface::class, $object::class); } if (null === $object->get()) { throw InvalidArgumentException::createForAlreadyNullReference(WeakRelationInterface::class); @@ -36,7 +36,7 @@ public function current(): WeakRelationInterface { $element = parent::current(); if (!($element instanceof WeakRelationInterface)) { - throw LogicException::createForInternalTypeMismatch(WeakRelationInterface::class, get_class($element)); + throw LogicException::createForInternalTypeMismatch(WeakRelationInterface::class, $element::class); } return $element; diff --git a/src/TypeCaster.php b/src/TypeCaster.php index fc2f976..46d6430 100644 --- a/src/TypeCaster.php +++ b/src/TypeCaster.php @@ -42,11 +42,9 @@ final class TypeCaster { /** - * @param mixed $value - * * @pure */ - public static function toString($value): ?string + public static function toString(mixed $value): ?string { if ($value === null || is_scalar($value) || (is_object($value) && method_exists($value, '__toString'))) { return (string) $value; @@ -56,11 +54,9 @@ public static function toString($value): ?string } /** - * @param mixed $value - * * @pure */ - public static function toFloat($value): ?float + public static function toFloat(mixed $value): ?float { $value = self::toString($value); if (is_numeric($value)) { @@ -71,11 +67,9 @@ public static function toFloat($value): ?float } /** - * @param mixed $value - * * @pure */ - public static function toInt($value): ?int + public static function toInt(mixed $value): ?int { $value = self::toFloat($value); if ($value !== null) { @@ -96,11 +90,9 @@ public static function toNull() } /** - * @param mixed $value - * * @pure */ - public static function toBool($value): ?bool + public static function toBool(mixed $value): ?bool { $value = self::toInt($value); if ($value !== null) { @@ -113,14 +105,12 @@ public static function toBool($value): ?bool /** * @template T * - * @param mixed $value * @param class-string $class * * @return T|null - * * @pure */ - public static function toClass($value, string $class): ?object + public static function toClass(mixed $value, string $class): ?object { if (is_a($value, $class)) { /** @var T */ @@ -131,13 +121,11 @@ public static function toClass($value, string $class): ?object } /** - * @param mixed $value * * @return list - * * @psalm-external-mutation-free */ - public static function toArray($value): ?array + public static function toArray(mixed $value): ?array { if (is_iterable($value)) { $tbr = []; @@ -154,13 +142,11 @@ public static function toArray($value): ?array } /** - * @param mixed $value * * @return CypherList|null - * * @pure */ - public static function toCypherList($value): ?CypherList + public static function toCypherList(mixed $value): ?CypherList { if (is_iterable($value)) { return CypherList::fromIterable($value); @@ -170,11 +156,9 @@ public static function toCypherList($value): ?CypherList } /** - * @param mixed $value - * * @return Dictionary|null */ - public static function toCypherMap($value): ?Dictionary + public static function toCypherMap(mixed $value): ?Dictionary { if (is_iterable($value)) { return Dictionary::fromIterable($value); From ae11fbd6e05a9add4f544de87c67e4638279b86e Mon Sep 17 00:00:00 2001 From: ghlen Date: Fri, 2 Dec 2022 15:32:00 +0530 Subject: [PATCH 12/15] removed composer.lock from version control --- .gitignore | 3 +- composer.lock | 5693 ------------------------------------------------- 2 files changed, 2 insertions(+), 5694 deletions(-) delete mode 100644 composer.lock diff --git a/.gitignore b/.gitignore index 81ba36f..49e1306 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,5 @@ infection.html /.php-cs-fixer.php /.php-cs-fixer.cache /tmp/ -/.idea \ No newline at end of file +/.idea +/composer.lock \ No newline at end of file diff --git a/composer.lock b/composer.lock deleted file mode 100644 index f407bca..0000000 --- a/composer.lock +++ /dev/null @@ -1,5693 +0,0 @@ -{ - "_readme": [ - "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", - "This file is @generated automatically" - ], - "content-hash": "dc2d232524193bcd43c8f5894a2b3052", - "packages": [], - "packages-dev": [ - { - "name": "amphp/amp", - "version": "v2.6.2", - "source": { - "type": "git", - "url": "https://github.com/amphp/amp.git", - "reference": "9d5100cebffa729aaffecd3ad25dc5aeea4f13bb" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/amp/zipball/9d5100cebffa729aaffecd3ad25dc5aeea4f13bb", - "reference": "9d5100cebffa729aaffecd3ad25dc5aeea4f13bb", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "require-dev": { - "amphp/php-cs-fixer-config": "dev-master", - "amphp/phpunit-util": "^1", - "ext-json": "*", - "jetbrains/phpstorm-stubs": "^2019.3", - "phpunit/phpunit": "^7 | ^8 | ^9", - "psalm/phar": "^3.11@dev", - "react/promise": "^2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.x-dev" - } - }, - "autoload": { - "files": [ - "lib/functions.php", - "lib/Internal/functions.php" - ], - "psr-4": { - "Amp\\": "lib" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Daniel Lowrey", - "email": "rdlowrey@php.net" - }, - { - "name": "Aaron Piotrowski", - "email": "aaron@trowski.com" - }, - { - "name": "Bob Weinand", - "email": "bobwei9@hotmail.com" - }, - { - "name": "Niklas Keller", - "email": "me@kelunik.com" - } - ], - "description": "A non-blocking concurrency framework for PHP applications.", - "homepage": "https://amphp.org/amp", - "keywords": [ - "async", - "asynchronous", - "awaitable", - "concurrency", - "event", - "event-loop", - "future", - "non-blocking", - "promise" - ], - "support": { - "irc": "irc://irc.freenode.org/amphp", - "issues": "https://github.com/amphp/amp/issues", - "source": "https://github.com/amphp/amp/tree/v2.6.2" - }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2022-02-20T17:52:18+00:00" - }, - { - "name": "amphp/byte-stream", - "version": "v1.8.1", - "source": { - "type": "git", - "url": "https://github.com/amphp/byte-stream.git", - "reference": "acbd8002b3536485c997c4e019206b3f10ca15bd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/byte-stream/zipball/acbd8002b3536485c997c4e019206b3f10ca15bd", - "reference": "acbd8002b3536485c997c4e019206b3f10ca15bd", - "shasum": "" - }, - "require": { - "amphp/amp": "^2", - "php": ">=7.1" - }, - "require-dev": { - "amphp/php-cs-fixer-config": "dev-master", - "amphp/phpunit-util": "^1.4", - "friendsofphp/php-cs-fixer": "^2.3", - "jetbrains/phpstorm-stubs": "^2019.3", - "phpunit/phpunit": "^6 || ^7 || ^8", - "psalm/phar": "^3.11.4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "files": [ - "lib/functions.php" - ], - "psr-4": { - "Amp\\ByteStream\\": "lib" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Aaron Piotrowski", - "email": "aaron@trowski.com" - }, - { - "name": "Niklas Keller", - "email": "me@kelunik.com" - } - ], - "description": "A stream abstraction to make working with non-blocking I/O simple.", - "homepage": "http://amphp.org/byte-stream", - "keywords": [ - "amp", - "amphp", - "async", - "io", - "non-blocking", - "stream" - ], - "support": { - "irc": "irc://irc.freenode.org/amphp", - "issues": "https://github.com/amphp/byte-stream/issues", - "source": "https://github.com/amphp/byte-stream/tree/v1.8.1" - }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2021-03-30T17:13:30+00:00" - }, - { - "name": "boesing/psalm-plugin-stringf", - "version": "1.2.0", - "source": { - "type": "git", - "url": "https://github.com/boesing/psalm-plugin-stringf.git", - "reference": "d70603ec58451206db01d9cfea437852ee8e8362" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/boesing/psalm-plugin-stringf/zipball/d70603ec58451206db01d9cfea437852ee8e8362", - "reference": "d70603ec58451206db01d9cfea437852ee8e8362", - "shasum": "" - }, - "require": { - "php": "^7.4 || ~8.0.0 || ~8.1.0", - "vimeo/psalm": "^4.23 || ^5.0", - "webmozart/assert": "^1.10" - }, - "require-dev": { - "codeception/codeception": "^4.1", - "codeception/module-asserts": "^2.0", - "codeception/module-phpbrowser": "^2.0", - "doctrine/coding-standard": "^9.0", - "symfony/console": "^5.4", - "symfony/finder": "^5.4", - "symfony/yaml": "^5.4", - "vimeo/psalm": "^4.23.0 || ^5.0 || 5.0.0@beta", - "weirdan/codeception-psalm-module": "^0.13.1" - }, - "type": "psalm-plugin", - "extra": { - "psalm": { - "pluginClass": "Boesing\\PsalmPluginStringf\\Plugin" - } - }, - "autoload": { - "psr-4": { - "Boesing\\PsalmPluginStringf\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "Psalm plugin to work with `sprintf`, `printf`, `sscanf` and `fscanf`.", - "support": { - "issues": "https://github.com/boesing/psalm-plugin-stringf/issues", - "source": "https://github.com/boesing/psalm-plugin-stringf/tree/1.2.0" - }, - "funding": [ - { - "url": "https://funding.communitybridge.org/projects/laminas-project", - "type": "community_bridge" - } - ], - "time": "2022-05-29T14:57:38+00:00" - }, - { - "name": "composer/package-versions-deprecated", - "version": "1.11.99.5", - "source": { - "type": "git", - "url": "https://github.com/composer/package-versions-deprecated.git", - "reference": "b4f54f74ef3453349c24a845d22392cd31e65f1d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/package-versions-deprecated/zipball/b4f54f74ef3453349c24a845d22392cd31e65f1d", - "reference": "b4f54f74ef3453349c24a845d22392cd31e65f1d", - "shasum": "" - }, - "require": { - "composer-plugin-api": "^1.1.0 || ^2.0", - "php": "^7 || ^8" - }, - "replace": { - "ocramius/package-versions": "1.11.99" - }, - "require-dev": { - "composer/composer": "^1.9.3 || ^2.0@dev", - "ext-zip": "^1.13", - "phpunit/phpunit": "^6.5 || ^7" - }, - "type": "composer-plugin", - "extra": { - "class": "PackageVersions\\Installer", - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "PackageVersions\\": "src/PackageVersions" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com" - }, - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be" - } - ], - "description": "Composer plugin that provides efficient querying for installed package versions (no runtime IO)", - "support": { - "issues": "https://github.com/composer/package-versions-deprecated/issues", - "source": "https://github.com/composer/package-versions-deprecated/tree/1.11.99.5" - }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2022-01-17T14:14:24+00:00" - }, - { - "name": "composer/pcre", - "version": "3.0.0", - "source": { - "type": "git", - "url": "https://github.com/composer/pcre.git", - "reference": "e300eb6c535192decd27a85bc72a9290f0d6b3bd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/pcre/zipball/e300eb6c535192decd27a85bc72a9290f0d6b3bd", - "reference": "e300eb6c535192decd27a85bc72a9290f0d6b3bd", - "shasum": "" - }, - "require": { - "php": "^7.4 || ^8.0" - }, - "require-dev": { - "phpstan/phpstan": "^1.3", - "phpstan/phpstan-strict-rules": "^1.1", - "symfony/phpunit-bridge": "^5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.x-dev" - } - }, - "autoload": { - "psr-4": { - "Composer\\Pcre\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" - } - ], - "description": "PCRE wrapping library that offers type-safe preg_* replacements.", - "keywords": [ - "PCRE", - "preg", - "regex", - "regular expression" - ], - "support": { - "issues": "https://github.com/composer/pcre/issues", - "source": "https://github.com/composer/pcre/tree/3.0.0" - }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2022-02-25T20:21:48+00:00" - }, - { - "name": "composer/semver", - "version": "3.3.2", - "source": { - "type": "git", - "url": "https://github.com/composer/semver.git", - "reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/semver/zipball/3953f23262f2bff1919fc82183ad9acb13ff62c9", - "reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9", - "shasum": "" - }, - "require": { - "php": "^5.3.2 || ^7.0 || ^8.0" - }, - "require-dev": { - "phpstan/phpstan": "^1.4", - "symfony/phpunit-bridge": "^4.2 || ^5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.x-dev" - } - }, - "autoload": { - "psr-4": { - "Composer\\Semver\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nils Adermann", - "email": "naderman@naderman.de", - "homepage": "http://www.naderman.de" - }, - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" - }, - { - "name": "Rob Bast", - "email": "rob.bast@gmail.com", - "homepage": "http://robbast.nl" - } - ], - "description": "Semver library that offers utilities, version constraint parsing and validation.", - "keywords": [ - "semantic", - "semver", - "validation", - "versioning" - ], - "support": { - "irc": "irc://irc.freenode.org/composer", - "issues": "https://github.com/composer/semver/issues", - "source": "https://github.com/composer/semver/tree/3.3.2" - }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2022-04-01T19:23:25+00:00" - }, - { - "name": "composer/xdebug-handler", - "version": "3.0.3", - "source": { - "type": "git", - "url": "https://github.com/composer/xdebug-handler.git", - "reference": "ced299686f41dce890debac69273b47ffe98a40c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/ced299686f41dce890debac69273b47ffe98a40c", - "reference": "ced299686f41dce890debac69273b47ffe98a40c", - "shasum": "" - }, - "require": { - "composer/pcre": "^1 || ^2 || ^3", - "php": "^7.2.5 || ^8.0", - "psr/log": "^1 || ^2 || ^3" - }, - "require-dev": { - "phpstan/phpstan": "^1.0", - "phpstan/phpstan-strict-rules": "^1.1", - "symfony/phpunit-bridge": "^6.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Composer\\XdebugHandler\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "John Stevenson", - "email": "john-stevenson@blueyonder.co.uk" - } - ], - "description": "Restarts a process without Xdebug.", - "keywords": [ - "Xdebug", - "performance" - ], - "support": { - "irc": "irc://irc.freenode.org/composer", - "issues": "https://github.com/composer/xdebug-handler/issues", - "source": "https://github.com/composer/xdebug-handler/tree/3.0.3" - }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2022-02-25T21:32:43+00:00" - }, - { - "name": "dnoegel/php-xdg-base-dir", - "version": "v0.1.1", - "source": { - "type": "git", - "url": "https://github.com/dnoegel/php-xdg-base-dir.git", - "reference": "8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/dnoegel/php-xdg-base-dir/zipball/8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd", - "reference": "8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd", - "shasum": "" - }, - "require": { - "php": ">=5.3.2" - }, - "require-dev": { - "phpunit/phpunit": "~7.0|~6.0|~5.0|~4.8.35" - }, - "type": "library", - "autoload": { - "psr-4": { - "XdgBaseDir\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "implementation of xdg base directory specification for php", - "support": { - "issues": "https://github.com/dnoegel/php-xdg-base-dir/issues", - "source": "https://github.com/dnoegel/php-xdg-base-dir/tree/v0.1.1" - }, - "time": "2019-12-04T15:06:13+00:00" - }, - { - "name": "doctrine/annotations", - "version": "1.13.3", - "source": { - "type": "git", - "url": "https://github.com/doctrine/annotations.git", - "reference": "648b0343343565c4a056bfc8392201385e8d89f0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/annotations/zipball/648b0343343565c4a056bfc8392201385e8d89f0", - "reference": "648b0343343565c4a056bfc8392201385e8d89f0", - "shasum": "" - }, - "require": { - "doctrine/lexer": "1.*", - "ext-tokenizer": "*", - "php": "^7.1 || ^8.0", - "psr/cache": "^1 || ^2 || ^3" - }, - "require-dev": { - "doctrine/cache": "^1.11 || ^2.0", - "doctrine/coding-standard": "^6.0 || ^8.1", - "phpstan/phpstan": "^1.4.10 || ^1.8.0", - "phpunit/phpunit": "^7.5 || ^8.0 || ^9.1.5", - "symfony/cache": "^4.4 || ^5.2", - "vimeo/psalm": "^4.10" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "Docblock Annotations Parser", - "homepage": "https://www.doctrine-project.org/projects/annotations.html", - "keywords": [ - "annotations", - "docblock", - "parser" - ], - "support": { - "issues": "https://github.com/doctrine/annotations/issues", - "source": "https://github.com/doctrine/annotations/tree/1.13.3" - }, - "time": "2022-07-02T10:48:51+00:00" - }, - { - "name": "doctrine/instantiator", - "version": "1.4.1", - "source": { - "type": "git", - "url": "https://github.com/doctrine/instantiator.git", - "reference": "10dcfce151b967d20fde1b34ae6640712c3891bc" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/10dcfce151b967d20fde1b34ae6640712c3891bc", - "reference": "10dcfce151b967d20fde1b34ae6640712c3891bc", - "shasum": "" - }, - "require": { - "php": "^7.1 || ^8.0" - }, - "require-dev": { - "doctrine/coding-standard": "^9", - "ext-pdo": "*", - "ext-phar": "*", - "phpbench/phpbench": "^0.16 || ^1", - "phpstan/phpstan": "^1.4", - "phpstan/phpstan-phpunit": "^1", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "vimeo/psalm": "^4.22" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com", - "homepage": "https://ocramius.github.io/" - } - ], - "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "homepage": "https://www.doctrine-project.org/projects/instantiator.html", - "keywords": [ - "constructor", - "instantiate" - ], - "support": { - "issues": "https://github.com/doctrine/instantiator/issues", - "source": "https://github.com/doctrine/instantiator/tree/1.4.1" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", - "type": "tidelift" - } - ], - "time": "2022-03-03T08:28:38+00:00" - }, - { - "name": "doctrine/lexer", - "version": "1.2.3", - "source": { - "type": "git", - "url": "https://github.com/doctrine/lexer.git", - "reference": "c268e882d4dbdd85e36e4ad69e02dc284f89d229" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/c268e882d4dbdd85e36e4ad69e02dc284f89d229", - "reference": "c268e882d4dbdd85e36e4ad69e02dc284f89d229", - "shasum": "" - }, - "require": { - "php": "^7.1 || ^8.0" - }, - "require-dev": { - "doctrine/coding-standard": "^9.0", - "phpstan/phpstan": "^1.3", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "vimeo/psalm": "^4.11" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Common\\Lexer\\": "lib/Doctrine/Common/Lexer" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", - "homepage": "https://www.doctrine-project.org/projects/lexer.html", - "keywords": [ - "annotations", - "docblock", - "lexer", - "parser", - "php" - ], - "support": { - "issues": "https://github.com/doctrine/lexer/issues", - "source": "https://github.com/doctrine/lexer/tree/1.2.3" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Flexer", - "type": "tidelift" - } - ], - "time": "2022-02-28T11:07:21+00:00" - }, - { - "name": "felixfbecker/advanced-json-rpc", - "version": "v3.2.1", - "source": { - "type": "git", - "url": "https://github.com/felixfbecker/php-advanced-json-rpc.git", - "reference": "b5f37dbff9a8ad360ca341f3240dc1c168b45447" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/felixfbecker/php-advanced-json-rpc/zipball/b5f37dbff9a8ad360ca341f3240dc1c168b45447", - "reference": "b5f37dbff9a8ad360ca341f3240dc1c168b45447", - "shasum": "" - }, - "require": { - "netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.0", - "php": "^7.1 || ^8.0", - "phpdocumentor/reflection-docblock": "^4.3.4 || ^5.0.0" - }, - "require-dev": { - "phpunit/phpunit": "^7.0 || ^8.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "AdvancedJsonRpc\\": "lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "ISC" - ], - "authors": [ - { - "name": "Felix Becker", - "email": "felix.b@outlook.com" - } - ], - "description": "A more advanced JSONRPC implementation", - "support": { - "issues": "https://github.com/felixfbecker/php-advanced-json-rpc/issues", - "source": "https://github.com/felixfbecker/php-advanced-json-rpc/tree/v3.2.1" - }, - "time": "2021-06-11T22:34:44+00:00" - }, - { - "name": "felixfbecker/language-server-protocol", - "version": "v1.5.2", - "source": { - "type": "git", - "url": "https://github.com/felixfbecker/php-language-server-protocol.git", - "reference": "6e82196ffd7c62f7794d778ca52b69feec9f2842" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/felixfbecker/php-language-server-protocol/zipball/6e82196ffd7c62f7794d778ca52b69feec9f2842", - "reference": "6e82196ffd7c62f7794d778ca52b69feec9f2842", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "require-dev": { - "phpstan/phpstan": "*", - "squizlabs/php_codesniffer": "^3.1", - "vimeo/psalm": "^4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "LanguageServerProtocol\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "ISC" - ], - "authors": [ - { - "name": "Felix Becker", - "email": "felix.b@outlook.com" - } - ], - "description": "PHP classes for the Language Server Protocol", - "keywords": [ - "language", - "microsoft", - "php", - "server" - ], - "support": { - "issues": "https://github.com/felixfbecker/php-language-server-protocol/issues", - "source": "https://github.com/felixfbecker/php-language-server-protocol/tree/v1.5.2" - }, - "time": "2022-03-02T22:36:06+00:00" - }, - { - "name": "friendsofphp/php-cs-fixer", - "version": "v3.10.0", - "source": { - "type": "git", - "url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git", - "reference": "76d7da666e66d83a1dc27a9d1c625c80cc4ac1fe" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/76d7da666e66d83a1dc27a9d1c625c80cc4ac1fe", - "reference": "76d7da666e66d83a1dc27a9d1c625c80cc4ac1fe", - "shasum": "" - }, - "require": { - "composer/semver": "^3.2", - "composer/xdebug-handler": "^3.0.3", - "doctrine/annotations": "^1.13", - "ext-json": "*", - "ext-tokenizer": "*", - "php": "^7.4 || ^8.0", - "sebastian/diff": "^4.0", - "symfony/console": "^5.4 || ^6.0", - "symfony/event-dispatcher": "^5.4 || ^6.0", - "symfony/filesystem": "^5.4 || ^6.0", - "symfony/finder": "^5.4 || ^6.0", - "symfony/options-resolver": "^5.4 || ^6.0", - "symfony/polyfill-mbstring": "^1.23", - "symfony/polyfill-php80": "^1.25", - "symfony/polyfill-php81": "^1.25", - "symfony/process": "^5.4 || ^6.0", - "symfony/stopwatch": "^5.4 || ^6.0" - }, - "require-dev": { - "justinrainbow/json-schema": "^5.2", - "keradus/cli-executor": "^1.5", - "mikey179/vfsstream": "^1.6.10", - "php-coveralls/php-coveralls": "^2.5.2", - "php-cs-fixer/accessible-object": "^1.1", - "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.2", - "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.2.1", - "phpspec/prophecy": "^1.15", - "phpspec/prophecy-phpunit": "^2.0", - "phpunit/phpunit": "^9.5", - "phpunitgoodpractices/polyfill": "^1.5", - "phpunitgoodpractices/traits": "^1.9.1", - "symfony/phpunit-bridge": "^6.0", - "symfony/yaml": "^5.4 || ^6.0" - }, - "suggest": { - "ext-dom": "For handling output formats in XML", - "ext-mbstring": "For handling non-UTF8 characters." - }, - "bin": [ - "php-cs-fixer" - ], - "type": "application", - "autoload": { - "psr-4": { - "PhpCsFixer\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Dariusz Rumiński", - "email": "dariusz.ruminski@gmail.com" - } - ], - "description": "A tool to automatically fix PHP code style", - "support": { - "issues": "https://github.com/FriendsOfPHP/PHP-CS-Fixer/issues", - "source": "https://github.com/FriendsOfPHP/PHP-CS-Fixer/tree/v3.10.0" - }, - "funding": [ - { - "url": "https://github.com/keradus", - "type": "github" - } - ], - "time": "2022-08-17T22:13:10+00:00" - }, - { - "name": "infection/abstract-testframework-adapter", - "version": "0.5.0", - "source": { - "type": "git", - "url": "https://github.com/infection/abstract-testframework-adapter.git", - "reference": "18925e20d15d1a5995bb85c9dc09e8751e1e069b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/infection/abstract-testframework-adapter/zipball/18925e20d15d1a5995bb85c9dc09e8751e1e069b", - "reference": "18925e20d15d1a5995bb85c9dc09e8751e1e069b", - "shasum": "" - }, - "require": { - "php": "^7.4 || ^8.0" - }, - "require-dev": { - "ergebnis/composer-normalize": "^2.8", - "friendsofphp/php-cs-fixer": "^2.17", - "phpunit/phpunit": "^9.5" - }, - "type": "library", - "autoload": { - "psr-4": { - "Infection\\AbstractTestFramework\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Maks Rafalko", - "email": "maks.rafalko@gmail.com" - } - ], - "description": "Abstract Test Framework Adapter for Infection", - "support": { - "issues": "https://github.com/infection/abstract-testframework-adapter/issues", - "source": "https://github.com/infection/abstract-testframework-adapter/tree/0.5.0" - }, - "funding": [ - { - "url": "https://github.com/infection", - "type": "github" - }, - { - "url": "https://opencollective.com/infection", - "type": "open_collective" - } - ], - "time": "2021-08-17T18:49:12+00:00" - }, - { - "name": "infection/extension-installer", - "version": "0.1.2", - "source": { - "type": "git", - "url": "https://github.com/infection/extension-installer.git", - "reference": "9b351d2910b9a23ab4815542e93d541e0ca0cdcf" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/infection/extension-installer/zipball/9b351d2910b9a23ab4815542e93d541e0ca0cdcf", - "reference": "9b351d2910b9a23ab4815542e93d541e0ca0cdcf", - "shasum": "" - }, - "require": { - "composer-plugin-api": "^1.1 || ^2.0" - }, - "require-dev": { - "composer/composer": "^1.9 || ^2.0", - "friendsofphp/php-cs-fixer": "^2.18, <2.19", - "infection/infection": "^0.15.2", - "php-coveralls/php-coveralls": "^2.4", - "phpstan/extension-installer": "^1.0", - "phpstan/phpstan": "^0.12.10", - "phpstan/phpstan-phpunit": "^0.12.6", - "phpstan/phpstan-strict-rules": "^0.12.2", - "phpstan/phpstan-webmozart-assert": "^0.12.2", - "phpunit/phpunit": "^9.5", - "vimeo/psalm": "^4.8" - }, - "type": "composer-plugin", - "extra": { - "class": "Infection\\ExtensionInstaller\\Plugin" - }, - "autoload": { - "psr-4": { - "Infection\\ExtensionInstaller\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Maks Rafalko", - "email": "maks.rafalko@gmail.com" - } - ], - "description": "Infection Extension Installer", - "support": { - "issues": "https://github.com/infection/extension-installer/issues", - "source": "https://github.com/infection/extension-installer/tree/0.1.2" - }, - "funding": [ - { - "url": "https://github.com/infection", - "type": "github" - }, - { - "url": "https://opencollective.com/infection", - "type": "open_collective" - } - ], - "time": "2021-10-20T22:08:34+00:00" - }, - { - "name": "infection/include-interceptor", - "version": "0.2.5", - "source": { - "type": "git", - "url": "https://github.com/infection/include-interceptor.git", - "reference": "0cc76d95a79d9832d74e74492b0a30139904bdf7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/infection/include-interceptor/zipball/0cc76d95a79d9832d74e74492b0a30139904bdf7", - "reference": "0cc76d95a79d9832d74e74492b0a30139904bdf7", - "shasum": "" - }, - "require-dev": { - "friendsofphp/php-cs-fixer": "^2.16", - "infection/infection": "^0.15.0", - "phan/phan": "^2.4 || ^3", - "php-coveralls/php-coveralls": "^2.2", - "phpstan/phpstan": "^0.12.8", - "phpunit/phpunit": "^8.5", - "vimeo/psalm": "^3.8" - }, - "type": "library", - "autoload": { - "psr-4": { - "Infection\\StreamWrapper\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Maks Rafalko", - "email": "maks.rafalko@gmail.com" - } - ], - "description": "Stream Wrapper: Include Interceptor. Allows to replace included (autoloaded) file with another one.", - "support": { - "issues": "https://github.com/infection/include-interceptor/issues", - "source": "https://github.com/infection/include-interceptor/tree/0.2.5" - }, - "funding": [ - { - "url": "https://github.com/infection", - "type": "github" - }, - { - "url": "https://opencollective.com/infection", - "type": "open_collective" - } - ], - "time": "2021-08-09T10:03:57+00:00" - }, - { - "name": "infection/infection", - "version": "0.26.13", - "source": { - "type": "git", - "url": "https://github.com/infection/infection.git", - "reference": "c2f121b1f86af20b1373236535abfe06e5358224" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/infection/infection/zipball/c2f121b1f86af20b1373236535abfe06e5358224", - "reference": "c2f121b1f86af20b1373236535abfe06e5358224", - "shasum": "" - }, - "require": { - "composer-runtime-api": "^2.0", - "composer/xdebug-handler": "^2.0 || ^3.0", - "ext-dom": "*", - "ext-json": "*", - "ext-libxml": "*", - "infection/abstract-testframework-adapter": "^0.5.0", - "infection/extension-installer": "^0.1.0", - "infection/include-interceptor": "^0.2.5", - "justinrainbow/json-schema": "^5.2.10", - "nikic/php-parser": "^4.13.2", - "ondram/ci-detector": "^4.1.0", - "php": "^8.0", - "sanmai/later": "^0.1.1", - "sanmai/pipeline": "^5.1 || ^6", - "sebastian/diff": "^3.0.2 || ^4.0", - "seld/jsonlint": "^1.7", - "symfony/console": "^5.4 || ^6.0", - "symfony/filesystem": "^5.4 || ^6.0", - "symfony/finder": "^5.4 || ^6.0", - "symfony/process": "^5.4 || ^6.0", - "thecodingmachine/safe": "^2.1.2", - "webmozart/assert": "^1.3" - }, - "conflict": { - "dg/bypass-finals": "*", - "phpunit/php-code-coverage": ">9 <9.1.4" - }, - "require-dev": { - "brianium/paratest": "^6.3", - "ext-simplexml": "*", - "helmich/phpunit-json-assert": "^3.0", - "phpspec/prophecy-phpunit": "^2.0", - "phpstan/extension-installer": "^1.1.0", - "phpstan/phpstan": "^1.3.0", - "phpstan/phpstan-phpunit": "^1.0.0", - "phpstan/phpstan-strict-rules": "^1.1.0", - "phpstan/phpstan-webmozart-assert": "^1.0.2", - "phpunit/phpunit": "^9.5.5", - "symfony/phpunit-bridge": "^5.4 || ^6.0", - "symfony/yaml": "^5.4 || ^6.0", - "thecodingmachine/phpstan-safe-rule": "^1.2.0" - }, - "bin": [ - "bin/infection" - ], - "type": "library", - "autoload": { - "psr-4": { - "Infection\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Maks Rafalko", - "email": "maks.rafalko@gmail.com", - "homepage": "https://twitter.com/maks_rafalko" - }, - { - "name": "Oleg Zhulnev", - "homepage": "https://github.com/sidz" - }, - { - "name": "Gert de Pagter", - "homepage": "https://github.com/BackEndTea" - }, - { - "name": "Théo FIDRY", - "email": "theo.fidry@gmail.com", - "homepage": "https://twitter.com/tfidry" - }, - { - "name": "Alexey Kopytko", - "email": "alexey@kopytko.com", - "homepage": "https://www.alexeykopytko.com" - }, - { - "name": "Andreas Möller", - "email": "am@localheinz.com", - "homepage": "https://localheinz.com" - } - ], - "description": "Infection is a Mutation Testing framework for PHP. The mutation adequacy score can be used to measure the effectiveness of a test set in terms of its ability to detect faults.", - "keywords": [ - "coverage", - "mutant", - "mutation framework", - "mutation testing", - "testing", - "unit testing" - ], - "support": { - "issues": "https://github.com/infection/infection/issues", - "source": "https://github.com/infection/infection/tree/0.26.13" - }, - "funding": [ - { - "url": "https://github.com/infection", - "type": "github" - }, - { - "url": "https://opencollective.com/infection", - "type": "open_collective" - } - ], - "time": "2022-06-23T12:48:45+00:00" - }, - { - "name": "justinrainbow/json-schema", - "version": "5.2.12", - "source": { - "type": "git", - "url": "https://github.com/justinrainbow/json-schema.git", - "reference": "ad87d5a5ca981228e0e205c2bc7dfb8e24559b60" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/justinrainbow/json-schema/zipball/ad87d5a5ca981228e0e205c2bc7dfb8e24559b60", - "reference": "ad87d5a5ca981228e0e205c2bc7dfb8e24559b60", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "friendsofphp/php-cs-fixer": "~2.2.20||~2.15.1", - "json-schema/json-schema-test-suite": "1.2.0", - "phpunit/phpunit": "^4.8.35" - }, - "bin": [ - "bin/validate-json" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "JsonSchema\\": "src/JsonSchema/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Bruno Prieto Reis", - "email": "bruno.p.reis@gmail.com" - }, - { - "name": "Justin Rainbow", - "email": "justin.rainbow@gmail.com" - }, - { - "name": "Igor Wiedler", - "email": "igor@wiedler.ch" - }, - { - "name": "Robert Schönthal", - "email": "seroscho@googlemail.com" - } - ], - "description": "A library to validate a json schema.", - "homepage": "https://github.com/justinrainbow/json-schema", - "keywords": [ - "json", - "schema" - ], - "support": { - "issues": "https://github.com/justinrainbow/json-schema/issues", - "source": "https://github.com/justinrainbow/json-schema/tree/5.2.12" - }, - "time": "2022-04-13T08:02:27+00:00" - }, - { - "name": "myclabs/deep-copy", - "version": "1.11.0", - "source": { - "type": "git", - "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/14daed4296fae74d9e3201d2c4925d1acb7aa614", - "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614", - "shasum": "" - }, - "require": { - "php": "^7.1 || ^8.0" - }, - "conflict": { - "doctrine/collections": "<1.6.8", - "doctrine/common": "<2.13.3 || >=3,<3.2.2" - }, - "require-dev": { - "doctrine/collections": "^1.6.8", - "doctrine/common": "^2.13.3 || ^3.2.2", - "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" - }, - "type": "library", - "autoload": { - "files": [ - "src/DeepCopy/deep_copy.php" - ], - "psr-4": { - "DeepCopy\\": "src/DeepCopy/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Create deep copies (clones) of your objects", - "keywords": [ - "clone", - "copy", - "duplicate", - "object", - "object graph" - ], - "support": { - "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.11.0" - }, - "funding": [ - { - "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", - "type": "tidelift" - } - ], - "time": "2022-03-03T13:19:32+00:00" - }, - { - "name": "netresearch/jsonmapper", - "version": "v4.0.0", - "source": { - "type": "git", - "url": "https://github.com/cweiske/jsonmapper.git", - "reference": "8bbc021a8edb2e4a7ea2f8ad4fa9ec9dce2fcb8d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/cweiske/jsonmapper/zipball/8bbc021a8edb2e4a7ea2f8ad4fa9ec9dce2fcb8d", - "reference": "8bbc021a8edb2e4a7ea2f8ad4fa9ec9dce2fcb8d", - "shasum": "" - }, - "require": { - "ext-json": "*", - "ext-pcre": "*", - "ext-reflection": "*", - "ext-spl": "*", - "php": ">=7.1" - }, - "require-dev": { - "phpunit/phpunit": "~7.5 || ~8.0 || ~9.0", - "squizlabs/php_codesniffer": "~3.5" - }, - "type": "library", - "autoload": { - "psr-0": { - "JsonMapper": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "OSL-3.0" - ], - "authors": [ - { - "name": "Christian Weiske", - "email": "cweiske@cweiske.de", - "homepage": "http://github.com/cweiske/jsonmapper/", - "role": "Developer" - } - ], - "description": "Map nested JSON structures onto PHP classes", - "support": { - "email": "cweiske@cweiske.de", - "issues": "https://github.com/cweiske/jsonmapper/issues", - "source": "https://github.com/cweiske/jsonmapper/tree/v4.0.0" - }, - "time": "2020-12-01T19:48:11+00:00" - }, - { - "name": "nikic/php-parser", - "version": "v4.14.0", - "source": { - "type": "git", - "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "34bea19b6e03d8153165d8f30bba4c3be86184c1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/34bea19b6e03d8153165d8f30bba4c3be86184c1", - "reference": "34bea19b6e03d8153165d8f30bba4c3be86184c1", - "shasum": "" - }, - "require": { - "ext-tokenizer": "*", - "php": ">=7.0" - }, - "require-dev": { - "ircmaxell/php-yacc": "^0.0.7", - "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" - }, - "bin": [ - "bin/php-parse" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.9-dev" - } - }, - "autoload": { - "psr-4": { - "PhpParser\\": "lib/PhpParser" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Nikita Popov" - } - ], - "description": "A PHP parser written in PHP", - "keywords": [ - "parser", - "php" - ], - "support": { - "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.14.0" - }, - "time": "2022-05-31T20:59:12+00:00" - }, - { - "name": "ondram/ci-detector", - "version": "4.1.0", - "source": { - "type": "git", - "url": "https://github.com/OndraM/ci-detector.git", - "reference": "8a4b664e916df82ff26a44709942dfd593fa6f30" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/OndraM/ci-detector/zipball/8a4b664e916df82ff26a44709942dfd593fa6f30", - "reference": "8a4b664e916df82ff26a44709942dfd593fa6f30", - "shasum": "" - }, - "require": { - "php": "^7.1 || ^8.0" - }, - "require-dev": { - "ergebnis/composer-normalize": "^2.2", - "lmc/coding-standard": "^1.3 || ^2.1", - "php-parallel-lint/php-parallel-lint": "^1.2", - "phpstan/extension-installer": "^1.0.5", - "phpstan/phpstan": "^0.12.58", - "phpstan/phpstan-phpunit": "^0.12.16", - "phpunit/phpunit": "^7.1 || ^8.0 || ^9.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "OndraM\\CiDetector\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Ondřej Machulda", - "email": "ondrej.machulda@gmail.com" - } - ], - "description": "Detect continuous integration environment and provide unified access to properties of current build", - "keywords": [ - "CircleCI", - "Codeship", - "Wercker", - "adapter", - "appveyor", - "aws", - "aws codebuild", - "azure", - "azure devops", - "azure pipelines", - "bamboo", - "bitbucket", - "buddy", - "ci-info", - "codebuild", - "continuous integration", - "continuousphp", - "devops", - "drone", - "github", - "gitlab", - "interface", - "jenkins", - "pipelines", - "sourcehut", - "teamcity", - "travis" - ], - "support": { - "issues": "https://github.com/OndraM/ci-detector/issues", - "source": "https://github.com/OndraM/ci-detector/tree/4.1.0" - }, - "time": "2021-04-14T09:16:52+00:00" - }, - { - "name": "openlss/lib-array2xml", - "version": "1.0.0", - "source": { - "type": "git", - "url": "https://github.com/nullivex/lib-array2xml.git", - "reference": "a91f18a8dfc69ffabe5f9b068bc39bb202c81d90" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nullivex/lib-array2xml/zipball/a91f18a8dfc69ffabe5f9b068bc39bb202c81d90", - "reference": "a91f18a8dfc69ffabe5f9b068bc39bb202c81d90", - "shasum": "" - }, - "require": { - "php": ">=5.3.2" - }, - "type": "library", - "autoload": { - "psr-0": { - "LSS": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache-2.0" - ], - "authors": [ - { - "name": "Bryan Tong", - "email": "bryan@nullivex.com", - "homepage": "https://www.nullivex.com" - }, - { - "name": "Tony Butler", - "email": "spudz76@gmail.com", - "homepage": "https://www.nullivex.com" - } - ], - "description": "Array2XML conversion library credit to lalit.org", - "homepage": "https://www.nullivex.com", - "keywords": [ - "array", - "array conversion", - "xml", - "xml conversion" - ], - "support": { - "issues": "https://github.com/nullivex/lib-array2xml/issues", - "source": "https://github.com/nullivex/lib-array2xml/tree/master" - }, - "time": "2019-03-29T20:06:56+00:00" - }, - { - "name": "phar-io/manifest", - "version": "2.0.3", - "source": { - "type": "git", - "url": "https://github.com/phar-io/manifest.git", - "reference": "97803eca37d319dfa7826cc2437fc020857acb53" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53", - "reference": "97803eca37d319dfa7826cc2437fc020857acb53", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-phar": "*", - "ext-xmlwriter": "*", - "phar-io/version": "^3.0.1", - "php": "^7.2 || ^8.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" - } - ], - "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", - "support": { - "issues": "https://github.com/phar-io/manifest/issues", - "source": "https://github.com/phar-io/manifest/tree/2.0.3" - }, - "time": "2021-07-20T11:28:43+00:00" - }, - { - "name": "phar-io/version", - "version": "3.2.1", - "source": { - "type": "git", - "url": "https://github.com/phar-io/version.git", - "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", - "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" - } - ], - "description": "Library for handling version information and constraints", - "support": { - "issues": "https://github.com/phar-io/version/issues", - "source": "https://github.com/phar-io/version/tree/3.2.1" - }, - "time": "2022-02-21T01:04:05+00:00" - }, - { - "name": "phpbench/container", - "version": "2.2.1", - "source": { - "type": "git", - "url": "https://github.com/phpbench/container.git", - "reference": "6d555ff7174fca13f9b1ec0b4a089ed41d0ab392" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpbench/container/zipball/6d555ff7174fca13f9b1ec0b4a089ed41d0ab392", - "reference": "6d555ff7174fca13f9b1ec0b4a089ed41d0ab392", - "shasum": "" - }, - "require": { - "psr/container": "^1.0|^2.0", - "symfony/options-resolver": "^4.2 || ^5.0 || ^6.0" - }, - "require-dev": { - "friendsofphp/php-cs-fixer": "^2.16", - "phpstan/phpstan": "^0.12.52", - "phpunit/phpunit": "^8" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.x-dev" - } - }, - "autoload": { - "psr-4": { - "PhpBench\\DependencyInjection\\": "lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Daniel Leech", - "email": "daniel@dantleech.com" - } - ], - "description": "Simple, configurable, service container.", - "support": { - "issues": "https://github.com/phpbench/container/issues", - "source": "https://github.com/phpbench/container/tree/2.2.1" - }, - "time": "2022-01-25T10:17:35+00:00" - }, - { - "name": "phpbench/dom", - "version": "0.3.2", - "source": { - "type": "git", - "url": "https://github.com/phpbench/dom.git", - "reference": "b013b717832ddbaadf2a40984b04bc66af9a7110" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpbench/dom/zipball/b013b717832ddbaadf2a40984b04bc66af9a7110", - "reference": "b013b717832ddbaadf2a40984b04bc66af9a7110", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "php": "^7.2||^8.0" - }, - "require-dev": { - "friendsofphp/php-cs-fixer": "^2.18", - "phpstan/phpstan": "^0.12.83", - "phpunit/phpunit": "^8.0||^9.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "psr-4": { - "PhpBench\\Dom\\": "lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Daniel Leech", - "email": "daniel@dantleech.com" - } - ], - "description": "DOM wrapper to simplify working with the PHP DOM implementation", - "support": { - "issues": "https://github.com/phpbench/dom/issues", - "source": "https://github.com/phpbench/dom/tree/0.3.2" - }, - "time": "2021-09-24T15:26:07+00:00" - }, - { - "name": "phpbench/phpbench", - "version": "1.2.6", - "source": { - "type": "git", - "url": "https://github.com/phpbench/phpbench.git", - "reference": "c30fac992e72b505a1f131790583647f4d3255c3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpbench/phpbench/zipball/c30fac992e72b505a1f131790583647f4d3255c3", - "reference": "c30fac992e72b505a1f131790583647f4d3255c3", - "shasum": "" - }, - "require": { - "doctrine/annotations": "^1.13", - "ext-dom": "*", - "ext-json": "*", - "ext-pcre": "*", - "ext-reflection": "*", - "ext-spl": "*", - "ext-tokenizer": "*", - "php": "^7.3 || ^8.0", - "phpbench/container": "^2.1", - "phpbench/dom": "~0.3.1", - "psr/log": "^1.1 || ^2.0 || ^3.0", - "seld/jsonlint": "^1.1", - "symfony/console": "^4.2 || ^5.0 || ^6.0", - "symfony/filesystem": "^4.2 || ^5.0 || ^6.0", - "symfony/finder": "^4.2 || ^5.0 || ^6.0", - "symfony/options-resolver": "^4.2 || ^5.0 || ^6.0", - "symfony/process": "^4.2 || ^5.0 || ^6.0", - "webmozart/path-util": "^2.3" - }, - "require-dev": { - "dantleech/invoke": "^2.0", - "friendsofphp/php-cs-fixer": "^3.0", - "jangregor/phpstan-prophecy": "^0.8.1", - "phpspec/prophecy": "^1.12", - "phpstan/phpstan": "^0.12.7", - "phpunit/phpunit": "^8.5.8 || ^9.0", - "symfony/error-handler": "^5.2 || ^6.0", - "symfony/var-dumper": "^4.0 || ^5.0 || ^6.0" - }, - "suggest": { - "ext-xdebug": "For Xdebug profiling extension." - }, - "bin": [ - "bin/phpbench" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.2-dev" - } - }, - "autoload": { - "files": [ - "lib/Report/Func/functions.php" - ], - "psr-4": { - "PhpBench\\": "lib/", - "PhpBench\\Extensions\\XDebug\\": "extensions/xdebug/lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Daniel Leech", - "email": "daniel@dantleech.com" - } - ], - "description": "PHP Benchmarking Framework", - "support": { - "issues": "https://github.com/phpbench/phpbench/issues", - "source": "https://github.com/phpbench/phpbench/tree/1.2.6" - }, - "funding": [ - { - "url": "https://github.com/dantleech", - "type": "github" - } - ], - "time": "2022-07-19T19:52:39+00:00" - }, - { - "name": "phpdocumentor/reflection-common", - "version": "2.2.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b", - "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-2.x": "2.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jaap van Otterdijk", - "email": "opensource@ijaap.nl" - } - ], - "description": "Common reflection classes used by phpdocumentor to reflect the code structure", - "homepage": "http://www.phpdoc.org", - "keywords": [ - "FQSEN", - "phpDocumentor", - "phpdoc", - "reflection", - "static analysis" - ], - "support": { - "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", - "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x" - }, - "time": "2020-06-27T09:03:43+00:00" - }, - { - "name": "phpdocumentor/reflection-docblock", - "version": "5.3.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "622548b623e81ca6d78b721c5e029f4ce664f170" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/622548b623e81ca6d78b721c5e029f4ce664f170", - "reference": "622548b623e81ca6d78b721c5e029f4ce664f170", - "shasum": "" - }, - "require": { - "ext-filter": "*", - "php": "^7.2 || ^8.0", - "phpdocumentor/reflection-common": "^2.2", - "phpdocumentor/type-resolver": "^1.3", - "webmozart/assert": "^1.9.1" - }, - "require-dev": { - "mockery/mockery": "~1.3.2", - "psalm/phar": "^4.8" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - }, - { - "name": "Jaap van Otterdijk", - "email": "account@ijaap.nl" - } - ], - "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "support": { - "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", - "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.3.0" - }, - "time": "2021-10-19T17:43:47+00:00" - }, - { - "name": "phpdocumentor/type-resolver", - "version": "1.6.1", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "77a32518733312af16a44300404e945338981de3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/77a32518733312af16a44300404e945338981de3", - "reference": "77a32518733312af16a44300404e945338981de3", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0", - "phpdocumentor/reflection-common": "^2.0" - }, - "require-dev": { - "ext-tokenizer": "*", - "psalm/phar": "^4.8" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-1.x": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - } - ], - "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", - "support": { - "issues": "https://github.com/phpDocumentor/TypeResolver/issues", - "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.6.1" - }, - "time": "2022-03-15T21:29:03+00:00" - }, - { - "name": "phpstan/phpstan", - "version": "1.8.2", - "source": { - "type": "git", - "url": "https://github.com/phpstan/phpstan.git", - "reference": "c53312ecc575caf07b0e90dee43883fdf90ca67c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/c53312ecc575caf07b0e90dee43883fdf90ca67c", - "reference": "c53312ecc575caf07b0e90dee43883fdf90ca67c", - "shasum": "" - }, - "require": { - "php": "^7.2|^8.0" - }, - "conflict": { - "phpstan/phpstan-shim": "*" - }, - "bin": [ - "phpstan", - "phpstan.phar" - ], - "type": "library", - "autoload": { - "files": [ - "bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "PHPStan - PHP Static Analysis Tool", - "support": { - "issues": "https://github.com/phpstan/phpstan/issues", - "source": "https://github.com/phpstan/phpstan/tree/1.8.2" - }, - "funding": [ - { - "url": "https://github.com/ondrejmirtes", - "type": "github" - }, - { - "url": "https://github.com/phpstan", - "type": "github" - }, - { - "url": "https://www.patreon.com/phpstan", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan", - "type": "tidelift" - } - ], - "time": "2022-07-20T09:57:31+00:00" - }, - { - "name": "phpunit/php-code-coverage", - "version": "9.2.16", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "2593003befdcc10db5e213f9f28814f5aa8ac073" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/2593003befdcc10db5e213f9f28814f5aa8ac073", - "reference": "2593003befdcc10db5e213f9f28814f5aa8ac073", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-libxml": "*", - "ext-xmlwriter": "*", - "nikic/php-parser": "^4.14", - "php": ">=7.3", - "phpunit/php-file-iterator": "^3.0.3", - "phpunit/php-text-template": "^2.0.2", - "sebastian/code-unit-reverse-lookup": "^2.0.2", - "sebastian/complexity": "^2.0", - "sebastian/environment": "^5.1.2", - "sebastian/lines-of-code": "^1.0.3", - "sebastian/version": "^3.0.1", - "theseer/tokenizer": "^1.2.0" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-pcov": "*", - "ext-xdebug": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "9.2-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", - "homepage": "https://github.com/sebastianbergmann/php-code-coverage", - "keywords": [ - "coverage", - "testing", - "xunit" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.16" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2022-08-20T05:26:47+00:00" - }, - { - "name": "phpunit/php-file-iterator", - "version": "3.0.6", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", - "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "FilterIterator implementation that filters files based on a list of suffixes.", - "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", - "keywords": [ - "filesystem", - "iterator" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2021-12-02T12:48:52+00:00" - }, - { - "name": "phpunit/php-invoker", - "version": "3.1.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-invoker.git", - "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67", - "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "ext-pcntl": "*", - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-pcntl": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Invoke callables with a timeout", - "homepage": "https://github.com/sebastianbergmann/php-invoker/", - "keywords": [ - "process" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-invoker/issues", - "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T05:58:55+00:00" - }, - { - "name": "phpunit/php-text-template", - "version": "2.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", - "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Simple template engine.", - "homepage": "https://github.com/sebastianbergmann/php-text-template/", - "keywords": [ - "template" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-text-template/issues", - "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T05:33:50+00:00" - }, - { - "name": "phpunit/php-timer", - "version": "5.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", - "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Utility class for timing", - "homepage": "https://github.com/sebastianbergmann/php-timer/", - "keywords": [ - "timer" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-timer/issues", - "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:16:10+00:00" - }, - { - "name": "phpunit/phpunit", - "version": "9.5.23", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "888556852e7e9bbeeedb9656afe46118765ade34" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/888556852e7e9bbeeedb9656afe46118765ade34", - "reference": "888556852e7e9bbeeedb9656afe46118765ade34", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.3.1", - "ext-dom": "*", - "ext-json": "*", - "ext-libxml": "*", - "ext-mbstring": "*", - "ext-xml": "*", - "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.10.1", - "phar-io/manifest": "^2.0.3", - "phar-io/version": "^3.0.2", - "php": ">=7.3", - "phpunit/php-code-coverage": "^9.2.13", - "phpunit/php-file-iterator": "^3.0.5", - "phpunit/php-invoker": "^3.1.1", - "phpunit/php-text-template": "^2.0.3", - "phpunit/php-timer": "^5.0.2", - "sebastian/cli-parser": "^1.0.1", - "sebastian/code-unit": "^1.0.6", - "sebastian/comparator": "^4.0.5", - "sebastian/diff": "^4.0.3", - "sebastian/environment": "^5.1.3", - "sebastian/exporter": "^4.0.3", - "sebastian/global-state": "^5.0.1", - "sebastian/object-enumerator": "^4.0.3", - "sebastian/resource-operations": "^3.0.3", - "sebastian/type": "^3.0", - "sebastian/version": "^3.0.2" - }, - "suggest": { - "ext-soap": "*", - "ext-xdebug": "*" - }, - "bin": [ - "phpunit" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "9.5-dev" - } - }, - "autoload": { - "files": [ - "src/Framework/Assert/Functions.php" - ], - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "The PHP Unit Testing framework.", - "homepage": "https://phpunit.de/", - "keywords": [ - "phpunit", - "testing", - "xunit" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.23" - }, - "funding": [ - { - "url": "https://phpunit.de/sponsors.html", - "type": "custom" - }, - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2022-08-22T14:01:36+00:00" - }, - { - "name": "psr/cache", - "version": "3.0.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/cache.git", - "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/cache/zipball/aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", - "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", - "shasum": "" - }, - "require": { - "php": ">=8.0.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Cache\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common interface for caching libraries", - "keywords": [ - "cache", - "psr", - "psr-6" - ], - "support": { - "source": "https://github.com/php-fig/cache/tree/3.0.0" - }, - "time": "2021-02-03T23:26:27+00:00" - }, - { - "name": "psr/container", - "version": "2.0.2", - "source": { - "type": "git", - "url": "https://github.com/php-fig/container.git", - "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", - "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", - "shasum": "" - }, - "require": { - "php": ">=7.4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Container\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common Container Interface (PHP FIG PSR-11)", - "homepage": "https://github.com/php-fig/container", - "keywords": [ - "PSR-11", - "container", - "container-interface", - "container-interop", - "psr" - ], - "support": { - "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/2.0.2" - }, - "time": "2021-11-05T16:47:00+00:00" - }, - { - "name": "psr/event-dispatcher", - "version": "1.0.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/event-dispatcher.git", - "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", - "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", - "shasum": "" - }, - "require": { - "php": ">=7.2.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\EventDispatcher\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Standard interfaces for event handling.", - "keywords": [ - "events", - "psr", - "psr-14" - ], - "support": { - "issues": "https://github.com/php-fig/event-dispatcher/issues", - "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" - }, - "time": "2019-01-08T18:20:26+00:00" - }, - { - "name": "psr/log", - "version": "3.0.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001", - "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001", - "shasum": "" - }, - "require": { - "php": ">=8.0.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Log\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", - "keywords": [ - "log", - "psr", - "psr-3" - ], - "support": { - "source": "https://github.com/php-fig/log/tree/3.0.0" - }, - "time": "2021-07-14T16:46:02+00:00" - }, - { - "name": "roave/no-leaks", - "version": "1.3.0", - "source": { - "type": "git", - "url": "https://github.com/Roave/no-leaks.git", - "reference": "1373c4f477d7adac6c4ccf2e98f7c8ddb891eb47" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Roave/no-leaks/zipball/1373c4f477d7adac6c4ccf2e98f7c8ddb891eb47", - "reference": "1373c4f477d7adac6c4ccf2e98f7c8ddb891eb47", - "shasum": "" - }, - "require": { - "ext-json": "*", - "php": "^7.4 || ^8.0", - "phpunit/phpunit": "^9.5.5" - }, - "require-dev": { - "doctrine/coding-standard": "^9.0.0", - "psalm/plugin-phpunit": "^0.16.1", - "roave/infection-static-analysis-plugin": "^1.8.0", - "squizlabs/php_codesniffer": "^3.6.0", - "vimeo/psalm": "^4.8.1" - }, - "bin": [ - "bin/roave-no-leaks" - ], - "type": "library", - "autoload": { - "psr-4": { - "Roave\\NoLeaks\\PHPUnit\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "support": { - "issues": "https://github.com/Roave/no-leaks/issues", - "source": "https://github.com/Roave/no-leaks/tree/1.3.0" - }, - "time": "2021-06-22T09:11:50+00:00" - }, - { - "name": "sanmai/later", - "version": "0.1.2", - "source": { - "type": "git", - "url": "https://github.com/sanmai/later.git", - "reference": "9b659fecef2030193fd02402955bc39629d5606f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sanmai/later/zipball/9b659fecef2030193fd02402955bc39629d5606f", - "reference": "9b659fecef2030193fd02402955bc39629d5606f", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "require-dev": { - "friendsofphp/php-cs-fixer": "^2.13", - "infection/infection": ">=0.10.5", - "phan/phan": ">=2", - "php-coveralls/php-coveralls": "^2.0", - "phpstan/phpstan": ">=0.10", - "phpunit/phpunit": ">=7.4", - "vimeo/psalm": ">=2" - }, - "type": "library", - "autoload": { - "files": [ - "src/functions.php" - ], - "psr-4": { - "Later\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache-2.0" - ], - "authors": [ - { - "name": "Alexey Kopytko", - "email": "alexey@kopytko.com" - } - ], - "description": "Later: deferred wrapper object", - "support": { - "issues": "https://github.com/sanmai/later/issues", - "source": "https://github.com/sanmai/later/tree/0.1.2" - }, - "funding": [ - { - "url": "https://github.com/sanmai", - "type": "github" - } - ], - "time": "2021-01-02T10:26:44+00:00" - }, - { - "name": "sanmai/pipeline", - "version": "v6.1", - "source": { - "type": "git", - "url": "https://github.com/sanmai/pipeline.git", - "reference": "3a88f2617237e18d5cd2aa38ca3d4b22770306c2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sanmai/pipeline/zipball/3a88f2617237e18d5cd2aa38ca3d4b22770306c2", - "reference": "3a88f2617237e18d5cd2aa38ca3d4b22770306c2", - "shasum": "" - }, - "require": { - "php": "^7.1 || ^8.0" - }, - "require-dev": { - "ergebnis/composer-normalize": "^2.8", - "friendsofphp/php-cs-fixer": "^3", - "infection/infection": ">=0.10.5", - "league/pipeline": "^1.0 || ^0.3", - "phan/phan": ">=1.1", - "php-coveralls/php-coveralls": "^2.4.1", - "phpstan/phpstan": ">=0.10", - "phpunit/phpunit": "^7.4 || ^8.1 || ^9.4", - "vimeo/psalm": ">=2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "v6.x-dev" - } - }, - "autoload": { - "files": [ - "src/functions.php" - ], - "psr-4": { - "Pipeline\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache-2.0" - ], - "authors": [ - { - "name": "Alexey Kopytko", - "email": "alexey@kopytko.com" - } - ], - "description": "General-purpose collections pipeline", - "support": { - "issues": "https://github.com/sanmai/pipeline/issues", - "source": "https://github.com/sanmai/pipeline/tree/v6.1" - }, - "funding": [ - { - "url": "https://github.com/sanmai", - "type": "github" - } - ], - "time": "2022-01-30T08:15:59+00:00" - }, - { - "name": "sebastian/cli-parser", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/cli-parser.git", - "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2", - "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for parsing CLI options", - "homepage": "https://github.com/sebastianbergmann/cli-parser", - "support": { - "issues": "https://github.com/sebastianbergmann/cli-parser/issues", - "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T06:08:49+00:00" - }, - { - "name": "sebastian/code-unit", - "version": "1.0.8", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit.git", - "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120", - "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Collection of value objects that represent the PHP code units", - "homepage": "https://github.com/sebastianbergmann/code-unit", - "support": { - "issues": "https://github.com/sebastianbergmann/code-unit/issues", - "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:08:54+00:00" - }, - { - "name": "sebastian/code-unit-reverse-lookup", - "version": "2.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", - "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Looks up which function or method a line of code belongs to", - "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", - "support": { - "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", - "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T05:30:19+00:00" - }, - { - "name": "sebastian/comparator", - "version": "4.0.6", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "55f4261989e546dc112258c7a75935a81a7ce382" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/55f4261989e546dc112258c7a75935a81a7ce382", - "reference": "55f4261989e546dc112258c7a75935a81a7ce382", - "shasum": "" - }, - "require": { - "php": ">=7.3", - "sebastian/diff": "^4.0", - "sebastian/exporter": "^4.0" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - } - ], - "description": "Provides the functionality to compare PHP values for equality", - "homepage": "https://github.com/sebastianbergmann/comparator", - "keywords": [ - "comparator", - "compare", - "equality" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/comparator/issues", - "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.6" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T15:49:45+00:00" - }, - { - "name": "sebastian/complexity", - "version": "2.0.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/complexity.git", - "reference": "739b35e53379900cc9ac327b2147867b8b6efd88" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/739b35e53379900cc9ac327b2147867b8b6efd88", - "reference": "739b35e53379900cc9ac327b2147867b8b6efd88", - "shasum": "" - }, - "require": { - "nikic/php-parser": "^4.7", - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for calculating the complexity of PHP code units", - "homepage": "https://github.com/sebastianbergmann/complexity", - "support": { - "issues": "https://github.com/sebastianbergmann/complexity/issues", - "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.2" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T15:52:27+00:00" - }, - { - "name": "sebastian/diff", - "version": "4.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/3461e3fccc7cfdfc2720be910d3bd73c69be590d", - "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3", - "symfony/process": "^4.2 || ^5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - } - ], - "description": "Diff implementation", - "homepage": "https://github.com/sebastianbergmann/diff", - "keywords": [ - "diff", - "udiff", - "unidiff", - "unified diff" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/diff/issues", - "source": "https://github.com/sebastianbergmann/diff/tree/4.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:10:38+00:00" - }, - { - "name": "sebastian/environment", - "version": "5.1.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/1b5dff7bb151a4db11d49d90e5408e4e938270f7", - "reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-posix": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides functionality to handle HHVM/PHP environments", - "homepage": "http://www.github.com/sebastianbergmann/environment", - "keywords": [ - "Xdebug", - "environment", - "hhvm" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/environment/issues", - "source": "https://github.com/sebastianbergmann/environment/tree/5.1.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2022-04-03T09:37:03+00:00" - }, - { - "name": "sebastian/exporter", - "version": "4.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "65e8b7db476c5dd267e65eea9cab77584d3cfff9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/65e8b7db476c5dd267e65eea9cab77584d3cfff9", - "reference": "65e8b7db476c5dd267e65eea9cab77584d3cfff9", - "shasum": "" - }, - "require": { - "php": ">=7.3", - "sebastian/recursion-context": "^4.0" - }, - "require-dev": { - "ext-mbstring": "*", - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "https://www.github.com/sebastianbergmann/exporter", - "keywords": [ - "export", - "exporter" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/exporter/issues", - "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2021-11-11T14:18:36+00:00" - }, - { - "name": "sebastian/global-state", - "version": "5.0.5", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/0ca8db5a5fc9c8646244e629625ac486fa286bf2", - "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2", - "shasum": "" - }, - "require": { - "php": ">=7.3", - "sebastian/object-reflector": "^2.0", - "sebastian/recursion-context": "^4.0" - }, - "require-dev": { - "ext-dom": "*", - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-uopz": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Snapshotting of global state", - "homepage": "http://www.github.com/sebastianbergmann/global-state", - "keywords": [ - "global state" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/global-state/issues", - "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.5" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2022-02-14T08:28:10+00:00" - }, - { - "name": "sebastian/lines-of-code", - "version": "1.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/lines-of-code.git", - "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc", - "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc", - "shasum": "" - }, - "require": { - "nikic/php-parser": "^4.6", - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for counting the lines of code in PHP source code", - "homepage": "https://github.com/sebastianbergmann/lines-of-code", - "support": { - "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", - "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-11-28T06:42:11+00:00" - }, - { - "name": "sebastian/object-enumerator", - "version": "4.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "5c9eeac41b290a3712d88851518825ad78f45c71" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71", - "reference": "5c9eeac41b290a3712d88851518825ad78f45c71", - "shasum": "" - }, - "require": { - "php": ">=7.3", - "sebastian/object-reflector": "^2.0", - "sebastian/recursion-context": "^4.0" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Traverses array structures and object graphs to enumerate all referenced objects", - "homepage": "https://github.com/sebastianbergmann/object-enumerator/", - "support": { - "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", - "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:12:34+00:00" - }, - { - "name": "sebastian/object-reflector", - "version": "2.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", - "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Allows reflection of object attributes, including inherited and non-public ones", - "homepage": "https://github.com/sebastianbergmann/object-reflector/", - "support": { - "issues": "https://github.com/sebastianbergmann/object-reflector/issues", - "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:14:26+00:00" - }, - { - "name": "sebastian/recursion-context", - "version": "4.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/cd9d8cf3c5804de4341c283ed787f099f5506172", - "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - } - ], - "description": "Provides functionality to recursively process PHP variables", - "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "support": { - "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:17:30+00:00" - }, - { - "name": "sebastian/resource-operations", - "version": "3.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", - "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides a list of PHP built-in functions that operate on resources", - "homepage": "https://www.github.com/sebastianbergmann/resource-operations", - "support": { - "issues": "https://github.com/sebastianbergmann/resource-operations/issues", - "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T06:45:17+00:00" - }, - { - "name": "sebastian/type", - "version": "3.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/type.git", - "reference": "b233b84bc4465aff7b57cf1c4bc75c86d00d6dad" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/b233b84bc4465aff7b57cf1c4bc75c86d00d6dad", - "reference": "b233b84bc4465aff7b57cf1c4bc75c86d00d6dad", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Collection of value objects that represent the types of the PHP type system", - "homepage": "https://github.com/sebastianbergmann/type", - "support": { - "issues": "https://github.com/sebastianbergmann/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/3.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2022-03-15T09:54:48+00:00" - }, - { - "name": "sebastian/version", - "version": "3.0.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/version.git", - "reference": "c6c1022351a901512170118436c764e473f6de8c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c", - "reference": "c6c1022351a901512170118436c764e473f6de8c", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library that helps with managing the version number of Git-hosted PHP projects", - "homepage": "https://github.com/sebastianbergmann/version", - "support": { - "issues": "https://github.com/sebastianbergmann/version/issues", - "source": "https://github.com/sebastianbergmann/version/tree/3.0.2" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T06:39:44+00:00" - }, - { - "name": "seld/jsonlint", - "version": "1.9.0", - "source": { - "type": "git", - "url": "https://github.com/Seldaek/jsonlint.git", - "reference": "4211420d25eba80712bff236a98960ef68b866b7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/4211420d25eba80712bff236a98960ef68b866b7", - "reference": "4211420d25eba80712bff236a98960ef68b866b7", - "shasum": "" - }, - "require": { - "php": "^5.3 || ^7.0 || ^8.0" - }, - "require-dev": { - "phpstan/phpstan": "^1.5", - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0 || ^8.5.13" - }, - "bin": [ - "bin/jsonlint" - ], - "type": "library", - "autoload": { - "psr-4": { - "Seld\\JsonLint\\": "src/Seld/JsonLint/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" - } - ], - "description": "JSON Linter", - "keywords": [ - "json", - "linter", - "parser", - "validator" - ], - "support": { - "issues": "https://github.com/Seldaek/jsonlint/issues", - "source": "https://github.com/Seldaek/jsonlint/tree/1.9.0" - }, - "funding": [ - { - "url": "https://github.com/Seldaek", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/seld/jsonlint", - "type": "tidelift" - } - ], - "time": "2022-04-01T13:37:23+00:00" - }, - { - "name": "symfony/console", - "version": "v6.1.3", - "source": { - "type": "git", - "url": "https://github.com/symfony/console.git", - "reference": "43fcb5c5966b43c56bcfa481368d90d748936ab8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/43fcb5c5966b43c56bcfa481368d90d748936ab8", - "reference": "43fcb5c5966b43c56bcfa481368d90d748936ab8", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-mbstring": "~1.0", - "symfony/service-contracts": "^1.1|^2|^3", - "symfony/string": "^5.4|^6.0" - }, - "conflict": { - "symfony/dependency-injection": "<5.4", - "symfony/dotenv": "<5.4", - "symfony/event-dispatcher": "<5.4", - "symfony/lock": "<5.4", - "symfony/process": "<5.4" - }, - "provide": { - "psr/log-implementation": "1.0|2.0|3.0" - }, - "require-dev": { - "psr/log": "^1|^2|^3", - "symfony/config": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/event-dispatcher": "^5.4|^6.0", - "symfony/lock": "^5.4|^6.0", - "symfony/process": "^5.4|^6.0", - "symfony/var-dumper": "^5.4|^6.0" - }, - "suggest": { - "psr/log": "For using the console logger", - "symfony/event-dispatcher": "", - "symfony/lock": "", - "symfony/process": "" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Console\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Eases the creation of beautiful and testable command line interfaces", - "homepage": "https://symfony.com", - "keywords": [ - "cli", - "command line", - "console", - "terminal" - ], - "support": { - "source": "https://github.com/symfony/console/tree/v6.1.3" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-07-22T14:17:57+00:00" - }, - { - "name": "symfony/deprecation-contracts", - "version": "v3.1.1", - "source": { - "type": "git", - "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "07f1b9cc2ffee6aaafcf4b710fbc38ff736bd918" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/07f1b9cc2ffee6aaafcf4b710fbc38ff736bd918", - "reference": "07f1b9cc2ffee6aaafcf4b710fbc38ff736bd918", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.1-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "autoload": { - "files": [ - "function.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "A generic function and convention to trigger deprecation notices", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.1.1" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-02-25T11:15:52+00:00" - }, - { - "name": "symfony/event-dispatcher", - "version": "v6.1.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "a0449a7ad7daa0f7c0acd508259f80544ab5a347" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/a0449a7ad7daa0f7c0acd508259f80544ab5a347", - "reference": "a0449a7ad7daa0f7c0acd508259f80544ab5a347", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "symfony/event-dispatcher-contracts": "^2|^3" - }, - "conflict": { - "symfony/dependency-injection": "<5.4" - }, - "provide": { - "psr/event-dispatcher-implementation": "1.0", - "symfony/event-dispatcher-implementation": "2.0|3.0" - }, - "require-dev": { - "psr/log": "^1|^2|^3", - "symfony/config": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/error-handler": "^5.4|^6.0", - "symfony/expression-language": "^5.4|^6.0", - "symfony/http-foundation": "^5.4|^6.0", - "symfony/service-contracts": "^1.1|^2|^3", - "symfony/stopwatch": "^5.4|^6.0" - }, - "suggest": { - "symfony/dependency-injection": "", - "symfony/http-kernel": "" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\EventDispatcher\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v6.1.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-05-05T16:51:07+00:00" - }, - { - "name": "symfony/event-dispatcher-contracts", - "version": "v3.1.1", - "source": { - "type": "git", - "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "02ff5eea2f453731cfbc6bc215e456b781480448" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/02ff5eea2f453731cfbc6bc215e456b781480448", - "reference": "02ff5eea2f453731cfbc6bc215e456b781480448", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "psr/event-dispatcher": "^1" - }, - "suggest": { - "symfony/event-dispatcher-implementation": "" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.1-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Contracts\\EventDispatcher\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Generic abstractions related to dispatching event", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.1.1" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-02-25T11:15:52+00:00" - }, - { - "name": "symfony/filesystem", - "version": "v6.1.3", - "source": { - "type": "git", - "url": "https://github.com/symfony/filesystem.git", - "reference": "c780e677cddda78417fa5187a7c6cd2f21110db9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/c780e677cddda78417fa5187a7c6cd2f21110db9", - "reference": "c780e677cddda78417fa5187a7c6cd2f21110db9", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-mbstring": "~1.8" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Filesystem\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides basic utilities for the filesystem", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/filesystem/tree/v6.1.3" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-07-20T14:45:06+00:00" - }, - { - "name": "symfony/finder", - "version": "v6.1.3", - "source": { - "type": "git", - "url": "https://github.com/symfony/finder.git", - "reference": "39696bff2c2970b3779a5cac7bf9f0b88fc2b709" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/39696bff2c2970b3779a5cac7bf9f0b88fc2b709", - "reference": "39696bff2c2970b3779a5cac7bf9f0b88fc2b709", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "symfony/filesystem": "^6.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Finder\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Finds files and directories via an intuitive fluent interface", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/finder/tree/v6.1.3" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-07-29T07:42:06+00:00" - }, - { - "name": "symfony/options-resolver", - "version": "v6.1.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/options-resolver.git", - "reference": "a3016f5442e28386ded73c43a32a5b68586dd1c4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/a3016f5442e28386ded73c43a32a5b68586dd1c4", - "reference": "a3016f5442e28386ded73c43a32a5b68586dd1c4", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "symfony/deprecation-contracts": "^2.1|^3" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\OptionsResolver\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides an improved replacement for the array_replace PHP function", - "homepage": "https://symfony.com", - "keywords": [ - "config", - "configuration", - "options" - ], - "support": { - "source": "https://github.com/symfony/options-resolver/tree/v6.1.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-02-25T11:15:52+00:00" - }, - { - "name": "symfony/polyfill-ctype", - "version": "v1.26.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4", - "reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "provide": { - "ext-ctype": "*" - }, - "suggest": { - "ext-ctype": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.26-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Ctype\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Gert de Pagter", - "email": "BackEndTea@gmail.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for ctype functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "ctype", - "polyfill", - "portable" - ], - "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.26.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-05-24T11:49:31+00:00" - }, - { - "name": "symfony/polyfill-intl-grapheme", - "version": "v1.26.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "433d05519ce6990bf3530fba6957499d327395c2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/433d05519ce6990bf3530fba6957499d327395c2", - "reference": "433d05519ce6990bf3530fba6957499d327395c2", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "suggest": { - "ext-intl": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.26-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Intl\\Grapheme\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for intl's grapheme_* functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "grapheme", - "intl", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.26.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-05-24T11:49:31+00:00" - }, - { - "name": "symfony/polyfill-intl-normalizer", - "version": "v1.26.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "219aa369ceff116e673852dce47c3a41794c14bd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/219aa369ceff116e673852dce47c3a41794c14bd", - "reference": "219aa369ceff116e673852dce47c3a41794c14bd", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "suggest": { - "ext-intl": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.26-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Intl\\Normalizer\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for intl's Normalizer class and related functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "intl", - "normalizer", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.26.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-05-24T11:49:31+00:00" - }, - { - "name": "symfony/polyfill-mbstring", - "version": "v1.26.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e", - "reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "provide": { - "ext-mbstring": "*" - }, - "suggest": { - "ext-mbstring": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.26-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Mbstring\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for the Mbstring extension", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "mbstring", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.26.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-05-24T11:49:31+00:00" - }, - { - "name": "symfony/polyfill-php80", - "version": "v1.26.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/cfa0ae98841b9e461207c13ab093d76b0fa7bace", - "reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.26-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php80\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Ion Bazan", - "email": "ion.bazan@gmail.com" - }, - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.26.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-05-10T07:21:04+00:00" - }, - { - "name": "symfony/polyfill-php81", - "version": "v1.26.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php81.git", - "reference": "13f6d1271c663dc5ae9fb843a8f16521db7687a1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/13f6d1271c663dc5ae9fb843a8f16521db7687a1", - "reference": "13f6d1271c663dc5ae9fb843a8f16521db7687a1", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.26-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php81\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php81/tree/v1.26.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-05-24T11:49:31+00:00" - }, - { - "name": "symfony/process", - "version": "v6.1.3", - "source": { - "type": "git", - "url": "https://github.com/symfony/process.git", - "reference": "a6506e99cfad7059b1ab5cab395854a0a0c21292" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/a6506e99cfad7059b1ab5cab395854a0a0c21292", - "reference": "a6506e99cfad7059b1ab5cab395854a0a0c21292", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Process\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Executes commands in sub-processes", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/process/tree/v6.1.3" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-06-27T17:24:16+00:00" - }, - { - "name": "symfony/service-contracts", - "version": "v3.1.1", - "source": { - "type": "git", - "url": "https://github.com/symfony/service-contracts.git", - "reference": "925e713fe8fcacf6bc05e936edd8dd5441a21239" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/925e713fe8fcacf6bc05e936edd8dd5441a21239", - "reference": "925e713fe8fcacf6bc05e936edd8dd5441a21239", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "psr/container": "^2.0" - }, - "conflict": { - "ext-psr": "<1.1|>=2" - }, - "suggest": { - "symfony/service-implementation": "" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.1-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Contracts\\Service\\": "" - }, - "exclude-from-classmap": [ - "/Test/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Generic abstractions related to writing services", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.1.1" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-05-30T19:18:58+00:00" - }, - { - "name": "symfony/stopwatch", - "version": "v6.1.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/stopwatch.git", - "reference": "77dedae82ce2a26e2e9b481855473fc3b3e4e54d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/77dedae82ce2a26e2e9b481855473fc3b3e4e54d", - "reference": "77dedae82ce2a26e2e9b481855473fc3b3e4e54d", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "symfony/service-contracts": "^1|^2|^3" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Stopwatch\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides a way to profile code", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/stopwatch/tree/v6.1.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-02-25T11:15:52+00:00" - }, - { - "name": "symfony/string", - "version": "v6.1.3", - "source": { - "type": "git", - "url": "https://github.com/symfony/string.git", - "reference": "f35241f45c30bcd9046af2bb200a7086f70e1d6b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/f35241f45c30bcd9046af2bb200a7086f70e1d6b", - "reference": "f35241f45c30bcd9046af2bb200a7086f70e1d6b", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-intl-grapheme": "~1.0", - "symfony/polyfill-intl-normalizer": "~1.0", - "symfony/polyfill-mbstring": "~1.0" - }, - "conflict": { - "symfony/translation-contracts": "<2.0" - }, - "require-dev": { - "symfony/error-handler": "^5.4|^6.0", - "symfony/http-client": "^5.4|^6.0", - "symfony/translation-contracts": "^2.0|^3.0", - "symfony/var-exporter": "^5.4|^6.0" - }, - "type": "library", - "autoload": { - "files": [ - "Resources/functions.php" - ], - "psr-4": { - "Symfony\\Component\\String\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", - "homepage": "https://symfony.com", - "keywords": [ - "grapheme", - "i18n", - "string", - "unicode", - "utf-8", - "utf8" - ], - "support": { - "source": "https://github.com/symfony/string/tree/v6.1.3" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-07-27T15:50:51+00:00" - }, - { - "name": "thecodingmachine/safe", - "version": "v2.2.3", - "source": { - "type": "git", - "url": "https://github.com/thecodingmachine/safe.git", - "reference": "e454a3142d2197694d1fda291a4462ccd3f66e12" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/thecodingmachine/safe/zipball/e454a3142d2197694d1fda291a4462ccd3f66e12", - "reference": "e454a3142d2197694d1fda291a4462ccd3f66e12", - "shasum": "" - }, - "require": { - "php": "^8.0" - }, - "require-dev": { - "phpstan/phpstan": "^1.5", - "phpunit/phpunit": "^9.5", - "squizlabs/php_codesniffer": "^3.2", - "thecodingmachine/phpstan-strict-rules": "^1.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.2.x-dev" - } - }, - "autoload": { - "files": [ - "deprecated/apc.php", - "deprecated/array.php", - "deprecated/datetime.php", - "deprecated/libevent.php", - "deprecated/password.php", - "deprecated/mssql.php", - "deprecated/stats.php", - "deprecated/strings.php", - "lib/special_cases.php", - "deprecated/mysqli.php", - "generated/apache.php", - "generated/apcu.php", - "generated/array.php", - "generated/bzip2.php", - "generated/calendar.php", - "generated/classobj.php", - "generated/com.php", - "generated/cubrid.php", - "generated/curl.php", - "generated/datetime.php", - "generated/dir.php", - "generated/eio.php", - "generated/errorfunc.php", - "generated/exec.php", - "generated/fileinfo.php", - "generated/filesystem.php", - "generated/filter.php", - "generated/fpm.php", - "generated/ftp.php", - "generated/funchand.php", - "generated/gettext.php", - "generated/gmp.php", - "generated/gnupg.php", - "generated/hash.php", - "generated/ibase.php", - "generated/ibmDb2.php", - "generated/iconv.php", - "generated/image.php", - "generated/imap.php", - "generated/info.php", - "generated/inotify.php", - "generated/json.php", - "generated/ldap.php", - "generated/libxml.php", - "generated/lzf.php", - "generated/mailparse.php", - "generated/mbstring.php", - "generated/misc.php", - "generated/mysql.php", - "generated/network.php", - "generated/oci8.php", - "generated/opcache.php", - "generated/openssl.php", - "generated/outcontrol.php", - "generated/pcntl.php", - "generated/pcre.php", - "generated/pgsql.php", - "generated/posix.php", - "generated/ps.php", - "generated/pspell.php", - "generated/readline.php", - "generated/rpminfo.php", - "generated/rrd.php", - "generated/sem.php", - "generated/session.php", - "generated/shmop.php", - "generated/sockets.php", - "generated/sodium.php", - "generated/solr.php", - "generated/spl.php", - "generated/sqlsrv.php", - "generated/ssdeep.php", - "generated/ssh2.php", - "generated/stream.php", - "generated/strings.php", - "generated/swoole.php", - "generated/uodbc.php", - "generated/uopz.php", - "generated/url.php", - "generated/var.php", - "generated/xdiff.php", - "generated/xml.php", - "generated/xmlrpc.php", - "generated/yaml.php", - "generated/yaz.php", - "generated/zip.php", - "generated/zlib.php" - ], - "classmap": [ - "lib/DateTime.php", - "lib/DateTimeImmutable.php", - "lib/Exceptions/", - "deprecated/Exceptions/", - "generated/Exceptions/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "PHP core functions that throw exceptions instead of returning FALSE on error", - "support": { - "issues": "https://github.com/thecodingmachine/safe/issues", - "source": "https://github.com/thecodingmachine/safe/tree/v2.2.3" - }, - "time": "2022-08-04T14:05:49+00:00" - }, - { - "name": "theseer/tokenizer", - "version": "1.2.1", - "source": { - "type": "git", - "url": "https://github.com/theseer/tokenizer.git", - "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e", - "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-tokenizer": "*", - "ext-xmlwriter": "*", - "php": "^7.2 || ^8.0" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - } - ], - "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", - "support": { - "issues": "https://github.com/theseer/tokenizer/issues", - "source": "https://github.com/theseer/tokenizer/tree/1.2.1" - }, - "funding": [ - { - "url": "https://github.com/theseer", - "type": "github" - } - ], - "time": "2021-07-28T10:34:58+00:00" - }, - { - "name": "vimeo/psalm", - "version": "4.26.0", - "source": { - "type": "git", - "url": "https://github.com/vimeo/psalm.git", - "reference": "6998fabb2bf528b65777bf9941920888d23c03ac" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/vimeo/psalm/zipball/6998fabb2bf528b65777bf9941920888d23c03ac", - "reference": "6998fabb2bf528b65777bf9941920888d23c03ac", - "shasum": "" - }, - "require": { - "amphp/amp": "^2.4.2", - "amphp/byte-stream": "^1.5", - "composer/package-versions-deprecated": "^1.8.0", - "composer/semver": "^1.4 || ^2.0 || ^3.0", - "composer/xdebug-handler": "^1.1 || ^2.0 || ^3.0", - "dnoegel/php-xdg-base-dir": "^0.1.1", - "ext-ctype": "*", - "ext-dom": "*", - "ext-json": "*", - "ext-libxml": "*", - "ext-mbstring": "*", - "ext-simplexml": "*", - "ext-tokenizer": "*", - "felixfbecker/advanced-json-rpc": "^3.0.3", - "felixfbecker/language-server-protocol": "^1.5", - "netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.0", - "nikic/php-parser": "^4.13", - "openlss/lib-array2xml": "^1.0", - "php": "^7.1|^8", - "sebastian/diff": "^3.0 || ^4.0", - "symfony/console": "^3.4.17 || ^4.1.6 || ^5.0 || ^6.0", - "symfony/polyfill-php80": "^1.25", - "webmozart/path-util": "^2.3" - }, - "provide": { - "psalm/psalm": "self.version" - }, - "require-dev": { - "bamarni/composer-bin-plugin": "^1.2", - "brianium/paratest": "^4.0||^6.0", - "ext-curl": "*", - "php-parallel-lint/php-parallel-lint": "^1.2", - "phpdocumentor/reflection-docblock": "^5", - "phpmyadmin/sql-parser": "5.1.0||dev-master", - "phpspec/prophecy": ">=1.9.0", - "phpunit/phpunit": "^9.0", - "psalm/plugin-phpunit": "^0.16", - "slevomat/coding-standard": "^7.0", - "squizlabs/php_codesniffer": "^3.5", - "symfony/process": "^4.3 || ^5.0 || ^6.0", - "weirdan/prophecy-shim": "^1.0 || ^2.0" - }, - "suggest": { - "ext-curl": "In order to send data to shepherd", - "ext-igbinary": "^2.0.5 is required, used to serialize caching data" - }, - "bin": [ - "psalm", - "psalm-language-server", - "psalm-plugin", - "psalm-refactor", - "psalter" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.x-dev", - "dev-3.x": "3.x-dev", - "dev-2.x": "2.x-dev", - "dev-1.x": "1.x-dev" - } - }, - "autoload": { - "files": [ - "src/functions.php", - "src/spl_object_id.php" - ], - "psr-4": { - "Psalm\\": "src/Psalm/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Matthew Brown" - } - ], - "description": "A static analysis tool for finding errors in PHP applications", - "keywords": [ - "code", - "inspection", - "php" - ], - "support": { - "issues": "https://github.com/vimeo/psalm/issues", - "source": "https://github.com/vimeo/psalm/tree/4.26.0" - }, - "time": "2022-07-31T13:10:26+00:00" - }, - { - "name": "webmozart/assert", - "version": "1.11.0", - "source": { - "type": "git", - "url": "https://github.com/webmozarts/assert.git", - "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991", - "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991", - "shasum": "" - }, - "require": { - "ext-ctype": "*", - "php": "^7.2 || ^8.0" - }, - "conflict": { - "phpstan/phpstan": "<0.12.20", - "vimeo/psalm": "<4.6.1 || 4.6.2" - }, - "require-dev": { - "phpunit/phpunit": "^8.5.13" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.10-dev" - } - }, - "autoload": { - "psr-4": { - "Webmozart\\Assert\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Assertions to validate method input/output with nice error messages.", - "keywords": [ - "assert", - "check", - "validate" - ], - "support": { - "issues": "https://github.com/webmozarts/assert/issues", - "source": "https://github.com/webmozarts/assert/tree/1.11.0" - }, - "time": "2022-06-03T18:03:27+00:00" - }, - { - "name": "webmozart/path-util", - "version": "2.3.0", - "source": { - "type": "git", - "url": "https://github.com/webmozart/path-util.git", - "reference": "d939f7edc24c9a1bb9c0dee5cb05d8e859490725" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/webmozart/path-util/zipball/d939f7edc24c9a1bb9c0dee5cb05d8e859490725", - "reference": "d939f7edc24c9a1bb9c0dee5cb05d8e859490725", - "shasum": "" - }, - "require": { - "php": ">=5.3.3", - "webmozart/assert": "~1.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.6", - "sebastian/version": "^1.0.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.3-dev" - } - }, - "autoload": { - "psr-4": { - "Webmozart\\PathUtil\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "A robust cross-platform utility for normalizing, comparing and modifying file paths.", - "support": { - "issues": "https://github.com/webmozart/path-util/issues", - "source": "https://github.com/webmozart/path-util/tree/2.3.0" - }, - "abandoned": "symfony/filesystem", - "time": "2015-12-17T08:42:14+00:00" - } - ], - "aliases": [], - "minimum-stability": "stable", - "stability-flags": [], - "prefer-stable": false, - "prefer-lowest": false, - "platform": { - "php": "^8.1" - }, - "platform-dev": [], - "plugin-api-version": "2.1.0" -} From ba3387183d522647266ff6349c30b0d1b0ac2687 Mon Sep 17 00:00:00 2001 From: ghlen Date: Fri, 2 Dec 2022 16:27:08 +0530 Subject: [PATCH 13/15] created date time convertible interface --- src/Contract/DateTimeConvertible.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 src/Contract/DateTimeConvertible.php diff --git a/src/Contract/DateTimeConvertible.php b/src/Contract/DateTimeConvertible.php new file mode 100644 index 0000000..8bf2d0c --- /dev/null +++ b/src/Contract/DateTimeConvertible.php @@ -0,0 +1,12 @@ + Date: Fri, 2 Dec 2022 16:36:34 +0530 Subject: [PATCH 14/15] implemented date time convertible where relevant --- src/Type/OGM/Date.php | 9 +++++- src/Type/OGM/DateTime.php | 10 ++++++ src/Type/OGM/DateTimeZoneId.php | 14 ++++++++- src/Type/OGM/LocalDateTime.php | 12 +++++++- src/Type/OGM/LocalTime.php | 54 --------------------------------- 5 files changed, 42 insertions(+), 57 deletions(-) delete mode 100644 src/Type/OGM/LocalTime.php diff --git a/src/Type/OGM/Date.php b/src/Type/OGM/Date.php index c08e0d5..7eb0d29 100644 --- a/src/Type/OGM/Date.php +++ b/src/Type/OGM/Date.php @@ -14,7 +14,9 @@ namespace Syndesi\CypherDataStructures\Type\OGM; use DateTimeImmutable; +use DateTimeInterface; use Exception; +use Syndesi\CypherDataStructures\Contract\DateTimeConvertible; use UnexpectedValueException; /** @@ -26,7 +28,7 @@ * * @psalm-suppress TypeDoesNotContainType */ -final class Date extends AbstractPropertyObject +final class Date extends AbstractPropertyObject implements DateTimeConvertible { public function __construct(private int $days) { @@ -70,4 +72,9 @@ public function getPackstreamMarker(): int { return 0x44; } + + public static function fromDateTime(DateTimeInterface $dateTime): DateTimeConvertible + { + return new self((int) $dateTime->diff((new \DateTime('@0')), true)->format('%a')); + } } diff --git a/src/Type/OGM/DateTime.php b/src/Type/OGM/DateTime.php index 9049400..ab7c8c9 100644 --- a/src/Type/OGM/DateTime.php +++ b/src/Type/OGM/DateTime.php @@ -14,6 +14,7 @@ namespace Syndesi\CypherDataStructures\Type\OGM; use DateTimeImmutable; +use DateTimeInterface; use DateTimeZone; use Exception; use RuntimeException; @@ -98,4 +99,13 @@ public function getPackstreamMarker(): int { return 0x49; } + + public static function fromDateTime(DateTimeInterface $dateTime): self + { + return new self( + $dateTime->getOffset(), + ((int) $dateTime->format('u') * 1000), + $dateTime->getTimezone()->getOffset($dateTime) + ); + } } diff --git a/src/Type/OGM/DateTimeZoneId.php b/src/Type/OGM/DateTimeZoneId.php index aae8194..9d36e30 100644 --- a/src/Type/OGM/DateTimeZoneId.php +++ b/src/Type/OGM/DateTimeZoneId.php @@ -14,8 +14,11 @@ namespace Syndesi\CypherDataStructures\Type\OGM; use DateTimeImmutable; +use DateTimeInterface; use DateTimeZone; use Exception; +use Syndesi\CypherDataStructures\Contract\DateTimeConvertible; + use function sprintf; /** @@ -27,7 +30,7 @@ * * @psalm-suppress TypeDoesNotContainType */ -final class DateTimeZoneId extends AbstractPropertyObject +final class DateTimeZoneId extends AbstractPropertyObject implements DateTimeConvertible { public function __construct(private int $seconds, private int $nanoseconds, private string $tzId) { @@ -98,4 +101,13 @@ public function getPackstreamMarker(): int { return 0x69; } + + public static function fromDateTime(DateTimeInterface $dateTime): self + { + return new self( + $dateTime->getOffset(), + ((int) $dateTime->format('u') * 1000), + $dateTime->getTimezone()->getName() + ); + } } diff --git a/src/Type/OGM/LocalDateTime.php b/src/Type/OGM/LocalDateTime.php index 01dd8d4..b1073c3 100644 --- a/src/Type/OGM/LocalDateTime.php +++ b/src/Type/OGM/LocalDateTime.php @@ -14,7 +14,9 @@ namespace Syndesi\CypherDataStructures\Type\OGM; use DateTimeImmutable; +use DateTimeInterface; use Exception; +use Syndesi\CypherDataStructures\Contract\DateTimeConvertible; use function sprintf; use UnexpectedValueException; @@ -27,7 +29,7 @@ * * @psalm-suppress TypeDoesNotContainType */ -final class LocalDateTime extends AbstractPropertyObject +final class LocalDateTime extends AbstractPropertyObject implements DateTimeConvertible { public function __construct(private int $seconds, private int $nanoseconds) { @@ -83,4 +85,12 @@ public function getPackstreamMarker(): int { return 0x64; } + + public static function fromDateTime(DateTimeInterface $dateTime): DateTimeConvertible + { + return new self( + $dateTime->getOffset(), + ((int) $dateTime->format('u') * 1000) + ); + } } diff --git a/src/Type/OGM/LocalTime.php b/src/Type/OGM/LocalTime.php deleted file mode 100644 index e104b18..0000000 --- a/src/Type/OGM/LocalTime.php +++ /dev/null @@ -1,54 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Syndesi\CypherDataStructures\Type\OGM; - -/** - * The time of day represented in nanoseconds. - * - * @psalm-immutable - * - * @extends AbstractPropertyObject - */ -final class LocalTime extends AbstractPropertyObject -{ - public function __construct(private int $nanoseconds) - { - } - - /** - * The nanoseconds that have passed since midnight. - */ - public function getNanoseconds(): int - { - return $this->nanoseconds; - } - - /** - * @return array{nanoseconds: int} - */ - public function toArray(): array - { - return ['nanoseconds' => $this->nanoseconds]; - } - - public function getProperties(): Dictionary - { - return new Dictionary($this); - } - - public function getPackstreamMarker(): int - { - return 0x74; - } -} From 4a362d5a42959bdbda12889a3576842654182791 Mon Sep 17 00:00:00 2001 From: ghlen Date: Fri, 2 Dec 2022 16:43:08 +0530 Subject: [PATCH 15/15] added list tests --- tests/Type/CypherListTest.php | 472 ++++++++++++++++++++++++++++++++ tests/Type/CypherTypeTest.php | 142 ++++++++++ tests/Type/DictionaryTest.php | 500 ++++++++++++++++++++++++++++++++++ 3 files changed, 1114 insertions(+) create mode 100644 tests/Type/CypherListTest.php create mode 100644 tests/Type/CypherTypeTest.php create mode 100644 tests/Type/DictionaryTest.php diff --git a/tests/Type/CypherListTest.php b/tests/Type/CypherListTest.php new file mode 100644 index 0000000..5047cdd --- /dev/null +++ b/tests/Type/CypherListTest.php @@ -0,0 +1,472 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Syndesi\CypherDataStructures\Tests\Type; + +use function array_sum; +use ArrayIterator; +use BadMethodCallException; +use Generator; +use function hexdec; +use function json_encode; +use Syndesi\CypherDataStructures\Type\Pair; +use Syndesi\CypherDataStructures\Type\OGM\CypherList; +use OutOfBoundsException; +use PHPUnit\Framework\TestCase; +use function range; +use stdClass; + +/** + * @psalm-suppress MixedOperand + * @psalm-suppress MixedAssignment + */ +final class CypherListTest extends TestCase +{ + /** @var CypherList */ + private CypherList $list; + + public function setUp(): void + { + parent::setUp(); + + $this->list = new CypherList(['A', 'B', 'C']); + } + + public function testFromIterableEqual(): void + { + $fromIterable = CypherList::fromIterable($this->list); + + self::assertNotSame($this->list, $fromIterable); + self::assertEquals($this->list->toArray(), $fromIterable->toArray()); + } + + public function testFromIterableArray(): void + { + $fromIterable = CypherList::fromIterable(['A', 'B', 'C']); + + self::assertNotSame($this->list, $fromIterable); + self::assertEquals($this->list, $fromIterable); + } + + public function testFromIterable(): void + { + $fromIterable = CypherList::fromIterable(new ArrayIterator(['A', 'B', 'C'])); + + self::assertNotSame($this->list, $fromIterable); + self::assertEquals($this->list->toArray(), $fromIterable->toArray()); + } + + public function testCount(): void + { + self::assertCount(3, $this->list); + } + + public function testCountEmpty(): void + { + self::assertCount(0, new CypherList()); + } + + public function testCopy(): void + { + $copy = $this->list->copy(); + + self::assertNotSame($this->list, $copy); + self::assertEquals($this->list->toArray(), $copy->toArray()); + } + + public function testCopyDepth(): void + { + $list = new CypherList([new stdClass()]); + $copy = $list->copy(); + + self::assertNotSame($list, $copy); + self::assertEquals($list->toArray(), $copy->toArray()); + self::assertSame($list[0], $copy[0]); + } + + public function testIsEmpty(): void + { + self::assertFalse($this->list->isEmpty()); + } + + public function testIsEmptyEmpty(): void + { + self::assertTrue((new CypherList())->isEmpty()); + } + + public function testToArray(): void + { + self::assertEquals(['A', 'B', 'C'], $this->list->toArray()); + } + + public function testMerge(): void + { + self::assertEquals((new CypherList(['A', 'B', 'C', 'A', 'B', 'C']))->toArray(), $this->list->merge($this->list)->toArray()); + } + + public function testHasKey(): void + { + self::assertFalse($this->list->hasKey(-1)); + self::assertTrue($this->list->hasKey(0)); + self::assertTrue($this->list->hasKey(1)); + self::assertTrue($this->list->hasKey(2)); + self::assertFalse($this->list->hasKey(3)); + } + + public function testFilterPermissive(): void + { + $filter = $this->list->filter(static fn () => true)->toArray(); + + self::assertEquals($this->list->toArray(), $filter); + self::assertNotSame($this->list, $filter); + } + + public function testFilterBlock(): void + { + $filter = $this->list->filter(static fn () => false)->toArray(); + + self::assertEquals([], $filter); + } + + public function testFilterSelective(): void + { + $filter = $this->list->filter(static fn (string $x, int $i) => $x === 'B' || $i === 2)->toArray(); + + self::assertEquals(['B', 'C'], $filter); + } + + public function testMap(): void + { + $filter = $this->list->map(static fn (string $x, int $i) => $i.':'.$x)->toArray(); + + self::assertEquals(['0:A', '1:B', '2:C'], $filter); + } + + public function testReduce(): void + { + $count = $this->list->reduce(static function (?int $initial, string $value, int $key) { + return ($initial ?? 0) + $key * hexdec($value); + }, 5); + + self::assertEquals(5 + hexdec('B') + 2 * hexdec('C'), $count); + } + + public function testFind(): void + { + self::assertFalse($this->list->find('X')); + self::assertEquals(0, $this->list->find('A')); + self::assertEquals(1, $this->list->find('B')); + self::assertEquals(2, $this->list->find('C')); + } + + public function testReversed(): void + { + self::assertEquals(['C', 'B', 'A'], $this->list->reversed()->toArray()); + self::assertEquals(['A', 'B', 'C'], $this->list->toArray()); + self::assertEquals(['A', 'B', 'C'], $this->list->reversed()->reversed()->toArray()); + } + + public function testSliceSingle(): void + { + $sliced = $this->list->slice(1, 1); + self::assertEquals(['B'], $sliced->toArray()); + } + + public function testSliceDouble(): void + { + $sliced = $this->list->slice(1, 2); + self::assertEquals(['B', 'C'], $sliced->toArray()); + } + + public function testSliceAll(): void + { + $sliced = $this->list->slice(0, 3); + self::assertEquals(['A', 'B', 'C'], $sliced->toArray()); + } + + public function testSliceTooMuch(): void + { + $sliced = $this->list->slice(0, 5); + self::assertEquals(['A', 'B', 'C'], $sliced->toArray()); + } + + public function testSliceEmpty(): void + { + $sliced = $this->list->slice(0, 0); + self::assertEquals([], $sliced->toArray()); + } + + public function testGetValid(): void + { + self::assertEquals('A', $this->list->get(0)); + self::assertEquals('B', $this->list->get(1)); + self::assertEquals('C', $this->list->get(2)); + } + + public function testFirst(): void + { + self::assertEquals('A', $this->list->first()); + } + + public function testFirstInvalid(): void + { + $this->expectException(OutOfBoundsException::class); + $this->expectExceptionMessage('Cannot grab first element of an empty list'); + (new CypherList())->first(); + } + + public function testLast(): void + { + self::assertEquals('C', $this->list->last()); + } + + public function testLastInvalid(): void + { + $this->expectException(OutOfBoundsException::class); + $this->expectExceptionMessage('Cannot grab last element of an empty list'); + (new CypherList())->last(); + } + + public function testGetInvalid(): void + { + $this->expectException(OutOfBoundsException::class); + $this->expectExceptionMessage('Offset: "3" does not exists in object of instance: Laudis\Neo4j\Types\CypherList'); + $this->list->get(3); + } + + public function testGetNegative(): void + { + $this->expectException(OutOfBoundsException::class); + $this->expectExceptionMessage('Offset: "-1" does not exists in object of instance: Laudis\Neo4j\Types\CypherList'); + $this->list->get(-1); + } + + public function testIteration(): void + { + $counter = 0; + foreach ($this->list as $key => $item) { + ++$counter; + self::assertEquals(['A', 'B', 'C'][$key], $item); + } + self::assertEquals(3, $counter); + } + + public function testIterationEmpty(): void + { + $counter = 0; + foreach ((new CypherList()) as $key => $item) { + ++$counter; + self::assertEquals(['A', 'B', 'C'][$key], $item); + } + self::assertEquals(0, $counter); + } + + public function testOffsetSet(): void + { + $this->expectException(BadMethodCallException::class); + $this->expectExceptionMessage('Laudis\Neo4j\Types\CypherList is immutable'); + + $this->list[0] = 'a'; + } + + public function testOffsetUnset(): void + { + $this->expectException(BadMethodCallException::class); + $this->expectExceptionMessage('Laudis\Neo4j\Types\CypherList is immutable'); + + unset($this->list[0]); + } + + public function testOffsetGetValid(): void + { + self::assertEquals('A', $this->list[0]); + self::assertEquals('B', $this->list[1]); + self::assertEquals('C', $this->list[2]); + } + + public function testOffsetGetInvalid(): void + { + $this->expectException(OutOfBoundsException::class); + $this->expectExceptionMessage('Offset: "3" does not exists in object of instance: Laudis\Neo4j\Types\CypherList'); + $this->list[3]; + } + + public function testOffsetGetNegative(): void + { + $this->expectException(OutOfBoundsException::class); + $this->expectExceptionMessage('Offset: "-1" does not exists in object of instance: Laudis\Neo4j\Types\CypherList'); + $this->list[-1]; + } + + public function testIssetValid(): void + { + self::assertTrue(isset($this->list[0])); + self::assertTrue(isset($this->list[1])); + self::assertTrue(isset($this->list[2])); + } + + public function testIssetInValid(): void + { + self::assertFalse(isset($this->list[-1])); + self::assertFalse(isset($this->list[3])); + } + + public function testIssetValidNull(): void + { + self::assertTrue(isset((new CypherList([null]))[0])); + } + + public function testJsonSerialize(): void + { + self::assertEquals('["A","B","C"]', json_encode($this->list, JSON_THROW_ON_ERROR)); + } + + public function testJsonSerializeEmpty(): void + { + self::assertEquals('[]', json_encode(new CypherList(), JSON_THROW_ON_ERROR)); + } + + public function testJoin(): void + { + self::assertEquals('A;B;C', $this->list->join(';')); + } + + public function testJoinEmpty(): void + { + self::assertEquals('', (new CypherList())->join('A')); + } + + public function testSortedDefault(): void + { + self::assertEquals($this->list->toArray(), $this->list->sorted()->toArray()); + self::assertEquals($this->list->toArray(), $this->list->reversed()->sorted()->toArray()); + } + + public function testSortedCustom(): void + { + $sorted = $this->list->sorted(static fn (string $x, string $y): int => -1 * ($x <=> $y)); + + self::assertEquals(['C', 'B', 'A'], $sorted->toArray()); + self::assertEquals(['A', 'B', 'C'], $this->list->toArray()); + } + + public function testEach(): void + { + $cntr = -1; + /** @psalm-suppress UnusedClosureParam */ + $this->list->each(static function (string $x, int $key) use (&$cntr) { $cntr = $key; }); + + self::assertEquals($this->list->count() - 1, $cntr); + } + + public function testMapTypings(): void + { + $map = CypherList::fromIterable(['a', 'b', 'c']) + ->map(static function (string $value, int $key): stdClass { + $tbr = new stdClass(); + + $tbr->key = $key; + $tbr->value = $value; + + return $tbr; + }) + ->map(static function (stdClass $class) { + return (string) $class->value; + }) + ->toArray(); + + self::assertEquals(['a', 'b', 'c'], $map); + } + + public function testKeyBy(): void + { + $object = new stdClass(); + $object->x = 'stdClassX'; + $object->y = 'wrong'; + $list = CypherList::fromIterable([ + 1, + $object, + ['x' => 'arrayX', 'y' => 'wrong'], + 'wrong', + ])->pluck('x'); + + self::assertEquals(['stdClassX', 'arrayX'], $list->toArray()); + } + + public function testCombined(): void + { + $i = 0; + $list = CypherList::fromIterable([0, 1, 2, 3])->map(static function ($x) use (&$i) { + ++$i; + + return $x; + }); + + /** @var int $i */ + self::assertEquals(0, $i); + + $pairs = $list->map(static fn ($x, $index): Pair => new Pair($index, $x)); + self::assertEquals(0, $i); + + self::assertCount(4, $pairs); + self::assertEquals(4, $i); + + self::assertCount(4, $list); + self::assertEquals(4, $i); + } + + public function testSlice(): void + { + $sumBefore = 0; + $sumAfter = 0; + $range = CypherList::fromIterable($this->infiniteIterator()) + ->map(static function ($x) use (&$sumBefore) { + $sumBefore += $x; + + return $x; + }) + ->slice(5, 3) + ->map(static function ($x) use (&$sumAfter) { + $sumAfter += $x; + + return $x; + }); + + /** @var int $sumBefore */ + /** @var int $sumAfter */ + $start = $range->get(0); + + self::assertEquals(5, $start); + + self::assertEquals(array_sum(range(0, 5)), $sumBefore); + self::assertEquals(5, $sumAfter); + + $end = $range->get(2); + + self::assertEquals(7, $end); + self::assertEquals(array_sum(range(0, 7)), $sumBefore); + self::assertEquals(array_sum(range(5, 7)), $sumAfter); + } + + /** + * @return Generator + */ + private function infiniteIterator(): Generator + { + $i = 0; + while (true) { + yield $i; + ++$i; + } + } +} diff --git a/tests/Type/CypherTypeTest.php b/tests/Type/CypherTypeTest.php new file mode 100644 index 0000000..48eed4c --- /dev/null +++ b/tests/Type/CypherTypeTest.php @@ -0,0 +1,142 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Syndesi\CypherDataStructures\Tests\Type; + +use BadMethodCallException; +use function json_encode; +use JsonException; +use Syndesi\CypherDataStructures\Type\OGM\AbstractCypherObject; +use OutOfBoundsException; +use PHPUnit\Framework\TestCase; + +/** + * @extends AbstractCypherObject + * @psalm-immutable + */ +final class BogusCypherObject extends AbstractCypherObject +{ + public function toArray(): array + { + return []; + } + + public function getPackstreamMarker(): int + { + return 0x0; + } +} + +/** + * @extends AbstractCypherObject + * @psalm-immutable + */ +final class BogusCypherObjectFilled extends AbstractCypherObject +{ + public function toArray(): array + { + return [ + 'a' => 'b', + 'c' => 'd', + ]; + } + + public function getPackstreamMarker(): int + { + return 0x0; + } +} + +final class CypherTypeTest extends TestCase +{ + /** + * @throws JsonException + * + * @psalm-suppress all + */ + public function testEmpty(): void + { + $empty = new BogusCypherObject(); + + self::assertEquals('[]', json_encode($empty, JSON_THROW_ON_ERROR)); + self::assertFalse(isset($empty[0])); + self::assertNull($empty[0] ?? null); + + $caught = null; + try { + $empty[0] = 'abc'; + } catch (BadMethodCallException $e) { + $caught = true; + } + self::assertTrue($caught, 'Empty is writable'); + + $caught = null; + try { + unset($empty[0]); + } catch (BadMethodCallException $e) { + $caught = true; + } + self::assertTrue($caught, 'Empty is writable'); + + $caught = null; + try { + $empty[0]; + } catch (OutOfBoundsException $e) { + $caught = true; + } + self::assertTrue($caught, 'Empty has still valid access'); + } + + /** + * @throws JsonException + * + * @psalm-suppress all + */ + public function testFilled(): void + { + $filled = new BogusCypherObjectFilled(); + + self::assertEquals('{"a":"b","c":"d"}', json_encode($filled, JSON_THROW_ON_ERROR)); + + self::assertFalse(isset($filled[0])); + self::assertNull($filled[0] ?? null); + + self::assertTrue(isset($filled['a'])); + self::assertTrue(isset($filled['c'])); + self::assertEquals('b', $filled['a']); + self::assertEquals('d', $filled['c']); + + $caught = null; + try { + $filled[0] = 'abc'; + } catch (BadMethodCallException $e) { + $caught = true; + } + self::assertTrue($caught, 'Filled is writable'); + $caught = null; + try { + unset($filled[0]); + } catch (BadMethodCallException $e) { + $caught = true; + } + self::assertTrue($caught, 'Filled is writable'); + + $caught = null; + try { + $filled[0]; + } catch (OutOfBoundsException $e) { + $caught = true; + } + self::assertTrue($caught, 'Filled has still valid access'); + } +} diff --git a/tests/Type/DictionaryTest.php b/tests/Type/DictionaryTest.php new file mode 100644 index 0000000..708e329 --- /dev/null +++ b/tests/Type/DictionaryTest.php @@ -0,0 +1,500 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Syndesi\CypherDataStructures\Tests\Type; + +use ArrayIterator; +use BadMethodCallException; +use Generator; +use IteratorAggregate; +use function json_encode; +use const JSON_THROW_ON_ERROR; +use Syndesi\CypherDataStructures\Type\Pair; +use Syndesi\CypherDataStructures\Exception\RuntimeTypeException; +use Syndesi\CypherDataStructures\Type\ArrayList; +use Syndesi\CypherDataStructures\Type\OGM\Dictionary; +use OutOfBoundsException; +use PHPUnit\Framework\TestCase; +use stdClass; + +final class DictionaryTest extends TestCase +{ + /** @var Dictionary */ + private Dictionary $map; + + public function setUp(): void + { + parent::setUp(); + + $this->map = new Dictionary(['A' => 'x', 'B' => 'y', 'C' => 'z']); + } + + public function testFromIterableEqual(): void + { + $fromIterable = Dictionary::fromIterable($this->map); + + self::assertNotSame($this->map, $fromIterable); + self::assertEquals($this->map->toArray(), $fromIterable->toArray()); + } + + public function testFromIterableArray(): void + { + $fromIterable = Dictionary::fromIterable(['A' => 'x', 'B' => 'y', 'C' => 'z']); + + self::assertNotSame($this->map, $fromIterable); + self::assertEquals($this->map->toArray(), $fromIterable->toArray()); + } + + public function testFromIterable(): void + { + $fromIterable = Dictionary::fromIterable(new ArrayIterator(['A' => 'x', 'B' => 'y', 'C' => 'z'])); + + self::assertNotSame($this->map, $fromIterable); + self::assertEquals($this->map->toArray(), $fromIterable->toArray()); + } + + public function testCount(): void + { + self::assertCount(3, $this->map); + } + + public function testCountEmpty(): void + { + self::assertCount(0, new Dictionary()); + } + + public function testCopy(): void + { + $copy = $this->map->copy(); + + self::assertNotSame($this->map, $copy); + self::assertEquals($this->map->toArray(), $copy->toArray()); + } + + public function testCopyDepth(): void + { + $list = new Dictionary(['A' => new stdClass()]); + $copy = $list->copy(); + + self::assertNotSame($list, $copy); + self::assertEquals($list->toArray(), $copy->toArray()); + self::assertSame($list['A'], $copy['A']); + } + + public function testIsEmpty(): void + { + self::assertFalse($this->map->isEmpty()); + } + + public function testIsEmptyEmpty(): void + { + self::assertTrue((new Dictionary())->isEmpty()); + } + + public function testToArray(): void + { + self::assertEquals(['A' => 'x', 'B' => 'y', 'C' => 'z'], $this->map->toArray()); + } + + public function testMerge(): void + { + self::assertEquals(['A' => 'x', 'B' => 'y', 'C' => 'z'], $this->map->merge($this->map)->toArray()); + } + + public function testMergeDifferent(): void + { + $merged = $this->map->merge(['B' => 'yy', 'C' => 'z', 'D' => 'e']); + self::assertEquals(['A' => 'x', 'B' => 'yy', 'C' => 'z', 'D' => 'e'], $merged->toArray()); + } + + public function testHasKey(): void + { + self::assertTrue($this->map->hasKey('A')); + self::assertTrue($this->map->hasKey('B')); + self::assertTrue($this->map->hasKey('C')); + self::assertFalse($this->map->hasKey('E')); + self::assertFalse($this->map->hasKey('a')); + } + + public function testFilterPermissive(): void + { + $filter = $this->map->filter(static fn () => true); + + self::assertEquals($this->map->toArray(), $filter->toArray()); + self::assertNotSame($this->map, $filter); + } + + public function testFilterBlock(): void + { + $filter = $this->map->filter(static fn () => false); + + self::assertEquals([], $filter->toArray()); + } + + public function testFilterSelective(): void + { + $filter = $this->map->filter(static fn (string $x, string $i) => !($i === 'B' || $x === 'z')); + + self::assertEquals(['A' => 'x'], $filter->toArray()); + } + + public function testMap(): void + { + $filter = $this->map->map(static fn (string $x, string $i) => $i.':'.$x); + + self::assertEquals(['A' => 'A:x', 'B' => 'B:y', 'C' => 'C:z'], $filter->toArray()); + } + + public function testReduce(): void + { + $count = $this->map->reduce(static function (?int $initial, string $key, string $value) { + return ($initial ?? 0) + ord($value) + ord($key); + }, 5); + + self::assertEquals(5 + ord('A') + ord('x') + ord('B') + ord('y') + ord('C') + ord('z'), $count); + } + + public function testFind(): void + { + self::assertFalse($this->map->find('A')); + self::assertFalse($this->map->find('X')); + self::assertEquals('C', $this->map->find('z')); + self::assertEquals('B', $this->map->find('y')); + self::assertEquals('A', $this->map->find('x')); + } + + public function testReversed(): void + { + self::assertEquals(['C' => 'z', 'B' => 'y', 'A' => 'x'], $this->map->reversed()->toArray()); + self::assertEquals(['A' => 'x', 'B' => 'y', 'C' => 'z'], $this->map->toArray()); + self::assertEquals(['A' => 'x', 'B' => 'y', 'C' => 'z'], $this->map->reversed()->reversed()->toArray()); + } + + public function testSliceSingle(): void + { + $sliced = $this->map->slice(1, 1); + self::assertEquals(['B' => 'y'], $sliced->toArray()); + } + + public function testSliceDouble(): void + { + $sliced = $this->map->slice(1, 2); + self::assertEquals(['B' => 'y', 'C' => 'z'], $sliced->toArray()); + } + + public function testSliceAll(): void + { + $sliced = $this->map->slice(0, 3)->toArray(); + self::assertEquals($this->map->toArray(), $sliced); + } + + public function testSliceTooMuch(): void + { + $sliced = $this->map->slice(0, 5); + self::assertEquals($this->map->toArray(), $sliced->toArray()); + } + + public function testSliceEmpty(): void + { + $sliced = $this->map->slice(0, 0); + self::assertEquals([], $sliced->toArray()); + } + + public function testGetValid(): void + { + self::assertEquals('x', $this->map->get('A')); + self::assertEquals('y', $this->map->get('B')); + self::assertEquals('z', $this->map->get('C')); + } + + public function testGetDefault(): void + { + self::assertEquals('x', $this->map->get('A', null)); + self::assertNull($this->map->get('x', null)); + self::assertEquals(new stdClass(), $this->map->get('Cd', new stdClass())); + } + + public function testFirst(): void + { + self::assertEquals(new Pair('A', 'x'), $this->map->first()); + } + + public function testFirstInvalid(): void + { + $this->expectException(OutOfBoundsException::class); + $this->expectExceptionMessage('Cannot grab first element of an empty map'); + (new Dictionary())->first(); + } + + public function testLast(): void + { + self::assertEquals(new Pair('C', 'z'), $this->map->last()); + } + + public function testLastInvalid(): void + { + $this->expectException(OutOfBoundsException::class); + $this->expectExceptionMessage('Cannot grab last element of an empty map'); + (new Dictionary())->last(); + } + + public function testGetInvalid(): void + { + $this->expectException(OutOfBoundsException::class); + $this->expectExceptionMessage('Cannot get item in sequence with key: a'); + $this->map->get('a'); + } + + public function testIteration(): void + { + $counter = 0; + foreach ($this->map as $key => $item) { + ++$counter; + self::assertEquals(['A' => 'x', 'B' => 'y', 'C' => 'z'][$key], $item); + } + self::assertEquals(3, $counter); + } + + public function testIterationEmpty(): void + { + $counter = 0; + foreach ((new Dictionary()) as $key => $item) { + ++$counter; + self::assertEquals(['A' => 'x'][$key], $item); + } + self::assertEquals(0, $counter); + } + + public function testOffsetSet(): void + { + $this->expectException(BadMethodCallException::class); + $this->expectExceptionMessage('Laudis\Neo4j\Types\Dictionary is immutable'); + + $this->map['A'] = 'a'; + } + + public function testOffsetUnset(): void + { + $this->expectException(BadMethodCallException::class); + $this->expectExceptionMessage('Laudis\Neo4j\Types\Dictionary is immutable'); + + unset($this->map['A']); + } + + public function testOffsetGetValid(): void + { + self::assertEquals('x', $this->map['A']); + self::assertEquals('y', $this->map['B']); + self::assertEquals('z', $this->map['C']); + } + + public function testOffsetGetInvalid(): void + { + $this->expectException(OutOfBoundsException::class); + $this->expectExceptionMessage('Offset: "AA" does not exists in object of instance: Laudis\Neo4j\Types\Dictionary'); + $this->map['AA']; + } + + public function testIssetValid(): void + { + self::assertTrue(isset($this->map['A'])); + self::assertTrue(isset($this->map['B'])); + self::assertTrue(isset($this->map['C'])); + } + + public function testIssetInValid(): void + { + self::assertFalse(isset($this->map['a'])); + } + + public function testIssetValidNull(): void + { + self::assertTrue(isset((new Dictionary(['a' => null]))['a'])); + } + + public function testJsonSerialize(): void + { + self::assertEquals('{"A":"x","B":"y","C":"z"}', json_encode($this->map, JSON_THROW_ON_ERROR)); + } + + public function testJsonSerializeEmpty(): void + { + self::assertEquals('{}', json_encode(new Dictionary(), JSON_THROW_ON_ERROR)); + } + + public function testJoin(): void + { + self::assertEquals('x;y;z', $this->map->join(';')); + } + + public function testJoinEmpty(): void + { + self::assertEquals('', (new Dictionary())->join('A')); + } + + public function testDiff(): void + { + $subtract = new Dictionary(['B' => 'x', 'Z' => 'z']); + $result = $this->map->diff($subtract); + + self::assertEquals(['A' => 'x', 'C' => 'z'], $result->toArray()); + self::assertEquals(['B' => 'x', 'Z' => 'z'], $subtract->toArray()); + self::assertEquals(['A' => 'x', 'B' => 'y', 'C' => 'z'], $this->map->toArray()); + } + + public function testDiffEmpty(): void + { + self::assertEquals(['A' => 'x', 'B' => 'y', 'C' => 'z'], $this->map->diff([])->toArray()); + } + + public function testIntersect(): void + { + $intersect = new Dictionary(['B' => 'x', 'Z' => 'z']); + $result = $this->map->intersect($intersect); + + self::assertEquals(['B' => 'y'], $result->toArray()); + self::assertEquals(['B' => 'x', 'Z' => 'z'], $intersect->toArray()); + self::assertEquals(['A' => 'x', 'B' => 'y', 'C' => 'z'], $this->map->toArray()); + } + + public function testUnion(): void + { + $intersect = new Dictionary(['B' => 'x', 'Z' => 'z']); + $result = $this->map->union($intersect); + + self::assertEquals(['A' => 'x', 'B' => 'y', 'C' => 'z', 'Z' => 'z'], $result->toArray()); + self::assertEquals(['B' => 'x', 'Z' => 'z'], $intersect->toArray()); + self::assertEquals(['A' => 'x', 'B' => 'y', 'C' => 'z'], $this->map->toArray()); + } + + public function testXor(): void + { + $intersect = new Dictionary(['B' => 'x', 'Z' => 'z']); + $result = $this->map->xor($intersect); + + self::assertEquals(['A' => 'x', 'C' => 'z', 'Z' => 'z'], $result->toArray()); + self::assertEquals(['B' => 'x', 'Z' => 'z'], $intersect->toArray()); + self::assertEquals(['A' => 'x', 'B' => 'y', 'C' => 'z'], $this->map->toArray()); + } + + public function testValue(): void + { + self::assertEquals(['x', 'y', 'z'], $this->map->values()->toArray()); + } + + public function testKeys(): void + { + self::assertEquals(['A', 'B', 'C'], $this->map->keys()->toArray()); + } + + public function testPairs(): void + { + $list = new ArrayList([new Pair('A', 'x'), new Pair('B', 'y'), new Pair('C', 'z')]); + self::assertEquals($list->toArray(), $this->map->pairs()->toArray()); + } + + public function testSkip(): void + { + self::assertEquals(new Pair('A', 'x'), $this->map->skip(0)); + self::assertEquals(new Pair('B', 'y'), $this->map->skip(1)); + self::assertEquals(new Pair('C', 'z'), $this->map->skip(2)); + } + + public function testSkipInvalid(): void + { + $this->expectException(OutOfBoundsException::class); + $this->expectExceptionMessage('Cannot skip to a pair at position: 4'); + self::assertEquals(new Pair('A', 'x'), $this->map->skip(4)); + } + + public function testInvalidConstruct(): void + { + $map = new Dictionary(new class() implements IteratorAggregate { + public function getIterator(): Generator + { + yield new stdClass() => 'x'; + } + }); + + self::assertEquals(Dictionary::fromIterable(['0' => 'x'])->toArray(), $map->toArray()); + } + + public function testSortedDefault(): void + { + self::assertEquals($this->map->toArray(), $this->map->sorted()->toArray()); + self::assertEquals($this->map->toArray(), $this->map->reversed()->sorted()->toArray()); + } + + public function testSortedCustom(): void + { + $sorted = $this->map->sorted(static fn (string $x, string $y): int => -1 * ($x <=> $y)); + + self::assertEquals(['C' => 'z', 'B' => 'y', 'A' => 'x'], $sorted->toArray()); + self::assertEquals(['A' => 'x', 'B' => 'y', 'C' => 'z'], $this->map->toArray()); + } + + public function testKSorted(): void + { + self::assertEquals($this->map->toArray(), $this->map->ksorted()->toArray()); + self::assertEquals($this->map->toArray(), $this->map->reversed()->ksorted()->toArray()); + } + + public function testKSortedCustom(): void + { + $sorted = $this->map->ksorted(static fn (string $x, string $y) => -1 * ($x <=> $y)); + + self::assertEquals(['C' => 'z', 'B' => 'y', 'A' => 'x'], $sorted->toArray()); + self::assertEquals(['A' => 'x', 'B' => 'y', 'C' => 'z'], $this->map->toArray()); + } + + public function testCasts(): void + { + $map = new Dictionary(['a' => null]); + + self::assertEquals('', $map->getAsString('a')); + + $this->expectException(RuntimeTypeException::class); + $map->getAsCartesian3DPoint('a'); + } + + public function getMap(): void + { + $map = Dictionary::fromIterable(['a' => 'b', 'c' => 'd']) + ->map(static function (string $value, string $key) { + $tbr = new stdClass(); + + $tbr->key = $key; + $tbr->value = $value; + + return $tbr; + }) + ->map(static function (stdClass $class) { + return (string) $class->value; + }); + + self::assertEquals(Dictionary::fromIterable(['a' => 'b', 'c' => 'd']), $map); + } + + public function testKeyBy(): void + { + $object = new stdClass(); + $object->x = 'stdClassX'; + $object->y = 'wrong'; + $list = Dictionary::fromIterable([ + 'w' => 1, + 'x' => $object, + 'y' => ['x' => 'arrayX', 'y' => 'wrong'], + 'z' => 'wrong', + ])->pluck('x'); + + self::assertEquals(['stdClassX', 'arrayX'], $list->toArray()); + } +}