From 356d911c3a777d938f3eda107303ab4cb2621dc6 Mon Sep 17 00:00:00 2001 From: r3hp1c Date: Sat, 2 Mar 2024 20:08:49 +0000 Subject: [PATCH 01/44] Proposal for verion 6.0.0 --- .github/workflows/ci.yml | 16 +- composer.json | 9 +- demo/composer.json | 8 +- demo/symfony5.4/composer.json | 2 +- demo/symfony5.4/config/bundles.php | 2 +- .../packages/ambta_doctrine_encrypt.yaml | 3 - .../config/packages/doctrine_encrypt.yaml | 3 + .../src/Entity/Annotation/Secret.php | 4 +- .../src/Entity/Attribute/Secret.php | 4 +- demo/symfony5.4/tests/SecretTest.php | 4 +- demo/symfony6.x/composer.json | 2 +- demo/symfony6.x/config/bundles.php | 2 +- .../packages/ambta_doctrine_encrypt.yaml | 3 - .../config/packages/doctrine_encrypt.yaml | 3 + .../src/Entity/Annotation/Secret.php | 4 +- .../src/Entity/Attribute/Secret.php | 4 +- demo/symfony6.x/tests/SecretTest.php | 4 +- demo/symfony7.x/composer.lock | 4 +- demo/symfony7.x/config/bundles.php | 2 +- .../packages/ambta_doctrine_encrypt.yaml | 3 - .../config/packages/doctrine_encrypt.yaml | 3 + demo/symfony7.x/phpunit.xml.dist | 3 - .../src/Entity/Attribute/Secret.php | 4 +- demo/symfony7.x/tests/SecretTest.php | 4 +- demo/symfony7.x_doctrine3.x/.env | 31 ++ demo/symfony7.x_doctrine3.x/.gitignore | 22 + demo/symfony7.x_doctrine3.x/README.md | 28 ++ demo/symfony7.x_doctrine3.x/bin/console | 17 + demo/symfony7.x_doctrine3.x/bin/phpunit | 23 + demo/symfony7.x_doctrine3.x/composer.json | 78 ++++ .../symfony7.x_doctrine3.x/config/bundles.php | 8 + .../config/packages/cache.yaml | 19 + .../config/packages/doctrine.yaml | 43 ++ .../config/packages/doctrine_encrypt.yaml | 3 + .../config/packages/framework.yaml | 23 + .../config/packages/routing.yaml | 12 + .../config/packages/twig.yaml | 8 + .../symfony7.x_doctrine3.x/config/preload.php | 5 + .../symfony7.x_doctrine3.x/config/routes.yaml | 5 + .../config/routes/annotations.yaml | 9 + .../config/routes/framework.yaml | 4 + .../config/services.yaml | 24 ++ demo/symfony7.x_doctrine3.x/public/index.php | 9 + .../src/Controller/.gitignore | 0 .../src/Controller/DefaultController.php | 44 ++ .../src/Entity/.gitignore | 0 .../src/Entity/Attribute/Secret.php | 92 ++++ .../src/Entity/SecretInterface.php | 11 + demo/symfony7.x_doctrine3.x/src/Kernel.php | 11 + .../src/Repository/.gitignore | 0 .../Repository/AbstractSecretRepository.php | 29 ++ .../Repository/Attribute/SecretRepository.php | 56 +++ demo/symfony7.x_doctrine3.x/symfony.lock | 112 +++++ .../tests/SecretTest.php | 68 +++ .../tests/bootstrap.php | 11 + phpunit.xml.dist | 1 - src/AmbtaDoctrineEncryptBundle.php | 17 - src/Command/AbstractCommand.php | 86 +--- .../DoctrineDecryptDatabaseCommand.php | 105 ++--- .../DoctrineEncryptDatabaseCommand.php | 87 +++- src/Command/DoctrineEncryptStatusCommand.php | 29 +- src/Configuration/Annotation.php | 12 - src/Configuration/Encrypted.php | 45 -- src/DependencyInjection/Configuration.php | 11 +- .../DoctrineEncryptExtension.php | 30 +- src/DoctrineEncryptBundle.php | 53 +++ src/Encryptors/DefuseEncryptor.php | 6 +- src/Encryptors/EncryptorInterface.php | 4 +- src/Encryptors/HaliteEncryptor.php | 13 +- src/Factories/SecretFactory.php | 8 +- src/Mapping/AttributeAnnotationReader.php | 114 ----- src/Mapping/AttributeReader.php | 102 ----- .../service_listeners_with_attributes.yml | 15 - src/Resources/config/services.yml | 27 +- .../services_subscriber_with_annotations.yml | 9 - ...criber_with_annotations_and_attributes.yml | 13 - src/Resources/config/services_with_secret.yml | 6 +- .../config/services_with_secretfactory.yml | 14 +- src/Resources/doc/usage.md | 75 ---- src/Service/Encrypt.php | 123 ++++++ src/Subscribers/DoctrineEncryptSubscriber.php | 401 ------------------ src/Traits/DoctrineEncrypt.php | 23 + src/Types/Encrypted.php | 29 ++ src/Types/EncryptedArray.php | 29 ++ src/Types/EncryptedDateTime.php | 29 ++ src/Types/EncryptedJSON.php | 29 ++ tests/DoctrineCompatibilityTrait.php | 20 +- .../Functional/AbstractFunctionalTestCase.php | 142 +++---- .../AbstractBasicQueryTestCase.php | 168 ++++++-- .../BasicQueryTest/BasicQueryDefuseTest.php | 6 +- .../BasicQueryTest/BasicQueryHaliteTest.php | 6 +- ...bstractDoctrineEncryptServiceTestCase.php} | 124 +----- .../DoctrineEncryptServiceDefuseTest.php | 14 + .../DoctrineEncryptServiceHaliteTest.php} | 8 +- .../DoctrineEncryptSubscriberDefuseTest.php | 14 - .../fixtures/Entity/AbstractVehicle.php | 28 +- .../fixtures/Entity/CascadeTarget.php | 23 +- .../fixtures/Entity/CascadeTargetArray.php | 63 +++ .../fixtures/Entity/CascadeTargetDateTime.php | 63 +++ .../fixtures/Entity/CascadeTargetJSON.php | 63 +++ .../Entity/CascadeTargetStrtoupper.php | 30 +- .../Entity/ClassTableInheritanceBase.php | 25 +- .../Entity/ClassTableInheritanceChild.php | 14 +- .../Entity/DateTimeJsonArrayTarget.php | 94 ---- tests/Functional/fixtures/Entity/Owner.php | 34 +- .../fixtures/Entity/VehicleBicycle.php | 8 +- .../Functional/fixtures/Entity/VehicleCar.php | 8 +- .../DoctrineEncryptExtensionTest.php | 34 +- tests/Unit/Encryptors/DefuseEncryptorTest.php | 4 +- tests/Unit/Encryptors/HaliteEncryptorTest.php | 4 +- .../Service/DoctrineEncryptServiceTest.php | 124 ++++++ .../DoctrineEncryptSubscriberTest.php | 358 ---------------- .../Subscribers/fixtures/ExtendedUser.php | 20 - tests/Unit/Subscribers/fixtures/User.php | 36 -- tests/Unit/Subscribers/fixtures/WithUser.php | 33 -- tests/bootstrap.php | 4 - 116 files changed, 1989 insertions(+), 2033 deletions(-) delete mode 100644 demo/symfony5.4/config/packages/ambta_doctrine_encrypt.yaml create mode 100644 demo/symfony5.4/config/packages/doctrine_encrypt.yaml delete mode 100644 demo/symfony6.x/config/packages/ambta_doctrine_encrypt.yaml create mode 100644 demo/symfony6.x/config/packages/doctrine_encrypt.yaml delete mode 100644 demo/symfony7.x/config/packages/ambta_doctrine_encrypt.yaml create mode 100644 demo/symfony7.x/config/packages/doctrine_encrypt.yaml create mode 100644 demo/symfony7.x_doctrine3.x/.env create mode 100644 demo/symfony7.x_doctrine3.x/.gitignore create mode 100644 demo/symfony7.x_doctrine3.x/README.md create mode 100755 demo/symfony7.x_doctrine3.x/bin/console create mode 100755 demo/symfony7.x_doctrine3.x/bin/phpunit create mode 100644 demo/symfony7.x_doctrine3.x/composer.json create mode 100644 demo/symfony7.x_doctrine3.x/config/bundles.php create mode 100644 demo/symfony7.x_doctrine3.x/config/packages/cache.yaml create mode 100644 demo/symfony7.x_doctrine3.x/config/packages/doctrine.yaml create mode 100644 demo/symfony7.x_doctrine3.x/config/packages/doctrine_encrypt.yaml create mode 100644 demo/symfony7.x_doctrine3.x/config/packages/framework.yaml create mode 100644 demo/symfony7.x_doctrine3.x/config/packages/routing.yaml create mode 100644 demo/symfony7.x_doctrine3.x/config/packages/twig.yaml create mode 100644 demo/symfony7.x_doctrine3.x/config/preload.php create mode 100644 demo/symfony7.x_doctrine3.x/config/routes.yaml create mode 100644 demo/symfony7.x_doctrine3.x/config/routes/annotations.yaml create mode 100644 demo/symfony7.x_doctrine3.x/config/routes/framework.yaml create mode 100644 demo/symfony7.x_doctrine3.x/config/services.yaml create mode 100644 demo/symfony7.x_doctrine3.x/public/index.php create mode 100644 demo/symfony7.x_doctrine3.x/src/Controller/.gitignore create mode 100644 demo/symfony7.x_doctrine3.x/src/Controller/DefaultController.php create mode 100644 demo/symfony7.x_doctrine3.x/src/Entity/.gitignore create mode 100644 demo/symfony7.x_doctrine3.x/src/Entity/Attribute/Secret.php create mode 100644 demo/symfony7.x_doctrine3.x/src/Entity/SecretInterface.php create mode 100644 demo/symfony7.x_doctrine3.x/src/Kernel.php create mode 100644 demo/symfony7.x_doctrine3.x/src/Repository/.gitignore create mode 100644 demo/symfony7.x_doctrine3.x/src/Repository/AbstractSecretRepository.php create mode 100644 demo/symfony7.x_doctrine3.x/src/Repository/Attribute/SecretRepository.php create mode 100644 demo/symfony7.x_doctrine3.x/symfony.lock create mode 100644 demo/symfony7.x_doctrine3.x/tests/SecretTest.php create mode 100644 demo/symfony7.x_doctrine3.x/tests/bootstrap.php delete mode 100644 src/AmbtaDoctrineEncryptBundle.php delete mode 100644 src/Configuration/Annotation.php delete mode 100644 src/Configuration/Encrypted.php create mode 100644 src/DoctrineEncryptBundle.php delete mode 100644 src/Mapping/AttributeAnnotationReader.php delete mode 100644 src/Mapping/AttributeReader.php delete mode 100644 src/Resources/config/service_listeners_with_attributes.yml delete mode 100644 src/Resources/config/services_subscriber_with_annotations.yml delete mode 100644 src/Resources/config/services_subscriber_with_annotations_and_attributes.yml create mode 100755 src/Service/Encrypt.php delete mode 100644 src/Subscribers/DoctrineEncryptSubscriber.php create mode 100755 src/Traits/DoctrineEncrypt.php create mode 100755 src/Types/Encrypted.php create mode 100755 src/Types/EncryptedArray.php create mode 100755 src/Types/EncryptedDateTime.php create mode 100755 src/Types/EncryptedJSON.php rename tests/Functional/{DoctrineEncryptSubscriber/AbstractDoctrineEncryptSubscriberTestCase.php => DoctrineEncryptService/AbstractDoctrineEncryptServiceTestCase.php} (69%) create mode 100644 tests/Functional/DoctrineEncryptService/DoctrineEncryptServiceDefuseTest.php rename tests/Functional/{DoctrineEncryptSubscriber/DoctrineEncryptSubscriberHaliteTest.php => DoctrineEncryptService/DoctrineEncryptServiceHaliteTest.php} (60%) delete mode 100644 tests/Functional/DoctrineEncryptSubscriber/DoctrineEncryptSubscriberDefuseTest.php create mode 100755 tests/Functional/fixtures/Entity/CascadeTargetArray.php create mode 100755 tests/Functional/fixtures/Entity/CascadeTargetDateTime.php create mode 100755 tests/Functional/fixtures/Entity/CascadeTargetJSON.php delete mode 100644 tests/Functional/fixtures/Entity/DateTimeJsonArrayTarget.php create mode 100644 tests/Unit/Service/DoctrineEncryptServiceTest.php delete mode 100644 tests/Unit/Subscribers/DoctrineEncryptSubscriberTest.php delete mode 100644 tests/Unit/Subscribers/fixtures/ExtendedUser.php delete mode 100644 tests/Unit/Subscribers/fixtures/User.php delete mode 100644 tests/Unit/Subscribers/fixtures/WithUser.php diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index eb37379a..fce5ae98 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -51,7 +51,7 @@ jobs: fail-fast: false matrix: # normal, highest, non-dev installs - php-version: ['7.2', '7.3', '7.4', '8.0', '8.1', '8.2'] + php-version: ['7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3'] composer-options: ['--prefer-stable'] dependency-versions: ['highest'] include: @@ -128,4 +128,16 @@ jobs: - name: Demo symfony7.x - Unit Tests run: demo/symfony7.x/vendor/bin/simple-phpunit -c demo/symfony7.x/phpunit.xml.dist - if: ${{ startsWith(matrix.php-version , '8.2') }} \ No newline at end of file + if: ${{ startsWith(matrix.php-version , '8.2') }} + + - name: Demo symfony7.x Doctrine3.x - Install dependencies + uses: "ramsey/composer-install@v2" + with: + dependency-versions: "${{ matrix.dependency-versions }}" + composer-options: "--prefer-dist --no-progress" + working-directory: "demo/symfony7.x_doctrine3.x" + if: ${{ startsWith(matrix.php-version , '8.3') }} + + - name: Demo symfony7.x Doctrine3.x - Unit Tests + run: demo/symfony7.x_doctrine3.x/vendor/bin/simple-phpunit -c demo/symfony7.x_doctrine3.x/phpunit.xml.dist + if: ${{ startsWith(matrix.php-version , '8.3') }} \ No newline at end of file diff --git a/composer.json b/composer.json index 6072c591..5e601074 100644 --- a/composer.json +++ b/composer.json @@ -6,8 +6,7 @@ "description": "Encrypted symfony entity's by verified and standardized libraries", "require": { "php": "^7.2|^8.0", - "paragonie/halite": "^4.6|^5.0", - "doctrine/orm": "^2.5", + "doctrine/orm": "^2.5|^3.0", "doctrine/doctrine-bundle": "^2.0.8|^2.1", "symfony/property-access": "^5.4|^6.0|^7.0", "symfony/dependency-injection": "^5.4|^6.0|^7.0", @@ -18,10 +17,10 @@ "symfony/expression-language": "^5.4|^6.0|^7.0" }, "require-dev": { + "paragonie/halite": "^5.0", "defuse/php-encryption": "^2.1", "doctrine/cache": "^1.11", "phpstan/phpstan": "^1.4", - "jetbrains/phpstorm-attributes": "^1.0", "phpcompatibility/php-compatibility": "^9.3", "symfony/phpunit-bridge": "^7.0" }, @@ -32,7 +31,7 @@ }, "autoload": { "psr-4": { - "Ambta\\DoctrineEncryptBundle\\": "src/" + "DoctrineEncryptBundle\\": "src/" } }, "scripts": { @@ -42,7 +41,7 @@ }, "autoload-dev": { "psr-4": { - "Ambta\\DoctrineEncryptBundle\\Tests\\": "tests/" + "DoctrineEncryptBundle\\Tests\\": "tests/" } }, "config": { diff --git a/demo/composer.json b/demo/composer.json index b943b38b..d900a292 100644 --- a/demo/composer.json +++ b/demo/composer.json @@ -19,7 +19,9 @@ "printf 'HALITE_SECRET=\"%s\"' \"$(cat shared/.Halite.key)\" > symfony6.x/.env.local", "printf 'HALITE_SECRET=\"%s\"' \"$(cat shared/.Halite.key)\" > symfony6.x/.env.test.local", "printf 'HALITE_SECRET=\"%s\"' \"$(cat shared/.Halite.key)\" > symfony7.x/.env.local", - "printf 'HALITE_SECRET=\"%s\"' \"$(cat shared/.Halite.key)\" > symfony7.x/.env.test.local" + "printf 'HALITE_SECRET=\"%s\"' \"$(cat shared/.Halite.key)\" > symfony7.x/.env.test.local", + "printf 'HALITE_SECRET=\"%s\"' \"$(cat shared/.Halite.key)\" > symfony7.x_doctrine3.x/.env.local", + "printf 'HALITE_SECRET=\"%s\"' \"$(cat shared/.Halite.key)\" > symfony7.x_doctrine3.x/.env.test.local" ] }, "extra": { @@ -27,9 +29,11 @@ "shared/templates": "symfony5.4/templates", "./shared/templates": "symfony6.x/templates", "././shared/templates": "symfony7.x/templates", + "./././shared/templates": "symfony7.x_doctrine3.x/templates", "shared/var/data.db": "symfony5.4/var/data.db", "./shared/var/data.db": "symfony6.x/var/data.db", - "././shared/var/data.db": "symfony7.x/var/data.db" + "././shared/var/data.db": "symfony7.x/var/data.db", + "./././shared/var/data.db": "symfony7.x_doctrine3.x/var/data.db" } } } diff --git a/demo/symfony5.4/composer.json b/demo/symfony5.4/composer.json index 8776fcc6..f080615e 100644 --- a/demo/symfony5.4/composer.json +++ b/demo/symfony5.4/composer.json @@ -76,4 +76,4 @@ "url": "../../" } ] -} +} \ No newline at end of file diff --git a/demo/symfony5.4/config/bundles.php b/demo/symfony5.4/config/bundles.php index 7a648836..621bccdb 100644 --- a/demo/symfony5.4/config/bundles.php +++ b/demo/symfony5.4/config/bundles.php @@ -4,5 +4,5 @@ Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true], Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true], Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true], - Ambta\DoctrineEncryptBundle\AmbtaDoctrineEncryptBundle::class => ['all' => true], + DoctrineEncryptBundle\DoctrineEncryptBundle::class => ['all' => true], ]; diff --git a/demo/symfony5.4/config/packages/ambta_doctrine_encrypt.yaml b/demo/symfony5.4/config/packages/ambta_doctrine_encrypt.yaml deleted file mode 100644 index ddbd65af..00000000 --- a/demo/symfony5.4/config/packages/ambta_doctrine_encrypt.yaml +++ /dev/null @@ -1,3 +0,0 @@ -ambta_doctrine_encrypt: - enable_secret_generation: false - secret: '%env(HALITE_SECRET)%' \ No newline at end of file diff --git a/demo/symfony5.4/config/packages/doctrine_encrypt.yaml b/demo/symfony5.4/config/packages/doctrine_encrypt.yaml new file mode 100644 index 00000000..76ec03d6 --- /dev/null +++ b/demo/symfony5.4/config/packages/doctrine_encrypt.yaml @@ -0,0 +1,3 @@ +doctrine_encrypt: + enable_secret_generation: false + secret: '%env(HALITE_SECRET)%' \ No newline at end of file diff --git a/demo/symfony5.4/src/Entity/Annotation/Secret.php b/demo/symfony5.4/src/Entity/Annotation/Secret.php index 26e42a84..64506ba1 100644 --- a/demo/symfony5.4/src/Entity/Annotation/Secret.php +++ b/demo/symfony5.4/src/Entity/Annotation/Secret.php @@ -2,7 +2,6 @@ namespace App\Entity\Annotation; -use Ambta\DoctrineEncryptBundle\Configuration\Encrypted; use Doctrine\ORM\Mapping as ORM; use App\Repository\Annotation\SecretRepository; @@ -19,8 +18,7 @@ class Secret implements \App\Entity\SecretInterface private $name; /** - * @ORM\Column(type="string",nullable=false) - * @Encrypted + * @ORM\Column(type="encrypted",nullable=false) */ private $secret; diff --git a/demo/symfony5.4/src/Entity/Attribute/Secret.php b/demo/symfony5.4/src/Entity/Attribute/Secret.php index 121af154..004f40c0 100644 --- a/demo/symfony5.4/src/Entity/Attribute/Secret.php +++ b/demo/symfony5.4/src/Entity/Attribute/Secret.php @@ -2,7 +2,6 @@ namespace App\Entity\Attribute; -use Ambta\DoctrineEncryptBundle\Configuration\Encrypted; use App\Repository\Attribute\SecretRepository; use Doctrine\ORM\Mapping as ORM; @@ -15,8 +14,7 @@ class Secret implements \App\Entity\SecretInterface private $name; - #[ORM\Column(type:"string", nullable:false)] - #[Encrypted] + #[ORM\Column(type:"encrypted", nullable:false)] private $secret; /** diff --git a/demo/symfony5.4/tests/SecretTest.php b/demo/symfony5.4/tests/SecretTest.php index 6b65211d..a6a5665d 100644 --- a/demo/symfony5.4/tests/SecretTest.php +++ b/demo/symfony5.4/tests/SecretTest.php @@ -2,7 +2,7 @@ namespace App\Tests; -use Ambta\DoctrineEncryptBundle\Subscribers\DoctrineEncryptSubscriber; +use DoctrineEncryptBundle\Service\Encrypt; use App\Entity; use Doctrine\ORM\EntityManagerInterface; use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; @@ -53,7 +53,7 @@ private function testSecretsAreEncryptedInDatabase(string $className) self::assertEquals($newSecretObject->getName(), $actualSecretObject->getName()); // Make sure it is encrypted self::assertNotEquals($newSecretObject->getSecret(),$actualRawSecret); - self::assertStringEndsWith(DoctrineEncryptSubscriber::ENCRYPTION_MARKER,$actualRawSecret); + self::assertStringEndsWith(Encrypt::ENCRYPTION_MARKER,$actualRawSecret); } /** diff --git a/demo/symfony6.x/composer.json b/demo/symfony6.x/composer.json index 941a3570..52752e7c 100644 --- a/demo/symfony6.x/composer.json +++ b/demo/symfony6.x/composer.json @@ -76,4 +76,4 @@ "url": "../../" } ] -} +} \ No newline at end of file diff --git a/demo/symfony6.x/config/bundles.php b/demo/symfony6.x/config/bundles.php index b7e7b92c..ebcead12 100644 --- a/demo/symfony6.x/config/bundles.php +++ b/demo/symfony6.x/config/bundles.php @@ -5,5 +5,5 @@ Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true], Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true], Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true], - Ambta\DoctrineEncryptBundle\AmbtaDoctrineEncryptBundle::class => ['all' => true], + DoctrineEncryptBundle\DoctrineEncryptBundle::class => ['all' => true], ]; diff --git a/demo/symfony6.x/config/packages/ambta_doctrine_encrypt.yaml b/demo/symfony6.x/config/packages/ambta_doctrine_encrypt.yaml deleted file mode 100644 index ddbd65af..00000000 --- a/demo/symfony6.x/config/packages/ambta_doctrine_encrypt.yaml +++ /dev/null @@ -1,3 +0,0 @@ -ambta_doctrine_encrypt: - enable_secret_generation: false - secret: '%env(HALITE_SECRET)%' \ No newline at end of file diff --git a/demo/symfony6.x/config/packages/doctrine_encrypt.yaml b/demo/symfony6.x/config/packages/doctrine_encrypt.yaml new file mode 100644 index 00000000..76ec03d6 --- /dev/null +++ b/demo/symfony6.x/config/packages/doctrine_encrypt.yaml @@ -0,0 +1,3 @@ +doctrine_encrypt: + enable_secret_generation: false + secret: '%env(HALITE_SECRET)%' \ No newline at end of file diff --git a/demo/symfony6.x/src/Entity/Annotation/Secret.php b/demo/symfony6.x/src/Entity/Annotation/Secret.php index 49dce58a..082f6a44 100644 --- a/demo/symfony6.x/src/Entity/Annotation/Secret.php +++ b/demo/symfony6.x/src/Entity/Annotation/Secret.php @@ -2,7 +2,6 @@ namespace App\Entity\Annotation; -use Ambta\DoctrineEncryptBundle\Configuration\Encrypted; use Doctrine\ORM\Mapping as ORM; use App\Repository\Annotation\SecretRepository; @@ -19,8 +18,7 @@ class Secret implements \App\Entity\SecretInterface private $name; /** - * @ORM\Column(type="string",nullable=false) - * @Encrypted + * @ORM\Column(type="encrypted",nullable=false) */ private $secret; diff --git a/demo/symfony6.x/src/Entity/Attribute/Secret.php b/demo/symfony6.x/src/Entity/Attribute/Secret.php index c76a80db..7e001053 100644 --- a/demo/symfony6.x/src/Entity/Attribute/Secret.php +++ b/demo/symfony6.x/src/Entity/Attribute/Secret.php @@ -2,7 +2,6 @@ namespace App\Entity\Attribute; -use Ambta\DoctrineEncryptBundle\Configuration\Encrypted; use App\Repository\Attribute\SecretRepository; use Doctrine\ORM\Mapping as ORM; @@ -16,8 +15,7 @@ class Secret implements \App\Entity\SecretInterface private $name; - #[ORM\Column(type:"string",nullable:false)] - #[Encrypted] + #[ORM\Column(type:"encrypted",nullable:false)] private $secret; /** diff --git a/demo/symfony6.x/tests/SecretTest.php b/demo/symfony6.x/tests/SecretTest.php index e2783e66..19d8b525 100644 --- a/demo/symfony6.x/tests/SecretTest.php +++ b/demo/symfony6.x/tests/SecretTest.php @@ -2,7 +2,7 @@ namespace App\Tests; -use Ambta\DoctrineEncryptBundle\Subscribers\DoctrineEncryptSubscriber; +use DoctrineEncryptBundle\Service\Encrypt; use App\Entity; use Doctrine\ORM\EntityManagerInterface; use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; @@ -53,7 +53,7 @@ private function testSecretsAreEncryptedInDatabase(string $className) self::assertEquals($newSecretObject->getName(), $actualSecretObject->getName()); // Make sure it is encrypted self::assertNotEquals($newSecretObject->getSecret(),$actualRawSecret); - self::assertStringEndsWith(DoctrineEncryptSubscriber::ENCRYPTION_MARKER,$actualRawSecret); + self::assertStringEndsWith(Encrypt::ENCRYPTION_MARKER,$actualRawSecret); } /** diff --git a/demo/symfony7.x/composer.lock b/demo/symfony7.x/composer.lock index f8325ab9..da56e3f5 100644 --- a/demo/symfony7.x/composer.lock +++ b/demo/symfony7.x/composer.lock @@ -1249,12 +1249,12 @@ "type": "library", "autoload": { "psr-4": { - "Ambta\\DoctrineEncryptBundle\\": "src/" + "DoctrineEncryptBundle\\": "src/" } }, "autoload-dev": { "psr-4": { - "Ambta\\DoctrineEncryptBundle\\Tests\\": "tests/" + "DoctrineEncryptBundle\\Tests\\": "tests/" } }, "scripts": { diff --git a/demo/symfony7.x/config/bundles.php b/demo/symfony7.x/config/bundles.php index 7566e6ac..9336f355 100644 --- a/demo/symfony7.x/config/bundles.php +++ b/demo/symfony7.x/config/bundles.php @@ -3,6 +3,6 @@ return [ Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true], Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true], - Ambta\DoctrineEncryptBundle\AmbtaDoctrineEncryptBundle::class => ['all' => true], + DoctrineEncryptBundle\DoctrineEncryptBundle::class => ['all' => true], Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true], ]; diff --git a/demo/symfony7.x/config/packages/ambta_doctrine_encrypt.yaml b/demo/symfony7.x/config/packages/ambta_doctrine_encrypt.yaml deleted file mode 100644 index ddbd65af..00000000 --- a/demo/symfony7.x/config/packages/ambta_doctrine_encrypt.yaml +++ /dev/null @@ -1,3 +0,0 @@ -ambta_doctrine_encrypt: - enable_secret_generation: false - secret: '%env(HALITE_SECRET)%' \ No newline at end of file diff --git a/demo/symfony7.x/config/packages/doctrine_encrypt.yaml b/demo/symfony7.x/config/packages/doctrine_encrypt.yaml new file mode 100644 index 00000000..76ec03d6 --- /dev/null +++ b/demo/symfony7.x/config/packages/doctrine_encrypt.yaml @@ -0,0 +1,3 @@ +doctrine_encrypt: + enable_secret_generation: false + secret: '%env(HALITE_SECRET)%' \ No newline at end of file diff --git a/demo/symfony7.x/phpunit.xml.dist b/demo/symfony7.x/phpunit.xml.dist index f317760c..61f479af 100644 --- a/demo/symfony7.x/phpunit.xml.dist +++ b/demo/symfony7.x/phpunit.xml.dist @@ -26,7 +26,4 @@ includeUncoveredFiles="true" > - - - diff --git a/demo/symfony7.x/src/Entity/Attribute/Secret.php b/demo/symfony7.x/src/Entity/Attribute/Secret.php index c76a80db..7e001053 100644 --- a/demo/symfony7.x/src/Entity/Attribute/Secret.php +++ b/demo/symfony7.x/src/Entity/Attribute/Secret.php @@ -2,7 +2,6 @@ namespace App\Entity\Attribute; -use Ambta\DoctrineEncryptBundle\Configuration\Encrypted; use App\Repository\Attribute\SecretRepository; use Doctrine\ORM\Mapping as ORM; @@ -16,8 +15,7 @@ class Secret implements \App\Entity\SecretInterface private $name; - #[ORM\Column(type:"string",nullable:false)] - #[Encrypted] + #[ORM\Column(type:"encrypted",nullable:false)] private $secret; /** diff --git a/demo/symfony7.x/tests/SecretTest.php b/demo/symfony7.x/tests/SecretTest.php index ec038ed6..918d6891 100644 --- a/demo/symfony7.x/tests/SecretTest.php +++ b/demo/symfony7.x/tests/SecretTest.php @@ -2,7 +2,7 @@ namespace App\Tests; -use Ambta\DoctrineEncryptBundle\Subscribers\DoctrineEncryptSubscriber; +use DoctrineEncryptBundle\Service\Encrypt; use App\Entity; use Doctrine\ORM\EntityManagerInterface; use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; @@ -53,7 +53,7 @@ private function testSecretsAreEncryptedInDatabase(string $className) self::assertEquals($newSecretObject->getName(), $actualSecretObject->getName()); // Make sure it is encrypted self::assertNotEquals($newSecretObject->getSecret(),$actualRawSecret); - self::assertStringEndsWith(DoctrineEncryptSubscriber::ENCRYPTION_MARKER,$actualRawSecret); + self::assertStringEndsWith(Encrypt::ENCRYPTION_MARKER,$actualRawSecret); } /** diff --git a/demo/symfony7.x_doctrine3.x/.env b/demo/symfony7.x_doctrine3.x/.env new file mode 100644 index 00000000..751352a3 --- /dev/null +++ b/demo/symfony7.x_doctrine3.x/.env @@ -0,0 +1,31 @@ +# In all environments, the following files are loaded if they exist, +# the latter taking precedence over the former: +# +# * .env contains default values for the environment variables needed by the app +# * .env.local uncommitted file with local overrides +# * .env.$APP_ENV committed environment-specific defaults +# * .env.$APP_ENV.local uncommitted environment-specific overrides +# +# Real environment variables win over .env files. +# +# DO NOT DEFINE PRODUCTION SECRETS IN THIS FILE NOR IN ANY OTHER COMMITTED FILES. +# https://symfony.com/doc/current/configuration/secrets.html +# +# Run "composer dump-env prod" to compile .env files for production use (requires symfony/flex >=1.2). +# https://symfony.com/doc/current/best_practices.html#use-environment-variables-for-infrastructure-configuration + +###> symfony/framework-bundle ### +APP_ENV=dev +APP_SECRET=6856f2521a71b9cace5415c5b1269956 +###< symfony/framework-bundle ### + +###> doctrine/doctrine-bundle ### +# Format described at https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url +# IMPORTANT: You MUST configure your server version, either here or in config/packages/doctrine.yaml +# +# DATABASE_URL="sqlite:///%kernel.project_dir%/var/data.db" +# DATABASE_URL="mysql://app:!ChangeMe!@127.0.0.1:3306/app?serverVersion=8.0.32&charset=utf8mb4" +# DATABASE_URL="mysql://app:!ChangeMe!@127.0.0.1:3306/app?serverVersion=10.11.2-MariaDB&charset=utf8mb4" +DATABASE_PATH="var/data.db" +DATABASE_URL="sqlite:///%kernel.project_dir%/var/data.db" +###< doctrine/doctrine-bundle ### diff --git a/demo/symfony7.x_doctrine3.x/.gitignore b/demo/symfony7.x_doctrine3.x/.gitignore new file mode 100644 index 00000000..ff329d37 --- /dev/null +++ b/demo/symfony7.x_doctrine3.x/.gitignore @@ -0,0 +1,22 @@ +# Ignore symlinks +/templates +/var/data.db +/.Halite.key + +# Ignore locked versions of composer +composer.lock + +###> symfony/framework-bundle ### +/.env.local +/.env.local.php +/.env.*.local +/config/secrets/prod/prod.decrypt.private.php +/public/bundles/ +/var/ +/vendor/ +###< symfony/framework-bundle ### + +###> symfony/phpunit-bridge ### +.phpunit.result.cache +/phpunit.xml +###< symfony/phpunit-bridge ### diff --git a/demo/symfony7.x_doctrine3.x/README.md b/demo/symfony7.x_doctrine3.x/README.md new file mode 100644 index 00000000..5295fba5 --- /dev/null +++ b/demo/symfony7.x_doctrine3.x/README.md @@ -0,0 +1,28 @@ +This demo-installation demonstrates a simple symfony 7.x-application using only attributes and Doctrine 3.x. + +Annotations are no longer allowed in symfony 7.x + +# How to use +```shell +# run `composer install` in parent-directory to create symlinks for shared files +cd ../ +composer install +cd - + +# Install packages +composer install + +# Serve the application +## Using symfony-cli +symfony serve +## Using php-builtin-server () +php -S localhost:8000 -t public +## Other possibility +### Use a webserver like apache or nginx + + +# Run unittests +vendor/bin/simple-phpunit +``` + + diff --git a/demo/symfony7.x_doctrine3.x/bin/console b/demo/symfony7.x_doctrine3.x/bin/console new file mode 100755 index 00000000..c933dc53 --- /dev/null +++ b/demo/symfony7.x_doctrine3.x/bin/console @@ -0,0 +1,17 @@ +#!/usr/bin/env php += 80000) { + require dirname(__DIR__).'/vendor/phpunit/phpunit/phpunit'; + } else { + define('PHPUNIT_COMPOSER_INSTALL', dirname(__DIR__).'/vendor/autoload.php'); + require PHPUNIT_COMPOSER_INSTALL; + PHPUnit\TextUI\Command::main(); + } +} else { + if (!is_file(dirname(__DIR__).'/vendor/symfony/phpunit-bridge/bin/simple-phpunit.php')) { + echo "Unable to find the `simple-phpunit.php` script in `vendor/symfony/phpunit-bridge/bin/`.\n"; + exit(1); + } + + require dirname(__DIR__).'/vendor/symfony/phpunit-bridge/bin/simple-phpunit.php'; +} diff --git a/demo/symfony7.x_doctrine3.x/composer.json b/demo/symfony7.x_doctrine3.x/composer.json new file mode 100644 index 00000000..815c669e --- /dev/null +++ b/demo/symfony7.x_doctrine3.x/composer.json @@ -0,0 +1,78 @@ +{ + "type": "project", + "license": "proprietary", + "minimum-stability": "stable", + "prefer-stable": true, + "require": { + "php": ">=8.3", + "ext-ctype": "*", + "ext-iconv": "*", + "doctrine/orm": "3.0", + "doctrineencryptbundle/doctrine-encrypt-bundle": "@dev", + "symfony/console": "7.0.*", + "symfony/dotenv": "7.0.*", + "symfony/flex": "^2", + "symfony/framework-bundle": "7.0.*", + "symfony/runtime": "7.0.*", + "symfony/twig-bundle": "7.0.*", + "symfony/yaml": "7.0.*" + }, + "require-dev": { + "symfony/phpunit-bridge": "^7.0" + }, + "config": { + "allow-plugins": { + "php-http/discovery": true, + "symfony/flex": true, + "symfony/runtime": true + }, + "sort-packages": true + }, + "autoload": { + "psr-4": { + "App\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "App\\Tests\\": "tests/" + } + }, + "replace": { + "symfony/polyfill-ctype": "*", + "symfony/polyfill-iconv": "*", + "symfony/polyfill-php72": "*", + "symfony/polyfill-php73": "*", + "symfony/polyfill-php74": "*", + "symfony/polyfill-php80": "*", + "symfony/polyfill-php81": "*", + "symfony/polyfill-php82": "*" + }, + "scripts": { + "auto-scripts": { + "cache:clear": "symfony-cmd", + "assets:install %PUBLIC_DIR%": "symfony-cmd" + }, + "post-install-cmd": [ + "@auto-scripts" + ], + "post-update-cmd": [ + "@auto-scripts" + ] + }, + "conflict": { + "symfony/symfony": "*" + }, + "extra": { + "symfony": { + "allow-contrib": false, + "require": "7.0.*" + } + }, + "repositories": [ + { + "type": "path", + "url": "../../" + } + ] +} diff --git a/demo/symfony7.x_doctrine3.x/config/bundles.php b/demo/symfony7.x_doctrine3.x/config/bundles.php new file mode 100644 index 00000000..9336f355 --- /dev/null +++ b/demo/symfony7.x_doctrine3.x/config/bundles.php @@ -0,0 +1,8 @@ + ['all' => true], + Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true], + DoctrineEncryptBundle\DoctrineEncryptBundle::class => ['all' => true], + Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true], +]; diff --git a/demo/symfony7.x_doctrine3.x/config/packages/cache.yaml b/demo/symfony7.x_doctrine3.x/config/packages/cache.yaml new file mode 100644 index 00000000..6899b720 --- /dev/null +++ b/demo/symfony7.x_doctrine3.x/config/packages/cache.yaml @@ -0,0 +1,19 @@ +framework: + cache: + # Unique name of your app: used to compute stable namespaces for cache keys. + #prefix_seed: your_vendor_name/app_name + + # The "app" cache stores to the filesystem by default. + # The data in this cache should persist between deploys. + # Other options include: + + # Redis + #app: cache.adapter.redis + #default_redis_provider: redis://localhost + + # APCu (not recommended with heavy random-write workloads as memory fragmentation can cause perf issues) + #app: cache.adapter.apcu + + # Namespaced pools use the above "app" backend by default + #pools: + #my.dedicated.cache: null diff --git a/demo/symfony7.x_doctrine3.x/config/packages/doctrine.yaml b/demo/symfony7.x_doctrine3.x/config/packages/doctrine.yaml new file mode 100644 index 00000000..87d77a85 --- /dev/null +++ b/demo/symfony7.x_doctrine3.x/config/packages/doctrine.yaml @@ -0,0 +1,43 @@ +doctrine: + dbal: + url: '%env(resolve:DATABASE_URL)%' + + # IMPORTANT: You MUST configure your server version, + # either here or in the DATABASE_URL env var (see .env file) + #server_version: '13' + orm: + auto_generate_proxy_classes: true + naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware + auto_mapping: true + mappings: + Attributes: + type: 'attribute' + is_bundle: false + dir: '%kernel.project_dir%/src/Entity/Attribute' + prefix: 'App\Entity\Attribute' + alias: App + +when@test: + doctrine: + dbal: + # "TEST_TOKEN" is typically set by ParaTest + dbname_suffix: '_test%env(default::TEST_TOKEN)%' + +when@prod: + doctrine: + orm: + auto_generate_proxy_classes: false + query_cache_driver: + type: pool + pool: doctrine.system_cache_pool + result_cache_driver: + type: pool + pool: doctrine.result_cache_pool + + framework: + cache: + pools: + doctrine.result_cache_pool: + adapter: cache.app + doctrine.system_cache_pool: + adapter: cache.system diff --git a/demo/symfony7.x_doctrine3.x/config/packages/doctrine_encrypt.yaml b/demo/symfony7.x_doctrine3.x/config/packages/doctrine_encrypt.yaml new file mode 100644 index 00000000..76ec03d6 --- /dev/null +++ b/demo/symfony7.x_doctrine3.x/config/packages/doctrine_encrypt.yaml @@ -0,0 +1,3 @@ +doctrine_encrypt: + enable_secret_generation: false + secret: '%env(HALITE_SECRET)%' \ No newline at end of file diff --git a/demo/symfony7.x_doctrine3.x/config/packages/framework.yaml b/demo/symfony7.x_doctrine3.x/config/packages/framework.yaml new file mode 100644 index 00000000..355bd4ce --- /dev/null +++ b/demo/symfony7.x_doctrine3.x/config/packages/framework.yaml @@ -0,0 +1,23 @@ +# see https://symfony.com/doc/current/reference/configuration/framework.html +framework: + secret: '%env(APP_SECRET)%' + #csrf_protection: true + handle_all_throwables: true + + # Enables session support. Note that the session will ONLY be started if you read or write from it. + # Remove or comment this section to explicitly disable session support. + session: + handler_id: null + cookie_secure: auto + cookie_samesite: lax + + #esi: true + #fragments: true + php_errors: + log: true + +when@test: + framework: + test: true + session: + storage_factory_id: session.storage.factory.mock_file diff --git a/demo/symfony7.x_doctrine3.x/config/packages/routing.yaml b/demo/symfony7.x_doctrine3.x/config/packages/routing.yaml new file mode 100644 index 00000000..4b766ce5 --- /dev/null +++ b/demo/symfony7.x_doctrine3.x/config/packages/routing.yaml @@ -0,0 +1,12 @@ +framework: + router: + utf8: true + + # Configure how to generate URLs in non-HTTP contexts, such as CLI commands. + # See https://symfony.com/doc/current/routing.html#generating-urls-in-commands + #default_uri: http://localhost + +when@prod: + framework: + router: + strict_requirements: null diff --git a/demo/symfony7.x_doctrine3.x/config/packages/twig.yaml b/demo/symfony7.x_doctrine3.x/config/packages/twig.yaml new file mode 100644 index 00000000..3cc1a452 --- /dev/null +++ b/demo/symfony7.x_doctrine3.x/config/packages/twig.yaml @@ -0,0 +1,8 @@ +twig: + default_path: '%kernel.project_dir%/templates' + globals: + appVersion: "7.x" + +when@test: + twig: + strict_variables: true diff --git a/demo/symfony7.x_doctrine3.x/config/preload.php b/demo/symfony7.x_doctrine3.x/config/preload.php new file mode 100644 index 00000000..5ebcdb21 --- /dev/null +++ b/demo/symfony7.x_doctrine3.x/config/preload.php @@ -0,0 +1,5 @@ +findAll(); + + return $this->render('index.html.twig',['secrets' => $secrets]); + } + + #[Route(name:'create', path:'/create')] + public function create(Request $request, EntityManagerInterface $em): Response + { + if (!$request->query->has('name') || !$request->query->has('secret') || !$request->query->has('type')) { + return new Response('Please specify name, secret and type in url-query'); + } + + $type = $request->query->get('type'); + if($type === 'attribute') { + $secret = new \App\Entity\Attribute\Secret(); + } else { + return new Response('Type is only allowed to be "attribute"'); + } + + $secret + ->setName($request->query->getAlnum('name')) + ->setSecret($request->query->getAlnum('secret')); + + $em->persist($secret); + $em->flush(); + + return new Response(sprintf('OK - secret %s stored',$secret->getName())); + } +} \ No newline at end of file diff --git a/demo/symfony7.x_doctrine3.x/src/Entity/.gitignore b/demo/symfony7.x_doctrine3.x/src/Entity/.gitignore new file mode 100644 index 00000000..e69de29b diff --git a/demo/symfony7.x_doctrine3.x/src/Entity/Attribute/Secret.php b/demo/symfony7.x_doctrine3.x/src/Entity/Attribute/Secret.php new file mode 100644 index 00000000..7e001053 --- /dev/null +++ b/demo/symfony7.x_doctrine3.x/src/Entity/Attribute/Secret.php @@ -0,0 +1,92 @@ +name; + } + + /** + * @param string $name + * + * @return $this + */ + public function setName($name): self + { + $this->name = $name; + + return $this; + } + + /** + * @return string + */ + public function getSecret() + { + return $this->secret; + } + + /** + * @param string $secret + * + * @return $this + */ + public function setSecret($secret): self + { + $this->secret = $secret; + + return $this; + } + + /** + * @return string + */ + public function getRawSecret() + { + return $this->rawSecret; + } + + /** + * @param mixed $rawSecret + * + * @return $this + */ + public function setRawSecret($rawSecret) + { + $this->rawSecret = $rawSecret; + + return $this; + } +} \ No newline at end of file diff --git a/demo/symfony7.x_doctrine3.x/src/Entity/SecretInterface.php b/demo/symfony7.x_doctrine3.x/src/Entity/SecretInterface.php new file mode 100644 index 00000000..cd234732 --- /dev/null +++ b/demo/symfony7.x_doctrine3.x/src/Entity/SecretInterface.php @@ -0,0 +1,11 @@ + The objects. + */ + public function findAll() + { + $qb = $this->createQueryBuilder('s'); + $qb->select('s') + ->addSelect('(s.secret) as rawSecret') + ->orderBy('s.name','ASC'); + $rawResult = $qb->getQuery()->getResult(); + + $result = []; + foreach ($rawResult as $row) { + $secret = $row[0]; + $secret->setRawSecret($row['rawSecret']); + $result[] = $secret; + } + + return $result; + } +} \ No newline at end of file diff --git a/demo/symfony7.x_doctrine3.x/src/Repository/Attribute/SecretRepository.php b/demo/symfony7.x_doctrine3.x/src/Repository/Attribute/SecretRepository.php new file mode 100644 index 00000000..fddf972c --- /dev/null +++ b/demo/symfony7.x_doctrine3.x/src/Repository/Attribute/SecretRepository.php @@ -0,0 +1,56 @@ += 80000) { + /** + * @method Secret|null find($id, $lockMode = null, $lockVersion = null) + * @method Secret|null findOneBy(array $criteria, array $orderBy = null) + * @method Secret[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) + */ + class SecretRepository extends AbstractSecretRepository + { + public function __construct(\Doctrine\Common\Persistence\ManagerRegistry $registry) + { + parent::__construct($registry, Secret::class); + } + } +} else { + /** + * Dummy-repository for php < 8.0 + */ + class SecretRepository + { + public function findAll() + { + return []; + } + + public function find($id, $lockMode = null, $lockVersion = null) + { + return null; + } + + public function findOneBy(array $criteria, array $orderBy = null) + { + return null; + } + + public function findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) + { + return []; + } + } +} \ No newline at end of file diff --git a/demo/symfony7.x_doctrine3.x/symfony.lock b/demo/symfony7.x_doctrine3.x/symfony.lock new file mode 100644 index 00000000..6c943110 --- /dev/null +++ b/demo/symfony7.x_doctrine3.x/symfony.lock @@ -0,0 +1,112 @@ +{ + "doctrine/annotations": { + "version": "2.0", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "1.10", + "ref": "64d8583af5ea57b7afa4aba4b159907f3a148b05" + } + }, + "doctrine/doctrine-bundle": { + "version": "2.11", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "2.10", + "ref": "0db4b12b5df45f5122213b4ecd18733ab7fa7d53" + }, + "files": [ + "config/packages/doctrine.yaml", + "src/Entity/.gitignore", + "src/Repository/.gitignore" + ] + }, + "doctrineencryptbundle/doctrine-encrypt-bundle": { + "version": "dev-symfony7" + }, + "symfony/console": { + "version": "7.0", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "5.3", + "ref": "da0c8be8157600ad34f10ff0c9cc91232522e047" + }, + "files": [ + "bin/console" + ] + }, + "symfony/flex": { + "version": "2.4", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "1.0", + "ref": "146251ae39e06a95be0fe3d13c807bcf3938b172" + }, + "files": [ + ".env" + ] + }, + "symfony/framework-bundle": { + "version": "7.0", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "7.0", + "ref": "de6e1b3e2bbbe69e36262d72c3f3db858b1ab391" + }, + "files": [ + "config/packages/cache.yaml", + "config/packages/framework.yaml", + "config/preload.php", + "config/routes/framework.yaml", + "config/services.yaml", + "public/index.php", + "src/Controller/.gitignore", + "src/Kernel.php" + ] + }, + "symfony/phpunit-bridge": { + "version": "7.0", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "6.3", + "ref": "1f5830c331065b6e4c9d5fa2105e322d29fcd573" + }, + "files": [ + ".env.test", + "bin/phpunit", + "phpunit.xml.dist", + "tests/bootstrap.php" + ] + }, + "symfony/routing": { + "version": "7.0", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "6.2", + "ref": "e0a11b4ccb8c9e70b574ff5ad3dfdcd41dec5aa6" + }, + "files": [ + "config/packages/routing.yaml", + "config/routes.yaml" + ] + }, + "symfony/twig-bundle": { + "version": "7.0", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "6.3", + "ref": "b7772eb20e92f3fb4d4fe756e7505b4ba2ca1a2c" + }, + "files": [ + "config/packages/twig.yaml", + "templates/base.html.twig" + ] + } +} diff --git a/demo/symfony7.x_doctrine3.x/tests/SecretTest.php b/demo/symfony7.x_doctrine3.x/tests/SecretTest.php new file mode 100644 index 00000000..918d6891 --- /dev/null +++ b/demo/symfony7.x_doctrine3.x/tests/SecretTest.php @@ -0,0 +1,68 @@ +get('doctrine.orm.entity_manager'); + + // Make sure we do not store testdata + $entityManager->beginTransaction(); + + $name = 'test123'; + $secretString = 'i am a secret string'; + + // Create entity to test with + $newSecretObject = (new $className) + ->setName($name) + ->setSecret($secretString); + + $entityManager->persist($newSecretObject); + $entityManager->flush(); + + // Fetch the actual data + $secretRepository = $entityManager->getRepository($className); + $qb = $secretRepository->createQueryBuilder('s'); + $qb->select('s') + ->addSelect('(s.secret) as rawSecret') + ->where('s.name = :name') + ->setParameter('name',$name) + ->orderBy('s.name','ASC'); + $result = $qb->getQuery()->getSingleResult(); + + $actualSecretObject = $result[0]; + $actualRawSecret = $result['rawSecret']; + + self::assertInstanceOf($className,$actualSecretObject); + self::assertEquals($newSecretObject->getSecret(), $actualSecretObject->getSecret()); + self::assertEquals($newSecretObject->getName(), $actualSecretObject->getName()); + // Make sure it is encrypted + self::assertNotEquals($newSecretObject->getSecret(),$actualRawSecret); + self::assertStringEndsWith(Encrypt::ENCRYPTION_MARKER,$actualRawSecret); + } + + /** + * @covers Entity\Attribute\Secret::getSecret + * @covers Entity\Attribute\Secret::getName + * @requires PHP 8.0 + */ + public function testAttributeSecretsAreEncryptedInDatabase() + { + $this->testSecretsAreEncryptedInDatabase(Entity\Attribute\Secret::class); + } +} diff --git a/demo/symfony7.x_doctrine3.x/tests/bootstrap.php b/demo/symfony7.x_doctrine3.x/tests/bootstrap.php new file mode 100644 index 00000000..469dccee --- /dev/null +++ b/demo/symfony7.x_doctrine3.x/tests/bootstrap.php @@ -0,0 +1,11 @@ +bootEnv(dirname(__DIR__).'/.env'); +} diff --git a/phpunit.xml.dist b/phpunit.xml.dist index e0767699..ad339a23 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -29,6 +29,5 @@ - diff --git a/src/AmbtaDoctrineEncryptBundle.php b/src/AmbtaDoctrineEncryptBundle.php deleted file mode 100644 index 11b24614..00000000 --- a/src/AmbtaDoctrineEncryptBundle.php +++ /dev/null @@ -1,17 +0,0 @@ - **/ abstract class AbstractCommand extends Command { @@ -22,31 +18,20 @@ abstract class AbstractCommand extends Command protected $entityManager; /** - * @var DoctrineEncryptSubscriber + * @var Encrypt */ - protected $subscriber; + protected $service; /** - * @var Reader|AttributeReader + * @param ContainerInterface $container + * + * @return void */ - protected $annotationReader; - - /** - * AbstractCommand constructor. - * - * @param EntityManager $entityManager - * @param Reader|AttributeReader $annotationReader - * @param DoctrineEncryptSubscriber $subscriber - */ - public function __construct( - EntityManagerInterface $entityManager, - $annotationReader, - DoctrineEncryptSubscriber $subscriber - ) { + public function __construct(EntityManagerInterface $entityManager, Encrypt $service) + { parent::__construct(); $this->entityManager = $entityManager; - $this->annotationReader = $annotationReader; - $this->subscriber = $subscriber; + $this->service = $service; } /** @@ -75,53 +60,4 @@ protected function getTableCount(string $entityName): int return (int) $query->getSingleScalarResult(); } - - /** - * Return an array of entity-metadata for all entities - * that have at least one encrypted property. - * - * @return array - */ - protected function getEncryptionableEntityMetaData(): array - { - $validMetaData = []; - $metaDataArray = $this->entityManager->getMetadataFactory()->getAllMetadata(); - - foreach ($metaDataArray as $entityMetaData) - { - if ($entityMetaData instanceof ClassMetadataInfo and $entityMetaData->isMappedSuperclass) { - continue; - } - - $properties = $this->getEncryptionableProperties($entityMetaData); - if (count($properties) == 0) { - continue; - } - - $validMetaData[] = $entityMetaData; - } - - return $validMetaData; - } - - /** - * @param $entityMetaData - * - * @return array - */ - protected function getEncryptionableProperties($entityMetaData): array - { - //Create reflectionClass for each meta data object - $reflectionClass = new \ReflectionClass($entityMetaData->name); - $propertyArray = $reflectionClass->getProperties(); - $properties = []; - - foreach ($propertyArray as $property) { - if ($this->annotationReader->getPropertyAnnotation($property, 'Ambta\DoctrineEncryptBundle\Configuration\Encrypted')) { - $properties[] = $property; - } - } - - return $properties; - } } diff --git a/src/Command/DoctrineDecryptDatabaseCommand.php b/src/Command/DoctrineDecryptDatabaseCommand.php index 592fa87f..4e80741c 100644 --- a/src/Command/DoctrineDecryptDatabaseCommand.php +++ b/src/Command/DoctrineDecryptDatabaseCommand.php @@ -1,21 +1,20 @@ - * @author Michael Feinbier */ class DoctrineDecryptDatabaseCommand extends AbstractCommand { @@ -37,22 +36,22 @@ protected function configure(): void */ protected function execute(InputInterface $input, OutputInterface $output): int { - // Get entity manager, question helper, subscriber service and annotation reader + // Get entity manager, question helper and service $question = $this->getHelper('question'); + $batchSize = $input->getArgument('batchSize'); // Get list of supported encryptors $supportedExtensions = DoctrineEncryptExtension::SupportedEncryptorClasses; - $batchSize = $input->getArgument('batchSize'); // If encryptor has been set use that encryptor else use default if ($input->getArgument('encryptor')) { if (isset($supportedExtensions[$input->getArgument('encryptor')])) { $reflection = new \ReflectionClass($supportedExtensions[$input->getArgument('encryptor')]); $encryptor = $reflection->newInstance(); - $this->subscriber->setEncryptor($encryptor); + $this->service->setEncryptor($encryptor); } else { if (class_exists($input->getArgument('encryptor'))) { - $this->subscriber->setEncryptor($input->getArgument('encryptor')); + $this->service->setEncryptor($input->getArgument('encryptor')); } else { $output->writeln('Given encryptor does not exists'); @@ -63,18 +62,25 @@ protected function execute(InputInterface $input, OutputInterface $output): int } } + $encryptTypes = array_keys(DoctrineEncryptBundle::ENCRYPT_TYPES); + + $totalPropertyCount = 0; + $encryptDetails = []; // Get entity manager metadata $metaDataArray = $this->entityManager->getMetadataFactory()->getAllMetadata(); - - // Set counter and loop through entity manager meta data - $propertyCount = 0; foreach ($metaDataArray as $metaData) { - if ($metaData instanceof ClassMetadataInfo and $metaData->isMappedSuperclass) { + if ($metaData instanceof ClassMetadata && $metaData->isMappedSuperclass) { continue; } - $countProperties = count($this->getEncryptionableProperties($metaData)); - $propertyCount += $countProperties; + foreach ($metaData->fieldMappings as $fieldMapping) { + if (in_array ($fieldMapping['type'], $encryptTypes)) { + if (! array_key_exists($metaData->name, $encryptDetails)) { + $encryptDetails[$metaData->name] = $metaData; + } + $totalPropertyCount++; + } + } } $defaultAnswer = false; @@ -87,8 +93,8 @@ protected function execute(InputInterface $input, OutputInterface $output): int } $confirmationQuestion = new ConfirmationQuestion( - '' . count($metaDataArray) . ' entities found which are containing ' . $propertyCount . ' properties with the encryption tag. ' . PHP_EOL . '' . - 'Which are going to be decrypted with [' . get_class($this->subscriber->getEncryptor()) . ']. ' . PHP_EOL . '' . + '' . count($encryptDetails) . ' entities found which are containing properties with the encryption types.' . PHP_EOL . '' . + 'Which are going to be decrypted with [' . get_class($this->service->getEncryptor()) . ']. ' . PHP_EOL . ''. 'Wrong settings can mess up your data and it will be unrecoverable. ' . PHP_EOL . '' . 'I advise you to make a backup. ' . PHP_EOL . '' . 'Continue with this action? (y/yes)', $defaultAnswer @@ -99,66 +105,61 @@ protected function execute(InputInterface $input, OutputInterface $output): int } // Start decrypting database + $_ENV['DOCTRINE_SKIP_ENCRYPT'] = true; $output->writeln('' . PHP_EOL . 'Decrypting all fields. This can take up to several minutes depending on the database size.'); - $valueCounter = 0; + $pac = PropertyAccess::createPropertyAccessor(); + $unitOfWork = $this->entityManager->getUnitOfWork(); + foreach ($encryptDetails as $entityName => $classMeta) { + $ctp = $classMeta->changeTrackingPolicy; + + // Tell the table class to not automatically calculate changed values but just + // mark those fields as dirty that get passed to propertyChanged function + // TODO : ClassMetadata::CHANGETRACKING_NOTIFY does not exist in latest version + $classMeta->setChangeTrackingPolicy(ClassMetadata::CHANGETRACKING_NOTIFY); - // Loop through entity manager meta data - foreach ($this->getEncryptionableEntityMetaData() as $metaData) { $i = 0; - $iterator = $this->getEntityIterator($metaData->name); - $totalCount = $this->getTableCount($metaData->name); + $valueCounter = 0; + $iterator = $this->getEntityIterator($entityName); + $totalCount = $this->getTableCount($entityName); - $output->writeln(sprintf('Processing %s', $metaData->name)); + $output->writeln(sprintf('Processing %s\'s records', $entityName)); $progressBar = new ProgressBar($output, $totalCount); foreach ($iterator as $row) { $entity = (is_array($row) ? $row[0] : $row); - // Create reflectionClass for each entity - $entityReflectionClass = new \ReflectionClass($entity); - - //Get the current encryptor used - $encryptorUsed = $this->subscriber->getEncryptor(); - - //Loop through the property's in the entity - foreach ($this->getEncryptionableProperties($metaData) as $property) { - $methodeName = ucfirst($property->getName()); - - $getter = 'get' . $methodeName; - $setter = 'set' . $methodeName; - - //Check if getter and setter are set - if ($entityReflectionClass->hasMethod($getter) && $entityReflectionClass->hasMethod($setter)) { - $unencrypted = $entity->$getter(); - $entity->$setter($unencrypted); - $valueCounter++; + // tell the unit of work that an value has changed no matter if the value + // is actually different from the value already persistent + // need all the values checked for the count + foreach ($metaData->fieldMappings as $fieldMapping) { + if (in_array ($fieldMapping['type'], $encryptTypes)) { + $value = $pac->getValue($entity, $fieldMapping['fieldName']); + if (! is_null ($value)) + { + // TODO : only need to set a single value + $valueCounter++; + $unitOfWork->propertyChanged($entity, $fieldMapping['fieldName'], $value, $value); + } } } - $this->subscriber->setEncryptor(null); - $this->entityManager->persist($entity); - if (($i % $batchSize) === 0) { $this->entityManager->flush(); $this->entityManager->clear(); } $progressBar->advance(1); $i++; - - $this->subscriber->setEncryptor($encryptorUsed); } - $progressBar->finish(); $output->writeln(''); - $encryptorUsed = $this->subscriber->getEncryptor(); - $this->subscriber->setEncryptor(null); $this->entityManager->flush(); $this->entityManager->clear(); - $this->subscriber->setEncryptor($encryptorUsed); + + $classMeta->setChangeTrackingPolicy($ctp); } - $output->writeln('' . PHP_EOL . 'Decryption finished values found: ' . $valueCounter . ', decrypted: ' . $this->subscriber->decryptCounter . '.' . PHP_EOL . 'All values are now decrypted.'); + $output->writeln('' . PHP_EOL . 'Decryption finished. Estimated values decrypted: ' . $valueCounter . '.' . PHP_EOL . 'All values are now decrypted.'); return defined('AbstractCommand::SUCCESS') ? AbstractCommand::SUCCESS : 0; } diff --git a/src/Command/DoctrineEncryptDatabaseCommand.php b/src/Command/DoctrineEncryptDatabaseCommand.php index b376c9ac..618f4789 100644 --- a/src/Command/DoctrineEncryptDatabaseCommand.php +++ b/src/Command/DoctrineEncryptDatabaseCommand.php @@ -1,20 +1,20 @@ - * @author Michael Feinbier */ class DoctrineEncryptDatabaseCommand extends AbstractCommand { @@ -36,7 +36,7 @@ protected function configure(): void */ protected function execute(InputInterface $input, OutputInterface $output): int { - // Get entity manager, question helper, subscriber service and annotation reader + // Get entity manager, question helper and service $question = $this->getHelper('question'); $batchSize = $input->getArgument('batchSize'); @@ -48,10 +48,10 @@ protected function execute(InputInterface $input, OutputInterface $output): int if (isset($supportedExtensions[$input->getArgument('encryptor')])) { $reflection = new \ReflectionClass($supportedExtensions[$input->getArgument('encryptor')]); $encryptor = $reflection->newInstance(); - $this->subscriber->setEncryptor($encryptor); + $this->service->setEncryptor($encryptor); } else { if (class_exists($input->getArgument('encryptor'))) { - $this->subscriber->setEncryptor($input->getArgument('encryptor')); + $this->service->setEncryptor($input->getArgument('encryptor')); } else { $output->writeln('Given encryptor does not exists'); @@ -62,6 +62,27 @@ protected function execute(InputInterface $input, OutputInterface $output): int } } + $encryptTypes = array_keys(DoctrineEncryptBundle::ENCRYPT_TYPES); + + $totalPropertyCount = 0; + $encryptDetails = []; + // Get entity manager metadata + $metaDataArray = $this->entityManager->getMetadataFactory()->getAllMetadata(); + foreach ($metaDataArray as $metaData) { + if ($metaData instanceof ClassMetadata && $metaData->isMappedSuperclass) { + continue; + } + + foreach ($metaData->fieldMappings as $fieldMapping) { + if (in_array ($fieldMapping['type'], $encryptTypes)) { + if (! array_key_exists($metaData->name, $encryptDetails)) { + $encryptDetails[$metaData->name] = $metaData; + } + $totalPropertyCount++; + } + } + } + $defaultAnswer = false; $answer = $input->getOption('answer'); if ($answer) { @@ -72,10 +93,9 @@ protected function execute(InputInterface $input, OutputInterface $output): int } // Get entity manager metadata - $metaDataArray = $this->getEncryptionableEntityMetaData(); $confirmationQuestion = new ConfirmationQuestion( - '' . count($metaDataArray) . ' entities found which are containing properties with the encryption tag.' . PHP_EOL . '' . - 'Which are going to be encrypted with [' . get_class($this->subscriber->getEncryptor()) . ']. ' . PHP_EOL . ''. + '' . count($encryptDetails) . ' entities found which are containing properties with the encryption tag.' . PHP_EOL . '' . + 'Which are going to be encrypted with [' . get_class($this->service->getEncryptor()) . ']. ' . PHP_EOL . ''. 'Wrong settings can mess up your data and it will be unrecoverable. ' . PHP_EOL . '' . 'I advise you to make a backup. ' . PHP_EOL . '' . 'Continue with this action? (y/yes)', $defaultAnswer @@ -85,37 +105,62 @@ protected function execute(InputInterface $input, OutputInterface $output): int return defined('AbstractCommand::FAILURE') ? AbstractCommand::FAILURE : 1; } - // Start decrypting database + // Start encrypting database $output->writeln('' . PHP_EOL . 'Encrypting all fields can take up to several minutes depending on the database size.'); - // Loop through entity manager meta data - foreach ($metaDataArray as $metaData) { + $pac = PropertyAccess::createPropertyAccessor(); + $unitOfWork = $this->entityManager->getUnitOfWork(); + foreach ($encryptDetails as $entityName => $classMeta) { + $ctp = $classMeta->changeTrackingPolicy; + + // Tell the table class to not automatically calculate changed values but just + // mark those fields as dirty that get passed to propertyChanged function + // TODO : ClassMetadata::CHANGETRACKING_NOTIFY does not exist in latest version + $classMeta->setChangeTrackingPolicy(ClassMetadata::CHANGETRACKING_NOTIFY); + $i = 0; - $iterator = $this->getEntityIterator($metaData->name); - $totalCount = $this->getTableCount($metaData->name); + $valueCounter = 0; + $iterator = $this->getEntityIterator($entityName); + $totalCount = $this->getTableCount($entityName); - $output->writeln(sprintf('Processing %s', $metaData->name)); + $output->writeln(sprintf('Processing %s\'s records', $entityName)); $progressBar = new ProgressBar($output, $totalCount); foreach ($iterator as $row) { $entity = (is_array($row) ? $row[0] : $row); - $this->subscriber->processFields($entity, $this->entityManager); - $this->entityManager->persist($entity); + + // tell the unit of work that an value has changed no matter if the value + // is actually different from the value already persistent + // need all the values checked for the count + foreach ($metaData->fieldMappings as $fieldMapping) { + if (in_array ($fieldMapping['type'], $encryptTypes)) { + $value = $pac->getValue($entity, $fieldMapping['fieldName']); + if (! is_null ($value)) + { + // TODO : only need to set a single value + $valueCounter++; + $unitOfWork->propertyChanged($entity, $fieldMapping['fieldName'], $value, $value); + } + } + } if (($i % $batchSize) === 0) { $this->entityManager->flush(); $this->entityManager->clear(); - $progressBar->advance($batchSize); } + $progressBar->advance(1); $i++; } $progressBar->finish(); $output->writeln(''); $this->entityManager->flush(); + $this->entityManager->clear(); + + $classMeta->setChangeTrackingPolicy($ctp); } // Say it is finished - $output->writeln('Encryption finished. Values encrypted: ' . $this->subscriber->encryptCounter . ' values.' . PHP_EOL . 'All values are now encrypted.'); + $output->writeln('' . PHP_EOL . 'Encryption finished. Estimated values encrypted: ' . $valueCounter . '.' . PHP_EOL . 'All values are now encrypted.'); return defined('AbstractCommand::SUCCESS') ? AbstractCommand::SUCCESS : 0; } diff --git a/src/Command/DoctrineEncryptStatusCommand.php b/src/Command/DoctrineEncryptStatusCommand.php index 6ed6344e..66772b4f 100644 --- a/src/Command/DoctrineEncryptStatusCommand.php +++ b/src/Command/DoctrineEncryptStatusCommand.php @@ -1,16 +1,14 @@ - * @author Michael Feinbier */ class DoctrineEncryptStatusCommand extends AbstractCommand { @@ -29,19 +27,26 @@ protected function configure(): void */ protected function execute(InputInterface $input, OutputInterface $output): int { - $metaDataArray = $this->entityManager->getMetadataFactory()->getAllMetadata(); + $encryptTypes = array_keys(DoctrineEncryptBundle::ENCRYPT_TYPES); $totalCount = 0; + $encryptDetails = []; + // Get entity manager metadata + $metaDataArray = $this->entityManager->getMetadataFactory()->getAllMetadata(); foreach ($metaDataArray as $metaData) { - if ($metaData instanceof ClassMetadataInfo && $metaData->isMappedSuperclass) { + if ($metaData instanceof ClassMetadata && $metaData->isMappedSuperclass) { continue; } $count = 0; - $encryptedPropertiesCount = count($this->getEncryptionableProperties($metaData)); - if ($encryptedPropertiesCount > 0) { - $totalCount += $encryptedPropertiesCount; - $count += $encryptedPropertiesCount; + foreach ($metaData->fieldMappings as $fieldMapping) { + if (in_array ($fieldMapping['type'], $encryptTypes)) { + if (! array_key_exists($metaData->name, $encryptDetails)) { + $encryptDetails[$metaData->name] = true; + } + $count++; + $totalCount++; + } } if ($count > 0) { @@ -52,7 +57,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int } $output->writeln(''); - $output->writeln(sprintf('%d entities found which are containing %d encrypted properties.', count($metaDataArray), $totalCount)); + $output->writeln(sprintf('%d entities found which contain %d encrypted properties.', count($encryptDetails), $totalCount)); return defined('AbstractCommand::SUCCESS') ? AbstractCommand::SUCCESS : 0; } diff --git a/src/Configuration/Annotation.php b/src/Configuration/Annotation.php deleted file mode 100644 index 0896617d..00000000 --- a/src/Configuration/Annotation.php +++ /dev/null @@ -1,12 +0,0 @@ - - * @Annotation - * @NamedArgumentConstructor - * @Target("PROPERTY") - */ -#[Attribute(Attribute::TARGET_PROPERTY)] -final class Encrypted implements Annotation -{ - private const ALLOWED_TYPES = [ - 'string', - 'datetime', - 'json', - 'array' - ]; - - /** - * @var string - */ - public $type; - - - - /** - * @param 'string'|'datetime'|'json'|'array' $type - */ - public function __construct(string $type = 'string') - { - if (!in_array ($type, self::ALLOWED_TYPES, true)) - { - throw new InvalidArgumentException (sprintf('%s is not a supported type for %s', $type, self::class)); - } - $this->type = $type; - } -} diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php index b9a5a330..10d9ce57 100644 --- a/src/DependencyInjection/Configuration.php +++ b/src/DependencyInjection/Configuration.php @@ -1,6 +1,6 @@ getRootNode(); - } else { - // BC layer for symfony/config 4.1 and older - $rootNode = $treeBuilder->root('ambta_doctrine_encrypt'); - } + $treeBuilder = new TreeBuilder('doctrine_encrypt'); + $rootNode = $treeBuilder->getRootNode(); // Grammar of config tree $rootNode diff --git a/src/DependencyInjection/DoctrineEncryptExtension.php b/src/DependencyInjection/DoctrineEncryptExtension.php index 10d30237..f1ca7ea6 100644 --- a/src/DependencyInjection/DoctrineEncryptExtension.php +++ b/src/DependencyInjection/DoctrineEncryptExtension.php @@ -1,9 +1,9 @@ setParameter('ambta_doctrine_encrypt.encryptor_class_name', $config['encryptor_class_full']); - $container->setParameter('ambta_doctrine_encrypt.secret_directory_path',$config['secret_directory_path']); - $container->setParameter('ambta_doctrine_encrypt.enable_secret_generation',$config['enable_secret_generation']); + $container->setParameter('doctrine_encrypt.encryptor_class_name', $config['encryptor_class_full']); + $container->setParameter('doctrine_encrypt.secret_directory_path',$config['secret_directory_path']); + $container->setParameter('doctrine_encrypt.enable_secret_generation',$config['enable_secret_generation']); if (isset($config['secret'])) { - $container->setParameter('ambta_doctrine_encrypt.secret',$config['secret']); + $container->setParameter('doctrine_encrypt.secret',$config['secret']); } // Load service file @@ -64,20 +64,6 @@ public function load(array $configs, ContainerBuilder $container): void if (Kernel::MAJOR_VERSION < 5 || (Kernel::MAJOR_VERSION === 5 && Kernel::MINOR_VERSION < 4)) { throw new \RuntimeException('doctrineencryptbundle/doctrine-encrypt-bundle expects symfony-version >= 5.4!'); } - - // Symfony 5-6 - if (Kernel::MAJOR_VERSION < 7) { - // PHP 7.x (no attributes) - if (PHP_VERSION_ID < 80000) { - $loader->load('services_subscriber_with_annotations.yml'); - // PHP 8.x (annotations and attributes) - } else { - $loader->load('services_subscriber_with_annotations_and_attributes.yml'); - } - // Symfony 7 (only attributes) - } else { - $loader->load('service_listeners_with_attributes.yml'); - } } /** @@ -87,6 +73,6 @@ public function load(array $configs, ContainerBuilder $container): void */ public function getAlias(): string { - return 'ambta_doctrine_encrypt'; + return 'doctrine_encrypt'; } } diff --git a/src/DoctrineEncryptBundle.php b/src/DoctrineEncryptBundle.php new file mode 100644 index 00000000..6d19db82 --- /dev/null +++ b/src/DoctrineEncryptBundle.php @@ -0,0 +1,53 @@ + Encrypted::class, + 'encrypted_datetime' => EncryptedDateTime::class, + 'encrypted_json' => EncryptedJSON::class, + 'encrypted_array' => EncryptedArray::class + ]; + + public function boot(): void + { + $connections = $this->container->get('doctrine')->getConnections(); + $service = $this->container->get('doctrine_encrypt.encrypt_service'); + foreach (self::ENCRYPT_TYPES as $encyptName => $encryptClass) + { + if (! Type::hasType($encyptName)) + { + Type::addType($encyptName, $encryptClass); + /** @var \DoctrineEncryptBundle\Traits\DoctrineEncrypt $addedType */ + $addedType = Type::getType($encyptName); + $addedType->setService($service); + } + + foreach ($connections as $connectionName => $connection) + { + $databasePlatform = $connection->getDatabasePlatform(); + if (! $databasePlatform->hasDoctrineTypeMappingFor($encyptName)) + { + $databasePlatform->registerDoctrineTypeMapping($encyptName,$encyptName); + } + } + } + } + + public function getContainerExtension(): ?ExtensionInterface + { + return new DoctrineEncryptExtension(); + } +} diff --git a/src/Encryptors/DefuseEncryptor.php b/src/Encryptors/DefuseEncryptor.php index e60f48de..d619e045 100644 --- a/src/Encryptors/DefuseEncryptor.php +++ b/src/Encryptors/DefuseEncryptor.php @@ -1,13 +1,9 @@ */ class DefuseEncryptor implements EncryptorInterface diff --git a/src/Encryptors/EncryptorInterface.php b/src/Encryptors/EncryptorInterface.php index fdb1847c..a1428e5d 100644 --- a/src/Encryptors/EncryptorInterface.php +++ b/src/Encryptors/EncryptorInterface.php @@ -1,11 +1,9 @@ */ interface EncryptorInterface { diff --git a/src/Encryptors/HaliteEncryptor.php b/src/Encryptors/HaliteEncryptor.php index 345ff1d4..029ba824 100644 --- a/src/Encryptors/HaliteEncryptor.php +++ b/src/Encryptors/HaliteEncryptor.php @@ -1,6 +1,6 @@ */ class HaliteEncryptor implements EncryptorInterface { - /** @var EncryptionKey|null */ + /** + * @var EncryptionKey|null + */ private $encryptionKey = null; - /** @var string */ + + /** + * @var string + */ private $secret; /** diff --git a/src/Factories/SecretFactory.php b/src/Factories/SecretFactory.php index 9a89caa9..4b5bd335 100644 --- a/src/Factories/SecretFactory.php +++ b/src/Factories/SecretFactory.php @@ -1,10 +1,10 @@ - * - * @internal - */ -final class AttributeAnnotationReader implements Reader -{ - /** - * @var Reader - */ - private $annotationReader; - - /** - * @var AttributeReader - */ - private $attributeReader; - - public function __construct(AttributeReader $attributeReader, Reader $annotationReader, string $cacheDir) - { - $this->attributeReader = $attributeReader; - $annotationsCache = new FilesystemAdapter('', 0, $cacheDir.'/doctrine_encrypt'); - $this->annotationReader = new PsrCachedReader ($annotationReader, $annotationsCache); - } - - /** - * @return Annotation[] - */ - public function getClassAnnotations(ReflectionClass $class): array - { - $annotations = $this->attributeReader->getClassAnnotations($class); - - if ([] !== $annotations) { - return $annotations; - } - - return $this->annotationReader->getClassAnnotations($class); - } - - /** - * @param class-string $annotationName the name of the annotation - * - * @return T|null the Annotation or NULL, if the requested annotation does not exist - * - * @template T - */ - public function getClassAnnotation(ReflectionClass $class, $annotationName) - { - $annotation = $this->attributeReader->getClassAnnotation($class, $annotationName); - - if (null !== $annotation) { - return $annotation; - } - - return $this->annotationReader->getClassAnnotation($class, $annotationName); - } - - /** - * @return Annotation[] - */ - public function getPropertyAnnotations(\ReflectionProperty $property): array - { - $propertyAnnotations = $this->attributeReader->getPropertyAnnotations($property); - - if ([] !== $propertyAnnotations) { - return $propertyAnnotations; - } - - return $this->annotationReader->getPropertyAnnotations($property); - } - - /** - * @param class-string $annotationName the name of the annotation - * - * @return T|null the Annotation or NULL, if the requested annotation does not exist - * - * @template T - */ - public function getPropertyAnnotation(\ReflectionProperty $property, $annotationName) - { - $annotation = $this->attributeReader->getPropertyAnnotation($property, $annotationName); - - if (null !== $annotation) { - return $annotation; - } - - return $this->annotationReader->getPropertyAnnotation($property, $annotationName); - } - - public function getMethodAnnotations(ReflectionMethod $method): array - { - throw new \BadMethodCallException('Not implemented'); - } - - /** - * @param ReflectionMethod $method - * @param $annotationName - * @return mixed - */ - public function getMethodAnnotation(ReflectionMethod $method, $annotationName): mixed - { - throw new \BadMethodCallException('Not implemented'); - } -} diff --git a/src/Mapping/AttributeReader.php b/src/Mapping/AttributeReader.php deleted file mode 100644 index bd82a031..00000000 --- a/src/Mapping/AttributeReader.php +++ /dev/null @@ -1,102 +0,0 @@ - - * - * @internal - */ -final class AttributeReader -{ - /** @var array */ - private $isRepeatableAttribute = []; - - /** - * @param ReflectionClass $class - * @return Annotation[] - */ - public function getClassAnnotations(ReflectionClass $class): array - { - return (method_exists($class, 'getAttributes')) ? $this->convertToAttributeInstances($class->getAttributes()) : []; - } - - /** - * @phpstan-param class-string $annotationName - * - * @return Annotation|Annotation[]|null - */ - public function getClassAnnotation(ReflectionClass $class, string $annotationName) - { - return $this->getClassAnnotations($class)[$annotationName] ?? null; - } - - /** - * @param \ReflectionProperty $property - * @return Annotation[] - */ - public function getPropertyAnnotations(\ReflectionProperty $property): array - { - return (method_exists($property, 'getAttributes')) ? $this->convertToAttributeInstances($property->getAttributes()) : []; - } - - /** - * @phpstan-param class-string $annotationName - * - * @return Annotation|Annotation[]|null - */ - public function getPropertyAnnotation(\ReflectionProperty $property, string $annotationName) - { - return $this->getPropertyAnnotations($property)[$annotationName] ?? null; - } - - /** - * @param array<\ReflectionAttribute> $attributes - * - * @return array - */ - private function convertToAttributeInstances(array $attributes): array - { - $instances = []; - - foreach ($attributes as $attribute) { - $attributeName = $attribute->getName(); - assert(is_string($attributeName)); - // Make sure we only get Gedmo Annotations - if (!is_subclass_of($attributeName, Annotation::class)) { - continue; - } - - $instance = $attribute->newInstance(); - assert($instance instanceof Annotation); - - if ($this->isRepeatable($attributeName)) { - if (!isset($instances[$attributeName])) { - $instances[$attributeName] = []; - } - - $instances[$attributeName][] = $instance; - } else { - $instances[$attributeName] = $instance; - } - } - - return $instances; - } - - private function isRepeatable(string $attributeClassName): bool - { - if (isset($this->isRepeatableAttribute[$attributeClassName])) { - return $this->isRepeatableAttribute[$attributeClassName]; - } - - $reflectionClass = new ReflectionClass($attributeClassName); - $attribute = $reflectionClass->getAttributes()[0]->newInstance(); - - return $this->isRepeatableAttribute[$attributeClassName] = ($attribute->flags & Attribute::IS_REPEATABLE) > 0; - } -} diff --git a/src/Resources/config/service_listeners_with_attributes.yml b/src/Resources/config/service_listeners_with_attributes.yml deleted file mode 100644 index 2e0c497e..00000000 --- a/src/Resources/config/service_listeners_with_attributes.yml +++ /dev/null @@ -1,15 +0,0 @@ -services: - ambta_doctrine_attribute_reader: - class: Ambta\DoctrineEncryptBundle\Mapping\AttributeReader - - ambta_doctrine_annotation_reader: '@ambta_doctrine_attribute_reader' - - ambta_doctrine_encrypt.orm_subscriber: - class: Ambta\DoctrineEncryptBundle\Subscribers\DoctrineEncryptSubscriber - arguments: [ '@ambta_doctrine_attribute_reader', '@ambta_doctrine_encrypt.encryptor' ] - tags: - - { name: 'doctrine.event_listener', event: 'postLoad' } - - { name: 'doctrine.event_listener', event: 'onFlush' } - - { name: 'doctrine.event_listener', event: 'preFlush' } - - { name: 'doctrine.event_listener', event: 'postFlush' } - - { name: 'doctrine.event_listener', event: 'onClear' } \ No newline at end of file diff --git a/src/Resources/config/services.yml b/src/Resources/config/services.yml index 067864e9..29e4287b 100644 --- a/src/Resources/config/services.yml +++ b/src/Resources/config/services.yml @@ -1,27 +1,26 @@ services: - ambta_doctrine_encrypt.subscriber: - alias: ambta_doctrine_encrypt.orm_subscriber + doctrine_encrypt.encrypt_service: + class: DoctrineEncryptBundle\Service\Encrypt + arguments: ["@doctrine_encrypt.encryptor"] + public: true - ambta_doctrine_encrypt.command.decrypt.database: - class: Ambta\DoctrineEncryptBundle\Command\DoctrineDecryptDatabaseCommand + doctrine_encrypt.command.decrypt.database: + class: DoctrineEncryptBundle\Command\DoctrineDecryptDatabaseCommand tags: ['console.command'] arguments: - "@doctrine.orm.entity_manager" - - "@ambta_doctrine_annotation_reader" - - "@ambta_doctrine_encrypt.subscriber" + - "@doctrine_encrypt.encrypt_service" - ambta_doctrine_encrypt.command.encrypt.database: - class: Ambta\DoctrineEncryptBundle\Command\DoctrineEncryptDatabaseCommand + doctrine_encrypt.command.encrypt.database: + class: DoctrineEncryptBundle\Command\DoctrineEncryptDatabaseCommand tags: ['console.command'] arguments: - "@doctrine.orm.entity_manager" - - "@ambta_doctrine_annotation_reader" - - "@ambta_doctrine_encrypt.subscriber" + - "@doctrine_encrypt.encrypt_service" - ambta_doctrine_encrypt.command.encrypt.status: - class: Ambta\DoctrineEncryptBundle\Command\DoctrineEncryptStatusCommand + doctrine_encrypt.command.encrypt.status: + class: DoctrineEncryptBundle\Command\DoctrineEncryptStatusCommand tags: ['console.command'] arguments: - "@doctrine.orm.entity_manager" - - "@ambta_doctrine_annotation_reader" - - "@ambta_doctrine_encrypt.subscriber" + - "@doctrine_encrypt.encrypt_service" diff --git a/src/Resources/config/services_subscriber_with_annotations.yml b/src/Resources/config/services_subscriber_with_annotations.yml deleted file mode 100644 index 6ef90ad3..00000000 --- a/src/Resources/config/services_subscriber_with_annotations.yml +++ /dev/null @@ -1,9 +0,0 @@ -services: - # Use the regular annotation reader - ambta_doctrine_annotation_reader: "@annotations.reader" - - ambta_doctrine_encrypt.orm_subscriber: - class: Ambta\DoctrineEncryptBundle\Subscribers\DoctrineEncryptSubscriber - arguments: ["@ambta_doctrine_annotation_reader", "@ambta_doctrine_encrypt.encryptor"] - tags: - - { name: doctrine.event_subscriber } \ No newline at end of file diff --git a/src/Resources/config/services_subscriber_with_annotations_and_attributes.yml b/src/Resources/config/services_subscriber_with_annotations_and_attributes.yml deleted file mode 100644 index f2f88b9b..00000000 --- a/src/Resources/config/services_subscriber_with_annotations_and_attributes.yml +++ /dev/null @@ -1,13 +0,0 @@ -services: - ambta_doctrine_attribute_reader: - class: Ambta\DoctrineEncryptBundle\Mapping\AttributeReader - - ambta_doctrine_annotation_reader: - class: Ambta\DoctrineEncryptBundle\Mapping\AttributeAnnotationReader - arguments: ["@ambta_doctrine_attribute_reader", "@annotations.reader", "%kernel.cache_dir%"] - - ambta_doctrine_encrypt.orm_subscriber: - class: Ambta\DoctrineEncryptBundle\Subscribers\DoctrineEncryptSubscriber - arguments: ["@ambta_doctrine_annotation_reader", "@ambta_doctrine_encrypt.encryptor"] - tags: - - { name: doctrine.event_subscriber } \ No newline at end of file diff --git a/src/Resources/config/services_with_secret.yml b/src/Resources/config/services_with_secret.yml index a98d13b5..303766e1 100644 --- a/src/Resources/config/services_with_secret.yml +++ b/src/Resources/config/services_with_secret.yml @@ -1,5 +1,5 @@ services: - ambta_doctrine_encrypt.encryptor: - class: "%ambta_doctrine_encrypt.encryptor_class_name%" + doctrine_encrypt.encryptor: + class: "%doctrine_encrypt.encryptor_class_name%" arguments: - $secret: "%ambta_doctrine_encrypt.secret%" \ No newline at end of file + $secret: "%doctrine_encrypt.secret%" \ No newline at end of file diff --git a/src/Resources/config/services_with_secretfactory.yml b/src/Resources/config/services_with_secretfactory.yml index 55fa670b..40bbdc73 100644 --- a/src/Resources/config/services_with_secretfactory.yml +++ b/src/Resources/config/services_with_secretfactory.yml @@ -1,11 +1,11 @@ services: - ambta_doctrine_encrypt.encryptor: - class: "%ambta_doctrine_encrypt.encryptor_class_name%" + doctrine_encrypt.encryptor: + class: "%doctrine_encrypt.encryptor_class_name%" arguments: - - '@=service("ambta_doctrine_encrypt.secret_factory").getSecret(parameter("ambta_doctrine_encrypt.encryptor_class_name"))' + - '@=service("doctrine_encrypt.secret_factory").getSecret(parameter("doctrine_encrypt.encryptor_class_name"))' - ambta_doctrine_encrypt.secret_factory: - class: Ambta\DoctrineEncryptBundle\Factories\SecretFactory + doctrine_encrypt.secret_factory: + class: DoctrineEncryptBundle\Factories\SecretFactory arguments: - $secretDirectory: '%ambta_doctrine_encrypt.secret_directory_path%' - $enableSecretCreation: '%ambta_doctrine_encrypt.enable_secret_generation%' \ No newline at end of file + $secretDirectory: '%doctrine_encrypt.secret_directory_path%' + $enableSecretCreation: '%doctrine_encrypt.enable_secret_generation%' \ No newline at end of file diff --git a/src/Resources/doc/usage.md b/src/Resources/doc/usage.md index 67ff2f5a..f749157a 100644 --- a/src/Resources/doc/usage.md +++ b/src/Resources/doc/usage.md @@ -1,11 +1,5 @@ # Usage -### Column Type - -Ensure that the column type for the property is always set to string or text. - -The column type should always relate back to one of the database supported string types as the encrypted data saved to the database will always be a string. - ### Entity ``` php @@ -39,75 +33,6 @@ class User { It is as simple as that, the field will now be encrypted the first time the users entity gets edited. We keep an prefix to check if data is encrypted or not so, unencrypted data will still work even if the field is encrypted. -#### Supported Data Types - -The supported data types to be encrypted and decrypted are: -* string (The Default) -* datetime -* json -* array - -Example usage in the Entity: - -```php -namespace Acme\DemoBundle\Entity; - -use Doctrine\ORM\Mapping as ORM; - -// importing @Encrypted annotation -use Ambta\DoctrineEncryptBundle\Configuration\Encrypted; - -/** - * @ORM\Entity - * @ORM\Table(name="test") - */ -class Test { - - .. - - /** - * @ORM\Column(type="string", name="string") - * @Encrypted - * @var string - */ - private $string; - - /** - * @ORM\Column(type="string", name="another_string") - * @Encrypted(type="string") - * @var string - */ - private $anotherString; - - /** - * @ORM\Column(type="text", name="datetime") - * @Encrypted(type="datetime") - * @var DateTime - */ - private $datetime; - - /** - * @ORM\Column(type="text", name="json") - * @Encrypted(type="json") - * @var array - */ - private $json; - - /** - * @ORM\Column(type="text", name="array") - * @Encrypted(type="array") - * @var array - */ - private $array; - - .. - -} -``` - -Please note again that the ORM Column types relate to string values as the saved data whould be the encrypted string. -If using MySql for example you will not be able to use the JSON functions directly in the database when the json data is encrypted. - ### Entity Method Behaviour The bundle will not know what the entity methods do in the getter and setter so if there are any additional behaviour. diff --git a/src/Service/Encrypt.php b/src/Service/Encrypt.php new file mode 100755 index 00000000..26df63b4 --- /dev/null +++ b/src/Service/Encrypt.php @@ -0,0 +1,123 @@ +'; + + /** + * Encryptor + * + * @var EncryptorInterface|null + */ + private $encryptor; + + /** + * Doctrine AbstractPlatform. Always uses MySQL80Platform to ensure that the values are encrypted and decrypted the same even if moved between databases + * + * @var AbstractPlatform + */ + private $platform; + + /** + * Initialization of service + * + * @param EncryptorInterface $encryptor (Optional) An EncryptorInterface. + */ + public function __construct(EncryptorInterface $encryptor) + { + $this->encryptor = $encryptor; + $this->platform = new MySQL80Platform(); + } + + /** + * Change the encryptor + * + * @param EncryptorInterface|null $encryptor + */ + public function setEncryptor(?EncryptorInterface $encryptor = null) + { + $this->encryptor = $encryptor; + } + + /** + * Get the current encryptor + * + * @return EncryptorInterface|null returns the encryptor class or null + */ + public function getEncryptor(): ?EncryptorInterface + { + return $this->encryptor; + } + + /** + * Process encrypt + * + * @param 'string'|'datetime'|'json'|'array' $type + * @param mixed $value + * + * @return mixed + * + */ + public function encrypt(string $type, mixed $value): mixed + { + // TODO : probably cannot return null when $this->encryptor is not set + if (is_null ($value) || is_null ($this->encryptor)) + { + return null; + } + + $encryptDbalType = Type::getType($type); + $usedValue = $encryptDbalType->convertToDatabaseValue($value, $this->platform); + if (array_key_exists('DOCTRINE_SKIP_ENCRYPT', $_ENV) && $_ENV['DOCTRINE_SKIP_ENCRYPT'] === true) + { + return $usedValue; + } + + if (substr($usedValue, -strlen(self::ENCRYPTION_MARKER)) != self::ENCRYPTION_MARKER) + { + return $this->getEncryptor()->encrypt($usedValue).self::ENCRYPTION_MARKER; + } + + return $usedValue; + } + + /** + * Process decrypt + * + * @param 'string'|'datetime'|'json'|'array' $type + * @param mixed $value + * + * @return mixed + * + */ + public function decrypt(string $type, mixed $value): mixed + { + // TODO : probably cannot return null when $this->encryptor is not set + if (is_null ($value) || is_null ($this->encryptor)) + { + return null; + } + + if (substr($value, -strlen(self::ENCRYPTION_MARKER)) == self::ENCRYPTION_MARKER) + { + $encryptDbalType = Type::getType($type); + $currentValue = $this->getEncryptor()->decrypt(substr($value, 0, -strlen(self::ENCRYPTION_MARKER))); + return $encryptDbalType->convertToPHPValue($currentValue, $this->platform); + } + + return $value; + } +} diff --git a/src/Subscribers/DoctrineEncryptSubscriber.php b/src/Subscribers/DoctrineEncryptSubscriber.php deleted file mode 100644 index 1b7d4c6e..00000000 --- a/src/Subscribers/DoctrineEncryptSubscriber.php +++ /dev/null @@ -1,401 +0,0 @@ -'; - - /** - * Encryptor interface namespace - */ - const ENCRYPTOR_INTERFACE_NS = 'Ambta\DoctrineEncryptBundle\Encryptors\EncryptorInterface'; - - /** - * Encrypted annotation full name - */ - const ENCRYPTED_ANN_NAME = 'Ambta\DoctrineEncryptBundle\Configuration\Encrypted'; - - /** - * Encryptor - * @var EncryptorInterface|null - */ - private $encryptor; - - /** - * Annotation reader - * @var Reader|AttributeReader - */ - private $annReader; - - /** - * Used for restoring the encryptor after changing it - * @var EncryptorInterface|string - */ - private $restoreEncryptor; - - /** - * Used for restoring the encryptor after changing it - * @var PropertyAccessorInterface|string - */ - private $pac; - - /** - * Count amount of decrypted values in this service - * @var integer - */ - public $decryptCounter = 0; - - /** - * Count amount of encrypted values in this service - * @var integer - */ - public $encryptCounter = 0; - - /** @var array */ - private $cachedDecryptions = []; - - /** @var array */ - private $cachedClassProperties = []; - - /** @var array */ - private $cachedClassPropertiesAreEmbedded = []; - - /** @var array */ - private $cachedClassPropertiesAreEncrypted = []; - - /** @var array */ - private $cachedClassesContainAnEncryptProperty = []; - - /** - * Initialization of subscriber - * - * @param Reader|AttributeReader $annReader - * @param EncryptorInterface $encryptor (Optional) An EncryptorInterface. - */ - public function __construct($annReader, EncryptorInterface $encryptor) - { - $this->annReader = $annReader; - $this->encryptor = $encryptor; - $this->restoreEncryptor = $this->encryptor; - $this->pac = PropertyAccess::createPropertyAccessor(); - } - - /** - * Change the encryptor - * - * @param EncryptorInterface|null $encryptor - */ - public function setEncryptor(?EncryptorInterface $encryptor = null) - { - $this->encryptor = $encryptor; - } - - /** - * Get the current encryptor - * - * @return EncryptorInterface|null returns the encryptor class or null - */ - public function getEncryptor(): ?EncryptorInterface - { - return $this->encryptor; - } - - /** - * Restore encryptor to the one set in the constructor. - */ - public function restoreEncryptor() - { - $this->encryptor = $this->restoreEncryptor; - } - - /** - * Listen a postLoad lifecycle event. - * Decrypt entities property's values when loaded into the entity manger - * - * @param LifecycleEventArgs $args - */ - public function postLoad($args) - { - $entity = $args->getObject(); - $this->processFields($entity, $args->getObjectManager(), false); - } - - /** - * Listen to onflush event - * Encrypt entities that are inserted into the database - * - * @param PreFlushEventArgs $preFlushEventArgs - */ - public function preFlush(PreFlushEventArgs $preFlushEventArgs) - { - $objectManager = method_exists($preFlushEventArgs, 'getObjectManager') ? $preFlushEventArgs->getObjectManager() : $preFlushEventArgs->getEntityManager(); - $unitOfWork = $objectManager->getUnitOfWork(); - foreach ($unitOfWork->getIdentityMap() as $entityName => $entityArray) { - if (isset($this->cachedDecryptions[$entityName])) { - foreach ($entityArray as $entityId => $instance) { - $this->processFields($instance, $objectManager, true); - } - } - } - $this->cachedDecryptions = []; - } - - /** - * Listen to onflush event - * Encrypt entities that are inserted into the database - * - * @param OnFlushEventArgs $onFlushEventArgs - */ - public function onFlush(OnFlushEventArgs $onFlushEventArgs) - { - $objectManager = method_exists($onFlushEventArgs, 'getObjectManager') ? $onFlushEventArgs->getObjectManager() : $onFlushEventArgs->getEntityManager(); - $unitOfWork = $objectManager->getUnitOfWork(); - foreach ($unitOfWork->getScheduledEntityInsertions() as $entity) { - $encryptCounterBefore = $this->encryptCounter; - $this->processFields($entity,$objectManager,true); - if ($this->encryptCounter > $encryptCounterBefore) { - $classMetadata = $objectManager->getClassMetadata(get_class($entity)); - $unitOfWork->recomputeSingleEntityChangeSet($classMetadata, $entity); - } - } - } - - /** - * Listen to postFlush event - * Decrypt entities after having been inserted into the database - * - * @param PostFlushEventArgs $postFlushEventArgs - */ - public function postFlush(PostFlushEventArgs $postFlushEventArgs) - { - $objectManager = method_exists($postFlushEventArgs, 'getObjectManager') ? $postFlushEventArgs->getObjectManager() : $postFlushEventArgs->getEntityManager(); - $unitOfWork = $objectManager->getUnitOfWork(); - foreach ($unitOfWork->getIdentityMap() as $entityMap) { - foreach ($entityMap as $entity) { - $this->processFields($entity,$objectManager, false); - } - } - } - - public function onClear(OnClearEventArgs $onClearEventArgs) - { - $this->cachedDecryptions = []; - $this->decryptCounter = 0; - $this->encryptCounter = 0; - } - - /** - * Realization of EventSubscriber interface method. - * - * @return array Return all events which this subscriber is listening - */ - public function getSubscribedEvents(): array - { - return array( - Events::postLoad, - Events::onFlush, - Events::preFlush, - Events::postFlush, - Events::onClear, - ); - } - - /** - * Process (encrypt/decrypt) entities fields - * - * @param Object $entity doctrine entity - * @param EntityManagerInterface $entityManager - * @param Boolean $isEncryptOperation If true - encrypt, false - decrypt entity - * - * @return object|null - * @throws \RuntimeException - * - */ - public function processFields(object $entity, EntityManagerInterface $entityManager, bool $isEncryptOperation = true): ?object - { - if (!empty($this->encryptor) && $this->containsEncryptProperties($entity)) { - $realClass = ClassUtils::getClass($entity); - - // Get ReflectionClass of our entity - $properties = $this->getClassProperties($realClass); - - // Foreach property in the reflection class - foreach ($properties as $refProperty) { - if ($this->isPropertyAnEmbeddedMapping($refProperty)) { - $this->handleEmbeddedAnnotation($entity, $entityManager, $refProperty, $isEncryptOperation); - continue; - } - - /** - * If property is an normal value and contains the Encrypt tag, lets encrypt/decrypt that property - */ - $encryptType = $this->getEncryptedPropertyType($refProperty); - if ($encryptType) { - $encryptDbalType = \Doctrine\DBAL\Types\Type::getType($encryptType); - $platform = new MySQL80Platform(); - $rootEntityName = $entityManager->getClassMetadata(get_class($entity))->rootEntityName; - - $value = $this->pac->getValue($entity, $refProperty->getName()); - if (!is_null($value) and !empty($value)) { - if ($isEncryptOperation) { - // Convert to a string using doctrine-type - $usedValue = $encryptDbalType->convertToDatabaseValue($value, $platform); - - if (isset($this->cachedDecryptions[$rootEntityName][spl_object_id($entity)][$refProperty->getName()][$usedValue])) { - $this->pac->setValue($entity, $refProperty->getName(), $this->cachedDecryptions[$rootEntityName][spl_object_id($entity)][$refProperty->getName()][$usedValue]); - } elseif (substr($usedValue, -strlen(self::ENCRYPTION_MARKER)) != self::ENCRYPTION_MARKER) { - $this->encryptCounter++; - $currentPropValue = $this->encryptor->encrypt($usedValue).self::ENCRYPTION_MARKER; - $this->pac->setValue($entity, $refProperty->getName(), $currentPropValue); - } - } else { - if (substr($value, -strlen(self::ENCRYPTION_MARKER)) == self::ENCRYPTION_MARKER) { - $this->decryptCounter++; - $currentPropValue = $this->encryptor->decrypt(substr($value, 0, -5)); - $this->cachedDecryptions[$rootEntityName][spl_object_id($entity)][$refProperty->getName()][$currentPropValue] = $value; - - // Convert from a string to the PHP-type again using dbal-type - $actualValue = $encryptDbalType->convertToPHPValue($currentPropValue, $platform); - $this->pac->setValue($entity, $refProperty->getName(),$actualValue); - } - } - } - } - } - - return $entity; - } - - return $entity; - } - - private function handleEmbeddedAnnotation($entity, EntityManagerInterface $entityManager, ReflectionProperty $embeddedProperty, bool $isEncryptOperation = true) - { - $propName = $embeddedProperty->getName(); - - $embeddedEntity = $this->pac->getValue($entity, $propName); - - if ($embeddedEntity) { - $this->processFields($embeddedEntity, $entityManager, $isEncryptOperation); - } - } - - /** - * Recursive function to get an associative array of class properties - * including inherited ones from extended classes - * - * @param string $className Class name - * - * @return array|ReflectionProperty[] - */ - private function getClassProperties(string $className): array - { - if (!array_key_exists($className,$this->cachedClassProperties)) { - $reflectionClass = new ReflectionClass($className); - $properties = $reflectionClass->getProperties(); - $propertiesArray = array(); - - foreach ($properties as $property) { - $propertyName = $property->getName(); - $propertiesArray[$propertyName] = $property; - } - - if ($parentClass = $reflectionClass->getParentClass()) { - $parentPropertiesArray = $this->getClassProperties($parentClass->getName()); - if (count($parentPropertiesArray) > 0) { - $propertiesArray = array_merge($parentPropertiesArray, $propertiesArray); - } - } - - $this->cachedClassProperties[$className] = $propertiesArray; - } - - return $this->cachedClassProperties[$className]; - } - - /** - * @return bool - */ - private function isPropertyAnEmbeddedMapping(ReflectionProperty $refProperty) - { - $key = $refProperty->getDeclaringClass()->getName().$refProperty->getName(); - if (!array_key_exists($key,$this->cachedClassPropertiesAreEmbedded)) { - $this->cachedClassPropertiesAreEmbedded[$key] = (bool) $this->annReader->getPropertyAnnotation($refProperty, 'Doctrine\ORM\Mapping\Embedded'); - } - - return $this->cachedClassPropertiesAreEmbedded[$key]; - } - - /** - * @return string|null - */ - private function getEncryptedPropertyType(ReflectionProperty $refProperty) - { - $key = $refProperty->getDeclaringClass()->getName().$refProperty->getName(); - if (!array_key_exists($key,$this->cachedClassPropertiesAreEncrypted)) { - $type = null; - $propertyAnnotation = $this->annReader->getPropertyAnnotation($refProperty, self::ENCRYPTED_ANN_NAME); - if ($propertyAnnotation) - { - $type = $propertyAnnotation->type; - } - $this->cachedClassPropertiesAreEncrypted[$key] = $type; - } - - return $this->cachedClassPropertiesAreEncrypted[$key]; - } - - private function containsEncryptProperties($entity) - { - $realClass = ClassUtils::getClass($entity); - - if (!array_key_exists($realClass,$this->cachedClassesContainAnEncryptProperty)) { - $this->cachedClassesContainAnEncryptProperty[$realClass] = false; - - // Get ReflectionClass of our entity - $properties = $this->getClassProperties($realClass); - - // Foreach property in the reflection class - foreach ($properties as $refProperty) { - if ($this->isPropertyAnEmbeddedMapping($refProperty)) { - $embeddedEntity = $this->pac->getValue($entity, $refProperty->getName()); - - if ($this->containsEncryptProperties($embeddedEntity)) { - $this->cachedClassesContainAnEncryptProperty[$realClass] = true; - } - } else { - if ($this->getEncryptedPropertyType($refProperty)) { - $this->cachedClassesContainAnEncryptProperty[$realClass] = true; - } - } - } - } - - return $this->cachedClassesContainAnEncryptProperty[$realClass]; - } -} diff --git a/src/Traits/DoctrineEncrypt.php b/src/Traits/DoctrineEncrypt.php new file mode 100755 index 00000000..a9b7ca4e --- /dev/null +++ b/src/Traits/DoctrineEncrypt.php @@ -0,0 +1,23 @@ +service = $service; + } +} diff --git a/src/Types/Encrypted.php b/src/Types/Encrypted.php new file mode 100755 index 00000000..84ce29c2 --- /dev/null +++ b/src/Types/Encrypted.php @@ -0,0 +1,29 @@ +service->decrypt ('string', $value); + } + + public function convertToDatabaseValue($value, AbstractPlatform $platform): mixed + { + return $this->service->encrypt ('string', $value); + } + + public function getName(): string + { + return self::TYPE; + } +} diff --git a/src/Types/EncryptedArray.php b/src/Types/EncryptedArray.php new file mode 100755 index 00000000..58dd5504 --- /dev/null +++ b/src/Types/EncryptedArray.php @@ -0,0 +1,29 @@ +service->decrypt ('simple_array', $value); + } + + public function convertToDatabaseValue($value, AbstractPlatform $platform): mixed + { + return $this->service->encrypt ('simple_array', $value); + } + + public function getName(): string + { + return self::TYPE; + } +} diff --git a/src/Types/EncryptedDateTime.php b/src/Types/EncryptedDateTime.php new file mode 100755 index 00000000..9552109c --- /dev/null +++ b/src/Types/EncryptedDateTime.php @@ -0,0 +1,29 @@ +service->decrypt ('datetime', $value); + } + + public function convertToDatabaseValue($value, AbstractPlatform $platform): mixed + { + return $this->service->encrypt ('datetime', $value); + } + + public function getName(): string + { + return self::TYPE; + } +} diff --git a/src/Types/EncryptedJSON.php b/src/Types/EncryptedJSON.php new file mode 100755 index 00000000..ba7a01c0 --- /dev/null +++ b/src/Types/EncryptedJSON.php @@ -0,0 +1,29 @@ +service->decrypt ('json', $value); + } + + public function convertToDatabaseValue($value, AbstractPlatform $platform): mixed + { + return $this->service->encrypt ('json', $value); + } + + public function getName(): string + { + return self::TYPE; + } +} diff --git a/tests/DoctrineCompatibilityTrait.php b/tests/DoctrineCompatibilityTrait.php index 071cce40..b12844e1 100644 --- a/tests/DoctrineCompatibilityTrait.php +++ b/tests/DoctrineCompatibilityTrait.php @@ -1,6 +1,6 @@ executeQuery()->fetchAllAssociative(); - } else { - $statement->execute(); - return $statement->fetchAll(); - } + return $statement->executeQuery()->fetchAllAssociative(); } /** @@ -24,13 +19,8 @@ private function executeStatementFetchAll(\Doctrine\DBAL\Statement $statement) * * Helper-method since methods changed in different supported versions of Doctrine */ - private function executeStatementFetch(\Doctrine\DBAL\Statement $statement) + public function executeStatementFetch(\Doctrine\DBAL\Statement $statement) { - if (method_exists($statement,'executeQuery')) { - return $statement->executeQuery()->fetchAssociative(); - } else { - $statement->execute(); - return $statement->fetch(); - } + return $statement->executeQuery()->fetchAssociative(); } } \ No newline at end of file diff --git a/tests/Functional/AbstractFunctionalTestCase.php b/tests/Functional/AbstractFunctionalTestCase.php index 6b976375..6077dc83 100644 --- a/tests/Functional/AbstractFunctionalTestCase.php +++ b/tests/Functional/AbstractFunctionalTestCase.php @@ -1,80 +1,97 @@ encryptor = $this->getEncryptor(); + $this->service = new Encrypt($this->encryptor); + + foreach (DoctrineEncryptBundle::ENCRYPT_TYPES as $encyptName => $encryptClass) + { + if (! Type::hasType($encyptName)) + { + Type::addType($encyptName, $encryptClass); + } + /** @var \DoctrineEncryptBundle\Traits\DoctrineEncrypt $addedType */ + $addedType = Type::getType($encyptName); + $addedType->setService($this->service); + } + + // Create a simple "default" Doctrine ORM configuration $isDevMode = true; $proxyDir = null; $cache = null; - $useSimpleAnnotationReader = false; + $reportFieldsWhereDeclared = true; - $config = Setup::createAnnotationMetadataConfiguration( - array(__DIR__ . "/fixtures/Entity"), + $config = ORMSetup::createAttributeMetadataConfiguration( + array(__DIR__.'/fixtures/Entity'), $isDevMode, $proxyDir, $cache, - $useSimpleAnnotationReader + $reportFieldsWhereDeclared ); + $config->setLazyGhostObjectEnabled (true); + $config->setSchemaManagerFactory(new DefaultSchemaManagerFactory()); // database configuration parameters $this->dbFile = tempnam(sys_get_temp_dir(), 'amb_db'); - $conn = array( + $connOptions = array( 'driver' => 'pdo_sqlite', 'path' => $this->dbFile, ); // obtaining the entity manager - $this->entityManager = EntityManager::create($conn, $config); + $conn = DriverManager::getConnection($connOptions, $config); + $dbalConf = $conn->getConfiguration(); + $this->entityManager = new EntityManager($conn, $dbalConf); $schemaTool = new SchemaTool($this->entityManager); $classes = $this->entityManager->getMetadataFactory()->getAllMetadata(); $schemaTool->dropSchema($classes); $schemaTool->createSchema($classes); - $this->sqlLoggerStack = new DebugStack(); - $this->entityManager->getConnection()->getConfiguration()->setSQLLogger($this->sqlLoggerStack); - - $this->encryptor = $this->getEncryptor(); - $annotationCacheDirectory = __DIR__.'/cache'; - $this->createNewCacheDirectory ($annotationCacheDirectory); - $annotationReader = new AttributeAnnotationReader (new AttributeReader(), new AnnotationReader(), $annotationCacheDirectory); - $this->subscriber = new DoctrineEncryptSubscriber($annotationReader, $this->encryptor); - $this->entityManager->getEventManager()->addEventSubscriber($this->subscriber); - error_reporting(E_ALL); } @@ -84,59 +101,6 @@ public function tearDown(): void unlink($this->dbFile); } - protected function createNewCacheDirectory (string $annotationCacheDirectory): void - { - $this->recurseRmdir ($annotationCacheDirectory); - mkdir ($annotationCacheDirectory); - } - - protected function recurseRmdir ($dir): bool - { - $contents = scandir($dir); - if (is_array ($contents)) - { - $files = array_diff ($contents, array('.','..')); - foreach ($files as $file) - { - (is_dir("$dir/$file") && !is_link("$dir/$file")) ? $this->recurseRmdir("$dir/$file") : unlink("$dir/$file"); - } - return rmdir($dir); - } - - return false; - } - - protected function getLatestInsertQuery(): ?array - { - $insertQueries = array_values(array_filter($this->sqlLoggerStack->queries, static function ($queryData) { - return stripos($queryData['sql'], 'INSERT ') === 0; - })); - - return current(array_reverse($insertQueries)) ?: null; - } - - protected function getLatestUpdateQuery(): ?array - { - $updateQueries = array_values(array_filter($this->sqlLoggerStack->queries,static function ($queryData) { - return stripos($queryData['sql'], 'UPDATE ') === 0; - })); - - return current(array_reverse($updateQueries)) ?: null; - } - - /** - * Using the SQL Logger Stack this method retrieves the current query count executed in this test. - */ - protected function getCurrentQueryCount(): int - { - return count($this->sqlLoggerStack->queries); - } - - protected function resetQueryStack(): void - { - $this->sqlLoggerStack->queries = []; - } - /** * Asserts that a string starts with a given prefix. * diff --git a/tests/Functional/BasicQueryTest/AbstractBasicQueryTestCase.php b/tests/Functional/BasicQueryTest/AbstractBasicQueryTestCase.php index 316b4979..42139ca4 100644 --- a/tests/Functional/BasicQueryTest/AbstractBasicQueryTestCase.php +++ b/tests/Functional/BasicQueryTest/AbstractBasicQueryTestCase.php @@ -1,11 +1,16 @@ setNotSecret('My public information'); $user->setSecret('top secret information'); $this->entityManager->persist($user); + $this->entityManager->getUnitOfWork()->computeChangeSets(); + $this->assertEquals(2, count($this->entityManager->getUnitOfWork()->getEntityChangeSet($user))); $this->entityManager->flush(); // Start transaction; insert; commit $this->assertEquals('top secret information',$user->getSecret()); - $this->assertEquals(3,$this->getCurrentQueryCount()); + + $user->setSecret('top secret information'); + $this->entityManager->persist($user); + $this->entityManager->getUnitOfWork()->computeChangeSets(); + $this->assertEquals(0, count($this->entityManager->getUnitOfWork()->getEntityChangeSet($user))); + + $user->setSecret('top secret info'); + $this->entityManager->persist($user); + $this->entityManager->getUnitOfWork()->computeChangeSets(); + $this->assertEquals(1, count($this->entityManager->getUnitOfWork()->getEntityChangeSet($user))); + $this->entityManager->flush(); } public function testNoUpdateOnReadEncrypted(): void { $this->entityManager->beginTransaction(); - $this->assertEquals(1,$this->getCurrentQueryCount()); $user = new CascadeTarget(); $user->setNotSecret('My public information'); $user->setSecret('top secret information'); $this->entityManager->persist($user); + $this->entityManager->getUnitOfWork()->computeChangeSets(); + $this->assertEquals(2, count($this->entityManager->getUnitOfWork()->getEntityChangeSet($user))); $this->entityManager->flush(); - $this->assertEquals(2,$this->getCurrentQueryCount()); // Test if no query is executed when doing nothing $this->entityManager->flush(); - $this->assertEquals(2,$this->getCurrentQueryCount()); // Test if no query is executed when reading unrelated field $user->getNotSecret(); + $this->entityManager->persist($user); + $this->entityManager->getUnitOfWork()->computeChangeSets(); + $this->assertEquals(0, count($this->entityManager->getUnitOfWork()->getEntityChangeSet($user))); $this->entityManager->flush(); - $this->assertEquals(2,$this->getCurrentQueryCount()); // Test if no query is executed when reading related field and if field is valid $this->assertEquals('top secret information',$user->getSecret()); + $this->entityManager->persist($user); + $this->entityManager->getUnitOfWork()->computeChangeSets(); + $this->assertEquals(0, count($this->entityManager->getUnitOfWork()->getEntityChangeSet($user))); $this->entityManager->flush(); - $this->assertEquals(2,$this->getCurrentQueryCount()); // Test if 1 query is executed when updating entity $user->setSecret('top secret information change'); + $this->entityManager->persist($user); + $this->entityManager->getUnitOfWork()->computeChangeSets(); + $this->assertEquals(1, count($this->entityManager->getUnitOfWork()->getEntityChangeSet($user))); $this->entityManager->flush(); - $this->assertEquals(3,$this->getCurrentQueryCount()); $this->assertEquals('top secret information change',$user->getSecret()); - - $this->entityManager->rollback(); - $this->assertEquals(4,$this->getCurrentQueryCount()); } public function testStoredDataIsEncrypted(): void @@ -66,21 +85,28 @@ public function testStoredDataIsEncrypted(): void $this->entityManager->persist($user); $this->entityManager->flush(); - $queryData = $this->getLatestInsertQuery(); - $params = array_values($queryData['params']); - $passwordData = $params[0] === 'My public information' ? $params[1] : $params[0]; + $connection = $this->entityManager->getConnection(); + $stmt = $connection->prepare('SELECT * from CascadeTarget WHERE id = ?'); + $stmt->bindValue(1, $user->getId()); + $results = $this->executeStatementFetchAll($stmt); + $passwordData = $results[0]['secret']; - $this->assertStringEndsWith(DoctrineEncryptSubscriber::ENCRYPTION_MARKER,$passwordData); + $this->assertStringEndsWith(Encrypt::ENCRYPTION_MARKER,$passwordData); $this->assertStringDoesNotContain('my secret',$passwordData); + $this->assertEquals('my secret',$user->getSecret()); $user->setSecret('my secret has changed'); $this->entityManager->flush(); - $queryData = $this->getLatestUpdateQuery(); - $passwordData = array_values($queryData['params'])[0]; + $connection = $this->entityManager->getConnection(); + $stmt = $connection->prepare('SELECT * from CascadeTarget WHERE id = ?'); + $stmt->bindValue(1, $user->getId()); + $results = $this->executeStatementFetchAll($stmt); + $passwordData = $results[0]['secret']; - $this->assertStringEndsWith(DoctrineEncryptSubscriber::ENCRYPTION_MARKER,$passwordData); - $this->assertStringDoesNotContain('my secret',$passwordData); + $this->assertStringEndsWith(Encrypt::ENCRYPTION_MARKER,$passwordData); + $this->assertStringDoesNotContain('my secret has changed',$passwordData); + $this->assertEquals('my secret has changed',$user->getSecret()); } public function testNoUpdateForUnalteredChildrenOfAbstractEntities() @@ -89,20 +115,96 @@ public function testNoUpdateForUnalteredChildrenOfAbstractEntities() $car->setSecret('top secret information'); $car->setNotSecret('123-test'); $this->entityManager->persist($car); + $this->entityManager->getUnitOfWork()->computeChangeSets(); + $this->assertEquals(3, count($this->entityManager->getUnitOfWork()->getEntityChangeSet($car))); $this->entityManager->flush(); - // start transaction, insert, commit - $this->assertEquals(3,$this->getCurrentQueryCount()); - - // Remove all logged queries - $this->resetQueryStack(); - // Set NotSecret with same data - this does not modify the entity and should not trigger an update $car->setNotSecret('123-test'); + $this->entityManager->persist($car); + $this->entityManager->getUnitOfWork()->computeChangeSets(); + $this->assertEquals(0, count($this->entityManager->getUnitOfWork()->getEntityChangeSet($car))); + $this->entityManager->flush(); + } + + public function testEntitySetterUseStrtoupper() + { + $user = new CascadeTargetStrtoupper(); + $user->setNotSecret('My public information'); + $user->setSecret('my secret'); + $this->entityManager->persist($user); $this->entityManager->flush(); - // Verify there are no queries executed - $this->assertNull($this->getLatestUpdateQuery()); - $this->assertEquals(0,$this->getCurrentQueryCount()); + $connection = $this->entityManager->getConnection(); + $stmt = $connection->prepare('SELECT * from CascadeTargetStrtoupper WHERE id = ?'); + $stmt->bindValue(1, $user->getId()); + $results = $this->executeStatementFetchAll($stmt); + $passwordData = $results[0]['secret']; + $secret = $user->getSecret(); + + $this->assertStringEndsWith(Encrypt::ENCRYPTION_MARKER,$passwordData); + $this->assertStringDoesNotContain('my secret',$passwordData); + $this->assertStringDoesNotContain('MY SECRET',$passwordData); + $this->assertEquals('MY SECRET', $secret); + } + + public function testEntityDateTime() + { + $datetime = new DateTime(); + $user = new CascadeTargetDateTime(); + $user->setNotSecret('My public information'); + $user->setSecret($datetime); + $this->entityManager->persist($user); + $this->entityManager->flush(); + + $connection = $this->entityManager->getConnection(); + $stmt = $connection->prepare('SELECT * from CascadeTargetDateTime WHERE id = ?'); + $stmt->bindValue(1, $user->getId()); + $results = $this->executeStatementFetchAll($stmt); + $passwordData = $results[0]['secret']; + $secret = $user->getSecret(); + + $this->assertStringEndsWith(Encrypt::ENCRYPTION_MARKER,$passwordData); + $this->assertEquals($datetime->format('Y-m-d H:i:s'), $secret->format('Y-m-d H:i:s')); + } + + public function testEntityJSON() + { + $json = ['test' => 'value']; + $user = new CascadeTargetJSON(); + $user->setNotSecret('My public information'); + $user->setSecret($json); + $this->entityManager->persist($user); + $this->entityManager->flush(); + + $connection = $this->entityManager->getConnection(); + $stmt = $connection->prepare('SELECT * from CascadeTargetJSON WHERE id = ?'); + $stmt->bindValue(1, $user->getId()); + $results = $this->executeStatementFetchAll($stmt); + $passwordData = $results[0]['secret']; + $secret = $user->getSecret(); + + $this->assertStringEndsWith(Encrypt::ENCRYPTION_MARKER,$passwordData); + $this->assertEquals($json, $secret); + } + + public function testEntityArray() + { + $array = ['test', 'value']; + $user = new CascadeTargetArray(); + $user->setNotSecret('My public information'); + $user->setSecret($array); + $this->entityManager->persist($user); + $this->entityManager->flush(); + + $connection = $this->entityManager->getConnection(); + $stmt = $connection->prepare('SELECT * from CascadeTargetArray WHERE id = ?'); + $stmt->bindValue(1, $user->getId()); + $results = $this->executeStatementFetchAll($stmt); + $passwordData = $results[0]['secret']; + $secret = $user->getSecret(); + + $this->assertStringEndsWith(Encrypt::ENCRYPTION_MARKER,$passwordData); + $this->assertEquals($array, $secret); } } diff --git a/tests/Functional/BasicQueryTest/BasicQueryDefuseTest.php b/tests/Functional/BasicQueryTest/BasicQueryDefuseTest.php index 5eec8c08..ed969c93 100644 --- a/tests/Functional/BasicQueryTest/BasicQueryDefuseTest.php +++ b/tests/Functional/BasicQueryTest/BasicQueryDefuseTest.php @@ -1,9 +1,9 @@ assertEquals($secret, $owner->getSecret()); $this->assertEquals($notSecret, $owner->getNotSecret()); + $this->entityManager->getUnitOfWork()->computeChangeSets(); + $this->assertEquals(0, count($this->entityManager->getUnitOfWork()->getEntityChangeSet($owner))); } - $stack = new DebugStack(); - $connection->getConfiguration()->setSQLLogger($stack); - $this->assertCount(0, $stack->queries); - $beforeFlush = $this->subscriber->encryptCounter; $em->flush(); - $afterFlush = $this->subscriber->encryptCounter; - // No encryption should have happened because we didn't change anything. - $this->assertEquals($beforeFlush, $afterFlush); - // No queries happened because we didn't change anything. - $this->assertCount(0, $stack->queries, "Unexpected queries:\n".var_export($stack->queries, true)); - - // flush again - $beforeFlush = $this->subscriber->encryptCounter; - $em->flush(); - $afterFlush = $this->subscriber->encryptCounter; - // No encryption should have happened because we didn't change anything. - $this->assertEquals($beforeFlush, $afterFlush); - // No queries happened because we didn't change anything. - $this->assertCount(0, $stack->queries, "Unexpected queries:\n".var_export($stack->queries, true)); $stmt->bindValue(1, $owner1Id); $results = $this->executeStatementFetchAll($stmt); @@ -249,25 +225,15 @@ public function testEncryptionDoesNotHappenWhenThereIsNoChangeClassInheritance() self::assertEquals($secretChild, $child->getSecretChild()); self::assertEquals($notSecretChild, $child->getNotSecretChild()); - $stack = new DebugStack(); - $connection->getConfiguration()->setSQLLogger($stack); - self::assertCount(0, $stack->queries); - $beforeFlush = $this->subscriber->encryptCounter; + $this->entityManager->getUnitOfWork()->computeChangeSets(); + $this->assertEquals(0, count($this->entityManager->getUnitOfWork()->getEntityChangeSet($child))); $em->flush(); - $afterFlush = $this->subscriber->encryptCounter; - // No encryption should have happened because we didn't change anything. - self::assertEquals($beforeFlush, $afterFlush); - // No queries happened because we didn't change anything. - self::assertCount(0, $stack->queries, "Unexpected queries:\n" . var_export($stack->queries, true)); + // No queries happened because we didn't change anything. + $this->entityManager->getUnitOfWork()->computeChangeSets(); + $this->assertEquals(0, count($this->entityManager->getUnitOfWork()->getEntityChangeSet($child))); // flush again - $beforeFlush = $this->subscriber->encryptCounter; $em->flush(); - $afterFlush = $this->subscriber->encryptCounter; - // No encryption should have happened because we didn't change anything. - self::assertEquals($beforeFlush, $afterFlush); - // No queries happened because we didn't change anything. - self::assertCount(0, $stack->queries, "Unexpected queries:\n" . var_export($stack->queries, true)); $stmtBase->bindValue(1, $childId); $result = $this->executeStatementFetch($stmtBase); @@ -309,11 +275,7 @@ public function testEncryptionDoesHappenWhenASecretIsChanged(): void /** @var Owner $owner */ $owner = $em->getRepository(Owner::class)->find($ownerId); $owner->setSecret('A NEW SECRET!!!'); - $beforeFlush = $this->subscriber->encryptCounter; $em->flush(); - $afterFlush = $this->subscriber->encryptCounter; - // No encryption should have happened because we didn't change anything. - $this->assertGreaterThan($beforeFlush, $afterFlush); $stmt->bindValue(1, $ownerId); $results = $this->executeStatementFetchAll($stmt); @@ -323,56 +285,4 @@ public function testEncryptionDoesHappenWhenASecretIsChanged(): void $this->assertStringEndsWith('', $shouldBeDifferentFromBefore); // is encrypted $this->assertNotEquals($originalEncryption, $shouldBeDifferentFromBefore); } - - public function testEntitySetterUseStrtoupper() - { - $user = new CascadeTargetStrtoupper(); - $user->setNotSecret('My public information'); - $user->setSecret('my secret'); - $this->entityManager->persist($user); - $this->entityManager->flush(); - - $queryData = $this->getLatestInsertQuery(); - $params = array_values($queryData['params']); - $passwordData = $params[0] === 'My public information' ? $params[1] : $params[0]; - $secret = $user->getSecret(); - - $this->assertStringEndsWith(DoctrineEncryptSubscriber::ENCRYPTION_MARKER,$passwordData); - $this->assertStringDoesNotContain('my secret',$passwordData); - $this->assertEquals('MY SECRET', $secret); - } - - public function testEntityWithDateTimeJsonAndArrayProperties() - { - $user = new DateTimeJsonArrayTarget(); - $datetime = new DateTime(); - $jsonArray = [ - 'key' => 'value' - ]; - $array = [0, 1]; - $user->setDate($datetime); - $user->setJson($jsonArray); - $user->setArray($array); - $this->entityManager->persist($user); - $this->entityManager->flush(); - - $queryData = $this->getLatestInsertQuery(); - $params = array_values($queryData['params']); - - foreach ($params as $param) - { - $this->assertStringEndsWith(DoctrineEncryptSubscriber::ENCRYPTION_MARKER,$param); - } - - $entityDate = $user->getDate(); - $entityJson = $user->getJson(); - $entityArray = $user->getArray(); - - // Doctrine datetime type is only for date and time. milliseconds and timezone is not stored. - // We only test the date and time accordingly - // https://www.doctrine-project.org/projects/doctrine-dbal/en/3.7/reference/types.html#datetime - $this->assertEquals($datetime->format('Y-m-d\\TH:i:s'), $entityDate->format('Y-m-d\\TH:i:s')); - $this->assertEquals($jsonArray, $entityJson); - $this->assertEquals($array, $entityArray); - } } diff --git a/tests/Functional/DoctrineEncryptService/DoctrineEncryptServiceDefuseTest.php b/tests/Functional/DoctrineEncryptService/DoctrineEncryptServiceDefuseTest.php new file mode 100644 index 00000000..7ffa48f3 --- /dev/null +++ b/tests/Functional/DoctrineEncryptService/DoctrineEncryptServiceDefuseTest.php @@ -0,0 +1,14 @@ + "VehicleCar","bike" => "VehicleBicycle"])] abstract class AbstractVehicle { /** * @var int - * @ORM\Id - * @ORM\Column(type="integer") - * @ORM\GeneratedValue */ + #[ORM\Id] + #[ORM\Column(type:"integer")] + #[ORM\GeneratedValue] private $id; - /** - * @Ambta\DoctrineEncryptBundle\Configuration\Encrypted() - * @ORM\Column(type="string", nullable=true) - */ + #[ORM\Column(type:"encrypted", nullable:true)] private $secret; - /** - * @ORM\Column(type="string", nullable=true) - */ + #[ORM\Column(type:"string", nullable:true)] private $notSecret; /** diff --git a/tests/Functional/fixtures/Entity/CascadeTarget.php b/tests/Functional/fixtures/Entity/CascadeTarget.php index c98a3f5a..d020a15f 100644 --- a/tests/Functional/fixtures/Entity/CascadeTarget.php +++ b/tests/Functional/fixtures/Entity/CascadeTarget.php @@ -1,32 +1,24 @@ notSecret = $notSecret; } - } \ No newline at end of file diff --git a/tests/Functional/fixtures/Entity/CascadeTargetArray.php b/tests/Functional/fixtures/Entity/CascadeTargetArray.php new file mode 100755 index 00000000..95e13760 --- /dev/null +++ b/tests/Functional/fixtures/Entity/CascadeTargetArray.php @@ -0,0 +1,63 @@ +id; + } + + /** + * @return mixed + */ + public function getSecret() + { + return $this->secret; + } + + /** + * @param mixed $secret + */ + public function setSecret($secret): void + { + $this->secret = $secret; + } + + /** + * @return mixed + */ + public function getNotSecret() + { + return $this->notSecret; + } + + /** + * @param mixed $notSecret + */ + public function setNotSecret($notSecret): void + { + $this->notSecret = $notSecret; + } +} \ No newline at end of file diff --git a/tests/Functional/fixtures/Entity/CascadeTargetDateTime.php b/tests/Functional/fixtures/Entity/CascadeTargetDateTime.php new file mode 100755 index 00000000..9a0303bb --- /dev/null +++ b/tests/Functional/fixtures/Entity/CascadeTargetDateTime.php @@ -0,0 +1,63 @@ +id; + } + + /** + * @return mixed + */ + public function getSecret() + { + return $this->secret; + } + + /** + * @param mixed $secret + */ + public function setSecret($secret): void + { + $this->secret = $secret; + } + + /** + * @return mixed + */ + public function getNotSecret() + { + return $this->notSecret; + } + + /** + * @param mixed $notSecret + */ + public function setNotSecret($notSecret): void + { + $this->notSecret = $notSecret; + } +} \ No newline at end of file diff --git a/tests/Functional/fixtures/Entity/CascadeTargetJSON.php b/tests/Functional/fixtures/Entity/CascadeTargetJSON.php new file mode 100755 index 00000000..d7c9ef94 --- /dev/null +++ b/tests/Functional/fixtures/Entity/CascadeTargetJSON.php @@ -0,0 +1,63 @@ +id; + } + + /** + * @return mixed + */ + public function getSecret() + { + return $this->secret; + } + + /** + * @param mixed $secret + */ + public function setSecret($secret): void + { + $this->secret = $secret; + } + + /** + * @return mixed + */ + public function getNotSecret() + { + return $this->notSecret; + } + + /** + * @param mixed $notSecret + */ + public function setNotSecret($notSecret): void + { + $this->notSecret = $notSecret; + } +} \ No newline at end of file diff --git a/tests/Functional/fixtures/Entity/CascadeTargetStrtoupper.php b/tests/Functional/fixtures/Entity/CascadeTargetStrtoupper.php index 30b2e99b..24bf2bc6 100644 --- a/tests/Functional/fixtures/Entity/CascadeTargetStrtoupper.php +++ b/tests/Functional/fixtures/Entity/CascadeTargetStrtoupper.php @@ -1,33 +1,24 @@ secret = $secret; + $this->secret = strtoupper ($secret); } /** diff --git a/tests/Functional/fixtures/Entity/ClassTableInheritanceBase.php b/tests/Functional/fixtures/Entity/ClassTableInheritanceBase.php index e5aa089d..19c2e728 100644 --- a/tests/Functional/fixtures/Entity/ClassTableInheritanceBase.php +++ b/tests/Functional/fixtures/Entity/ClassTableInheritanceBase.php @@ -1,34 +1,27 @@ id; - } - - /** - * @return mixed - */ - public function getDate() - { - return $this->date; - } - - /** - * @param mixed $date - */ - public function setDate($date): void - { - $this->date = $date; - } - - /** - * @return mixed - */ - public function getJson() - { - return $this->json; - } - - /** - * @param mixed $json - */ - public function setJson($json): void - { - $this->json = $json; - } - - /** - * @return mixed - */ - public function getArray() - { - return $this->array; - } - - /** - * @param mixed $array - */ - public function setArray($array): void - { - $this->array = $array; - } -} diff --git a/tests/Functional/fixtures/Entity/Owner.php b/tests/Functional/fixtures/Entity/Owner.php index 92aa7341..4cde214e 100644 --- a/tests/Functional/fixtures/Entity/Owner.php +++ b/tests/Functional/fixtures/Entity/Owner.php @@ -1,41 +1,31 @@ cascaded = $cascaded; } -} +} \ No newline at end of file diff --git a/tests/Functional/fixtures/Entity/VehicleBicycle.php b/tests/Functional/fixtures/Entity/VehicleBicycle.php index 5865614d..5bf1c0ec 100644 --- a/tests/Functional/fixtures/Entity/VehicleBicycle.php +++ b/tests/Functional/fixtures/Entity/VehicleBicycle.php @@ -1,19 +1,17 @@ createContainer(); $this->extension->load([[]], $container); - $this->assertSame(HaliteEncryptor::class, $container->getParameter('ambta_doctrine_encrypt.encryptor_class_name')); + $this->assertSame(HaliteEncryptor::class, $container->getParameter('doctrine_encrypt.encryptor_class_name')); } public function testConfigLoadHalite(): void @@ -49,7 +49,7 @@ public function testConfigLoadHalite(): void ]; $this->extension->load([$config], $container); - $this->assertSame(HaliteEncryptor::class, $container->getParameter('ambta_doctrine_encrypt.encryptor_class_name')); + $this->assertSame(HaliteEncryptor::class, $container->getParameter('doctrine_encrypt.encryptor_class_name')); } public function testConfigLoadDefuse(): void @@ -61,7 +61,7 @@ public function testConfigLoadDefuse(): void ]; $this->extension->load([$config], $container); - $this->assertSame(DefuseEncryptor::class, $container->getParameter('ambta_doctrine_encrypt.encryptor_class_name')); + $this->assertSame(DefuseEncryptor::class, $container->getParameter('doctrine_encrypt.encryptor_class_name')); } public function testConfigLoadCustomEncryptor(): void @@ -72,7 +72,7 @@ public function testConfigLoadCustomEncryptor(): void ]; $this->extension->load([$config], $container); - $this->assertSame(self::class, $container->getParameter('ambta_doctrine_encrypt.encryptor_class_name')); + $this->assertSame(self::class, $container->getParameter('doctrine_encrypt.encryptor_class_name')); } public function testConfigImpossibleToUseSecretAndSecret_directory_path(): void @@ -96,10 +96,10 @@ public function testConfigUseSecret(): void ]; $this->extension->load([$config], $container); - $this->assertIsString($container->getParameter('ambta_doctrine_encrypt.secret')); - $this->assertStringNotContainsString('Halite',$container->getParameter('ambta_doctrine_encrypt.secret')); - $this->assertStringNotContainsString('.key',$container->getParameter('ambta_doctrine_encrypt.secret')); - $this->assertEquals('my-secret',$container->getParameter('ambta_doctrine_encrypt.secret')); + $this->assertIsString($container->getParameter('doctrine_encrypt.secret')); + $this->assertStringNotContainsString('Halite',$container->getParameter('doctrine_encrypt.secret')); + $this->assertStringNotContainsString('.key',$container->getParameter('doctrine_encrypt.secret')); + $this->assertEquals('my-secret',$container->getParameter('doctrine_encrypt.secret')); } public function testHaliteSecretIsCreatedWhenSecretFileDoesNotExistAndSecretCreationIsEnabled(): void @@ -111,7 +111,7 @@ public function testHaliteSecretIsCreatedWhenSecretFileDoesNotExistAndSecretCrea ]; $this->extension->load([$config], $container); - $secretArgument = $container->getDefinition('ambta_doctrine_encrypt.encryptor')->getArgument(0); + $secretArgument = $container->getDefinition('doctrine_encrypt.encryptor')->getArgument(0); if ($secretArgument instanceof Expression) { $actualSecret = $container->resolveServices($secretArgument); } else { @@ -138,7 +138,7 @@ public function testDefuseSecretIsCreatedWhenSecretFileDoesNotExistAndSecretCrea ]; $this->extension->load([$config], $container); - $secretArgument = $container->getDefinition('ambta_doctrine_encrypt.encryptor')->getArgument(0); + $secretArgument = $container->getDefinition('doctrine_encrypt.encryptor')->getArgument(0); if ($secretArgument instanceof Expression) { $actualSecret = $container->resolveServices($secretArgument); } else { @@ -165,14 +165,12 @@ public function testSecretIsNotCreatedWhenSecretFileDoesNotExistAndSecretCreatio $this->expectException(\RuntimeException::class); if (method_exists($this,'expectExceptionMessageMatches')) { $this->expectExceptionMessageMatches('/DoctrineEncryptBundle: Unable to create secret.*/'); - } elseif(method_exists($this,'expectExceptionMessageRegExp')) { - $this->expectExceptionMessageRegExp('/DoctrineEncryptBundle: Unable to create secret.*/'); } else { $this->markAsRisky('Unable to see if the exception matches the actual message'); } - $secretArgument = $container->getDefinition('ambta_doctrine_encrypt.encryptor')->getArgument(0); + $secretArgument = $container->getDefinition('doctrine_encrypt.encryptor')->getArgument(0); if ($secretArgument instanceof Expression) { $container->resolveServices($secretArgument); } @@ -191,7 +189,7 @@ public function testSecretsAreReadFromFile(): void ]; $this->extension->load([$config], $container); - $secretArgument = $container->getDefinition('ambta_doctrine_encrypt.encryptor')->getArgument(0); + $secretArgument = $container->getDefinition('doctrine_encrypt.encryptor')->getArgument(0); if ($secretArgument instanceof Expression) { $actualSecret = $container->resolveServices($secretArgument); } else { diff --git a/tests/Unit/Encryptors/DefuseEncryptorTest.php b/tests/Unit/Encryptors/DefuseEncryptorTest.php index d2e52d24..14425110 100644 --- a/tests/Unit/Encryptors/DefuseEncryptorTest.php +++ b/tests/Unit/Encryptors/DefuseEncryptorTest.php @@ -1,8 +1,8 @@ createMock(EncryptorInterface::class); + $encryptor + ->expects($this->any()) + ->method('encrypt') + ->willReturnCallback(function (string $arg) { + return 'encrypted-'.$arg; + }) + ; + $encryptor + ->expects($this->any()) + ->method('decrypt') + ->willReturnCallback(function (string $arg) { + return preg_replace('/^encrypted-/', '', $arg); + }) + ; + + $this->service = new Encrypt($encryptor); + } + + public function testEncrypt(): void + { + $string = 'Test'; + $result = $this->service->encrypt ('string', $string); + + $this->assertEquals('encrypted-'.$string.Encrypt::ENCRYPTION_MARKER, $result); + } + + public function testDecrypt(): void + { + $string = 'encrypted-Test'.Encrypt::ENCRYPTION_MARKER; + $result = $this->service->decrypt ('string', $string); + + $this->assertEquals('Test', $result); + } + + public function testEncryptDateTime(): void + { + $datetime = new DateTime(); + $result = $this->service->encrypt ('datetime', $datetime); + + $this->assertEquals('encrypted-'.$datetime->format('Y-m-d H:i:s').Encrypt::ENCRYPTION_MARKER, $result); + } + + public function testDecryptDateTime(): void + { + $datetime = new DateTime(); + $encrypted = $this->service->encrypt ('datetime', $datetime); + + $result = $this->service->decrypt ('datetime', $encrypted); + + $this->assertEquals($datetime->format('Y-m-d H:i:s'), $result->format('Y-m-d H:i:s')); + } + + public function testEncryptJSON(): void + { + $json = '{"test":"value"}'; + $jsonData = json_decode($json, true); + $result = $this->service->encrypt ('json', $jsonData); + + $this->assertEquals('encrypted-'.$json.Encrypt::ENCRYPTION_MARKER, $result); + } + + public function testDecryptJSON(): void + { + $json = '{"test":"value"}'; + $jsonData = json_decode($json, true); + $encrypted = $this->service->encrypt ('json', $jsonData); + + $result = $this->service->decrypt ('json', $encrypted); + + $this->assertEquals($jsonData, $result); + } + + public function testEncryptArray(): void + { + $array = ['test', 'value']; + $result = $this->service->encrypt ('simple_array', $array); + + $this->assertEquals('encrypted-'.implode(',',$array).Encrypt::ENCRYPTION_MARKER, $result); + } + + public function testDecryptArray(): void + { + $array = ['test', 'value']; + $encrypted = $this->service->encrypt ('simple_array', $array); + + $result = $this->service->decrypt ('simple_array', $encrypted); + + $this->assertEquals($array, $result); + } +} diff --git a/tests/Unit/Subscribers/DoctrineEncryptSubscriberTest.php b/tests/Unit/Subscribers/DoctrineEncryptSubscriberTest.php deleted file mode 100644 index 1b550f69..00000000 --- a/tests/Unit/Subscribers/DoctrineEncryptSubscriberTest.php +++ /dev/null @@ -1,358 +0,0 @@ -encryptor = $this->createMock(EncryptorInterface::class); - $this->encryptor - ->expects($this->any()) - ->method('encrypt') - ->willReturnCallback(function (string $arg) { - return 'encrypted-'.$arg; - }) - ; - $this->encryptor - ->expects($this->any()) - ->method('decrypt') - ->willReturnCallback(function (string $arg) { - return preg_replace('/^encrypted-/', '', $arg); - }) - ; - - $this->reader = $this->createMock(Reader::class); - $this->reader->expects($this->any()) - ->method('getPropertyAnnotation') - ->willReturnCallback(function (\ReflectionProperty $reflProperty, string $class) { - if (Encrypted::class === $class) { - if (\in_array($reflProperty->getName(), ['name', 'address', 'extra'])) - { - return new $class(); - } - } - if (Embedded::class === $class) { - return 'user' === $reflProperty->getName(); - } - - return false; - }) - ; - - $this->conn = $this->createMock(Connection::class); - $this->conn->method('getDatabasePlatform') - ->willReturnCallback(function() { - return new MySQL80Platform(); - }); - - $this->em = $this->createMock(EntityManagerInterface::class); - $this->em->method('getClassMetadata') - ->willReturnCallback(function (string $className) { - $classMetaData = $this->createMock(ClassMetadata::class); - $classMetaData->rootEntityName = $className; - - return $classMetaData; - }); - $this->em->method('getConnection') - ->willReturnCallback(function() { - return $this->conn; - }); - - $this->subscriber = new DoctrineEncryptSubscriber($this->reader, $this->encryptor); - } - - public function testSetRestorEncryptor(): void - { - $replaceEncryptor = $this->createMock(EncryptorInterface::class); - - $this->assertSame($this->encryptor, $this->subscriber->getEncryptor()); - $this->subscriber->setEncryptor($replaceEncryptor); - $this->assertSame($replaceEncryptor, $this->subscriber->getEncryptor()); - $this->subscriber->restoreEncryptor(); - $this->assertSame($this->encryptor, $this->subscriber->getEncryptor()); - } - - private function triggerProcessFields(Object $entity, bool $encrypt) - { - $class = new ReflectionClass(DoctrineEncryptSubscriber::class); - $method = $class->getMethod('processFields'); - $method->setAccessible(true); - $method->invokeArgs($this->subscriber,[$entity,$this->em,$encrypt]); - } - - public function testProcessFieldsEncrypt(): void - { - $user = new User('David', 'Switzerland'); - - $this->triggerProcessFields($user,true); - - $this->assertStringStartsWith('encrypted-', $user->name); - $this->assertStringStartsWith('encrypted-', $user->getAddress()); - } - - public function testProcessFieldsEncryptExtend(): void - { - $user = new ExtendedUser('David', 'Switzerland', 'extra'); - - $this->triggerProcessFields($user,true); - - $this->assertStringStartsWith('encrypted-', $user->name); - $this->assertStringStartsWith('encrypted-', $user->getAddress()); - $this->assertStringStartsWith('encrypted-', $user->extra); - } - - public function testProcessFieldsEncryptEmbedded(): void - { - - $withUser = new WithUser('Thing', 'foo', new User('David', 'Switzerland')); - - $this->triggerProcessFields($withUser,true); - - $this->assertStringStartsWith('encrypted-', $withUser->name); - $this->assertSame('foo', $withUser->foo); - $this->assertStringStartsWith('encrypted-', $withUser->user->name); - $this->assertStringStartsWith('encrypted-', $withUser->user->getAddress()); - } - - public function testProcessFieldsEncryptNull(): void - { - $user = new User('David', null); - - $this->triggerProcessFields($user,true); - - $this->assertStringStartsWith('encrypted-', $user->name); - $this->assertNull($user->getAddress()); - } - - public function testProcessFieldsNoEncryptor(): void - { - $user = new User('David', 'Switzerland'); - - $this->subscriber->setEncryptor(null); - $this->triggerProcessFields($user,true); - - $this->assertSame('David', $user->name); - $this->assertSame('Switzerland', $user->getAddress()); - } - - public function testProcessFieldsDecrypt(): void - { - $user = new User('encrypted-David', 'encrypted-Switzerland'); - - $this->triggerProcessFields($user,false); - - $this->assertSame('David', $user->name); - $this->assertSame('Switzerland', $user->getAddress()); - } - - public function testProcessFieldsDecryptExtended(): void - { - $user = new ExtendedUser('encrypted-David', 'encrypted-Switzerland', 'encrypted-extra'); - - $this->triggerProcessFields($user,false); - - $this->assertSame('David', $user->name); - $this->assertSame('Switzerland', $user->getAddress()); - $this->assertSame('extra', $user->extra); - } - - public function testProcessFieldsDecryptEmbedded(): void - { - $withUser = new WithUser('encrypted-Thing', 'foo', new User('encrypted-David', 'encrypted-Switzerland')); - - $this->triggerProcessFields($withUser,false); - - $this->assertSame('Thing', $withUser->name); - $this->assertSame('foo', $withUser->foo); - $this->assertSame('David', $withUser->user->name); - $this->assertSame('Switzerland', $withUser->user->getAddress()); - } - - public function testProcessFieldsDecryptNull(): void - { - $user = new User('encrypted-David', null); - - $this->triggerProcessFields($user,false); - - $this->assertSame('David', $user->name); - $this->assertNull($user->getAddress()); - } - - public function testProcessFieldsDecryptNonEncrypted(): void - { - // no trailing but somethint that our mock decrypt would change if called - $user = new User('encrypted-David', 'encrypted-Switzerland'); - - $this->triggerProcessFields($user,false); - - $this->assertSame('encrypted-David', $user->name); - $this->assertSame('encrypted-Switzerland', $user->getAddress()); - } - - /** - * Test that fields are encrypted before flushing. - */ - public function testOnFlush(): void - { - $user = new User('David', 'Switzerland'); - - $uow = $this->createMock(UnitOfWork::class); - $uow->expects($this->any()) - ->method('getScheduledEntityInsertions') - ->willReturn([$user]) - ; - $em = $this->createMock(EntityManagerInterface::class); - $em->expects($this->any()) - ->method('getUnitOfWork') - ->willReturn($uow) - ; - $classMetaData = $this->createMock(ClassMetadata::class); - $classMetaData->rootEntityName = User::class; - $em->method('getClassMetadata') - ->willReturnCallback(function (string $className) { - $classMetaData = $this->createMock(ClassMetadata::class); - $classMetaData->rootEntityName = $className; - - return $classMetaData; - }); - $em->method('getConnection') - ->willReturnCallback(function() { - return $this->conn; - }); - $uow->expects($this->any())->method('recomputeSingleEntityChangeSet'); - - $onFlush = new OnFlushEventArgs($em); - - $this->subscriber->onFlush($onFlush); - - $this->assertStringStartsWith('encrypted-', $user->name); - $this->assertStringStartsWith('encrypted-', $user->getAddress()); - } - - /** - * Test that fields are decrypted again after flushing - */ - public function testPostFlush(): void - { - $user = new User('encrypted-David', 'encrypted-Switzerland'); - - $uow = $this->createMock(UnitOfWork::class); - $uow->expects($this->any()) - ->method('getIdentityMap') - ->willReturn([[$user]]) - ; - $em = $this->createMock(EntityManagerInterface::class); - $em->expects($this->any()) - ->method('getUnitOfWork') - ->willReturn($uow) - ; - $classMetaData = $this->createMock(ClassMetadata::class); - $classMetaData->rootEntityName = User::class; - $em->method('getClassMetadata') - ->willReturnCallback(function (string $className) { - $classMetaData = $this->createMock(ClassMetadata::class); - $classMetaData->rootEntityName = $className; - - return $classMetaData; - }); - $em->method('getConnection') - ->willReturnCallback(function() { - return $this->conn; - }); - - $postFlush = new PostFlushEventArgs($em); - - $this->subscriber->postFlush($postFlush); - - $this->assertSame('David', $user->name); - $this->assertSame('Switzerland', $user->getAddress()); - } - - public function testAnnotationsAreOnlyReadOnce(): void - { - $reader = $this->createMock(Reader::class); - $reader->expects($this->exactly(4)) // 2 properties and test if embedded and encrypted - ->method('getPropertyAnnotation') - ->willReturnCallback(function (\ReflectionProperty $reflProperty, string $class) { - if (Encrypted::class === $class) { - if (\in_array($reflProperty->getName(), ['name', 'address', 'extra'])) - { - return new $class(); - } - } - if (Embedded::class === $class) { - return 'user' === $reflProperty->getName(); - } - - return false; - }) - ; - - $subscriber = new DoctrineEncryptSubscriber($reader, $this->encryptor); - - - $user = new User('David', 'Switzerland'); - - $class = new ReflectionClass(DoctrineEncryptSubscriber::class); - $method = $class->getMethod('processFields'); - $method->setAccessible(true); - $method->invokeArgs($subscriber,[$user,$this->em,true]); - - // Execute second time and see if we once more read the propertyannotation - $method->invokeArgs($subscriber,[$user,$this->em,true]); - } -} diff --git a/tests/Unit/Subscribers/fixtures/ExtendedUser.php b/tests/Unit/Subscribers/fixtures/ExtendedUser.php deleted file mode 100644 index b58424c4..00000000 --- a/tests/Unit/Subscribers/fixtures/ExtendedUser.php +++ /dev/null @@ -1,20 +0,0 @@ -extra = $extra; - } -} diff --git a/tests/Unit/Subscribers/fixtures/User.php b/tests/Unit/Subscribers/fixtures/User.php deleted file mode 100644 index a11053da..00000000 --- a/tests/Unit/Subscribers/fixtures/User.php +++ /dev/null @@ -1,36 +0,0 @@ -name = $name; - $this->address = $address; - } - - public function getAddress(): ?string - { - return $this->address; - } - - public function setAddress(?string $address): void - { - $this->address = $address; - } -} diff --git a/tests/Unit/Subscribers/fixtures/WithUser.php b/tests/Unit/Subscribers/fixtures/WithUser.php deleted file mode 100644 index 35cc179a..00000000 --- a/tests/Unit/Subscribers/fixtures/WithUser.php +++ /dev/null @@ -1,33 +0,0 @@ -name = $name; - $this->foo = $foo; - $this->user = $user; - } -} diff --git a/tests/bootstrap.php b/tests/bootstrap.php index a796b334..9e6ad3aa 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -6,7 +6,3 @@ } $autoload = require $file; - -if (method_exists(Doctrine\Common\Annotations\AnnotationRegistry::class,'registerLoader')) { - Doctrine\Common\Annotations\AnnotationRegistry::registerLoader([$autoload, 'loadClass']); -} From 6c36fdc246969f5199db410306b874fd49333a12 Mon Sep 17 00:00:00 2001 From: r3hp1c Date: Sat, 2 Mar 2024 20:34:40 +0000 Subject: [PATCH 02/44] add paragonie/halite to composer.json for demos --- demo/symfony5.4/composer.json | 2 +- demo/symfony6.x/composer.json | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/demo/symfony5.4/composer.json b/demo/symfony5.4/composer.json index f080615e..b2dfa145 100644 --- a/demo/symfony5.4/composer.json +++ b/demo/symfony5.4/composer.json @@ -9,7 +9,7 @@ "ext-iconv": "*", "doctrineencryptbundle/doctrine-encrypt-bundle": "@dev", "doctrine/persistence": "^3.2", - "paragonie/halite": "^4.6|^5.0", + "paragonie/halite": "^4.6", "symfony/console": "5.4.*", "symfony/dotenv": "5.4.*", "symfony/flex": "^1.21|^2", diff --git a/demo/symfony6.x/composer.json b/demo/symfony6.x/composer.json index 52752e7c..7349f073 100644 --- a/demo/symfony6.x/composer.json +++ b/demo/symfony6.x/composer.json @@ -8,6 +8,7 @@ "ext-ctype": "*", "ext-iconv": "*", "doctrineencryptbundle/doctrine-encrypt-bundle": "@dev", + "paragonie/halite": "^5.0", "symfony/console": "6.0.*", "symfony/dotenv": "6.0.*", "symfony/flex": "^2", From b06779f0696b3c59441ffee2450ffce1618e23fe Mon Sep 17 00:00:00 2001 From: r3hp1c Date: Sat, 2 Mar 2024 20:37:41 +0000 Subject: [PATCH 03/44] update PHPCompatibility to 8.3 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fce5ae98..2aea4401 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -40,7 +40,7 @@ jobs: run: "vendor/bin/phpstan analyze" - name: "PHPCompatibility" - run: "vendor/bin/phpcs src/ tests/ --standard=PHPCompatibility --runtime-set testVersion 7.2-8.1" + run: "vendor/bin/phpcs src/ tests/ --standard=PHPCompatibility --runtime-set testVersion 7.2-8.3" tests: name: "Tests ${{ matrix.php-version }} ${{ matrix.dependency-versions }}" From a32339515278c16bc5ceef328460b3e5804d5e45 Mon Sep 17 00:00:00 2001 From: r3hp1c Date: Sat, 2 Mar 2024 20:44:39 +0000 Subject: [PATCH 04/44] add paragonie/halite 4.6 to composer.json --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 5e601074..9aca399a 100644 --- a/composer.json +++ b/composer.json @@ -17,7 +17,7 @@ "symfony/expression-language": "^5.4|^6.0|^7.0" }, "require-dev": { - "paragonie/halite": "^5.0", + "paragonie/halite": "^4.6|^5.0", "defuse/php-encryption": "^2.1", "doctrine/cache": "^1.11", "phpstan/phpstan": "^1.4", From d7fe8ac939bf7c3a74a27567babf355cc53927e8 Mon Sep 17 00:00:00 2001 From: r3hp1c Date: Sat, 2 Mar 2024 20:49:38 +0000 Subject: [PATCH 05/44] attempt to fix: TypeError: Argument 2 passed to DoctrineEncryptBundle\Service\Encrypt::encrypt() must be an instance of DoctrineEncryptBundle\Service\mixed --- src/Service/Encrypt.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Service/Encrypt.php b/src/Service/Encrypt.php index 26df63b4..4f8e6335 100755 --- a/src/Service/Encrypt.php +++ b/src/Service/Encrypt.php @@ -71,7 +71,7 @@ public function getEncryptor(): ?EncryptorInterface * @return mixed * */ - public function encrypt(string $type, mixed $value): mixed + public function encrypt(string $type, $value): mixed { // TODO : probably cannot return null when $this->encryptor is not set if (is_null ($value) || is_null ($this->encryptor)) @@ -103,7 +103,7 @@ public function encrypt(string $type, mixed $value): mixed * @return mixed * */ - public function decrypt(string $type, mixed $value): mixed + public function decrypt(string $type, $value): mixed { // TODO : probably cannot return null when $this->encryptor is not set if (is_null ($value) || is_null ($this->encryptor)) From daa7dd362d53dd24d22f92e3b3cdf355112d6abd Mon Sep 17 00:00:00 2001 From: r3hp1c Date: Sat, 2 Mar 2024 20:51:50 +0000 Subject: [PATCH 06/44] attempt to fix: TypeError: Return value of DoctrineEncryptBundle\Service\Encrypt::encrypt() must be an instance of DoctrineEncryptBundle\Service\mixed --- src/Service/Encrypt.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Service/Encrypt.php b/src/Service/Encrypt.php index 4f8e6335..f714ba84 100755 --- a/src/Service/Encrypt.php +++ b/src/Service/Encrypt.php @@ -71,7 +71,7 @@ public function getEncryptor(): ?EncryptorInterface * @return mixed * */ - public function encrypt(string $type, $value): mixed + public function encrypt(string $type, $value) { // TODO : probably cannot return null when $this->encryptor is not set if (is_null ($value) || is_null ($this->encryptor)) @@ -103,7 +103,7 @@ public function encrypt(string $type, $value): mixed * @return mixed * */ - public function decrypt(string $type, $value): mixed + public function decrypt(string $type, $value) { // TODO : probably cannot return null when $this->encryptor is not set if (is_null ($value) || is_null ($this->encryptor)) From 6cb15494584742c21ee104ddb2e4c3ee5bdd732b Mon Sep 17 00:00:00 2001 From: r3hp1c Date: Sat, 2 Mar 2024 20:56:54 +0000 Subject: [PATCH 07/44] attempt to fix: LogicException: Lazy ghost objects cannot be enabled because the symfony/var-exporter library version 6.2 or higher is not installed. --- composer.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 9aca399a..451a7f9a 100644 --- a/composer.json +++ b/composer.json @@ -14,7 +14,8 @@ "symfony/http-kernel": "^5.4|^6.0|^7.0", "symfony/config": "^5.4|^6.0|^7.0", "doctrine/annotations": "^1.13|^2.0", - "symfony/expression-language": "^5.4|^6.0|^7.0" + "symfony/expression-language": "^5.4|^6.0|^7.0", + "symfony/var-exporter": "^6.2|^7.0" }, "require-dev": { "paragonie/halite": "^4.6|^5.0", From c0614ceab9c2a9fb0966c3e4b37bc4f2c05d08b2 Mon Sep 17 00:00:00 2001 From: r3hp1c Date: Sat, 2 Mar 2024 20:59:50 +0000 Subject: [PATCH 08/44] undo attempt to fix: LogicException: Lazy ghost objects cannot be enabled because the symfony/var-exporter library version 6.2 or higher is not installed. --- composer.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 451a7f9a..9aca399a 100644 --- a/composer.json +++ b/composer.json @@ -14,8 +14,7 @@ "symfony/http-kernel": "^5.4|^6.0|^7.0", "symfony/config": "^5.4|^6.0|^7.0", "doctrine/annotations": "^1.13|^2.0", - "symfony/expression-language": "^5.4|^6.0|^7.0", - "symfony/var-exporter": "^6.2|^7.0" + "symfony/expression-language": "^5.4|^6.0|^7.0" }, "require-dev": { "paragonie/halite": "^4.6|^5.0", From 238a0caa0643d516e4adda0f6090324db5f108be Mon Sep 17 00:00:00 2001 From: r3hp1c Date: Sat, 2 Mar 2024 21:07:01 +0000 Subject: [PATCH 09/44] attempt to fix: LogicException: The attribute metadata driver cannot be enabled on PHP 7 --- .../Functional/AbstractFunctionalTestCase.php | 39 ++++++++++++------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/tests/Functional/AbstractFunctionalTestCase.php b/tests/Functional/AbstractFunctionalTestCase.php index 6077dc83..8738946e 100644 --- a/tests/Functional/AbstractFunctionalTestCase.php +++ b/tests/Functional/AbstractFunctionalTestCase.php @@ -60,19 +60,32 @@ public function setUp(): void } // Create a simple "default" Doctrine ORM configuration - $isDevMode = true; - $proxyDir = null; - $cache = null; - $reportFieldsWhereDeclared = true; - - $config = ORMSetup::createAttributeMetadataConfiguration( - array(__DIR__.'/fixtures/Entity'), - $isDevMode, - $proxyDir, - $cache, - $reportFieldsWhereDeclared - ); - $config->setLazyGhostObjectEnabled (true); + $isDevMode = true; + $proxyDir = null; + $cache = null; + + if (version_compare(PHP_VERSION, '8.0.0', '<')) { + $useSimpleAnnotationReader = false; + $config = ORMSetup::createAnnotationMetadataConfiguration( + array(__DIR__.'/fixtures/Entity'), + $isDevMode, + $proxyDir, + $cache, + $useSimpleAnnotationReader + ); + } + else + { + $reportFieldsWhereDeclared = true; + $config = ORMSetup::createAttributeMetadataConfiguration( + array(__DIR__.'/fixtures/Entity'), + $isDevMode, + $proxyDir, + $cache, + $reportFieldsWhereDeclared + ); + $config->setLazyGhostObjectEnabled (true); + } $config->setSchemaManagerFactory(new DefaultSchemaManagerFactory()); // database configuration parameters From cf95fe54bbba093c6b18e5337e40ab4031d54f2e Mon Sep 17 00:00:00 2001 From: r3hp1c Date: Sat, 2 Mar 2024 21:09:59 +0000 Subject: [PATCH 10/44] attempt to fix: Error: Call to undefined method Doctrine\ORM\Configuration::setSchemaManagerFactory() --- tests/Functional/AbstractFunctionalTestCase.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Functional/AbstractFunctionalTestCase.php b/tests/Functional/AbstractFunctionalTestCase.php index 8738946e..58c3d78b 100644 --- a/tests/Functional/AbstractFunctionalTestCase.php +++ b/tests/Functional/AbstractFunctionalTestCase.php @@ -85,8 +85,8 @@ public function setUp(): void $reportFieldsWhereDeclared ); $config->setLazyGhostObjectEnabled (true); + $config->setSchemaManagerFactory(new DefaultSchemaManagerFactory()); } - $config->setSchemaManagerFactory(new DefaultSchemaManagerFactory()); // database configuration parameters $this->dbFile = tempnam(sys_get_temp_dir(), 'amb_db'); From be061804e82934601896f19eaac188794df87b33 Mon Sep 17 00:00:00 2001 From: r3hp1c Date: Sat, 2 Mar 2024 21:22:11 +0000 Subject: [PATCH 11/44] attempt to fix: Error: Class 'Doctrine\ORM\ORMSetup' not found --- tests/Functional/AbstractFunctionalTestCase.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/Functional/AbstractFunctionalTestCase.php b/tests/Functional/AbstractFunctionalTestCase.php index 58c3d78b..978d064c 100644 --- a/tests/Functional/AbstractFunctionalTestCase.php +++ b/tests/Functional/AbstractFunctionalTestCase.php @@ -9,6 +9,7 @@ use DoctrineEncryptBundle\Service\Encrypt; use Doctrine\DBAL\Types\Type; use Doctrine\ORM\EntityManager; +use Doctrine\ORM\Tools\Setup; use Doctrine\ORM\ORMSetup; use Doctrine\ORM\Tools\SchemaTool; use DoctrineEncryptBundle\DoctrineEncryptBundle; @@ -66,7 +67,7 @@ public function setUp(): void if (version_compare(PHP_VERSION, '8.0.0', '<')) { $useSimpleAnnotationReader = false; - $config = ORMSetup::createAnnotationMetadataConfiguration( + $config = Setup::createAnnotationMetadataConfiguration( array(__DIR__.'/fixtures/Entity'), $isDevMode, $proxyDir, From dcbb0bae6b7f1f4879268cb6e5071a17a9a56296 Mon Sep 17 00:00:00 2001 From: r3hp1c Date: Sat, 2 Mar 2024 21:26:16 +0000 Subject: [PATCH 12/44] attempt to fix: Error: Call to protected Doctrine\ORM\EntityManager::__construct() --- .../Functional/AbstractFunctionalTestCase.php | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/tests/Functional/AbstractFunctionalTestCase.php b/tests/Functional/AbstractFunctionalTestCase.php index 978d064c..6aa25b2e 100644 --- a/tests/Functional/AbstractFunctionalTestCase.php +++ b/tests/Functional/AbstractFunctionalTestCase.php @@ -60,6 +60,13 @@ public function setUp(): void $addedType->setService($this->service); } + // database configuration parameters + $this->dbFile = tempnam(sys_get_temp_dir(), 'amb_db'); + $connOptions = array( + 'driver' => 'pdo_sqlite', + 'path' => $this->dbFile, + ); + // Create a simple "default" Doctrine ORM configuration $isDevMode = true; $proxyDir = null; @@ -74,6 +81,8 @@ public function setUp(): void $cache, $useSimpleAnnotationReader ); + // obtaining the entity manager + $this->entityManager = EntityManager::create($connOptions, $config); } else { @@ -87,19 +96,12 @@ public function setUp(): void ); $config->setLazyGhostObjectEnabled (true); $config->setSchemaManagerFactory(new DefaultSchemaManagerFactory()); + // obtaining the entity manager + $conn = DriverManager::getConnection($connOptions, $config); + $dbalConf = $conn->getConfiguration(); + $this->entityManager = new EntityManager($conn, $dbalConf); } - // database configuration parameters - $this->dbFile = tempnam(sys_get_temp_dir(), 'amb_db'); - $connOptions = array( - 'driver' => 'pdo_sqlite', - 'path' => $this->dbFile, - ); - - // obtaining the entity manager - $conn = DriverManager::getConnection($connOptions, $config); - $dbalConf = $conn->getConfiguration(); - $this->entityManager = new EntityManager($conn, $dbalConf); $schemaTool = new SchemaTool($this->entityManager); $classes = $this->entityManager->getMetadataFactory()->getAllMetadata(); From b6cd9c30ba7dd109c6f77ac5e6afbbe81d80a588 Mon Sep 17 00:00:00 2001 From: r3hp1c Date: Sat, 2 Mar 2024 21:33:03 +0000 Subject: [PATCH 13/44] Added back some annotations to try and fix some checks --- .../fixtures/Entity/CascadeTarget.php | 9 +++++++++ tests/Functional/fixtures/Entity/Owner.php | 18 +++++++++++++++--- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/tests/Functional/fixtures/Entity/CascadeTarget.php b/tests/Functional/fixtures/Entity/CascadeTarget.php index d020a15f..1ac1810e 100644 --- a/tests/Functional/fixtures/Entity/CascadeTarget.php +++ b/tests/Functional/fixtures/Entity/CascadeTarget.php @@ -9,15 +9,24 @@ class CascadeTarget { /** * @var int + * @ORM\Id + * @ORM\Column(type="integer") + * @ORM\GeneratedValue */ #[ORM\Id] #[ORM\Column(type:"integer")] #[ORM\GeneratedValue()] private $id; + /** + * @ORM\Column(type="encrypted", nullable=true) + */ #[ORM\Column(type:"encrypted", nullable:true)] private $secret; + /** + * @ORM\Column(type="string", nullable=true) + */ #[ORM\Column(type:"string", nullable:true)] private $notSecret; diff --git a/tests/Functional/fixtures/Entity/Owner.php b/tests/Functional/fixtures/Entity/Owner.php index 4cde214e..cd9d9713 100644 --- a/tests/Functional/fixtures/Entity/Owner.php +++ b/tests/Functional/fixtures/Entity/Owner.php @@ -11,21 +11,33 @@ class Owner /** * @var int + * @ORM\Id + * @ORM\Column(type="integer") + * @ORM\GeneratedValue */ #[ORM\Id] #[ORM\Column(type:"integer")] #[ORM\GeneratedValue] private $id; + /** + * @ORM\Column(type="encrypted", nullable=true) + */ #[ORM\Column(type:"encrypted", nullable:true)] private $secret; + /** + * @ORM\Column(type="string", nullable=true) + */ #[ORM\Column(type:"string", nullable:true)] private $notSecret; - #[ORM\OneToOne( - targetEntity:CascadeTarget::class, - cascade:["persist"])] + /** + * @ORM\OneToOne( + * targetEntity="DoctrineEncryptBundle\Tests\Functional\fixtures\Entity\CascadeTarget", + * cascade={"persist"}) + */ + #[ORM\OneToOne(targetEntity:CascadeTarget::class, cascade:["persist"])] private $cascaded; public function getId() From 7140f01133d6f0bcb518335354734bbc38a2e121 Mon Sep 17 00:00:00 2001 From: r3hp1c Date: Sat, 2 Mar 2024 21:35:15 +0000 Subject: [PATCH 14/44] Added back some annotations to try and fix some checks --- tests/Functional/fixtures/Entity/CascadeTarget.php | 3 +++ tests/Functional/fixtures/Entity/Owner.php | 3 +++ 2 files changed, 6 insertions(+) diff --git a/tests/Functional/fixtures/Entity/CascadeTarget.php b/tests/Functional/fixtures/Entity/CascadeTarget.php index 1ac1810e..ed95cac0 100644 --- a/tests/Functional/fixtures/Entity/CascadeTarget.php +++ b/tests/Functional/fixtures/Entity/CascadeTarget.php @@ -4,6 +4,9 @@ use Doctrine\ORM\Mapping as ORM; +/** + * @ORM\Entity() + */ #[ORM\Entity()] class CascadeTarget { diff --git a/tests/Functional/fixtures/Entity/Owner.php b/tests/Functional/fixtures/Entity/Owner.php index cd9d9713..d1892f6d 100644 --- a/tests/Functional/fixtures/Entity/Owner.php +++ b/tests/Functional/fixtures/Entity/Owner.php @@ -5,6 +5,9 @@ use Doctrine\ORM\Mapping as ORM; +/** + * @ORM\Entity() + */ #[ORM\Entity()] class Owner { From 5fd44bd0491c496c9872e3c7f7f993e0431397e2 Mon Sep 17 00:00:00 2001 From: r3hp1c Date: Sat, 2 Mar 2024 21:37:59 +0000 Subject: [PATCH 15/44] attempt to fix: TypeError: Return value of DoctrineEncryptBundle\Types\Encrypted::convertToDatabaseValue() must be an instance of DoctrineEncryptBundle\Types\mixed --- src/Types/Encrypted.php | 4 ++-- src/Types/EncryptedArray.php | 4 ++-- src/Types/EncryptedDateTime.php | 4 ++-- src/Types/EncryptedJSON.php | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Types/Encrypted.php b/src/Types/Encrypted.php index 84ce29c2..d8808bf0 100755 --- a/src/Types/Encrypted.php +++ b/src/Types/Encrypted.php @@ -12,12 +12,12 @@ class Encrypted extends StringType const TYPE = 'encrypted'; - public function convertToPHPValue($value, AbstractPlatform $platform): mixed + public function convertToPHPValue($value, AbstractPlatform $platform) { return $this->service->decrypt ('string', $value); } - public function convertToDatabaseValue($value, AbstractPlatform $platform): mixed + public function convertToDatabaseValue($value, AbstractPlatform $platform) { return $this->service->encrypt ('string', $value); } diff --git a/src/Types/EncryptedArray.php b/src/Types/EncryptedArray.php index 58dd5504..a85219d2 100755 --- a/src/Types/EncryptedArray.php +++ b/src/Types/EncryptedArray.php @@ -12,12 +12,12 @@ class EncryptedArray extends TextType const TYPE = 'encrypted_array'; - public function convertToPHPValue($value, AbstractPlatform $platform): mixed + public function convertToPHPValue($value, AbstractPlatform $platform) { return $this->service->decrypt ('simple_array', $value); } - public function convertToDatabaseValue($value, AbstractPlatform $platform): mixed + public function convertToDatabaseValue($value, AbstractPlatform $platform) { return $this->service->encrypt ('simple_array', $value); } diff --git a/src/Types/EncryptedDateTime.php b/src/Types/EncryptedDateTime.php index 9552109c..0340a397 100755 --- a/src/Types/EncryptedDateTime.php +++ b/src/Types/EncryptedDateTime.php @@ -12,12 +12,12 @@ class EncryptedDateTime extends StringType const TYPE = 'encrypted_datetime'; - public function convertToPHPValue($value, AbstractPlatform $platform): mixed + public function convertToPHPValue($value, AbstractPlatform $platform) { return $this->service->decrypt ('datetime', $value); } - public function convertToDatabaseValue($value, AbstractPlatform $platform): mixed + public function convertToDatabaseValue($value, AbstractPlatform $platform) { return $this->service->encrypt ('datetime', $value); } diff --git a/src/Types/EncryptedJSON.php b/src/Types/EncryptedJSON.php index ba7a01c0..17a4d7e1 100755 --- a/src/Types/EncryptedJSON.php +++ b/src/Types/EncryptedJSON.php @@ -12,12 +12,12 @@ class EncryptedJSON extends TextType const TYPE = 'encrypted_json'; - public function convertToPHPValue($value, AbstractPlatform $platform): mixed + public function convertToPHPValue($value, AbstractPlatform $platform) { return $this->service->decrypt ('json', $value); } - public function convertToDatabaseValue($value, AbstractPlatform $platform): mixed + public function convertToDatabaseValue($value, AbstractPlatform $platform) { return $this->service->encrypt ('json', $value); } From 645c790d8cf2b2f72b6d10c51646c3f21095565b Mon Sep 17 00:00:00 2001 From: r3hp1c Date: Sat, 2 Mar 2024 21:40:44 +0000 Subject: [PATCH 16/44] attempt to fix: Error: Call to undefined method Doctrine\DBAL\Statement::executeQuery() --- tests/DoctrineCompatibilityTrait.php | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/tests/DoctrineCompatibilityTrait.php b/tests/DoctrineCompatibilityTrait.php index b12844e1..4f4f7703 100644 --- a/tests/DoctrineCompatibilityTrait.php +++ b/tests/DoctrineCompatibilityTrait.php @@ -11,7 +11,12 @@ trait DoctrineCompatibilityTrait */ public function executeStatementFetchAll(\Doctrine\DBAL\Statement $statement) { - return $statement->executeQuery()->fetchAllAssociative(); + if (method_exists($statement,'executeQuery')) { + return $statement->executeQuery()->fetchAllAssociative(); + } else { + $statement->execute(); + return $statement->fetchAll(); + } } /** @@ -21,6 +26,11 @@ public function executeStatementFetchAll(\Doctrine\DBAL\Statement $statement) */ public function executeStatementFetch(\Doctrine\DBAL\Statement $statement) { - return $statement->executeQuery()->fetchAssociative(); + if (method_exists($statement,'executeQuery')) { + return $statement->executeQuery()->fetchAssociative(); + } else { + $statement->execute(); + return $statement->fetch(); + } } } \ No newline at end of file From be4876c2c389eae9232bf570fe2108dec8be8dc9 Mon Sep 17 00:00:00 2001 From: r3hp1c Date: Sat, 2 Mar 2024 21:49:22 +0000 Subject: [PATCH 17/44] Added back some annotations to try and fix some checks --- .../fixtures/Entity/AbstractVehicle.php | 15 +++++++++++++++ .../fixtures/Entity/CascadeTargetArray.php | 12 ++++++++++++ .../fixtures/Entity/CascadeTargetDateTime.php | 12 ++++++++++++ .../fixtures/Entity/CascadeTargetJSON.php | 12 ++++++++++++ .../fixtures/Entity/CascadeTargetStrtoupper.php | 12 ++++++++++++ .../fixtures/Entity/ClassTableInheritanceBase.php | 14 ++++++++++++++ .../Entity/ClassTableInheritanceChild.php | 9 +++++++++ .../Functional/fixtures/Entity/VehicleBicycle.php | 4 ++++ tests/Functional/fixtures/Entity/VehicleCar.php | 4 ++++ 9 files changed, 94 insertions(+) diff --git a/tests/Functional/fixtures/Entity/AbstractVehicle.php b/tests/Functional/fixtures/Entity/AbstractVehicle.php index 3c2ba8a5..f9bfac40 100644 --- a/tests/Functional/fixtures/Entity/AbstractVehicle.php +++ b/tests/Functional/fixtures/Entity/AbstractVehicle.php @@ -4,6 +4,12 @@ use Doctrine\ORM\Mapping as ORM; +/** + * @ORM\Entity() + * @ORM\InheritanceType("SINGLE_TABLE") + * @ORM\DiscriminatorColumn(name="type", type="string") + * @ORM\DiscriminatorMap({"car" = "VehicleCar","bike" = "VehicleBicycle"}) + */ #[ORM\Entity()] #[ORM\InheritanceType("SINGLE_TABLE")] #[ORM\DiscriminatorColumn(name:"type", type:"string")] @@ -12,15 +18,24 @@ abstract class AbstractVehicle { /** * @var int + * @ORM\Id + * @ORM\Column(type="integer") + * @ORM\GeneratedValue */ #[ORM\Id] #[ORM\Column(type:"integer")] #[ORM\GeneratedValue] private $id; + /** + * @ORM\Column(type="encrypted", nullable=true) + */ #[ORM\Column(type:"encrypted", nullable:true)] private $secret; + /** + * @ORM\Column(type="string", nullable=true) + */ #[ORM\Column(type:"string", nullable:true)] private $notSecret; diff --git a/tests/Functional/fixtures/Entity/CascadeTargetArray.php b/tests/Functional/fixtures/Entity/CascadeTargetArray.php index 95e13760..ff045502 100755 --- a/tests/Functional/fixtures/Entity/CascadeTargetArray.php +++ b/tests/Functional/fixtures/Entity/CascadeTargetArray.php @@ -4,20 +4,32 @@ use Doctrine\ORM\Mapping as ORM; +/** + * @ORM\Entity() + */ #[ORM\Entity()] class CascadeTargetArray { /** * @var int + * @ORM\Id + * @ORM\Column(type="integer") + * @ORM\GeneratedValue */ #[ORM\Id] #[ORM\Column(type:"integer")] #[ORM\GeneratedValue()] private $id; + /** + * @ORM\Column(type="encrypted_array", nullable=true) + */ #[ORM\Column(type:"encrypted_array", nullable:true)] private $secret; + /** + * @ORM\Column(type="string", nullable=true) + */ #[ORM\Column(type:"string", nullable:true)] private $notSecret; diff --git a/tests/Functional/fixtures/Entity/CascadeTargetDateTime.php b/tests/Functional/fixtures/Entity/CascadeTargetDateTime.php index 9a0303bb..d08626cd 100755 --- a/tests/Functional/fixtures/Entity/CascadeTargetDateTime.php +++ b/tests/Functional/fixtures/Entity/CascadeTargetDateTime.php @@ -4,20 +4,32 @@ use Doctrine\ORM\Mapping as ORM; +/** + * @ORM\Entity() + */ #[ORM\Entity()] class CascadeTargetDateTime { /** * @var int + * @ORM\Id + * @ORM\Column(type="integer") + * @ORM\GeneratedValue */ #[ORM\Id] #[ORM\Column(type:"integer")] #[ORM\GeneratedValue()] private $id; + /** + * @ORM\Column(type="encrypted_datetime", nullable=true) + */ #[ORM\Column(type:"encrypted_datetime", nullable:true)] private $secret; + /** + * @ORM\Column(type="string", nullable=true) + */ #[ORM\Column(type:"string", nullable:true)] private $notSecret; diff --git a/tests/Functional/fixtures/Entity/CascadeTargetJSON.php b/tests/Functional/fixtures/Entity/CascadeTargetJSON.php index d7c9ef94..439d8c7e 100755 --- a/tests/Functional/fixtures/Entity/CascadeTargetJSON.php +++ b/tests/Functional/fixtures/Entity/CascadeTargetJSON.php @@ -4,20 +4,32 @@ use Doctrine\ORM\Mapping as ORM; +/** + * @ORM\Entity() + */ #[ORM\Entity()] class CascadeTargetJSON { /** * @var int + * @ORM\Id + * @ORM\Column(type="integer") + * @ORM\GeneratedValue */ #[ORM\Id] #[ORM\Column(type:"integer")] #[ORM\GeneratedValue()] private $id; + /** + * @ORM\Column(type="encrypted_json", nullable=true) + */ #[ORM\Column(type:"encrypted_json", nullable:true)] private $secret; + /** + * @ORM\Column(type="string", nullable=true) + */ #[ORM\Column(type:"string", nullable:true)] private $notSecret; diff --git a/tests/Functional/fixtures/Entity/CascadeTargetStrtoupper.php b/tests/Functional/fixtures/Entity/CascadeTargetStrtoupper.php index 24bf2bc6..8d496c90 100644 --- a/tests/Functional/fixtures/Entity/CascadeTargetStrtoupper.php +++ b/tests/Functional/fixtures/Entity/CascadeTargetStrtoupper.php @@ -4,20 +4,32 @@ use Doctrine\ORM\Mapping as ORM; +/** + * @ORM\Entity() + */ #[ORM\Entity()] class CascadeTargetStrtoupper { /** * @var int + * @ORM\Id + * @ORM\Column(type="integer") + * @ORM\GeneratedValue */ #[ORM\Id] #[ORM\Column(type:"integer")] #[ORM\GeneratedValue] private $id; + /** + * @ORM\Column(type="encrypted", nullable=true) + */ #[ORM\Column(type:"encrypted", nullable:true)] private $secret; + /** + * @ORM\Column(type="string", nullable=true) + */ #[ORM\Column(type:"string", nullable:true)] private $notSecret; diff --git a/tests/Functional/fixtures/Entity/ClassTableInheritanceBase.php b/tests/Functional/fixtures/Entity/ClassTableInheritanceBase.php index 19c2e728..5592eb65 100644 --- a/tests/Functional/fixtures/Entity/ClassTableInheritanceBase.php +++ b/tests/Functional/fixtures/Entity/ClassTableInheritanceBase.php @@ -4,6 +4,11 @@ use Doctrine\ORM\Mapping as ORM; +/** + * @ORM\Entity + * @ORM\InheritanceType("JOINED") + * @ORM\DiscriminatorColumn(name="discr", type="string") + */ #[ORM\Entity] #[ORM\InheritanceType("JOINED")] #[ORM\DiscriminatorColumn(name:"discr", type:"string")] @@ -12,15 +17,24 @@ class ClassTableInheritanceBase /** * @var int + * @ORM\Id + * @ORM\Column(type="integer") + * @ORM\GeneratedValue */ #[ORM\Id] #[ORM\Column(type:"integer")] #[ORM\GeneratedValue] private $id; + /** + * @ORM\Column(type="encrypted", nullable=true) + */ #[ORM\Column(type:"encrypted", nullable:true)] private $secretBase; + /** + * @ORM\Column(type="string", nullable=true) + */ #[ORM\Column(type:"string", nullable:true)] private $notSecretBase; diff --git a/tests/Functional/fixtures/Entity/ClassTableInheritanceChild.php b/tests/Functional/fixtures/Entity/ClassTableInheritanceChild.php index 56a167df..56da1426 100644 --- a/tests/Functional/fixtures/Entity/ClassTableInheritanceChild.php +++ b/tests/Functional/fixtures/Entity/ClassTableInheritanceChild.php @@ -5,12 +5,21 @@ use Doctrine\ORM\Mapping as ORM; +/** + * @ORM\Entity() + */ #[ORM\Entity] class ClassTableInheritanceChild extends ClassTableInheritanceBase { + /** + * @ORM\Column(type="encrypted", nullable=true) + */ #[ORM\Column(type:"encrypted", nullable:true)] private $secretChild; + /** + * @ORM\Column(type="string", nullable=true) + */ #[ORM\Column(type:"string", nullable:true)] private $notSecretChild; diff --git a/tests/Functional/fixtures/Entity/VehicleBicycle.php b/tests/Functional/fixtures/Entity/VehicleBicycle.php index 5bf1c0ec..e4e0f904 100644 --- a/tests/Functional/fixtures/Entity/VehicleBicycle.php +++ b/tests/Functional/fixtures/Entity/VehicleBicycle.php @@ -5,11 +5,15 @@ use Doctrine\ORM\Mapping as ORM; +/** + * @ORM\Entity() + */ #[ORM\Entity()] class VehicleBicycle extends AbstractVehicle { /** * @var bool + * @ORM\Column(type="boolean") */ #[ORM\Column(type:"boolean")] private $hasSidewheels = false; diff --git a/tests/Functional/fixtures/Entity/VehicleCar.php b/tests/Functional/fixtures/Entity/VehicleCar.php index d68a6a1b..16ac3dfc 100644 --- a/tests/Functional/fixtures/Entity/VehicleCar.php +++ b/tests/Functional/fixtures/Entity/VehicleCar.php @@ -5,11 +5,15 @@ use Doctrine\ORM\Mapping as ORM; +/** + * @ORM\Entity() + */ #[ORM\Entity()] class VehicleCar extends AbstractVehicle { /** * @var string + * @ORM\Column(type="string", length=10) */ #[ORM\Column(type:"string", length:10)] private $licensePlate; From 63a1284897849099118a1e89213bce9858425442 Mon Sep 17 00:00:00 2001 From: r3hp1c Date: Sat, 2 Mar 2024 21:55:48 +0000 Subject: [PATCH 18/44] attempt to fix checks failing after tests pass due to deprecation notices --- phpunit.xml.dist | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/phpunit.xml.dist b/phpunit.xml.dist index ad339a23..4b72e168 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -18,10 +18,12 @@ ./Command - ./Configuration ./DependencyInjection ./Encryptors - ./Subscribers + ./Factories + ./Service + ./Traits + ./Types @@ -29,5 +31,6 @@ + From 8436bc5acddcf60d71054d9e1b70ec261682b1c9 Mon Sep 17 00:00:00 2001 From: r3hp1c Date: Sat, 2 Mar 2024 22:00:21 +0000 Subject: [PATCH 19/44] attempt to fix: LogicException: Lazy ghost objects cannot be enabled because the symfony/var-exporter library version 6.2 or higher is not installed. --- tests/Functional/AbstractFunctionalTestCase.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Functional/AbstractFunctionalTestCase.php b/tests/Functional/AbstractFunctionalTestCase.php index 6aa25b2e..f27cfb5b 100644 --- a/tests/Functional/AbstractFunctionalTestCase.php +++ b/tests/Functional/AbstractFunctionalTestCase.php @@ -94,7 +94,7 @@ public function setUp(): void $cache, $reportFieldsWhereDeclared ); - $config->setLazyGhostObjectEnabled (true); + // $config->setLazyGhostObjectEnabled (true); $config->setSchemaManagerFactory(new DefaultSchemaManagerFactory()); // obtaining the entity manager $conn = DriverManager::getConnection($connOptions, $config); From e5d6ab3ac1ddac6c45446a0194999cfb16715ab7 Mon Sep 17 00:00:00 2001 From: r3hp1c Date: Sun, 3 Mar 2024 09:39:33 +0000 Subject: [PATCH 20/44] Dropped PHP support below 8.1 and old code that caused deprecation notices --- .github/workflows/ci.yml | 14 +- composer.json | 9 +- demo/symfony5.4/composer.json | 8 +- demo/symfony5.4/config/packages/doctrine.yaml | 7 + .../config/packages/php8/doctrine.yaml | 16 - demo/symfony6.x/composer.json | 9 +- demo/symfony6.x/config/packages/doctrine.yaml | 1 + demo/symfony7.x/composer.json | 2 + demo/symfony7.x/composer.lock | 2722 ++--------------- demo/symfony7.x/config/packages/doctrine.yaml | 2 + .../Repository/AbstractSecretRepository.php | 2 +- demo/symfony7.x/symfony.lock | 9 - demo/symfony7.x_doctrine3.x/composer.json | 3 +- .../config/packages/doctrine.yaml | 2 + demo/symfony7.x_doctrine3.x/phpunit.xml.dist | 30 + .../Repository/AbstractSecretRepository.php | 2 +- .../Repository/Attribute/SecretRepository.php | 55 +- demo/symfony7.x_doctrine3.x/symfony.lock | 9 - .../tests/SecretTest.php | 2 +- src/DoctrineEncryptBundle.php | 2 +- src/Types/Encrypted.php | 4 +- src/Types/EncryptedArray.php | 4 +- src/Types/EncryptedDateTime.php | 4 +- src/Types/EncryptedJSON.php | 4 +- tests/DoctrineCompatibilityTrait.php | 14 +- .../Functional/AbstractFunctionalTestCase.php | 46 +- .../fixtures/Entity/AbstractVehicle.php | 15 - .../fixtures/Entity/CascadeTarget.php | 12 - .../fixtures/Entity/CascadeTargetArray.php | 12 - .../fixtures/Entity/CascadeTargetDateTime.php | 12 - .../fixtures/Entity/CascadeTargetJSON.php | 12 - .../Entity/CascadeTargetStrtoupper.php | 12 - .../Entity/ClassTableInheritanceBase.php | 14 - .../Entity/ClassTableInheritanceChild.php | 9 - tests/Functional/fixtures/Entity/Owner.php | 17 - .../fixtures/Entity/VehicleBicycle.php | 4 - .../Functional/fixtures/Entity/VehicleCar.php | 4 - 37 files changed, 419 insertions(+), 2686 deletions(-) delete mode 100644 demo/symfony5.4/config/packages/php8/doctrine.yaml create mode 100755 demo/symfony7.x_doctrine3.x/phpunit.xml.dist diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2aea4401..9b7bf472 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,7 +22,7 @@ jobs: uses: "shivammathur/setup-php@v2" with: coverage: "none" - php-version: "8.0" + php-version: "8.1" - name: "Validate composer.json" run: "composer validate --strict --no-check-lock" @@ -40,7 +40,7 @@ jobs: run: "vendor/bin/phpstan analyze" - name: "PHPCompatibility" - run: "vendor/bin/phpcs src/ tests/ --standard=PHPCompatibility --runtime-set testVersion 7.2-8.3" + run: "vendor/bin/phpcs src/ tests/ --standard=PHPCompatibility --runtime-set testVersion 8.1-8.3" tests: name: "Tests ${{ matrix.php-version }} ${{ matrix.dependency-versions }}" @@ -51,16 +51,16 @@ jobs: fail-fast: false matrix: # normal, highest, non-dev installs - php-version: ['7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3'] + php-version: ['8.1', '8.2', '8.3'] composer-options: ['--prefer-stable'] dependency-versions: ['highest'] include: # testing lowest PHP version with lowest dependencies - - php-version: '7.2.5' + - php-version: '8.1' dependency-versions: 'lowest' composer-options: '--prefer-lowest' env: - SYMFONY_PHPUNIT_VERSION: 7 + SYMFONY_PHPUNIT_VERSION: 9 steps: - name: "Checkout code" @@ -85,7 +85,7 @@ jobs: - name: Unit Tests run: vendor/bin/simple-phpunit env: - SYMFONY_PHPUNIT_VERSION: "${{ matrix.dependency-versions == 'lowest' && '7' || '' }}" + SYMFONY_PHPUNIT_VERSION: "${{ matrix.dependency-versions == 'lowest' && '9' || '' }}" - name: Install symlinks for demo's uses: "ramsey/composer-install@v2" @@ -104,7 +104,7 @@ jobs: - name: Demo symfony5.4 - Unit Tests run: demo/symfony5.4/bin/phpunit -c demo/symfony5.4/phpunit.xml.dist env: - SYMFONY_PHPUNIT_VERSION: "${{ matrix.dependency-versions == 'lowest' && '7' || '' }}" + SYMFONY_PHPUNIT_VERSION: "${{ matrix.dependency-versions == 'lowest' && '9' || '' }}" - name: Demo symfony6.x - Install dependencies uses: "ramsey/composer-install@v2" diff --git a/composer.json b/composer.json index 9aca399a..bd52716a 100644 --- a/composer.json +++ b/composer.json @@ -5,16 +5,14 @@ "license": "MIT", "description": "Encrypted symfony entity's by verified and standardized libraries", "require": { - "php": "^7.2|^8.0", + "php": "^8.1", "doctrine/orm": "^2.5|^3.0", "doctrine/doctrine-bundle": "^2.0.8|^2.1", "symfony/property-access": "^5.4|^6.0|^7.0", "symfony/dependency-injection": "^5.4|^6.0|^7.0", "symfony/yaml": "^5.4|^6.0|^7.0", "symfony/http-kernel": "^5.4|^6.0|^7.0", - "symfony/config": "^5.4|^6.0|^7.0", - "doctrine/annotations": "^1.13|^2.0", - "symfony/expression-language": "^5.4|^6.0|^7.0" + "symfony/config": "^5.4|^6.0|^7.0" }, "require-dev": { "paragonie/halite": "^4.6|^5.0", @@ -22,7 +20,8 @@ "doctrine/cache": "^1.11", "phpstan/phpstan": "^1.4", "phpcompatibility/php-compatibility": "^9.3", - "symfony/phpunit-bridge": "^7.0" + "symfony/phpunit-bridge": "^7.0", + "symfony/expression-language": "^5.4|^6.0|^7.0" }, "suggest": { "defuse/php-encryption": "Alternative for halite for use with older php-versions", diff --git a/demo/symfony5.4/composer.json b/demo/symfony5.4/composer.json index b2dfa145..3f829a5a 100644 --- a/demo/symfony5.4/composer.json +++ b/demo/symfony5.4/composer.json @@ -4,9 +4,10 @@ "minimum-stability": "stable", "prefer-stable": true, "require": { - "php": ">=7.2.5", + "php": "^8.1", "ext-ctype": "*", "ext-iconv": "*", + "doctrine/orm": "^2.5", "doctrineencryptbundle/doctrine-encrypt-bundle": "@dev", "doctrine/persistence": "^3.2", "paragonie/halite": "^4.6", @@ -16,7 +17,8 @@ "symfony/framework-bundle": "5.4.*", "symfony/runtime": "5.4.*", "symfony/twig-bundle": "5.4.*", - "symfony/yaml": "5.4.*" + "symfony/yaml": "5.4.*", + "doctrine/annotations": "^2.0" }, "require-dev": { "symfony/phpunit-bridge": "^7.0" @@ -76,4 +78,4 @@ "url": "../../" } ] -} \ No newline at end of file +} diff --git a/demo/symfony5.4/config/packages/doctrine.yaml b/demo/symfony5.4/config/packages/doctrine.yaml index 7f2c0c90..56f7e5d9 100644 --- a/demo/symfony5.4/config/packages/doctrine.yaml +++ b/demo/symfony5.4/config/packages/doctrine.yaml @@ -6,6 +6,7 @@ doctrine: # either here or in the DATABASE_URL env var (see .env file) #server_version: '15' orm: + enable_lazy_ghost_objects: true auto_generate_proxy_classes: true naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware auto_mapping: true @@ -16,6 +17,12 @@ doctrine: dir: '%kernel.project_dir%/src/Entity/Annotation' prefix: 'App\Entity\Annotation' alias: App + Attributes: + type: 'attribute' + is_bundle: false + dir: '%kernel.project_dir%/src/Entity/Attribute' + prefix: 'App\Entity\Attribute' + alias: App when@test: doctrine: diff --git a/demo/symfony5.4/config/packages/php8/doctrine.yaml b/demo/symfony5.4/config/packages/php8/doctrine.yaml deleted file mode 100644 index 1710f9fa..00000000 --- a/demo/symfony5.4/config/packages/php8/doctrine.yaml +++ /dev/null @@ -1,16 +0,0 @@ -doctrine: - orm: - mappings: - Annotation: - type: 'annotation' - is_bundle: false - dir: '%kernel.project_dir%/src/Entity/Annotation' - prefix: 'App\Entity\Annotation' - alias: App - Attributes: - type: 'attribute' - is_bundle: false - dir: '%kernel.project_dir%/src/Entity/Attribute' - prefix: 'App\Entity\Attribute' - alias: App - diff --git a/demo/symfony6.x/composer.json b/demo/symfony6.x/composer.json index 7349f073..091bcdd4 100644 --- a/demo/symfony6.x/composer.json +++ b/demo/symfony6.x/composer.json @@ -4,17 +4,20 @@ "minimum-stability": "stable", "prefer-stable": true, "require": { - "php": ">=8.0.2", + "php": "^8.1", "ext-ctype": "*", "ext-iconv": "*", + "doctrine/orm": "^2.5", "doctrineencryptbundle/doctrine-encrypt-bundle": "@dev", + "doctrine/persistence": "^3.2", "paragonie/halite": "^5.0", "symfony/console": "6.0.*", "symfony/dotenv": "6.0.*", "symfony/flex": "^2", "symfony/framework-bundle": "6.0.*", "symfony/runtime": "6.0.*", - "symfony/twig-bundle": "6.0.*" + "symfony/twig-bundle": "6.0.*", + "doctrine/annotations": "^2.0" }, "require-dev": { "symfony/maker-bundle": "^1.0", @@ -77,4 +80,4 @@ "url": "../../" } ] -} \ No newline at end of file +} diff --git a/demo/symfony6.x/config/packages/doctrine.yaml b/demo/symfony6.x/config/packages/doctrine.yaml index bff6abbf..a82625fe 100644 --- a/demo/symfony6.x/config/packages/doctrine.yaml +++ b/demo/symfony6.x/config/packages/doctrine.yaml @@ -6,6 +6,7 @@ doctrine: # either here or in the DATABASE_URL env var (see .env file) #server_version: '13' orm: + enable_lazy_ghost_objects: true auto_generate_proxy_classes: true naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware auto_mapping: true diff --git a/demo/symfony7.x/composer.json b/demo/symfony7.x/composer.json index 1c314051..d5835f1d 100644 --- a/demo/symfony7.x/composer.json +++ b/demo/symfony7.x/composer.json @@ -7,7 +7,9 @@ "php": ">=8.2", "ext-ctype": "*", "ext-iconv": "*", + "doctrine/orm": "^2.5", "doctrineencryptbundle/doctrine-encrypt-bundle": "@dev", + "doctrine/persistence": "^3.2", "symfony/console": "7.0.*", "symfony/dotenv": "7.0.*", "symfony/flex": "^2", diff --git a/demo/symfony7.x/composer.lock b/demo/symfony7.x/composer.lock index da56e3f5..e76b8a2e 100644 --- a/demo/symfony7.x/composer.lock +++ b/demo/symfony7.x/composer.lock @@ -4,84 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "71eca238f24ddce773e7b05a12d47577", + "content-hash": "c55532552561076ce660bd65e2e7815b", "packages": [ - { - "name": "doctrine/annotations", - "version": "2.0.1", - "source": { - "type": "git", - "url": "https://github.com/doctrine/annotations.git", - "reference": "e157ef3f3124bbf6fe7ce0ffd109e8a8ef284e7f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/annotations/zipball/e157ef3f3124bbf6fe7ce0ffd109e8a8ef284e7f", - "reference": "e157ef3f3124bbf6fe7ce0ffd109e8a8ef284e7f", - "shasum": "" - }, - "require": { - "doctrine/lexer": "^2 || ^3", - "ext-tokenizer": "*", - "php": "^7.2 || ^8.0", - "psr/cache": "^1 || ^2 || ^3" - }, - "require-dev": { - "doctrine/cache": "^2.0", - "doctrine/coding-standard": "^10", - "phpstan/phpstan": "^1.8.0", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "symfony/cache": "^5.4 || ^6", - "vimeo/psalm": "^4.10" - }, - "suggest": { - "php": "PHP 8.0 or higher comes with attributes, a native replacement for annotations" - }, - "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/2.0.1" - }, - "time": "2023-02-02T22:02:53+00:00" - }, { "name": "doctrine/cache", "version": "2.2.0", @@ -177,16 +101,16 @@ }, { "name": "doctrine/collections", - "version": "2.1.4", + "version": "2.2.0", "source": { "type": "git", "url": "https://github.com/doctrine/collections.git", - "reference": "72328a11443a0de79967104ad36ba7b30bded134" + "reference": "07e16cd7b80a2cffed99e36b541876af172f0257" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/collections/zipball/72328a11443a0de79967104ad36ba7b30bded134", - "reference": "72328a11443a0de79967104ad36ba7b30bded134", + "url": "https://api.github.com/repos/doctrine/collections/zipball/07e16cd7b80a2cffed99e36b541876af172f0257", + "reference": "07e16cd7b80a2cffed99e36b541876af172f0257", "shasum": "" }, "require": { @@ -198,7 +122,7 @@ "ext-json": "*", "phpstan/phpstan": "^1.8", "phpstan/phpstan-phpunit": "^1.0", - "phpunit/phpunit": "^9.5", + "phpunit/phpunit": "^10.5", "vimeo/psalm": "^5.11" }, "type": "library", @@ -243,7 +167,7 @@ ], "support": { "issues": "https://github.com/doctrine/collections/issues", - "source": "https://github.com/doctrine/collections/tree/2.1.4" + "source": "https://github.com/doctrine/collections/tree/2.2.0" }, "funding": [ { @@ -259,7 +183,7 @@ "type": "tidelift" } ], - "time": "2023-10-03T09:22:33+00:00" + "time": "2024-02-25T22:55:36+00:00" }, { "name": "doctrine/common", @@ -354,16 +278,16 @@ }, { "name": "doctrine/dbal", - "version": "3.7.2", + "version": "3.8.2", "source": { "type": "git", "url": "https://github.com/doctrine/dbal.git", - "reference": "0ac3c270590e54910715e9a1a044cc368df282b2" + "reference": "a19a1d05ca211f41089dffcc387733a6875196cb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/dbal/zipball/0ac3c270590e54910715e9a1a044cc368df282b2", - "reference": "0ac3c270590e54910715e9a1a044cc368df282b2", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/a19a1d05ca211f41089dffcc387733a6875196cb", + "reference": "a19a1d05ca211f41089dffcc387733a6875196cb", "shasum": "" }, "require": { @@ -379,14 +303,14 @@ "doctrine/coding-standard": "12.0.0", "fig/log-test": "^1", "jetbrains/phpstorm-stubs": "2023.1", - "phpstan/phpstan": "1.10.42", + "phpstan/phpstan": "1.10.57", "phpstan/phpstan-strict-rules": "^1.5", - "phpunit/phpunit": "9.6.13", + "phpunit/phpunit": "9.6.16", "psalm/plugin-phpunit": "0.18.4", "slevomat/coding-standard": "8.13.1", - "squizlabs/php_codesniffer": "3.7.2", - "symfony/cache": "^5.4|^6.0", - "symfony/console": "^4.4|^5.4|^6.0", + "squizlabs/php_codesniffer": "3.8.1", + "symfony/cache": "^5.4|^6.0|^7.0", + "symfony/console": "^4.4|^5.4|^6.0|^7.0", "vimeo/psalm": "4.30.0" }, "suggest": { @@ -447,7 +371,7 @@ ], "support": { "issues": "https://github.com/doctrine/dbal/issues", - "source": "https://github.com/doctrine/dbal/tree/3.7.2" + "source": "https://github.com/doctrine/dbal/tree/3.8.2" }, "funding": [ { @@ -463,20 +387,20 @@ "type": "tidelift" } ], - "time": "2023-11-19T08:06:58+00:00" + "time": "2024-02-12T18:36:36+00:00" }, { "name": "doctrine/deprecations", - "version": "1.1.2", + "version": "1.1.3", "source": { "type": "git", "url": "https://github.com/doctrine/deprecations.git", - "reference": "4f2d4f2836e7ec4e7a8625e75c6aa916004db931" + "reference": "dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/deprecations/zipball/4f2d4f2836e7ec4e7a8625e75c6aa916004db931", - "reference": "4f2d4f2836e7ec4e7a8625e75c6aa916004db931", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab", + "reference": "dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab", "shasum": "" }, "require": { @@ -508,22 +432,22 @@ "homepage": "https://www.doctrine-project.org/", "support": { "issues": "https://github.com/doctrine/deprecations/issues", - "source": "https://github.com/doctrine/deprecations/tree/1.1.2" + "source": "https://github.com/doctrine/deprecations/tree/1.1.3" }, - "time": "2023-09-27T20:04:15+00:00" + "time": "2024-01-30T19:34:25+00:00" }, { "name": "doctrine/doctrine-bundle", - "version": "2.11.1", + "version": "2.11.3", "source": { "type": "git", "url": "https://github.com/doctrine/DoctrineBundle.git", - "reference": "4089f1424b724786c062aea50aae5f773449b94b" + "reference": "492725310ae9a1b5b20d6ae09fb5ae6404616e68" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/DoctrineBundle/zipball/4089f1424b724786c062aea50aae5f773449b94b", - "reference": "4089f1424b724786c062aea50aae5f773449b94b", + "url": "https://api.github.com/repos/doctrine/DoctrineBundle/zipball/492725310ae9a1b5b20d6ae09fb5ae6404616e68", + "reference": "492725310ae9a1b5b20d6ae09fb5ae6404616e68", "shasum": "" }, "require": { @@ -544,18 +468,18 @@ }, "conflict": { "doctrine/annotations": ">=3.0", - "doctrine/orm": "<2.14 || >=4.0", + "doctrine/orm": "<2.17 || >=4.0", "twig/twig": "<1.34 || >=2.0 <2.4" }, "require-dev": { "doctrine/annotations": "^1 || ^2", "doctrine/coding-standard": "^12", "doctrine/deprecations": "^1.0", - "doctrine/orm": "^2.14 || ^3.0", + "doctrine/orm": "^2.17 || ^3.0", "friendsofphp/proxy-manager-lts": "^1.0", - "phpunit/phpunit": "^9.5.26 || ^10.0", + "phpunit/phpunit": "^9.5.26", "psalm/plugin-phpunit": "^0.18.4", - "psalm/plugin-symfony": "^4", + "psalm/plugin-symfony": "^5", "psr/log": "^1.1.4 || ^2.0 || ^3.0", "symfony/phpunit-bridge": "^6.1 || ^7.0", "symfony/property-info": "^5.4 || ^6.0 || ^7.0", @@ -568,7 +492,7 @@ "symfony/web-profiler-bundle": "^5.4 || ^6.0 || ^7.0", "symfony/yaml": "^5.4 || ^6.0 || ^7.0", "twig/twig": "^1.34 || ^2.12 || ^3.0", - "vimeo/psalm": "^4.30" + "vimeo/psalm": "^5.15" }, "suggest": { "doctrine/orm": "The Doctrine ORM integration is optional in the bundle.", @@ -613,7 +537,7 @@ ], "support": { "issues": "https://github.com/doctrine/DoctrineBundle/issues", - "source": "https://github.com/doctrine/DoctrineBundle/tree/2.11.1" + "source": "https://github.com/doctrine/DoctrineBundle/tree/2.11.3" }, "funding": [ { @@ -629,7 +553,7 @@ "type": "tidelift" } ], - "time": "2023-11-15T20:01:50+00:00" + "time": "2024-02-10T20:56:20+00:00" }, { "name": "doctrine/event-manager", @@ -724,16 +648,16 @@ }, { "name": "doctrine/inflector", - "version": "2.0.8", + "version": "2.0.10", "source": { "type": "git", "url": "https://github.com/doctrine/inflector.git", - "reference": "f9301a5b2fb1216b2b08f02ba04dc45423db6bff" + "reference": "5817d0659c5b50c9b950feb9af7b9668e2c436bc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/inflector/zipball/f9301a5b2fb1216b2b08f02ba04dc45423db6bff", - "reference": "f9301a5b2fb1216b2b08f02ba04dc45423db6bff", + "url": "https://api.github.com/repos/doctrine/inflector/zipball/5817d0659c5b50c9b950feb9af7b9668e2c436bc", + "reference": "5817d0659c5b50c9b950feb9af7b9668e2c436bc", "shasum": "" }, "require": { @@ -795,7 +719,7 @@ ], "support": { "issues": "https://github.com/doctrine/inflector/issues", - "source": "https://github.com/doctrine/inflector/tree/2.0.8" + "source": "https://github.com/doctrine/inflector/tree/2.0.10" }, "funding": [ { @@ -811,7 +735,7 @@ "type": "tidelift" } ], - "time": "2023-06-16T13:40:37+00:00" + "time": "2024-02-18T20:23:39+00:00" }, { "name": "doctrine/instantiator", @@ -885,28 +809,27 @@ }, { "name": "doctrine/lexer", - "version": "2.1.0", + "version": "3.0.1", "source": { "type": "git", "url": "https://github.com/doctrine/lexer.git", - "reference": "39ab8fcf5a51ce4b85ca97c7a7d033eb12831124" + "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/39ab8fcf5a51ce4b85ca97c7a7d033eb12831124", - "reference": "39ab8fcf5a51ce4b85ca97c7a7d033eb12831124", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd", + "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd", "shasum": "" }, "require": { - "doctrine/deprecations": "^1.0", - "php": "^7.1 || ^8.0" + "php": "^8.1" }, "require-dev": { - "doctrine/coding-standard": "^9 || ^10", - "phpstan/phpstan": "^1.3", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "doctrine/coding-standard": "^12", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^10.5", "psalm/plugin-phpunit": "^0.18.3", - "vimeo/psalm": "^4.11 || ^5.0" + "vimeo/psalm": "^5.21" }, "type": "library", "autoload": { @@ -943,7 +866,7 @@ ], "support": { "issues": "https://github.com/doctrine/lexer/issues", - "source": "https://github.com/doctrine/lexer/tree/2.1.0" + "source": "https://github.com/doctrine/lexer/tree/3.0.1" }, "funding": [ { @@ -959,20 +882,20 @@ "type": "tidelift" } ], - "time": "2022-12-14T08:49:07+00:00" + "time": "2024-02-05T11:56:58+00:00" }, { "name": "doctrine/orm", - "version": "2.17.1", + "version": "2.18.2", "source": { "type": "git", "url": "https://github.com/doctrine/orm.git", - "reference": "1a4fe6e0bb67762370937a7e6cee3da40a9122d1" + "reference": "52a6a21387380b09419a66a7ec1c66f6cab69b20" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/orm/zipball/1a4fe6e0bb67762370937a7e6cee3da40a9122d1", - "reference": "1a4fe6e0bb67762370937a7e6cee3da40a9122d1", + "url": "https://api.github.com/repos/doctrine/orm/zipball/52a6a21387380b09419a66a7ec1c66f6cab69b20", + "reference": "52a6a21387380b09419a66a7ec1c66f6cab69b20", "shasum": "" }, "require": { @@ -985,7 +908,7 @@ "doctrine/event-manager": "^1.2 || ^2", "doctrine/inflector": "^1.4 || ^2.0", "doctrine/instantiator": "^1.3 || ^2", - "doctrine/lexer": "^2", + "doctrine/lexer": "^2 || ^3", "doctrine/persistence": "^2.4 || ^3", "ext-ctype": "*", "php": "^7.1 || ^8.0", @@ -1001,14 +924,14 @@ "doctrine/annotations": "^1.13 || ^2", "doctrine/coding-standard": "^9.0.2 || ^12.0", "phpbench/phpbench": "^0.16.10 || ^1.0", - "phpstan/phpstan": "~1.4.10 || 1.10.35", + "phpstan/phpstan": "~1.4.10 || 1.10.59", "phpunit/phpunit": "^7.5 || ^8.5 || ^9.6", "psr/log": "^1 || ^2 || ^3", "squizlabs/php_codesniffer": "3.7.2", - "symfony/cache": "^4.4 || ^5.4 || ^6.0", - "symfony/var-exporter": "^4.4 || ^5.4 || ^6.2", - "symfony/yaml": "^3.4 || ^4.0 || ^5.0 || ^6.0", - "vimeo/psalm": "4.30.0 || 5.15.0" + "symfony/cache": "^4.4 || ^5.4 || ^6.4 || ^7.0", + "symfony/var-exporter": "^4.4 || ^5.4 || ^6.2 || ^7.0", + "symfony/yaml": "^3.4 || ^4.0 || ^5.0 || ^6.0 || ^7.0", + "vimeo/psalm": "4.30.0 || 5.22.2" }, "suggest": { "ext-dom": "Provides support for XSD validation for XML mapping files", @@ -1021,7 +944,7 @@ "type": "library", "autoload": { "psr-4": { - "Doctrine\\ORM\\": "lib/Doctrine/ORM" + "Doctrine\\ORM\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -1058,22 +981,22 @@ ], "support": { "issues": "https://github.com/doctrine/orm/issues", - "source": "https://github.com/doctrine/orm/tree/2.17.1" + "source": "https://github.com/doctrine/orm/tree/2.18.2" }, - "time": "2023-11-17T06:25:40+00:00" + "time": "2024-03-01T09:47:18+00:00" }, { "name": "doctrine/persistence", - "version": "3.2.0", + "version": "3.3.1", "source": { "type": "git", "url": "https://github.com/doctrine/persistence.git", - "reference": "63fee8c33bef740db6730eb2a750cd3da6495603" + "reference": "b6fd1f126b13c1f7e7321f7338b14a19116b5de4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/persistence/zipball/63fee8c33bef740db6730eb2a750cd3da6495603", - "reference": "63fee8c33bef740db6730eb2a750cd3da6495603", + "url": "https://api.github.com/repos/doctrine/persistence/zipball/b6fd1f126b13c1f7e7321f7338b14a19116b5de4", + "reference": "b6fd1f126b13c1f7e7321f7338b14a19116b5de4", "shasum": "" }, "require": { @@ -1142,7 +1065,7 @@ ], "support": { "issues": "https://github.com/doctrine/persistence/issues", - "source": "https://github.com/doctrine/persistence/tree/3.2.0" + "source": "https://github.com/doctrine/persistence/tree/3.3.1" }, "funding": [ { @@ -1158,20 +1081,20 @@ "type": "tidelift" } ], - "time": "2023-05-17T18:32:04+00:00" + "time": "2024-03-01T19:53:13+00:00" }, { "name": "doctrine/sql-formatter", - "version": "1.1.3", + "version": "1.2.0", "source": { "type": "git", "url": "https://github.com/doctrine/sql-formatter.git", - "reference": "25a06c7bf4c6b8218f47928654252863ffc890a5" + "reference": "a321d114e0a18e6497f8a2cd6f890e000cc17ecc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/sql-formatter/zipball/25a06c7bf4c6b8218f47928654252863ffc890a5", - "reference": "25a06c7bf4c6b8218f47928654252863ffc890a5", + "url": "https://api.github.com/repos/doctrine/sql-formatter/zipball/a321d114e0a18e6497f8a2cd6f890e000cc17ecc", + "reference": "a321d114e0a18e6497f8a2cd6f890e000cc17ecc", "shasum": "" }, "require": { @@ -1208,27 +1131,24 @@ ], "support": { "issues": "https://github.com/doctrine/sql-formatter/issues", - "source": "https://github.com/doctrine/sql-formatter/tree/1.1.3" + "source": "https://github.com/doctrine/sql-formatter/tree/1.2.0" }, - "time": "2022-05-23T21:33:49+00:00" + "time": "2023-08-16T21:49:04+00:00" }, { "name": "doctrineencryptbundle/doctrine-encrypt-bundle", - "version": "dev-symfony7", + "version": "6.0.x-dev", "dist": { "type": "path", "url": "../..", - "reference": "9f23159c8a9c27a86110bd81f1e704b714df5074" + "reference": "8436bc5acddcf60d71054d9e1b70ec261682b1c9" }, "require": { - "doctrine/annotations": "^1.13|^2.0", - "doctrine/doctrine-bundle": "^2.0", - "doctrine/orm": "^2.5", - "paragonie/halite": "^4.6|^5.0", - "php": "^7.2|^8.0", + "doctrine/doctrine-bundle": "^2.0.8|^2.1", + "doctrine/orm": "^2.5|^3.0", + "php": "^8.1", "symfony/config": "^5.4|^6.0|^7.0", "symfony/dependency-injection": "^5.4|^6.0|^7.0", - "symfony/expression-language": "^5.4|^6.0|^7.0", "symfony/http-kernel": "^5.4|^6.0|^7.0", "symfony/property-access": "^5.4|^6.0|^7.0", "symfony/yaml": "^5.4|^6.0|^7.0" @@ -1236,10 +1156,11 @@ "require-dev": { "defuse/php-encryption": "^2.1", "doctrine/cache": "^1.11", - "jetbrains/phpstorm-attributes": "^1.0", + "paragonie/halite": "^4.6|^5.0", "phpcompatibility/php-compatibility": "^9.3", "phpstan/phpstan": "^1.4", - "symfony/phpunit-bridge": "^6.0|^7.0" + "symfony/expression-language": "^5.4|^6.0|^7.0", + "symfony/phpunit-bridge": "^7.0" }, "suggest": { "defuse/php-encryption": "Alternative for halite for use with older php-versions", @@ -1284,333 +1205,6 @@ "relative": true } }, - { - "name": "paragonie/constant_time_encoding", - "version": "v2.6.3", - "source": { - "type": "git", - "url": "https://github.com/paragonie/constant_time_encoding.git", - "reference": "58c3f47f650c94ec05a151692652a868995d2938" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/58c3f47f650c94ec05a151692652a868995d2938", - "reference": "58c3f47f650c94ec05a151692652a868995d2938", - "shasum": "" - }, - "require": { - "php": "^7|^8" - }, - "require-dev": { - "phpunit/phpunit": "^6|^7|^8|^9", - "vimeo/psalm": "^1|^2|^3|^4" - }, - "type": "library", - "autoload": { - "psr-4": { - "ParagonIE\\ConstantTime\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Paragon Initiative Enterprises", - "email": "security@paragonie.com", - "homepage": "https://paragonie.com", - "role": "Maintainer" - }, - { - "name": "Steve 'Sc00bz' Thomas", - "email": "steve@tobtu.com", - "homepage": "https://www.tobtu.com", - "role": "Original Developer" - } - ], - "description": "Constant-time Implementations of RFC 4648 Encoding (Base-64, Base-32, Base-16)", - "keywords": [ - "base16", - "base32", - "base32_decode", - "base32_encode", - "base64", - "base64_decode", - "base64_encode", - "bin2hex", - "encoding", - "hex", - "hex2bin", - "rfc4648" - ], - "support": { - "email": "info@paragonie.com", - "issues": "https://github.com/paragonie/constant_time_encoding/issues", - "source": "https://github.com/paragonie/constant_time_encoding" - }, - "time": "2022-06-14T06:56:20+00:00" - }, - { - "name": "paragonie/halite", - "version": "v5.1.0", - "source": { - "type": "git", - "url": "https://github.com/paragonie/halite.git", - "reference": "666f9770a12bd8a49cefba16c759baa4843dbf5a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/paragonie/halite/zipball/666f9770a12bd8a49cefba16c759baa4843dbf5a", - "reference": "666f9770a12bd8a49cefba16c759baa4843dbf5a", - "shasum": "" - }, - "require": { - "ext-json": "*", - "paragonie/constant_time_encoding": "^2", - "paragonie/hidden-string": "^1|^2", - "paragonie/sodium_compat": "^1.17", - "php": "^8.1" - }, - "require-dev": { - "phpunit/phpunit": "^9", - "vimeo/psalm": "^4" - }, - "type": "library", - "autoload": { - "psr-4": { - "ParagonIE\\Halite\\": "./src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MPL-2.0" - ], - "authors": [ - { - "name": "Paragon Initiative Enterprises", - "email": "info@paragonie.com", - "homepage": "https://paragonie.com" - } - ], - "description": "High-level cryptography interface powered by libsodium", - "homepage": "https://github.com/paragonie/halite", - "keywords": [ - "Argon2i", - "BLAKE", - "BLAKE2", - "BLAKE2b", - "Curve25519", - "Ed25519", - "X25519", - "Xsalsa20", - "argon2", - "cryptography", - "encryption", - "ext-sodium", - "hashing", - "libsodium", - "password", - "public-key", - "signatures", - "sodium" - ], - "support": { - "docs": "https://github.com/paragonie/halite/tree/master/doc", - "issues": "https://github.com/paragonie/halite/issues", - "source": "https://github.com/paragonie/halite/tree/v5.1.0" - }, - "time": "2022-05-23T05:02:50+00:00" - }, - { - "name": "paragonie/hidden-string", - "version": "v2.0.0", - "source": { - "type": "git", - "url": "https://github.com/paragonie/hidden-string.git", - "reference": "151e53d55bfc67dd58087cdf8762dd8177ea7575" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/paragonie/hidden-string/zipball/151e53d55bfc67dd58087cdf8762dd8177ea7575", - "reference": "151e53d55bfc67dd58087cdf8762dd8177ea7575", - "shasum": "" - }, - "require": { - "paragonie/constant_time_encoding": "^2", - "paragonie/sodium_compat": "^1.6", - "php": "^7.4|^8" - }, - "require-dev": { - "phpunit/phpunit": "^6|^7|^8|^9", - "vimeo/psalm": "^3|^4" - }, - "type": "library", - "autoload": { - "psr-4": { - "ParagonIE\\HiddenString\\": "./src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MPL-2.0" - ], - "authors": [ - { - "name": "Paragon Initiative Enterprises", - "email": "info@paragonie.com", - "homepage": "https://paragonie.com" - } - ], - "description": "Encapsulate strings in an object to hide them from stack traces", - "homepage": "https://github.com/paragonie/hidden-string", - "keywords": [ - "hidden", - "stack trace", - "string" - ], - "support": { - "issues": "https://github.com/paragonie/hidden-string/issues", - "source": "https://github.com/paragonie/hidden-string/tree/v2.0.0" - }, - "time": "2020-12-06T15:07:44+00:00" - }, - { - "name": "paragonie/random_compat", - "version": "v9.99.100", - "source": { - "type": "git", - "url": "https://github.com/paragonie/random_compat.git", - "reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/paragonie/random_compat/zipball/996434e5492cb4c3edcb9168db6fbb1359ef965a", - "reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a", - "shasum": "" - }, - "require": { - "php": ">= 7" - }, - "require-dev": { - "phpunit/phpunit": "4.*|5.*", - "vimeo/psalm": "^1" - }, - "suggest": { - "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." - }, - "type": "library", - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Paragon Initiative Enterprises", - "email": "security@paragonie.com", - "homepage": "https://paragonie.com" - } - ], - "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", - "keywords": [ - "csprng", - "polyfill", - "pseudorandom", - "random" - ], - "support": { - "email": "info@paragonie.com", - "issues": "https://github.com/paragonie/random_compat/issues", - "source": "https://github.com/paragonie/random_compat" - }, - "time": "2020-10-15T08:29:30+00:00" - }, - { - "name": "paragonie/sodium_compat", - "version": "v1.20.0", - "source": { - "type": "git", - "url": "https://github.com/paragonie/sodium_compat.git", - "reference": "e592a3e06d1fa0d43988c7c7d9948ca836f644b6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/paragonie/sodium_compat/zipball/e592a3e06d1fa0d43988c7c7d9948ca836f644b6", - "reference": "e592a3e06d1fa0d43988c7c7d9948ca836f644b6", - "shasum": "" - }, - "require": { - "paragonie/random_compat": ">=1", - "php": "^5.2.4|^5.3|^5.4|^5.5|^5.6|^7|^8" - }, - "require-dev": { - "phpunit/phpunit": "^3|^4|^5|^6|^7|^8|^9" - }, - "suggest": { - "ext-libsodium": "PHP < 7.0: Better performance, password hashing (Argon2i), secure memory management (memzero), and better security.", - "ext-sodium": "PHP >= 7.0: Better performance, password hashing (Argon2i), secure memory management (memzero), and better security." - }, - "type": "library", - "autoload": { - "files": [ - "autoload.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "ISC" - ], - "authors": [ - { - "name": "Paragon Initiative Enterprises", - "email": "security@paragonie.com" - }, - { - "name": "Frank Denis", - "email": "jedisct1@pureftpd.org" - } - ], - "description": "Pure PHP implementation of libsodium; uses the PHP extension if it exists", - "keywords": [ - "Authentication", - "BLAKE2b", - "ChaCha20", - "ChaCha20-Poly1305", - "Chapoly", - "Curve25519", - "Ed25519", - "EdDSA", - "Edwards-curve Digital Signature Algorithm", - "Elliptic Curve Diffie-Hellman", - "Poly1305", - "Pure-PHP cryptography", - "RFC 7748", - "RFC 8032", - "Salpoly", - "Salsa20", - "X25519", - "XChaCha20-Poly1305", - "XSalsa20-Poly1305", - "Xchacha20", - "Xsalsa20", - "aead", - "cryptography", - "ecdh", - "elliptic curve", - "elliptic curve cryptography", - "encryption", - "libsodium", - "php", - "public-key cryptography", - "secret-key cryptography", - "side-channel resistant" - ], - "support": { - "issues": "https://github.com/paragonie/sodium_compat/issues", - "source": "https://github.com/paragonie/sodium_compat/tree/v1.20.0" - }, - "time": "2023-04-30T00:54:53+00:00" - }, { "name": "psr/cache", "version": "3.0.0", @@ -1815,16 +1409,16 @@ }, { "name": "symfony/cache", - "version": "v7.0.0", + "version": "v7.0.4", "source": { "type": "git", "url": "https://github.com/symfony/cache.git", - "reference": "5e2376f726d61541b9617512e374808d12c1dc22" + "reference": "fc822951dd360a593224bb2cef90a087d0dff60f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/5e2376f726d61541b9617512e374808d12c1dc22", - "reference": "5e2376f726d61541b9617512e374808d12c1dc22", + "url": "https://api.github.com/repos/symfony/cache/zipball/fc822951dd360a593224bb2cef90a087d0dff60f", + "reference": "fc822951dd360a593224bb2cef90a087d0dff60f", "shasum": "" }, "require": { @@ -1891,7 +1485,7 @@ "psr6" ], "support": { - "source": "https://github.com/symfony/cache/tree/v7.0.0" + "source": "https://github.com/symfony/cache/tree/v7.0.4" }, "funding": [ { @@ -1907,7 +1501,7 @@ "type": "tidelift" } ], - "time": "2023-11-25T15:40:35+00:00" + "time": "2024-02-22T20:27:20+00:00" }, { "name": "symfony/cache-contracts", @@ -1987,16 +1581,16 @@ }, { "name": "symfony/config", - "version": "v7.0.0", + "version": "v7.0.4", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "8789646600f4e7e451dde9e1dc81cfa429f3857a" + "reference": "44deeba7233f08f383185ffa37dace3b3bc87364" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/8789646600f4e7e451dde9e1dc81cfa429f3857a", - "reference": "8789646600f4e7e451dde9e1dc81cfa429f3857a", + "url": "https://api.github.com/repos/symfony/config/zipball/44deeba7233f08f383185ffa37dace3b3bc87364", + "reference": "44deeba7233f08f383185ffa37dace3b3bc87364", "shasum": "" }, "require": { @@ -2042,7 +1636,7 @@ "description": "Helps you find, load, combine, autofill and validate configuration values of any kind", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/config/tree/v7.0.0" + "source": "https://github.com/symfony/config/tree/v7.0.4" }, "funding": [ { @@ -2058,20 +1652,20 @@ "type": "tidelift" } ], - "time": "2023-11-09T08:30:23+00:00" + "time": "2024-02-26T07:52:39+00:00" }, { "name": "symfony/console", - "version": "v7.0.1", + "version": "v7.0.4", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "cdce5c684b2f920bb1343deecdfba356ffad83d5" + "reference": "6b099f3306f7c9c2d2786ed736d0026b2903205f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/cdce5c684b2f920bb1343deecdfba356ffad83d5", - "reference": "cdce5c684b2f920bb1343deecdfba356ffad83d5", + "url": "https://api.github.com/repos/symfony/console/zipball/6b099f3306f7c9c2d2786ed736d0026b2903205f", + "reference": "6b099f3306f7c9c2d2786ed736d0026b2903205f", "shasum": "" }, "require": { @@ -2135,7 +1729,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.0.1" + "source": "https://github.com/symfony/console/tree/v7.0.4" }, "funding": [ { @@ -2151,20 +1745,20 @@ "type": "tidelift" } ], - "time": "2023-12-01T15:10:06+00:00" + "time": "2024-02-22T20:27:20+00:00" }, { "name": "symfony/dependency-injection", - "version": "v7.0.1", + "version": "v7.0.4", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "f6667642954bce638733f254c39e5b5700b47ba4" + "reference": "47f37af245df8457ea63409fc242b3cc825ce5eb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/f6667642954bce638733f254c39e5b5700b47ba4", - "reference": "f6667642954bce638733f254c39e5b5700b47ba4", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/47f37af245df8457ea63409fc242b3cc825ce5eb", + "reference": "47f37af245df8457ea63409fc242b3cc825ce5eb", "shasum": "" }, "require": { @@ -2215,7 +1809,7 @@ "description": "Allows you to standardize and centralize the way objects are constructed in your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/dependency-injection/tree/v7.0.1" + "source": "https://github.com/symfony/dependency-injection/tree/v7.0.4" }, "funding": [ { @@ -2231,7 +1825,7 @@ "type": "tidelift" } ], - "time": "2023-12-01T15:10:06+00:00" + "time": "2024-02-22T20:27:20+00:00" }, { "name": "symfony/deprecation-contracts", @@ -2302,16 +1896,16 @@ }, { "name": "symfony/doctrine-bridge", - "version": "v7.0.0", + "version": "v7.0.4", "source": { "type": "git", "url": "https://github.com/symfony/doctrine-bridge.git", - "reference": "5e8e95e8389d03f2f3ae16a6c7c804849ed483b5" + "reference": "aded7ef586f9c75a04627326a5748f29ceba3506" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/doctrine-bridge/zipball/5e8e95e8389d03f2f3ae16a6c7c804849ed483b5", - "reference": "5e8e95e8389d03f2f3ae16a6c7c804849ed483b5", + "url": "https://api.github.com/repos/symfony/doctrine-bridge/zipball/aded7ef586f9c75a04627326a5748f29ceba3506", + "reference": "aded7ef586f9c75a04627326a5748f29ceba3506", "shasum": "" }, "require": { @@ -2388,7 +1982,7 @@ "description": "Provides integration for Doctrine with various Symfony components", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/doctrine-bridge/tree/v7.0.0" + "source": "https://github.com/symfony/doctrine-bridge/tree/v7.0.4" }, "funding": [ { @@ -2404,20 +1998,20 @@ "type": "tidelift" } ], - "time": "2023-11-17T16:04:05+00:00" + "time": "2024-02-04T16:21:40+00:00" }, { "name": "symfony/dotenv", - "version": "v7.0.0", + "version": "v7.0.4", "source": { "type": "git", "url": "https://github.com/symfony/dotenv.git", - "reference": "782d55cb978921499086df75888bda88888ad1c3" + "reference": "8017ea2f0ff4fbda6ae1bf3f5409d5ecff982067" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dotenv/zipball/782d55cb978921499086df75888bda88888ad1c3", - "reference": "782d55cb978921499086df75888bda88888ad1c3", + "url": "https://api.github.com/repos/symfony/dotenv/zipball/8017ea2f0ff4fbda6ae1bf3f5409d5ecff982067", + "reference": "8017ea2f0ff4fbda6ae1bf3f5409d5ecff982067", "shasum": "" }, "require": { @@ -2462,7 +2056,7 @@ "environment" ], "support": { - "source": "https://github.com/symfony/dotenv/tree/v7.0.0" + "source": "https://github.com/symfony/dotenv/tree/v7.0.4" }, "funding": [ { @@ -2478,20 +2072,20 @@ "type": "tidelift" } ], - "time": "2023-10-26T18:22:49+00:00" + "time": "2024-02-09T10:53:15+00:00" }, { "name": "symfony/error-handler", - "version": "v7.0.0", + "version": "v7.0.4", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "80b1258be1b84c12a345d0ec3881bbf2e5270cc2" + "reference": "677b24759decff69e65b1e9d1471d90f95ced880" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/80b1258be1b84c12a345d0ec3881bbf2e5270cc2", - "reference": "80b1258be1b84c12a345d0ec3881bbf2e5270cc2", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/677b24759decff69e65b1e9d1471d90f95ced880", + "reference": "677b24759decff69e65b1e9d1471d90f95ced880", "shasum": "" }, "require": { @@ -2537,7 +2131,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v7.0.0" + "source": "https://github.com/symfony/error-handler/tree/v7.0.4" }, "funding": [ { @@ -2553,20 +2147,20 @@ "type": "tidelift" } ], - "time": "2023-10-20T16:35:23+00:00" + "time": "2024-02-22T20:27:20+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v7.0.0", + "version": "v7.0.3", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "c459b40ffe67c49af6fd392aac374c9edf8a027e" + "reference": "834c28d533dd0636f910909d01b9ff45cc094b5e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/c459b40ffe67c49af6fd392aac374c9edf8a027e", - "reference": "c459b40ffe67c49af6fd392aac374c9edf8a027e", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/834c28d533dd0636f910909d01b9ff45cc094b5e", + "reference": "834c28d533dd0636f910909d01b9ff45cc094b5e", "shasum": "" }, "require": { @@ -2617,7 +2211,7 @@ "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/v7.0.0" + "source": "https://github.com/symfony/event-dispatcher/tree/v7.0.3" }, "funding": [ { @@ -2633,7 +2227,7 @@ "type": "tidelift" } ], - "time": "2023-07-27T16:29:09+00:00" + "time": "2024-01-23T15:02:46+00:00" }, { "name": "symfony/event-dispatcher-contracts", @@ -2712,28 +2306,28 @@ "time": "2023-05-23T14:45:45+00:00" }, { - "name": "symfony/expression-language", - "version": "v7.0.0", + "name": "symfony/filesystem", + "version": "v7.0.3", "source": { "type": "git", - "url": "https://github.com/symfony/expression-language.git", - "reference": "46520d885b340f44a369967835a4bec178d7ab3d" + "url": "https://github.com/symfony/filesystem.git", + "reference": "2890e3a825bc0c0558526c04499c13f83e1b6b12" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/expression-language/zipball/46520d885b340f44a369967835a4bec178d7ab3d", - "reference": "46520d885b340f44a369967835a4bec178d7ab3d", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/2890e3a825bc0c0558526c04499c13f83e1b6b12", + "reference": "2890e3a825bc0c0558526c04499c13f83e1b6b12", "shasum": "" }, "require": { "php": ">=8.2", - "symfony/cache": "^6.4|^7.0", - "symfony/service-contracts": "^2.5|^3" + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.8" }, "type": "library", "autoload": { "psr-4": { - "Symfony\\Component\\ExpressionLanguage\\": "" + "Symfony\\Component\\Filesystem\\": "" }, "exclude-from-classmap": [ "/Tests/" @@ -2753,10 +2347,10 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Provides an engine that can compile and evaluate expressions", + "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/expression-language/tree/v7.0.0" + "source": "https://github.com/symfony/filesystem/tree/v7.0.3" }, "funding": [ { @@ -2772,87 +2366,24 @@ "type": "tidelift" } ], - "time": "2023-07-27T16:29:09+00:00" + "time": "2024-01-23T15:02:46+00:00" }, { - "name": "symfony/filesystem", + "name": "symfony/finder", "version": "v7.0.0", "source": { "type": "git", - "url": "https://github.com/symfony/filesystem.git", - "reference": "7da8ea2362a283771478c5f7729cfcb43a76b8b7" + "url": "https://github.com/symfony/finder.git", + "reference": "6e5688d69f7cfc4ed4a511e96007e06c2d34ce56" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/7da8ea2362a283771478c5f7729cfcb43a76b8b7", - "reference": "7da8ea2362a283771478c5f7729cfcb43a76b8b7", + "url": "https://api.github.com/repos/symfony/finder/zipball/6e5688d69f7cfc4ed4a511e96007e06c2d34ce56", + "reference": "6e5688d69f7cfc4ed4a511e96007e06c2d34ce56", "shasum": "" }, "require": { - "php": ">=8.2", - "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/v7.0.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": "2023-07-27T06:33:22+00:00" - }, - { - "name": "symfony/finder", - "version": "v7.0.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/finder.git", - "reference": "6e5688d69f7cfc4ed4a511e96007e06c2d34ce56" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/6e5688d69f7cfc4ed4a511e96007e06c2d34ce56", - "reference": "6e5688d69f7cfc4ed4a511e96007e06c2d34ce56", - "shasum": "" - }, - "require": { - "php": ">=8.2" + "php": ">=8.2" }, "require-dev": { "symfony/filesystem": "^6.4|^7.0" @@ -2903,16 +2434,16 @@ }, { "name": "symfony/flex", - "version": "v2.4.2", + "version": "v2.4.5", "source": { "type": "git", "url": "https://github.com/symfony/flex.git", - "reference": "67ee785f1aedada76461de7a7ec10cd7f8ff8d36" + "reference": "b0a405f40614c9f584b489d54f91091817b0e26e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/flex/zipball/67ee785f1aedada76461de7a7ec10cd7f8ff8d36", - "reference": "67ee785f1aedada76461de7a7ec10cd7f8ff8d36", + "url": "https://api.github.com/repos/symfony/flex/zipball/b0a405f40614c9f584b489d54f91091817b0e26e", + "reference": "b0a405f40614c9f584b489d54f91091817b0e26e", "shasum": "" }, "require": { @@ -2948,7 +2479,7 @@ "description": "Composer plugin for Symfony", "support": { "issues": "https://github.com/symfony/flex/issues", - "source": "https://github.com/symfony/flex/tree/v2.4.2" + "source": "https://github.com/symfony/flex/tree/v2.4.5" }, "funding": [ { @@ -2964,20 +2495,20 @@ "type": "tidelift" } ], - "time": "2023-12-05T14:09:35+00:00" + "time": "2024-03-02T08:16:47+00:00" }, { "name": "symfony/framework-bundle", - "version": "v7.0.1", + "version": "v7.0.4", "source": { "type": "git", "url": "https://github.com/symfony/framework-bundle.git", - "reference": "71f790cc6a81828b810c830ad72b1bc4c8ceaf74" + "reference": "b58bcb2f9c32405b8fbaa24a1e38c8a10bad7b21" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/71f790cc6a81828b810c830ad72b1bc4c8ceaf74", - "reference": "71f790cc6a81828b810c830ad72b1bc4c8ceaf74", + "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/b58bcb2f9c32405b8fbaa24a1e38c8a10bad7b21", + "reference": "b58bcb2f9c32405b8fbaa24a1e38c8a10bad7b21", "shasum": "" }, "require": { @@ -3015,7 +2546,7 @@ "symfony/mime": "<6.4", "symfony/property-access": "<6.4", "symfony/property-info": "<6.4", - "symfony/scheduler": "<6.4", + "symfony/scheduler": "<6.4.4|>=7.0.0,<7.0.4", "symfony/security-core": "<6.4", "symfony/security-csrf": "<6.4", "symfony/serializer": "<6.4", @@ -3053,7 +2584,7 @@ "symfony/process": "^6.4|^7.0", "symfony/property-info": "^6.4|^7.0", "symfony/rate-limiter": "^6.4|^7.0", - "symfony/scheduler": "^6.4|^7.0", + "symfony/scheduler": "^6.4.4|^7.0.4", "symfony/security-bundle": "^6.4|^7.0", "symfony/semaphore": "^6.4|^7.0", "symfony/serializer": "^6.4|^7.0", @@ -3094,7 +2625,7 @@ "description": "Provides a tight integration between Symfony components and the Symfony full-stack framework", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/framework-bundle/tree/v7.0.1" + "source": "https://github.com/symfony/framework-bundle/tree/v7.0.4" }, "funding": [ { @@ -3110,20 +2641,20 @@ "type": "tidelift" } ], - "time": "2023-12-01T16:37:31+00:00" + "time": "2024-02-26T07:52:39+00:00" }, { "name": "symfony/http-foundation", - "version": "v7.0.0", + "version": "v7.0.4", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "47d72323200934694def5d57083899d774a2b110" + "reference": "439fdfdd344943254b1ef6278613e79040548045" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/47d72323200934694def5d57083899d774a2b110", - "reference": "47d72323200934694def5d57083899d774a2b110", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/439fdfdd344943254b1ef6278613e79040548045", + "reference": "439fdfdd344943254b1ef6278613e79040548045", "shasum": "" }, "require": { @@ -3171,7 +2702,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v7.0.0" + "source": "https://github.com/symfony/http-foundation/tree/v7.0.4" }, "funding": [ { @@ -3187,20 +2718,20 @@ "type": "tidelift" } ], - "time": "2023-11-07T15:10:37+00:00" + "time": "2024-02-08T19:22:56+00:00" }, { "name": "symfony/http-kernel", - "version": "v7.0.1", + "version": "v7.0.4", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "4787639523dcdda32f69063f7fca2ad709f3c6d2" + "reference": "065e2234d907c0fc4fc942bf223f7cfc016d0ac7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/4787639523dcdda32f69063f7fca2ad709f3c6d2", - "reference": "4787639523dcdda32f69063f7fca2ad709f3c6d2", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/065e2234d907c0fc4fc942bf223f7cfc016d0ac7", + "reference": "065e2234d907c0fc4fc942bf223f7cfc016d0ac7", "shasum": "" }, "require": { @@ -3248,7 +2779,7 @@ "symfony/process": "^6.4|^7.0", "symfony/property-access": "^6.4|^7.0", "symfony/routing": "^6.4|^7.0", - "symfony/serializer": "^6.4|^7.0", + "symfony/serializer": "^6.4.4|^7.0.4", "symfony/stopwatch": "^6.4|^7.0", "symfony/translation": "^6.4|^7.0", "symfony/translation-contracts": "^2.5|^3", @@ -3283,7 +2814,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v7.0.1" + "source": "https://github.com/symfony/http-kernel/tree/v7.0.4" }, "funding": [ { @@ -3299,20 +2830,20 @@ "type": "tidelift" } ], - "time": "2023-12-01T17:08:48+00:00" + "time": "2024-02-27T06:35:35+00:00" }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.28.0", + "version": "v1.29.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "875e90aeea2777b6f135677f618529449334a612" + "reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/875e90aeea2777b6f135677f618529449334a612", - "reference": "875e90aeea2777b6f135677f618529449334a612", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/32a9da87d7b3245e09ac426c83d334ae9f06f80f", + "reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f", "shasum": "" }, "require": { @@ -3323,9 +2854,6 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -3364,7 +2892,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.29.0" }, "funding": [ { @@ -3380,20 +2908,20 @@ "type": "tidelift" } ], - "time": "2023-01-26T09:26:14+00:00" + "time": "2024-01-29T20:11:03+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.28.0", + "version": "v1.29.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92" + "reference": "bc45c394692b948b4d383a08d7753968bed9a83d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", - "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/bc45c394692b948b4d383a08d7753968bed9a83d", + "reference": "bc45c394692b948b4d383a08d7753968bed9a83d", "shasum": "" }, "require": { @@ -3404,9 +2932,6 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -3448,7 +2973,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.29.0" }, "funding": [ { @@ -3464,20 +2989,20 @@ "type": "tidelift" } ], - "time": "2023-01-26T09:26:14+00:00" + "time": "2024-01-29T20:11:03+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.28.0", + "version": "v1.29.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "42292d99c55abe617799667f454222c54c60e229" + "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/42292d99c55abe617799667f454222c54c60e229", - "reference": "42292d99c55abe617799667f454222c54c60e229", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9773676c8a1bb1f8d4340a62efe641cf76eda7ec", + "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec", "shasum": "" }, "require": { @@ -3491,9 +3016,6 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -3531,7 +3053,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.29.0" }, "funding": [ { @@ -3547,20 +3069,20 @@ "type": "tidelift" } ], - "time": "2023-07-28T09:04:16+00:00" + "time": "2024-01-29T20:11:03+00:00" }, { "name": "symfony/polyfill-php83", - "version": "v1.28.0", + "version": "v1.29.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php83.git", - "reference": "b0f46ebbeeeda3e9d2faebdfbf4b4eae9b59fa11" + "reference": "86fcae159633351e5fd145d1c47de6c528f8caff" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/b0f46ebbeeeda3e9d2faebdfbf4b4eae9b59fa11", - "reference": "b0f46ebbeeeda3e9d2faebdfbf4b4eae9b59fa11", + "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/86fcae159633351e5fd145d1c47de6c528f8caff", + "reference": "86fcae159633351e5fd145d1c47de6c528f8caff", "shasum": "" }, "require": { @@ -3569,9 +3091,6 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -3611,7 +3130,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php83/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-php83/tree/v1.29.0" }, "funding": [ { @@ -3627,20 +3146,20 @@ "type": "tidelift" } ], - "time": "2023-08-16T06:22:46+00:00" + "time": "2024-01-29T20:11:03+00:00" }, { "name": "symfony/property-access", - "version": "v7.0.0", + "version": "v7.0.4", "source": { "type": "git", "url": "https://github.com/symfony/property-access.git", - "reference": "740e8cb8c54a4f16c82179e8558c29d9fc49901d" + "reference": "44e3746d4de8d0961a44ee332c74dd0918266127" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/property-access/zipball/740e8cb8c54a4f16c82179e8558c29d9fc49901d", - "reference": "740e8cb8c54a4f16c82179e8558c29d9fc49901d", + "url": "https://api.github.com/repos/symfony/property-access/zipball/44e3746d4de8d0961a44ee332c74dd0918266127", + "reference": "44e3746d4de8d0961a44ee332c74dd0918266127", "shasum": "" }, "require": { @@ -3687,7 +3206,7 @@ "reflection" ], "support": { - "source": "https://github.com/symfony/property-access/tree/v7.0.0" + "source": "https://github.com/symfony/property-access/tree/v7.0.4" }, "funding": [ { @@ -3703,20 +3222,20 @@ "type": "tidelift" } ], - "time": "2023-09-27T14:05:33+00:00" + "time": "2024-02-16T13:44:10+00:00" }, { "name": "symfony/property-info", - "version": "v7.0.0", + "version": "v7.0.3", "source": { "type": "git", "url": "https://github.com/symfony/property-info.git", - "reference": "ce627df05f5629ce4feec536ee827ad0a12689b6" + "reference": "e160f92ea827243abf2dbf36b8460b1377194406" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/property-info/zipball/ce627df05f5629ce4feec536ee827ad0a12689b6", - "reference": "ce627df05f5629ce4feec536ee827ad0a12689b6", + "url": "https://api.github.com/repos/symfony/property-info/zipball/e160f92ea827243abf2dbf36b8460b1377194406", + "reference": "e160f92ea827243abf2dbf36b8460b1377194406", "shasum": "" }, "require": { @@ -3770,7 +3289,7 @@ "validator" ], "support": { - "source": "https://github.com/symfony/property-info/tree/v7.0.0" + "source": "https://github.com/symfony/property-info/tree/v7.0.3" }, "funding": [ { @@ -3786,20 +3305,20 @@ "type": "tidelift" } ], - "time": "2023-11-25T08:38:27+00:00" + "time": "2024-01-23T15:02:46+00:00" }, { "name": "symfony/routing", - "version": "v7.0.1", + "version": "v7.0.3", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "fc55062907669835af6408558ae4d1dafef74b1e" + "reference": "858b26756ffc35a11238b269b484ee3a393a74d3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/fc55062907669835af6408558ae4d1dafef74b1e", - "reference": "fc55062907669835af6408558ae4d1dafef74b1e", + "url": "https://api.github.com/repos/symfony/routing/zipball/858b26756ffc35a11238b269b484ee3a393a74d3", + "reference": "858b26756ffc35a11238b269b484ee3a393a74d3", "shasum": "" }, "require": { @@ -3851,7 +3370,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v7.0.1" + "source": "https://github.com/symfony/routing/tree/v7.0.3" }, "funding": [ { @@ -3867,20 +3386,20 @@ "type": "tidelift" } ], - "time": "2023-12-01T15:10:06+00:00" + "time": "2024-01-30T13:55:15+00:00" }, { "name": "symfony/runtime", - "version": "v7.0.0", + "version": "v7.0.3", "source": { "type": "git", "url": "https://github.com/symfony/runtime.git", - "reference": "65a4e69b1cdcee4f4f7a619a41d4b7ec79e85406" + "reference": "ef2c2fd4b40fb8cd22221154399ad8888e81cdb5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/runtime/zipball/65a4e69b1cdcee4f4f7a619a41d4b7ec79e85406", - "reference": "65a4e69b1cdcee4f4f7a619a41d4b7ec79e85406", + "url": "https://api.github.com/repos/symfony/runtime/zipball/ef2c2fd4b40fb8cd22221154399ad8888e81cdb5", + "reference": "ef2c2fd4b40fb8cd22221154399ad8888e81cdb5", "shasum": "" }, "require": { @@ -3930,7 +3449,7 @@ "runtime" ], "support": { - "source": "https://github.com/symfony/runtime/tree/v7.0.0" + "source": "https://github.com/symfony/runtime/tree/v7.0.3" }, "funding": [ { @@ -3946,25 +3465,25 @@ "type": "tidelift" } ], - "time": "2023-10-20T16:35:23+00:00" + "time": "2024-01-23T15:02:46+00:00" }, { "name": "symfony/service-contracts", - "version": "v3.4.0", + "version": "v3.4.1", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "b3313c2dbffaf71c8de2934e2ea56ed2291a3838" + "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/b3313c2dbffaf71c8de2934e2ea56ed2291a3838", - "reference": "b3313c2dbffaf71c8de2934e2ea56ed2291a3838", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/fe07cbc8d837f60caf7018068e350cc5163681a0", + "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0", "shasum": "" }, "require": { "php": ">=8.1", - "psr/container": "^2.0" + "psr/container": "^1.1|^2.0" }, "conflict": { "ext-psr": "<1.1|>=2" @@ -4012,7 +3531,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.4.0" + "source": "https://github.com/symfony/service-contracts/tree/v3.4.1" }, "funding": [ { @@ -4028,20 +3547,20 @@ "type": "tidelift" } ], - "time": "2023-07-30T20:28:31+00:00" + "time": "2023-12-26T14:02:43+00:00" }, { "name": "symfony/string", - "version": "v7.0.0", + "version": "v7.0.4", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "92bd2bfbba476d4a1838e5e12168bef2fd1e6620" + "reference": "f5832521b998b0bec40bee688ad5de98d4cf111b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/92bd2bfbba476d4a1838e5e12168bef2fd1e6620", - "reference": "92bd2bfbba476d4a1838e5e12168bef2fd1e6620", + "url": "https://api.github.com/repos/symfony/string/zipball/f5832521b998b0bec40bee688ad5de98d4cf111b", + "reference": "f5832521b998b0bec40bee688ad5de98d4cf111b", "shasum": "" }, "require": { @@ -4098,7 +3617,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v7.0.0" + "source": "https://github.com/symfony/string/tree/v7.0.4" }, "funding": [ { @@ -4114,20 +3633,20 @@ "type": "tidelift" } ], - "time": "2023-11-29T08:40:23+00:00" + "time": "2024-02-01T13:17:36+00:00" }, { "name": "symfony/translation-contracts", - "version": "v3.4.0", + "version": "v3.4.1", "source": { "type": "git", "url": "https://github.com/symfony/translation-contracts.git", - "reference": "dee0c6e5b4c07ce851b462530088e64b255ac9c5" + "reference": "06450585bf65e978026bda220cdebca3f867fde7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/dee0c6e5b4c07ce851b462530088e64b255ac9c5", - "reference": "dee0c6e5b4c07ce851b462530088e64b255ac9c5", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/06450585bf65e978026bda220cdebca3f867fde7", + "reference": "06450585bf65e978026bda220cdebca3f867fde7", "shasum": "" }, "require": { @@ -4176,7 +3695,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/translation-contracts/tree/v3.4.0" + "source": "https://github.com/symfony/translation-contracts/tree/v3.4.1" }, "funding": [ { @@ -4192,20 +3711,20 @@ "type": "tidelift" } ], - "time": "2023-07-25T15:08:44+00:00" + "time": "2023-12-26T14:02:43+00:00" }, { "name": "symfony/twig-bridge", - "version": "v7.0.0", + "version": "v7.0.4", "source": { "type": "git", "url": "https://github.com/symfony/twig-bridge.git", - "reference": "883b7b035670b02e06f1dd6cbe71fa1dabcdec7d" + "reference": "d16aa4eb5bdaeb6e7407782431dc70530f3b1df5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/883b7b035670b02e06f1dd6cbe71fa1dabcdec7d", - "reference": "883b7b035670b02e06f1dd6cbe71fa1dabcdec7d", + "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/d16aa4eb5bdaeb6e7407782431dc70530f3b1df5", + "reference": "d16aa4eb5bdaeb6e7407782431dc70530f3b1df5", "shasum": "" }, "require": { @@ -4248,7 +3767,7 @@ "symfony/security-core": "^6.4|^7.0", "symfony/security-csrf": "^6.4|^7.0", "symfony/security-http": "^6.4|^7.0", - "symfony/serializer": "^6.4|^7.0", + "symfony/serializer": "^6.4.3|^7.0.3", "symfony/stopwatch": "^6.4|^7.0", "symfony/translation": "^6.4|^7.0", "symfony/web-link": "^6.4|^7.0", @@ -4284,7 +3803,7 @@ "description": "Provides integration for Twig with various Symfony components", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/twig-bridge/tree/v7.0.0" + "source": "https://github.com/symfony/twig-bridge/tree/v7.0.4" }, "funding": [ { @@ -4300,20 +3819,20 @@ "type": "tidelift" } ], - "time": "2023-11-26T15:16:53+00:00" + "time": "2024-02-15T11:33:06+00:00" }, { "name": "symfony/twig-bundle", - "version": "v7.0.0", + "version": "v7.0.4", "source": { "type": "git", "url": "https://github.com/symfony/twig-bundle.git", - "reference": "42c4a60f1b83894cd85a6b00533f8216c413ac11" + "reference": "acab2368f53491e018bf31ef48b39df55a6812ef" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/twig-bundle/zipball/42c4a60f1b83894cd85a6b00533f8216c413ac11", - "reference": "42c4a60f1b83894cd85a6b00533f8216c413ac11", + "url": "https://api.github.com/repos/symfony/twig-bundle/zipball/acab2368f53491e018bf31ef48b39df55a6812ef", + "reference": "acab2368f53491e018bf31ef48b39df55a6812ef", "shasum": "" }, "require": { @@ -4368,7 +3887,7 @@ "description": "Provides a tight integration of Twig into the Symfony full-stack framework", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/twig-bundle/tree/v7.0.0" + "source": "https://github.com/symfony/twig-bundle/tree/v7.0.4" }, "funding": [ { @@ -4384,20 +3903,20 @@ "type": "tidelift" } ], - "time": "2023-11-26T15:16:53+00:00" + "time": "2024-02-15T11:33:06+00:00" }, { "name": "symfony/var-dumper", - "version": "v7.0.0", + "version": "v7.0.4", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "cf0220fc7607476fd0d001ab3ed9e830d1fdda56" + "reference": "e03ad7c1535e623edbb94c22cc42353e488c6670" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/cf0220fc7607476fd0d001ab3ed9e830d1fdda56", - "reference": "cf0220fc7607476fd0d001ab3ed9e830d1fdda56", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/e03ad7c1535e623edbb94c22cc42353e488c6670", + "reference": "e03ad7c1535e623edbb94c22cc42353e488c6670", "shasum": "" }, "require": { @@ -4451,7 +3970,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v7.0.0" + "source": "https://github.com/symfony/var-dumper/tree/v7.0.4" }, "funding": [ { @@ -4467,20 +3986,20 @@ "type": "tidelift" } ], - "time": "2023-11-27T12:39:18+00:00" + "time": "2024-02-15T11:33:06+00:00" }, { "name": "symfony/var-exporter", - "version": "v7.0.1", + "version": "v7.0.4", "source": { "type": "git", "url": "https://github.com/symfony/var-exporter.git", - "reference": "a3d7c877414fcd59ab7075ecdc3b8f9c00f7bcc3" + "reference": "dfb0acb6803eb714f05d97dd4c5abe6d5fa9fe41" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-exporter/zipball/a3d7c877414fcd59ab7075ecdc3b8f9c00f7bcc3", - "reference": "a3d7c877414fcd59ab7075ecdc3b8f9c00f7bcc3", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/dfb0acb6803eb714f05d97dd4c5abe6d5fa9fe41", + "reference": "dfb0acb6803eb714f05d97dd4c5abe6d5fa9fe41", "shasum": "" }, "require": { @@ -4525,7 +4044,7 @@ "serialize" ], "support": { - "source": "https://github.com/symfony/var-exporter/tree/v7.0.1" + "source": "https://github.com/symfony/var-exporter/tree/v7.0.4" }, "funding": [ { @@ -4541,20 +4060,20 @@ "type": "tidelift" } ], - "time": "2023-11-30T11:38:21+00:00" + "time": "2024-02-26T10:35:24+00:00" }, { "name": "symfony/yaml", - "version": "v7.0.0", + "version": "v7.0.3", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "0055b230c408428b9b5cde7c55659555be5c0278" + "reference": "2d4fca631c00700597e9442a0b2451ce234513d3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/0055b230c408428b9b5cde7c55659555be5c0278", - "reference": "0055b230c408428b9b5cde7c55659555be5c0278", + "url": "https://api.github.com/repos/symfony/yaml/zipball/2d4fca631c00700597e9442a0b2451ce234513d3", + "reference": "2d4fca631c00700597e9442a0b2451ce234513d3", "shasum": "" }, "require": { @@ -4596,7 +4115,7 @@ "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v7.0.0" + "source": "https://github.com/symfony/yaml/tree/v7.0.3" }, "funding": [ { @@ -4612,7 +4131,7 @@ "type": "tidelift" } ], - "time": "2023-11-07T10:26:03+00:00" + "time": "2024-01-23T15:02:46+00:00" }, { "name": "twig/twig", @@ -4689,1698 +4208,85 @@ ], "packages-dev": [ { - "name": "myclabs/deep-copy", - "version": "1.11.1", + "name": "symfony/phpunit-bridge", + "version": "v7.0.4", "source": { "type": "git", - "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c" + "url": "https://github.com/symfony/phpunit-bridge.git", + "reference": "54ca13ec990a40411ad978e08d994fca6cdd865f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", - "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", + "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/54ca13ec990a40411ad978e08d994fca6cdd865f", + "reference": "54ca13ec990a40411ad978e08d994fca6cdd865f", "shasum": "" }, "require": { - "php": "^7.1 || ^8.0" + "php": ">=7.2.5" }, "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.1" - }, - "funding": [ - { - "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", - "type": "tidelift" - } - ], - "time": "2023-03-08T13:26:56+00:00" - }, - { - "name": "nikic/php-parser", - "version": "v4.17.1", - "source": { - "type": "git", - "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d", - "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d", - "shasum": "" - }, - "require": { - "ext-tokenizer": "*", - "php": ">=7.0" + "phpunit/phpunit": "<7.5|9.1.2" }, "require-dev": { - "ircmaxell/php-yacc": "^0.0.7", - "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" + "symfony/deprecation-contracts": "^2.5|^3.0", + "symfony/error-handler": "^5.4|^6.4|^7.0", + "symfony/polyfill-php81": "^1.27" }, "bin": [ - "bin/php-parse" + "bin/simple-phpunit" ], - "type": "library", + "type": "symfony-bridge", "extra": { - "branch-alias": { - "dev-master": "4.9-dev" + "thanks": { + "name": "phpunit/phpunit", + "url": "https://github.com/sebastianbergmann/phpunit" } }, "autoload": { + "files": [ + "bootstrap.php" + ], "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.17.1" - }, - "time": "2023-08-13T19:53:39+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/" + "Symfony\\Bridge\\PhpUnit\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" }, { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "description": "Provides utilities for PHPUnit, especially user deprecation notices management", + "homepage": "https://symfony.com", "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/" - ] + "source": "https://github.com/symfony/phpunit-bridge/tree/v7.0.4" }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ + "funding": [ { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" + "url": "https://symfony.com/sponsor", + "type": "custom" }, { - "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": "phpunit/php-code-coverage", - "version": "10.1.9", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "a56a9ab2f680246adcf3db43f38ddf1765774735" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/a56a9ab2f680246adcf3db43f38ddf1765774735", - "reference": "a56a9ab2f680246adcf3db43f38ddf1765774735", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-libxml": "*", - "ext-xmlwriter": "*", - "nikic/php-parser": "^4.15", - "php": ">=8.1", - "phpunit/php-file-iterator": "^4.0", - "phpunit/php-text-template": "^3.0", - "sebastian/code-unit-reverse-lookup": "^3.0", - "sebastian/complexity": "^3.0", - "sebastian/environment": "^6.0", - "sebastian/lines-of-code": "^2.0", - "sebastian/version": "^4.0", - "theseer/tokenizer": "^1.2.0" - }, - "require-dev": { - "phpunit/phpunit": "^10.1" - }, - "suggest": { - "ext-pcov": "PHP extension that provides line coverage", - "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "10.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": "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", - "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.9" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-11-23T12:23:20+00:00" - }, - { - "name": "phpunit/php-file-iterator", - "version": "4.1.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/a95037b6d9e608ba092da1b23931e537cadc3c3c", - "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "4.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", - "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/4.1.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-08-31T06:24:48+00:00" - }, - { - "name": "phpunit/php-invoker", - "version": "4.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-invoker.git", - "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", - "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "ext-pcntl": "*", - "phpunit/phpunit": "^10.0" - }, - "suggest": { - "ext-pcntl": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "4.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": "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/4.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-02-03T06:56:09+00:00" - }, - { - "name": "phpunit/php-text-template", - "version": "3.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/0c7b06ff49e3d5072f057eb1fa59258bf287a748", - "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "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": "Simple template engine.", - "homepage": "https://github.com/sebastianbergmann/php-text-template/", - "keywords": [ - "template" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-text-template/issues", - "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", - "source": "https://github.com/sebastianbergmann/php-text-template/tree/3.0.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-08-31T14:07:24+00:00" - }, - { - "name": "phpunit/php-timer", - "version": "6.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/e2a2d67966e740530f4a3343fe2e030ffdc1161d", - "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "6.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/6.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-02-03T06:57:52+00:00" - }, - { - "name": "phpunit/phpunit", - "version": "10.5.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "5aedff46afba98dddecaa12349ec044d9103d4fe" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/5aedff46afba98dddecaa12349ec044d9103d4fe", - "reference": "5aedff46afba98dddecaa12349ec044d9103d4fe", - "shasum": "" - }, - "require": { - "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": ">=8.1", - "phpunit/php-code-coverage": "^10.1.5", - "phpunit/php-file-iterator": "^4.0", - "phpunit/php-invoker": "^4.0", - "phpunit/php-text-template": "^3.0", - "phpunit/php-timer": "^6.0", - "sebastian/cli-parser": "^2.0", - "sebastian/code-unit": "^2.0", - "sebastian/comparator": "^5.0", - "sebastian/diff": "^5.0", - "sebastian/environment": "^6.0", - "sebastian/exporter": "^5.1", - "sebastian/global-state": "^6.0.1", - "sebastian/object-enumerator": "^5.0", - "sebastian/recursion-context": "^5.0", - "sebastian/type": "^4.0", - "sebastian/version": "^4.0" - }, - "suggest": { - "ext-soap": "To be able to generate mocks based on WSDL files" - }, - "bin": [ - "phpunit" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "10.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", - "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.2" - }, - "funding": [ - { - "url": "https://phpunit.de/sponsors.html", - "type": "custom" - }, - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", - "type": "tidelift" - } - ], - "time": "2023-12-05T14:54:33+00:00" - }, - { - "name": "sebastian/cli-parser", - "version": "2.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/cli-parser.git", - "reference": "efdc130dbbbb8ef0b545a994fd811725c5282cae" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/efdc130dbbbb8ef0b545a994fd811725c5282cae", - "reference": "efdc130dbbbb8ef0b545a994fd811725c5282cae", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "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 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/2.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-02-03T06:58:15+00:00" - }, - { - "name": "sebastian/code-unit", - "version": "2.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit.git", - "reference": "a81fee9eef0b7a76af11d121767abc44c104e503" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/a81fee9eef0b7a76af11d121767abc44c104e503", - "reference": "a81fee9eef0b7a76af11d121767abc44c104e503", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "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": "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/2.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-02-03T06:58:43+00:00" - }, - { - "name": "sebastian/code-unit-reverse-lookup", - "version": "3.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", - "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "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": "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/3.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-02-03T06:59:15+00:00" - }, - { - "name": "sebastian/comparator", - "version": "5.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "2db5010a484d53ebf536087a70b4a5423c102372" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2db5010a484d53ebf536087a70b4a5423c102372", - "reference": "2db5010a484d53ebf536087a70b4a5423c102372", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-mbstring": "*", - "php": ">=8.1", - "sebastian/diff": "^5.0", - "sebastian/exporter": "^5.0" - }, - "require-dev": { - "phpunit/phpunit": "^10.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "5.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", - "security": "https://github.com/sebastianbergmann/comparator/security/policy", - "source": "https://github.com/sebastianbergmann/comparator/tree/5.0.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-08-14T13:18:12+00:00" - }, - { - "name": "sebastian/complexity", - "version": "3.1.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/complexity.git", - "reference": "68cfb347a44871f01e33ab0ef8215966432f6957" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/68cfb347a44871f01e33ab0ef8215966432f6957", - "reference": "68cfb347a44871f01e33ab0ef8215966432f6957", - "shasum": "" - }, - "require": { - "nikic/php-parser": "^4.10", - "php": ">=8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "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": "Library for calculating the complexity of PHP code units", - "homepage": "https://github.com/sebastianbergmann/complexity", - "support": { - "issues": "https://github.com/sebastianbergmann/complexity/issues", - "security": "https://github.com/sebastianbergmann/complexity/security/policy", - "source": "https://github.com/sebastianbergmann/complexity/tree/3.1.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-09-28T11:50:59+00:00" - }, - { - "name": "sebastian/diff", - "version": "5.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "912dc2fbe3e3c1e7873313cc801b100b6c68c87b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/912dc2fbe3e3c1e7873313cc801b100b6c68c87b", - "reference": "912dc2fbe3e3c1e7873313cc801b100b6c68c87b", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.0", - "symfony/process": "^4.2 || ^5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "5.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", - "security": "https://github.com/sebastianbergmann/diff/security/policy", - "source": "https://github.com/sebastianbergmann/diff/tree/5.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-05-01T07:48:21+00:00" - }, - { - "name": "sebastian/environment", - "version": "6.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "43c751b41d74f96cbbd4e07b7aec9675651e2951" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/43c751b41d74f96cbbd4e07b7aec9675651e2951", - "reference": "43c751b41d74f96cbbd4e07b7aec9675651e2951", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.0" - }, - "suggest": { - "ext-posix": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "6.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 functionality to handle HHVM/PHP environments", - "homepage": "https://github.com/sebastianbergmann/environment", - "keywords": [ - "Xdebug", - "environment", - "hhvm" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/environment/issues", - "security": "https://github.com/sebastianbergmann/environment/security/policy", - "source": "https://github.com/sebastianbergmann/environment/tree/6.0.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-04-11T05:39:26+00:00" - }, - { - "name": "sebastian/exporter", - "version": "5.1.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "64f51654862e0f5e318db7e9dcc2292c63cdbddc" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/64f51654862e0f5e318db7e9dcc2292c63cdbddc", - "reference": "64f51654862e0f5e318db7e9dcc2292c63cdbddc", - "shasum": "" - }, - "require": { - "ext-mbstring": "*", - "php": ">=8.1", - "sebastian/recursion-context": "^5.0" - }, - "require-dev": { - "phpunit/phpunit": "^10.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "5.1-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", - "security": "https://github.com/sebastianbergmann/exporter/security/policy", - "source": "https://github.com/sebastianbergmann/exporter/tree/5.1.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-09-24T13:22:09+00:00" - }, - { - "name": "sebastian/global-state", - "version": "6.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "7ea9ead78f6d380d2a667864c132c2f7b83055e4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/7ea9ead78f6d380d2a667864c132c2f7b83055e4", - "reference": "7ea9ead78f6d380d2a667864c132c2f7b83055e4", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "sebastian/object-reflector": "^3.0", - "sebastian/recursion-context": "^5.0" - }, - "require-dev": { - "ext-dom": "*", - "phpunit/phpunit": "^10.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "6.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", - "security": "https://github.com/sebastianbergmann/global-state/security/policy", - "source": "https://github.com/sebastianbergmann/global-state/tree/6.0.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-07-19T07:19:23+00:00" - }, - { - "name": "sebastian/lines-of-code", - "version": "2.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/lines-of-code.git", - "reference": "649e40d279e243d985aa8fb6e74dd5bb28dc185d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/649e40d279e243d985aa8fb6e74dd5bb28dc185d", - "reference": "649e40d279e243d985aa8fb6e74dd5bb28dc185d", - "shasum": "" - }, - "require": { - "nikic/php-parser": "^4.10", - "php": ">=8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "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 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", - "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", - "source": "https://github.com/sebastianbergmann/lines-of-code/tree/2.0.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-08-31T09:25:50+00:00" - }, - { - "name": "sebastian/object-enumerator", - "version": "5.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/202d0e344a580d7f7d04b3fafce6933e59dae906", - "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "sebastian/object-reflector": "^3.0", - "sebastian/recursion-context": "^5.0" - }, - "require-dev": { - "phpunit/phpunit": "^10.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "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": "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/5.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-02-03T07:08:32+00:00" - }, - { - "name": "sebastian/object-reflector", - "version": "3.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "24ed13d98130f0e7122df55d06c5c4942a577957" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/24ed13d98130f0e7122df55d06c5c4942a577957", - "reference": "24ed13d98130f0e7122df55d06c5c4942a577957", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "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": "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/3.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-02-03T07:06:18+00:00" - }, - { - "name": "sebastian/recursion-context", - "version": "5.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "05909fb5bc7df4c52992396d0116aed689f93712" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/05909fb5bc7df4c52992396d0116aed689f93712", - "reference": "05909fb5bc7df4c52992396d0116aed689f93712", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "5.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": "https://github.com/sebastianbergmann/recursion-context", - "support": { - "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/5.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-02-03T07:05:40+00:00" - }, - { - "name": "sebastian/type", - "version": "4.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/type.git", - "reference": "462699a16464c3944eefc02ebdd77882bd3925bf" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/462699a16464c3944eefc02ebdd77882bd3925bf", - "reference": "462699a16464c3944eefc02ebdd77882bd3925bf", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "4.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/4.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-02-03T07:10:45+00:00" - }, - { - "name": "sebastian/version", - "version": "4.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/version.git", - "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c51fa83a5d8f43f1402e3f32a005e6262244ef17", - "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "4.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/4.0.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-02-07T11:34:05+00:00" - }, - { - "name": "symfony/phpunit-bridge", - "version": "v7.0.1", - "source": { - "type": "git", - "url": "https://github.com/symfony/phpunit-bridge.git", - "reference": "c2d059b25e31274157dd7727131cd1cf33650207" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/c2d059b25e31274157dd7727131cd1cf33650207", - "reference": "c2d059b25e31274157dd7727131cd1cf33650207", - "shasum": "" - }, - "require": { - "php": ">=7.2.5" - }, - "conflict": { - "phpunit/phpunit": "<7.5|9.1.2" - }, - "require-dev": { - "symfony/deprecation-contracts": "^2.5|^3.0", - "symfony/error-handler": "^5.4|^6.4|^7.0", - "symfony/polyfill-php81": "^1.27" - }, - "bin": [ - "bin/simple-phpunit" - ], - "type": "symfony-bridge", - "extra": { - "thanks": { - "name": "phpunit/phpunit", - "url": "https://github.com/sebastianbergmann/phpunit" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Bridge\\PhpUnit\\": "" - }, - "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 utilities for PHPUnit, especially user deprecation notices management", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/phpunit-bridge/tree/v7.0.1" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" + "url": "https://github.com/fabpot", + "type": "github" }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2023-12-01T09:26:31+00:00" - }, - { - "name": "theseer/tokenizer", - "version": "1.2.2", - "source": { - "type": "git", - "url": "https://github.com/theseer/tokenizer.git", - "reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/b2ad5003ca10d4ee50a12da31de12a5774ba6b96", - "reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96", - "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.2" - }, - "funding": [ - { - "url": "https://github.com/theseer", - "type": "github" - } - ], - "time": "2023-11-20T00:12:19+00:00" + "time": "2024-02-08T19:22:56+00:00" } ], "aliases": [], diff --git a/demo/symfony7.x/config/packages/doctrine.yaml b/demo/symfony7.x/config/packages/doctrine.yaml index 87d77a85..6ea6f4be 100644 --- a/demo/symfony7.x/config/packages/doctrine.yaml +++ b/demo/symfony7.x/config/packages/doctrine.yaml @@ -6,6 +6,8 @@ doctrine: # either here or in the DATABASE_URL env var (see .env file) #server_version: '13' orm: + report_fields_where_declared: true + enable_lazy_ghost_objects: true auto_generate_proxy_classes: true naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware auto_mapping: true diff --git a/demo/symfony7.x/src/Repository/AbstractSecretRepository.php b/demo/symfony7.x/src/Repository/AbstractSecretRepository.php index 5caa75d1..840bc639 100644 --- a/demo/symfony7.x/src/Repository/AbstractSecretRepository.php +++ b/demo/symfony7.x/src/Repository/AbstractSecretRepository.php @@ -9,7 +9,7 @@ abstract class AbstractSecretRepository extends ServiceEntityRepository /** * @return array The objects. */ - public function findAll() + public function findAll(): array { $qb = $this->createQueryBuilder('s'); $qb->select('s') diff --git a/demo/symfony7.x/symfony.lock b/demo/symfony7.x/symfony.lock index bc57875d..52c86ecd 100644 --- a/demo/symfony7.x/symfony.lock +++ b/demo/symfony7.x/symfony.lock @@ -1,13 +1,4 @@ { - "doctrine/annotations": { - "version": "2.0", - "recipe": { - "repo": "github.com/symfony/recipes", - "branch": "main", - "version": "1.10", - "ref": "64d8583af5ea57b7afa4aba4b159907f3a148b05" - } - }, "doctrine/doctrine-bundle": { "version": "2.11", "recipe": { diff --git a/demo/symfony7.x_doctrine3.x/composer.json b/demo/symfony7.x_doctrine3.x/composer.json index 815c669e..6d55eff2 100644 --- a/demo/symfony7.x_doctrine3.x/composer.json +++ b/demo/symfony7.x_doctrine3.x/composer.json @@ -7,8 +7,9 @@ "php": ">=8.3", "ext-ctype": "*", "ext-iconv": "*", - "doctrine/orm": "3.0", + "doctrine/orm": "^3.0", "doctrineencryptbundle/doctrine-encrypt-bundle": "@dev", + "doctrine/persistence": "^3.2", "symfony/console": "7.0.*", "symfony/dotenv": "7.0.*", "symfony/flex": "^2", diff --git a/demo/symfony7.x_doctrine3.x/config/packages/doctrine.yaml b/demo/symfony7.x_doctrine3.x/config/packages/doctrine.yaml index 87d77a85..6ea6f4be 100644 --- a/demo/symfony7.x_doctrine3.x/config/packages/doctrine.yaml +++ b/demo/symfony7.x_doctrine3.x/config/packages/doctrine.yaml @@ -6,6 +6,8 @@ doctrine: # either here or in the DATABASE_URL env var (see .env file) #server_version: '13' orm: + report_fields_where_declared: true + enable_lazy_ghost_objects: true auto_generate_proxy_classes: true naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware auto_mapping: true diff --git a/demo/symfony7.x_doctrine3.x/phpunit.xml.dist b/demo/symfony7.x_doctrine3.x/phpunit.xml.dist new file mode 100755 index 00000000..ba1bd023 --- /dev/null +++ b/demo/symfony7.x_doctrine3.x/phpunit.xml.dist @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + tests + + + + + + diff --git a/demo/symfony7.x_doctrine3.x/src/Repository/AbstractSecretRepository.php b/demo/symfony7.x_doctrine3.x/src/Repository/AbstractSecretRepository.php index 5caa75d1..840bc639 100644 --- a/demo/symfony7.x_doctrine3.x/src/Repository/AbstractSecretRepository.php +++ b/demo/symfony7.x_doctrine3.x/src/Repository/AbstractSecretRepository.php @@ -9,7 +9,7 @@ abstract class AbstractSecretRepository extends ServiceEntityRepository /** * @return array The objects. */ - public function findAll() + public function findAll(): array { $qb = $this->createQueryBuilder('s'); $qb->select('s') diff --git a/demo/symfony7.x_doctrine3.x/src/Repository/Attribute/SecretRepository.php b/demo/symfony7.x_doctrine3.x/src/Repository/Attribute/SecretRepository.php index fddf972c..fe0fd580 100644 --- a/demo/symfony7.x_doctrine3.x/src/Repository/Attribute/SecretRepository.php +++ b/demo/symfony7.x_doctrine3.x/src/Repository/Attribute/SecretRepository.php @@ -5,52 +5,15 @@ use App\Entity\Attribute\Secret; use App\Repository\AbstractSecretRepository; -// Alias is needed because of test with both php 7.2, 7.4 and 8.0 -if (!interface_exists('\Doctrine\Common\Persistence\ManagerRegistry')) { - class_alias( - '\Doctrine\Persistence\ManagerRegistry', - '\Doctrine\Common\Persistence\ManagerRegistry' - ); -} - - -if (PHP_VERSION_ID >= 80000) { - /** - * @method Secret|null find($id, $lockMode = null, $lockVersion = null) - * @method Secret|null findOneBy(array $criteria, array $orderBy = null) - * @method Secret[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) - */ - class SecretRepository extends AbstractSecretRepository - { - public function __construct(\Doctrine\Common\Persistence\ManagerRegistry $registry) - { - parent::__construct($registry, Secret::class); - } - } -} else { - /** - * Dummy-repository for php < 8.0 - */ - class SecretRepository +/** + * @method Secret|null find($id, $lockMode = null, $lockVersion = null) + * @method Secret|null findOneBy(array $criteria, array $orderBy = null) + * @method Secret[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) + */ +class SecretRepository extends AbstractSecretRepository +{ + public function __construct(\Doctrine\Common\Persistence\ManagerRegistry $registry) { - public function findAll() - { - return []; - } - - public function find($id, $lockMode = null, $lockVersion = null) - { - return null; - } - - public function findOneBy(array $criteria, array $orderBy = null) - { - return null; - } - - public function findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) - { - return []; - } + parent::__construct($registry, Secret::class); } } \ No newline at end of file diff --git a/demo/symfony7.x_doctrine3.x/symfony.lock b/demo/symfony7.x_doctrine3.x/symfony.lock index 6c943110..38e55c4c 100644 --- a/demo/symfony7.x_doctrine3.x/symfony.lock +++ b/demo/symfony7.x_doctrine3.x/symfony.lock @@ -1,13 +1,4 @@ { - "doctrine/annotations": { - "version": "2.0", - "recipe": { - "repo": "github.com/symfony/recipes", - "branch": "main", - "version": "1.10", - "ref": "64d8583af5ea57b7afa4aba4b159907f3a148b05" - } - }, "doctrine/doctrine-bundle": { "version": "2.11", "recipe": { diff --git a/demo/symfony7.x_doctrine3.x/tests/SecretTest.php b/demo/symfony7.x_doctrine3.x/tests/SecretTest.php index 918d6891..df1f17ee 100644 --- a/demo/symfony7.x_doctrine3.x/tests/SecretTest.php +++ b/demo/symfony7.x_doctrine3.x/tests/SecretTest.php @@ -13,7 +13,7 @@ protected function setUp(): void { parent::setUp(); - self::bootKernel([]); + self::bootKernel(); } private function testSecretsAreEncryptedInDatabase(string $className) diff --git a/src/DoctrineEncryptBundle.php b/src/DoctrineEncryptBundle.php index 6d19db82..0086efab 100644 --- a/src/DoctrineEncryptBundle.php +++ b/src/DoctrineEncryptBundle.php @@ -40,7 +40,7 @@ public function boot(): void $databasePlatform = $connection->getDatabasePlatform(); if (! $databasePlatform->hasDoctrineTypeMappingFor($encyptName)) { - $databasePlatform->registerDoctrineTypeMapping($encyptName,$encyptName); + $databasePlatform->registerDoctrineTypeMapping($encyptName, $encyptName); } } } diff --git a/src/Types/Encrypted.php b/src/Types/Encrypted.php index d8808bf0..56abc2c8 100755 --- a/src/Types/Encrypted.php +++ b/src/Types/Encrypted.php @@ -12,12 +12,12 @@ class Encrypted extends StringType const TYPE = 'encrypted'; - public function convertToPHPValue($value, AbstractPlatform $platform) + public function convertToPHPValue(mixed $value, AbstractPlatform $platform): mixed { return $this->service->decrypt ('string', $value); } - public function convertToDatabaseValue($value, AbstractPlatform $platform) + public function convertToDatabaseValue(mixed $value, AbstractPlatform $platform): mixed { return $this->service->encrypt ('string', $value); } diff --git a/src/Types/EncryptedArray.php b/src/Types/EncryptedArray.php index a85219d2..5695bded 100755 --- a/src/Types/EncryptedArray.php +++ b/src/Types/EncryptedArray.php @@ -12,12 +12,12 @@ class EncryptedArray extends TextType const TYPE = 'encrypted_array'; - public function convertToPHPValue($value, AbstractPlatform $platform) + public function convertToPHPValue(mixed $value, AbstractPlatform $platform): mixed { return $this->service->decrypt ('simple_array', $value); } - public function convertToDatabaseValue($value, AbstractPlatform $platform) + public function convertToDatabaseValue(mixed $value, AbstractPlatform $platform): mixed { return $this->service->encrypt ('simple_array', $value); } diff --git a/src/Types/EncryptedDateTime.php b/src/Types/EncryptedDateTime.php index 0340a397..f6117941 100755 --- a/src/Types/EncryptedDateTime.php +++ b/src/Types/EncryptedDateTime.php @@ -12,12 +12,12 @@ class EncryptedDateTime extends StringType const TYPE = 'encrypted_datetime'; - public function convertToPHPValue($value, AbstractPlatform $platform) + public function convertToPHPValue(mixed $value, AbstractPlatform $platform): mixed { return $this->service->decrypt ('datetime', $value); } - public function convertToDatabaseValue($value, AbstractPlatform $platform) + public function convertToDatabaseValue(mixed $value, AbstractPlatform $platform): mixed { return $this->service->encrypt ('datetime', $value); } diff --git a/src/Types/EncryptedJSON.php b/src/Types/EncryptedJSON.php index 17a4d7e1..7f7a1aa7 100755 --- a/src/Types/EncryptedJSON.php +++ b/src/Types/EncryptedJSON.php @@ -12,12 +12,12 @@ class EncryptedJSON extends TextType const TYPE = 'encrypted_json'; - public function convertToPHPValue($value, AbstractPlatform $platform) + public function convertToPHPValue(mixed $value, AbstractPlatform $platform): mixed { return $this->service->decrypt ('json', $value); } - public function convertToDatabaseValue($value, AbstractPlatform $platform) + public function convertToDatabaseValue(mixed $value, AbstractPlatform $platform): mixed { return $this->service->encrypt ('json', $value); } diff --git a/tests/DoctrineCompatibilityTrait.php b/tests/DoctrineCompatibilityTrait.php index 4f4f7703..b12844e1 100644 --- a/tests/DoctrineCompatibilityTrait.php +++ b/tests/DoctrineCompatibilityTrait.php @@ -11,12 +11,7 @@ trait DoctrineCompatibilityTrait */ public function executeStatementFetchAll(\Doctrine\DBAL\Statement $statement) { - if (method_exists($statement,'executeQuery')) { - return $statement->executeQuery()->fetchAllAssociative(); - } else { - $statement->execute(); - return $statement->fetchAll(); - } + return $statement->executeQuery()->fetchAllAssociative(); } /** @@ -26,11 +21,6 @@ public function executeStatementFetchAll(\Doctrine\DBAL\Statement $statement) */ public function executeStatementFetch(\Doctrine\DBAL\Statement $statement) { - if (method_exists($statement,'executeQuery')) { - return $statement->executeQuery()->fetchAssociative(); - } else { - $statement->execute(); - return $statement->fetch(); - } + return $statement->executeQuery()->fetchAssociative(); } } \ No newline at end of file diff --git a/tests/Functional/AbstractFunctionalTestCase.php b/tests/Functional/AbstractFunctionalTestCase.php index f27cfb5b..89466342 100644 --- a/tests/Functional/AbstractFunctionalTestCase.php +++ b/tests/Functional/AbstractFunctionalTestCase.php @@ -9,7 +9,6 @@ use DoctrineEncryptBundle\Service\Encrypt; use Doctrine\DBAL\Types\Type; use Doctrine\ORM\EntityManager; -use Doctrine\ORM\Tools\Setup; use Doctrine\ORM\ORMSetup; use Doctrine\ORM\Tools\SchemaTool; use DoctrineEncryptBundle\DoctrineEncryptBundle; @@ -71,37 +70,20 @@ public function setUp(): void $isDevMode = true; $proxyDir = null; $cache = null; - - if (version_compare(PHP_VERSION, '8.0.0', '<')) { - $useSimpleAnnotationReader = false; - $config = Setup::createAnnotationMetadataConfiguration( - array(__DIR__.'/fixtures/Entity'), - $isDevMode, - $proxyDir, - $cache, - $useSimpleAnnotationReader - ); - // obtaining the entity manager - $this->entityManager = EntityManager::create($connOptions, $config); - } - else - { - $reportFieldsWhereDeclared = true; - $config = ORMSetup::createAttributeMetadataConfiguration( - array(__DIR__.'/fixtures/Entity'), - $isDevMode, - $proxyDir, - $cache, - $reportFieldsWhereDeclared - ); - // $config->setLazyGhostObjectEnabled (true); - $config->setSchemaManagerFactory(new DefaultSchemaManagerFactory()); - // obtaining the entity manager - $conn = DriverManager::getConnection($connOptions, $config); - $dbalConf = $conn->getConfiguration(); - $this->entityManager = new EntityManager($conn, $dbalConf); - } - + $reportFieldsWhereDeclared = true; + $config = ORMSetup::createAttributeMetadataConfiguration( + array(__DIR__.'/fixtures/Entity'), + $isDevMode, + $proxyDir, + $cache, + $reportFieldsWhereDeclared + ); + $config->setLazyGhostObjectEnabled (true); + $config->setSchemaManagerFactory(new DefaultSchemaManagerFactory()); + // obtaining the entity manager + $conn = DriverManager::getConnection($connOptions, $config); + $dbalConf = $conn->getConfiguration(); + $this->entityManager = new EntityManager($conn, $dbalConf); $schemaTool = new SchemaTool($this->entityManager); $classes = $this->entityManager->getMetadataFactory()->getAllMetadata(); diff --git a/tests/Functional/fixtures/Entity/AbstractVehicle.php b/tests/Functional/fixtures/Entity/AbstractVehicle.php index f9bfac40..3c2ba8a5 100644 --- a/tests/Functional/fixtures/Entity/AbstractVehicle.php +++ b/tests/Functional/fixtures/Entity/AbstractVehicle.php @@ -4,12 +4,6 @@ use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity() - * @ORM\InheritanceType("SINGLE_TABLE") - * @ORM\DiscriminatorColumn(name="type", type="string") - * @ORM\DiscriminatorMap({"car" = "VehicleCar","bike" = "VehicleBicycle"}) - */ #[ORM\Entity()] #[ORM\InheritanceType("SINGLE_TABLE")] #[ORM\DiscriminatorColumn(name:"type", type:"string")] @@ -18,24 +12,15 @@ abstract class AbstractVehicle { /** * @var int - * @ORM\Id - * @ORM\Column(type="integer") - * @ORM\GeneratedValue */ #[ORM\Id] #[ORM\Column(type:"integer")] #[ORM\GeneratedValue] private $id; - /** - * @ORM\Column(type="encrypted", nullable=true) - */ #[ORM\Column(type:"encrypted", nullable:true)] private $secret; - /** - * @ORM\Column(type="string", nullable=true) - */ #[ORM\Column(type:"string", nullable:true)] private $notSecret; diff --git a/tests/Functional/fixtures/Entity/CascadeTarget.php b/tests/Functional/fixtures/Entity/CascadeTarget.php index ed95cac0..d020a15f 100644 --- a/tests/Functional/fixtures/Entity/CascadeTarget.php +++ b/tests/Functional/fixtures/Entity/CascadeTarget.php @@ -4,32 +4,20 @@ use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity() - */ #[ORM\Entity()] class CascadeTarget { /** * @var int - * @ORM\Id - * @ORM\Column(type="integer") - * @ORM\GeneratedValue */ #[ORM\Id] #[ORM\Column(type:"integer")] #[ORM\GeneratedValue()] private $id; - /** - * @ORM\Column(type="encrypted", nullable=true) - */ #[ORM\Column(type:"encrypted", nullable:true)] private $secret; - /** - * @ORM\Column(type="string", nullable=true) - */ #[ORM\Column(type:"string", nullable:true)] private $notSecret; diff --git a/tests/Functional/fixtures/Entity/CascadeTargetArray.php b/tests/Functional/fixtures/Entity/CascadeTargetArray.php index ff045502..95e13760 100755 --- a/tests/Functional/fixtures/Entity/CascadeTargetArray.php +++ b/tests/Functional/fixtures/Entity/CascadeTargetArray.php @@ -4,32 +4,20 @@ use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity() - */ #[ORM\Entity()] class CascadeTargetArray { /** * @var int - * @ORM\Id - * @ORM\Column(type="integer") - * @ORM\GeneratedValue */ #[ORM\Id] #[ORM\Column(type:"integer")] #[ORM\GeneratedValue()] private $id; - /** - * @ORM\Column(type="encrypted_array", nullable=true) - */ #[ORM\Column(type:"encrypted_array", nullable:true)] private $secret; - /** - * @ORM\Column(type="string", nullable=true) - */ #[ORM\Column(type:"string", nullable:true)] private $notSecret; diff --git a/tests/Functional/fixtures/Entity/CascadeTargetDateTime.php b/tests/Functional/fixtures/Entity/CascadeTargetDateTime.php index d08626cd..9a0303bb 100755 --- a/tests/Functional/fixtures/Entity/CascadeTargetDateTime.php +++ b/tests/Functional/fixtures/Entity/CascadeTargetDateTime.php @@ -4,32 +4,20 @@ use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity() - */ #[ORM\Entity()] class CascadeTargetDateTime { /** * @var int - * @ORM\Id - * @ORM\Column(type="integer") - * @ORM\GeneratedValue */ #[ORM\Id] #[ORM\Column(type:"integer")] #[ORM\GeneratedValue()] private $id; - /** - * @ORM\Column(type="encrypted_datetime", nullable=true) - */ #[ORM\Column(type:"encrypted_datetime", nullable:true)] private $secret; - /** - * @ORM\Column(type="string", nullable=true) - */ #[ORM\Column(type:"string", nullable:true)] private $notSecret; diff --git a/tests/Functional/fixtures/Entity/CascadeTargetJSON.php b/tests/Functional/fixtures/Entity/CascadeTargetJSON.php index 439d8c7e..d7c9ef94 100755 --- a/tests/Functional/fixtures/Entity/CascadeTargetJSON.php +++ b/tests/Functional/fixtures/Entity/CascadeTargetJSON.php @@ -4,32 +4,20 @@ use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity() - */ #[ORM\Entity()] class CascadeTargetJSON { /** * @var int - * @ORM\Id - * @ORM\Column(type="integer") - * @ORM\GeneratedValue */ #[ORM\Id] #[ORM\Column(type:"integer")] #[ORM\GeneratedValue()] private $id; - /** - * @ORM\Column(type="encrypted_json", nullable=true) - */ #[ORM\Column(type:"encrypted_json", nullable:true)] private $secret; - /** - * @ORM\Column(type="string", nullable=true) - */ #[ORM\Column(type:"string", nullable:true)] private $notSecret; diff --git a/tests/Functional/fixtures/Entity/CascadeTargetStrtoupper.php b/tests/Functional/fixtures/Entity/CascadeTargetStrtoupper.php index 8d496c90..24bf2bc6 100644 --- a/tests/Functional/fixtures/Entity/CascadeTargetStrtoupper.php +++ b/tests/Functional/fixtures/Entity/CascadeTargetStrtoupper.php @@ -4,32 +4,20 @@ use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity() - */ #[ORM\Entity()] class CascadeTargetStrtoupper { /** * @var int - * @ORM\Id - * @ORM\Column(type="integer") - * @ORM\GeneratedValue */ #[ORM\Id] #[ORM\Column(type:"integer")] #[ORM\GeneratedValue] private $id; - /** - * @ORM\Column(type="encrypted", nullable=true) - */ #[ORM\Column(type:"encrypted", nullable:true)] private $secret; - /** - * @ORM\Column(type="string", nullable=true) - */ #[ORM\Column(type:"string", nullable:true)] private $notSecret; diff --git a/tests/Functional/fixtures/Entity/ClassTableInheritanceBase.php b/tests/Functional/fixtures/Entity/ClassTableInheritanceBase.php index 5592eb65..19c2e728 100644 --- a/tests/Functional/fixtures/Entity/ClassTableInheritanceBase.php +++ b/tests/Functional/fixtures/Entity/ClassTableInheritanceBase.php @@ -4,11 +4,6 @@ use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - * @ORM\InheritanceType("JOINED") - * @ORM\DiscriminatorColumn(name="discr", type="string") - */ #[ORM\Entity] #[ORM\InheritanceType("JOINED")] #[ORM\DiscriminatorColumn(name:"discr", type:"string")] @@ -17,24 +12,15 @@ class ClassTableInheritanceBase /** * @var int - * @ORM\Id - * @ORM\Column(type="integer") - * @ORM\GeneratedValue */ #[ORM\Id] #[ORM\Column(type:"integer")] #[ORM\GeneratedValue] private $id; - /** - * @ORM\Column(type="encrypted", nullable=true) - */ #[ORM\Column(type:"encrypted", nullable:true)] private $secretBase; - /** - * @ORM\Column(type="string", nullable=true) - */ #[ORM\Column(type:"string", nullable:true)] private $notSecretBase; diff --git a/tests/Functional/fixtures/Entity/ClassTableInheritanceChild.php b/tests/Functional/fixtures/Entity/ClassTableInheritanceChild.php index 56da1426..56a167df 100644 --- a/tests/Functional/fixtures/Entity/ClassTableInheritanceChild.php +++ b/tests/Functional/fixtures/Entity/ClassTableInheritanceChild.php @@ -5,21 +5,12 @@ use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity() - */ #[ORM\Entity] class ClassTableInheritanceChild extends ClassTableInheritanceBase { - /** - * @ORM\Column(type="encrypted", nullable=true) - */ #[ORM\Column(type:"encrypted", nullable:true)] private $secretChild; - /** - * @ORM\Column(type="string", nullable=true) - */ #[ORM\Column(type:"string", nullable:true)] private $notSecretChild; diff --git a/tests/Functional/fixtures/Entity/Owner.php b/tests/Functional/fixtures/Entity/Owner.php index d1892f6d..ff98c0c9 100644 --- a/tests/Functional/fixtures/Entity/Owner.php +++ b/tests/Functional/fixtures/Entity/Owner.php @@ -5,41 +5,24 @@ use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity() - */ #[ORM\Entity()] class Owner { /** * @var int - * @ORM\Id - * @ORM\Column(type="integer") - * @ORM\GeneratedValue */ #[ORM\Id] #[ORM\Column(type:"integer")] #[ORM\GeneratedValue] private $id; - /** - * @ORM\Column(type="encrypted", nullable=true) - */ #[ORM\Column(type:"encrypted", nullable:true)] private $secret; - /** - * @ORM\Column(type="string", nullable=true) - */ #[ORM\Column(type:"string", nullable:true)] private $notSecret; - /** - * @ORM\OneToOne( - * targetEntity="DoctrineEncryptBundle\Tests\Functional\fixtures\Entity\CascadeTarget", - * cascade={"persist"}) - */ #[ORM\OneToOne(targetEntity:CascadeTarget::class, cascade:["persist"])] private $cascaded; diff --git a/tests/Functional/fixtures/Entity/VehicleBicycle.php b/tests/Functional/fixtures/Entity/VehicleBicycle.php index e4e0f904..5bf1c0ec 100644 --- a/tests/Functional/fixtures/Entity/VehicleBicycle.php +++ b/tests/Functional/fixtures/Entity/VehicleBicycle.php @@ -5,15 +5,11 @@ use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity() - */ #[ORM\Entity()] class VehicleBicycle extends AbstractVehicle { /** * @var bool - * @ORM\Column(type="boolean") */ #[ORM\Column(type:"boolean")] private $hasSidewheels = false; diff --git a/tests/Functional/fixtures/Entity/VehicleCar.php b/tests/Functional/fixtures/Entity/VehicleCar.php index 16ac3dfc..d68a6a1b 100644 --- a/tests/Functional/fixtures/Entity/VehicleCar.php +++ b/tests/Functional/fixtures/Entity/VehicleCar.php @@ -5,15 +5,11 @@ use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity() - */ #[ORM\Entity()] class VehicleCar extends AbstractVehicle { /** * @var string - * @ORM\Column(type="string", length=10) */ #[ORM\Column(type:"string", length:10)] private $licensePlate; From f1fffbb9a191db39c42493bf4f66ae18398a0113 Mon Sep 17 00:00:00 2001 From: r3hp1c Date: Sun, 3 Mar 2024 10:35:57 +0000 Subject: [PATCH 21/44] Fix for the commands to not use ClassMetadata::CHANGETRACKING_NOTIFY that was removed in Doctrine ORM 3 --- .../DoctrineDecryptDatabaseCommand.php | 30 +++++++++++-------- .../DoctrineEncryptDatabaseCommand.php | 30 ++++++++++++------- 2 files changed, 37 insertions(+), 23 deletions(-) diff --git a/src/Command/DoctrineDecryptDatabaseCommand.php b/src/Command/DoctrineDecryptDatabaseCommand.php index 4e80741c..da8f91bb 100644 --- a/src/Command/DoctrineDecryptDatabaseCommand.php +++ b/src/Command/DoctrineDecryptDatabaseCommand.php @@ -111,13 +111,6 @@ protected function execute(InputInterface $input, OutputInterface $output): int $pac = PropertyAccess::createPropertyAccessor(); $unitOfWork = $this->entityManager->getUnitOfWork(); foreach ($encryptDetails as $entityName => $classMeta) { - $ctp = $classMeta->changeTrackingPolicy; - - // Tell the table class to not automatically calculate changed values but just - // mark those fields as dirty that get passed to propertyChanged function - // TODO : ClassMetadata::CHANGETRACKING_NOTIFY does not exist in latest version - $classMeta->setChangeTrackingPolicy(ClassMetadata::CHANGETRACKING_NOTIFY); - $i = 0; $valueCounter = 0; $iterator = $this->getEntityIterator($entityName); @@ -128,21 +121,36 @@ protected function execute(InputInterface $input, OutputInterface $output): int foreach ($iterator as $row) { $entity = (is_array($row) ? $row[0] : $row); + $changeData = []; // tell the unit of work that an value has changed no matter if the value // is actually different from the value already persistent // need all the values checked for the count foreach ($metaData->fieldMappings as $fieldMapping) { if (in_array ($fieldMapping['type'], $encryptTypes)) { $value = $pac->getValue($entity, $fieldMapping['fieldName']); - if (! is_null ($value)) + if (! is_null ($value) && ! empty($value)) { - // TODO : only need to set a single value $valueCounter++; - $unitOfWork->propertyChanged($entity, $fieldMapping['fieldName'], $value, $value); + array_push($changeData, ['fieldName' => $fieldMapping['fieldName'], 'value' => $value]); } } } + if (count($changeData)) + { + $originalData = $unitOfWork->getOriginalEntityData($entity); + foreach ($changeData as $changeDetail) + { + $originalData[$changeDetail['fieldName']] = null; + } + $unitOfWork->setOriginalEntityData($entity, $originalData); + foreach ($changeData as $changeDetail) + { + $unitOfWork->propertyChanged($entity, $changeDetail['fieldName'], null, $changeDetail['value']); + } + $this->entityManager->persist($entity); + } + if (($i % $batchSize) === 0) { $this->entityManager->flush(); $this->entityManager->clear(); @@ -155,8 +163,6 @@ protected function execute(InputInterface $input, OutputInterface $output): int $output->writeln(''); $this->entityManager->flush(); $this->entityManager->clear(); - - $classMeta->setChangeTrackingPolicy($ctp); } $output->writeln('' . PHP_EOL . 'Decryption finished. Estimated values decrypted: ' . $valueCounter . '.' . PHP_EOL . 'All values are now decrypted.'); diff --git a/src/Command/DoctrineEncryptDatabaseCommand.php b/src/Command/DoctrineEncryptDatabaseCommand.php index 618f4789..7204dc88 100644 --- a/src/Command/DoctrineEncryptDatabaseCommand.php +++ b/src/Command/DoctrineEncryptDatabaseCommand.php @@ -111,13 +111,6 @@ protected function execute(InputInterface $input, OutputInterface $output): int $pac = PropertyAccess::createPropertyAccessor(); $unitOfWork = $this->entityManager->getUnitOfWork(); foreach ($encryptDetails as $entityName => $classMeta) { - $ctp = $classMeta->changeTrackingPolicy; - - // Tell the table class to not automatically calculate changed values but just - // mark those fields as dirty that get passed to propertyChanged function - // TODO : ClassMetadata::CHANGETRACKING_NOTIFY does not exist in latest version - $classMeta->setChangeTrackingPolicy(ClassMetadata::CHANGETRACKING_NOTIFY); - $i = 0; $valueCounter = 0; $iterator = $this->getEntityIterator($entityName); @@ -128,21 +121,36 @@ protected function execute(InputInterface $input, OutputInterface $output): int foreach ($iterator as $row) { $entity = (is_array($row) ? $row[0] : $row); + $changeData = []; // tell the unit of work that an value has changed no matter if the value // is actually different from the value already persistent // need all the values checked for the count foreach ($metaData->fieldMappings as $fieldMapping) { if (in_array ($fieldMapping['type'], $encryptTypes)) { $value = $pac->getValue($entity, $fieldMapping['fieldName']); - if (! is_null ($value)) + if (! is_null ($value) && ! empty($value)) { - // TODO : only need to set a single value $valueCounter++; - $unitOfWork->propertyChanged($entity, $fieldMapping['fieldName'], $value, $value); + array_push($changeData, ['fieldName' => $fieldMapping['fieldName'], 'value' => $value]); } } } + if (count($changeData)) + { + $originalData = $unitOfWork->getOriginalEntityData($entity); + foreach ($changeData as $changeDetail) + { + $originalData[$changeDetail['fieldName']] = null; + } + $unitOfWork->setOriginalEntityData($entity, $originalData); + foreach ($changeData as $changeDetail) + { + $unitOfWork->propertyChanged($entity, $changeDetail['fieldName'], null, $changeDetail['value']); + } + $this->entityManager->persist($entity); + } + if (($i % $batchSize) === 0) { $this->entityManager->flush(); $this->entityManager->clear(); @@ -156,7 +164,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $this->entityManager->flush(); $this->entityManager->clear(); - $classMeta->setChangeTrackingPolicy($ctp); + // $classMeta->setChangeTrackingPolicy($ctp); } // Say it is finished From bf092c63cddb779dda27a903646a1eba94cb6af9 Mon Sep 17 00:00:00 2001 From: r3hp1c Date: Sun, 3 Mar 2024 10:42:03 +0000 Subject: [PATCH 22/44] Add paragonie/halite for the symfony 7 demos --- demo/symfony7.x/composer.json | 1 + demo/symfony7.x/composer.lock | 331 +++++++++++++++++++++- demo/symfony7.x_doctrine3.x/composer.json | 1 + 3 files changed, 331 insertions(+), 2 deletions(-) diff --git a/demo/symfony7.x/composer.json b/demo/symfony7.x/composer.json index d5835f1d..bace50e2 100644 --- a/demo/symfony7.x/composer.json +++ b/demo/symfony7.x/composer.json @@ -10,6 +10,7 @@ "doctrine/orm": "^2.5", "doctrineencryptbundle/doctrine-encrypt-bundle": "@dev", "doctrine/persistence": "^3.2", + "paragonie/halite": "^5.0", "symfony/console": "7.0.*", "symfony/dotenv": "7.0.*", "symfony/flex": "^2", diff --git a/demo/symfony7.x/composer.lock b/demo/symfony7.x/composer.lock index e76b8a2e..98365be6 100644 --- a/demo/symfony7.x/composer.lock +++ b/demo/symfony7.x/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "c55532552561076ce660bd65e2e7815b", + "content-hash": "b607657f8bb963e1502c3194da36fb42", "packages": [ { "name": "doctrine/cache", @@ -1141,7 +1141,7 @@ "dist": { "type": "path", "url": "../..", - "reference": "8436bc5acddcf60d71054d9e1b70ec261682b1c9" + "reference": "f1fffbb9a191db39c42493bf4f66ae18398a0113" }, "require": { "doctrine/doctrine-bundle": "^2.0.8|^2.1", @@ -1205,6 +1205,333 @@ "relative": true } }, + { + "name": "paragonie/constant_time_encoding", + "version": "v2.6.3", + "source": { + "type": "git", + "url": "https://github.com/paragonie/constant_time_encoding.git", + "reference": "58c3f47f650c94ec05a151692652a868995d2938" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/58c3f47f650c94ec05a151692652a868995d2938", + "reference": "58c3f47f650c94ec05a151692652a868995d2938", + "shasum": "" + }, + "require": { + "php": "^7|^8" + }, + "require-dev": { + "phpunit/phpunit": "^6|^7|^8|^9", + "vimeo/psalm": "^1|^2|^3|^4" + }, + "type": "library", + "autoload": { + "psr-4": { + "ParagonIE\\ConstantTime\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Paragon Initiative Enterprises", + "email": "security@paragonie.com", + "homepage": "https://paragonie.com", + "role": "Maintainer" + }, + { + "name": "Steve 'Sc00bz' Thomas", + "email": "steve@tobtu.com", + "homepage": "https://www.tobtu.com", + "role": "Original Developer" + } + ], + "description": "Constant-time Implementations of RFC 4648 Encoding (Base-64, Base-32, Base-16)", + "keywords": [ + "base16", + "base32", + "base32_decode", + "base32_encode", + "base64", + "base64_decode", + "base64_encode", + "bin2hex", + "encoding", + "hex", + "hex2bin", + "rfc4648" + ], + "support": { + "email": "info@paragonie.com", + "issues": "https://github.com/paragonie/constant_time_encoding/issues", + "source": "https://github.com/paragonie/constant_time_encoding" + }, + "time": "2022-06-14T06:56:20+00:00" + }, + { + "name": "paragonie/halite", + "version": "v5.1.0", + "source": { + "type": "git", + "url": "https://github.com/paragonie/halite.git", + "reference": "666f9770a12bd8a49cefba16c759baa4843dbf5a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paragonie/halite/zipball/666f9770a12bd8a49cefba16c759baa4843dbf5a", + "reference": "666f9770a12bd8a49cefba16c759baa4843dbf5a", + "shasum": "" + }, + "require": { + "ext-json": "*", + "paragonie/constant_time_encoding": "^2", + "paragonie/hidden-string": "^1|^2", + "paragonie/sodium_compat": "^1.17", + "php": "^8.1" + }, + "require-dev": { + "phpunit/phpunit": "^9", + "vimeo/psalm": "^4" + }, + "type": "library", + "autoload": { + "psr-4": { + "ParagonIE\\Halite\\": "./src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MPL-2.0" + ], + "authors": [ + { + "name": "Paragon Initiative Enterprises", + "email": "info@paragonie.com", + "homepage": "https://paragonie.com" + } + ], + "description": "High-level cryptography interface powered by libsodium", + "homepage": "https://github.com/paragonie/halite", + "keywords": [ + "Argon2i", + "BLAKE", + "BLAKE2", + "BLAKE2b", + "Curve25519", + "Ed25519", + "X25519", + "Xsalsa20", + "argon2", + "cryptography", + "encryption", + "ext-sodium", + "hashing", + "libsodium", + "password", + "public-key", + "signatures", + "sodium" + ], + "support": { + "docs": "https://github.com/paragonie/halite/tree/master/doc", + "issues": "https://github.com/paragonie/halite/issues", + "source": "https://github.com/paragonie/halite/tree/v5.1.0" + }, + "time": "2022-05-23T05:02:50+00:00" + }, + { + "name": "paragonie/hidden-string", + "version": "v2.0.0", + "source": { + "type": "git", + "url": "https://github.com/paragonie/hidden-string.git", + "reference": "151e53d55bfc67dd58087cdf8762dd8177ea7575" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paragonie/hidden-string/zipball/151e53d55bfc67dd58087cdf8762dd8177ea7575", + "reference": "151e53d55bfc67dd58087cdf8762dd8177ea7575", + "shasum": "" + }, + "require": { + "paragonie/constant_time_encoding": "^2", + "paragonie/sodium_compat": "^1.6", + "php": "^7.4|^8" + }, + "require-dev": { + "phpunit/phpunit": "^6|^7|^8|^9", + "vimeo/psalm": "^3|^4" + }, + "type": "library", + "autoload": { + "psr-4": { + "ParagonIE\\HiddenString\\": "./src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MPL-2.0" + ], + "authors": [ + { + "name": "Paragon Initiative Enterprises", + "email": "info@paragonie.com", + "homepage": "https://paragonie.com" + } + ], + "description": "Encapsulate strings in an object to hide them from stack traces", + "homepage": "https://github.com/paragonie/hidden-string", + "keywords": [ + "hidden", + "stack trace", + "string" + ], + "support": { + "issues": "https://github.com/paragonie/hidden-string/issues", + "source": "https://github.com/paragonie/hidden-string/tree/v2.0.0" + }, + "time": "2020-12-06T15:07:44+00:00" + }, + { + "name": "paragonie/random_compat", + "version": "v9.99.100", + "source": { + "type": "git", + "url": "https://github.com/paragonie/random_compat.git", + "reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paragonie/random_compat/zipball/996434e5492cb4c3edcb9168db6fbb1359ef965a", + "reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a", + "shasum": "" + }, + "require": { + "php": ">= 7" + }, + "require-dev": { + "phpunit/phpunit": "4.*|5.*", + "vimeo/psalm": "^1" + }, + "suggest": { + "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." + }, + "type": "library", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Paragon Initiative Enterprises", + "email": "security@paragonie.com", + "homepage": "https://paragonie.com" + } + ], + "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", + "keywords": [ + "csprng", + "polyfill", + "pseudorandom", + "random" + ], + "support": { + "email": "info@paragonie.com", + "issues": "https://github.com/paragonie/random_compat/issues", + "source": "https://github.com/paragonie/random_compat" + }, + "time": "2020-10-15T08:29:30+00:00" + }, + { + "name": "paragonie/sodium_compat", + "version": "v1.20.0", + "source": { + "type": "git", + "url": "https://github.com/paragonie/sodium_compat.git", + "reference": "e592a3e06d1fa0d43988c7c7d9948ca836f644b6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paragonie/sodium_compat/zipball/e592a3e06d1fa0d43988c7c7d9948ca836f644b6", + "reference": "e592a3e06d1fa0d43988c7c7d9948ca836f644b6", + "shasum": "" + }, + "require": { + "paragonie/random_compat": ">=1", + "php": "^5.2.4|^5.3|^5.4|^5.5|^5.6|^7|^8" + }, + "require-dev": { + "phpunit/phpunit": "^3|^4|^5|^6|^7|^8|^9" + }, + "suggest": { + "ext-libsodium": "PHP < 7.0: Better performance, password hashing (Argon2i), secure memory management (memzero), and better security.", + "ext-sodium": "PHP >= 7.0: Better performance, password hashing (Argon2i), secure memory management (memzero), and better security." + }, + "type": "library", + "autoload": { + "files": [ + "autoload.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "ISC" + ], + "authors": [ + { + "name": "Paragon Initiative Enterprises", + "email": "security@paragonie.com" + }, + { + "name": "Frank Denis", + "email": "jedisct1@pureftpd.org" + } + ], + "description": "Pure PHP implementation of libsodium; uses the PHP extension if it exists", + "keywords": [ + "Authentication", + "BLAKE2b", + "ChaCha20", + "ChaCha20-Poly1305", + "Chapoly", + "Curve25519", + "Ed25519", + "EdDSA", + "Edwards-curve Digital Signature Algorithm", + "Elliptic Curve Diffie-Hellman", + "Poly1305", + "Pure-PHP cryptography", + "RFC 7748", + "RFC 8032", + "Salpoly", + "Salsa20", + "X25519", + "XChaCha20-Poly1305", + "XSalsa20-Poly1305", + "Xchacha20", + "Xsalsa20", + "aead", + "cryptography", + "ecdh", + "elliptic curve", + "elliptic curve cryptography", + "encryption", + "libsodium", + "php", + "public-key cryptography", + "secret-key cryptography", + "side-channel resistant" + ], + "support": { + "issues": "https://github.com/paragonie/sodium_compat/issues", + "source": "https://github.com/paragonie/sodium_compat/tree/v1.20.0" + }, + "time": "2023-04-30T00:54:53+00:00" + }, { "name": "psr/cache", "version": "3.0.0", diff --git a/demo/symfony7.x_doctrine3.x/composer.json b/demo/symfony7.x_doctrine3.x/composer.json index 6d55eff2..25e083e0 100644 --- a/demo/symfony7.x_doctrine3.x/composer.json +++ b/demo/symfony7.x_doctrine3.x/composer.json @@ -10,6 +10,7 @@ "doctrine/orm": "^3.0", "doctrineencryptbundle/doctrine-encrypt-bundle": "@dev", "doctrine/persistence": "^3.2", + "paragonie/halite": "^5.0", "symfony/console": "7.0.*", "symfony/dotenv": "7.0.*", "symfony/flex": "^2", From 4b39cdcea72fea13916744fbdc2a61923663d6b3 Mon Sep 17 00:00:00 2001 From: r3hp1c Date: Sun, 3 Mar 2024 10:54:54 +0000 Subject: [PATCH 23/44] Symfony 7 tests to run on PHP version 8.2 and 8.3. Fixed Doctrine 3 Registry class. --- .github/workflows/ci.yml | 8 ++++---- .../src/Repository/Attribute/SecretRepository.php | 3 ++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9b7bf472..bb9ec895 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -124,11 +124,11 @@ jobs: dependency-versions: "${{ matrix.dependency-versions }}" composer-options: "--prefer-dist --no-progress" working-directory: "demo/symfony7.x" - if: ${{ startsWith(matrix.php-version , '8.2') }} + if: ${{ matrix.php-version == '8.2' || matrix.php-version == '8.3' }} - name: Demo symfony7.x - Unit Tests run: demo/symfony7.x/vendor/bin/simple-phpunit -c demo/symfony7.x/phpunit.xml.dist - if: ${{ startsWith(matrix.php-version , '8.2') }} + if: ${{ matrix.php-version == '8.2' || matrix.php-version == '8.3' }} - name: Demo symfony7.x Doctrine3.x - Install dependencies uses: "ramsey/composer-install@v2" @@ -136,8 +136,8 @@ jobs: dependency-versions: "${{ matrix.dependency-versions }}" composer-options: "--prefer-dist --no-progress" working-directory: "demo/symfony7.x_doctrine3.x" - if: ${{ startsWith(matrix.php-version , '8.3') }} + if: ${{ matrix.php-version == '8.2' || matrix.php-version == '8.3' }} - name: Demo symfony7.x Doctrine3.x - Unit Tests run: demo/symfony7.x_doctrine3.x/vendor/bin/simple-phpunit -c demo/symfony7.x_doctrine3.x/phpunit.xml.dist - if: ${{ startsWith(matrix.php-version , '8.3') }} \ No newline at end of file + if: ${{ matrix.php-version == '8.2' || matrix.php-version == '8.3' }} \ No newline at end of file diff --git a/demo/symfony7.x_doctrine3.x/src/Repository/Attribute/SecretRepository.php b/demo/symfony7.x_doctrine3.x/src/Repository/Attribute/SecretRepository.php index fe0fd580..c4255662 100644 --- a/demo/symfony7.x_doctrine3.x/src/Repository/Attribute/SecretRepository.php +++ b/demo/symfony7.x_doctrine3.x/src/Repository/Attribute/SecretRepository.php @@ -4,6 +4,7 @@ use App\Entity\Attribute\Secret; use App\Repository\AbstractSecretRepository; +use Doctrine\Bundle\DoctrineBundle\Registry; /** * @method Secret|null find($id, $lockMode = null, $lockVersion = null) @@ -12,7 +13,7 @@ */ class SecretRepository extends AbstractSecretRepository { - public function __construct(\Doctrine\Common\Persistence\ManagerRegistry $registry) + public function __construct(Registry $registry) { parent::__construct($registry, Secret::class); } From f66e6ce28727959b5524de574a2a9767d0274cfe Mon Sep 17 00:00:00 2001 From: r3hp1c Date: Sun, 3 Mar 2024 11:02:42 +0000 Subject: [PATCH 24/44] Fix PHP version in composer.json --- demo/symfony7.x_doctrine3.x/composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demo/symfony7.x_doctrine3.x/composer.json b/demo/symfony7.x_doctrine3.x/composer.json index 25e083e0..06a3f1de 100644 --- a/demo/symfony7.x_doctrine3.x/composer.json +++ b/demo/symfony7.x_doctrine3.x/composer.json @@ -4,7 +4,7 @@ "minimum-stability": "stable", "prefer-stable": true, "require": { - "php": ">=8.3", + "php": ">=8.2", "ext-ctype": "*", "ext-iconv": "*", "doctrine/orm": "^3.0", From e71725c3d94df5810c1d62520b843cc40bf1da51 Mon Sep 17 00:00:00 2001 From: r3hp1c Date: Sun, 3 Mar 2024 11:07:13 +0000 Subject: [PATCH 25/44] Changed Doctrine ORM 3 ManagerRegistry --- .../src/Repository/Attribute/SecretRepository.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/demo/symfony7.x_doctrine3.x/src/Repository/Attribute/SecretRepository.php b/demo/symfony7.x_doctrine3.x/src/Repository/Attribute/SecretRepository.php index c4255662..6cd86e30 100644 --- a/demo/symfony7.x_doctrine3.x/src/Repository/Attribute/SecretRepository.php +++ b/demo/symfony7.x_doctrine3.x/src/Repository/Attribute/SecretRepository.php @@ -4,7 +4,7 @@ use App\Entity\Attribute\Secret; use App\Repository\AbstractSecretRepository; -use Doctrine\Bundle\DoctrineBundle\Registry; +use Doctrine\Persistence\ManagerRegistry; /** * @method Secret|null find($id, $lockMode = null, $lockVersion = null) @@ -13,7 +13,7 @@ */ class SecretRepository extends AbstractSecretRepository { - public function __construct(Registry $registry) + public function __construct(ManagerRegistry $registry) { parent::__construct($registry, Secret::class); } From e59f1226fbb862a4b8ef195e6de3605242f1c2be Mon Sep 17 00:00:00 2001 From: r3hp1c Date: Sun, 3 Mar 2024 11:15:31 +0000 Subject: [PATCH 26/44] Fix vendor/bin/phpcs testVarsion to 8.1-8.3 --- composer.json | 2 +- demo/symfony7.x/composer.lock | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index bd52716a..ad62bc5e 100644 --- a/composer.json +++ b/composer.json @@ -36,7 +36,7 @@ "scripts": { "post-install-cmd": "\"vendor/bin/phpcs\" --config-set installed_paths vendor/phpcompatibility/php-compatibility", "post-update-cmd" : "\"vendor/bin/phpcs\" --config-set installed_paths vendor/phpcompatibility/php-compatibility", - "phpcs-compatibility-test" : "vendor/bin/phpcs src/ tests/ --standard=PHPCompatibility --runtime-set testVersion 7.2-8.1" + "phpcs-compatibility-test" : "vendor/bin/phpcs src/ tests/ --standard=PHPCompatibility --runtime-set testVersion 8.1-8.3" }, "autoload-dev": { "psr-4": { diff --git a/demo/symfony7.x/composer.lock b/demo/symfony7.x/composer.lock index 98365be6..ba2d766d 100644 --- a/demo/symfony7.x/composer.lock +++ b/demo/symfony7.x/composer.lock @@ -1141,7 +1141,7 @@ "dist": { "type": "path", "url": "../..", - "reference": "f1fffbb9a191db39c42493bf4f66ae18398a0113" + "reference": "e71725c3d94df5810c1d62520b843cc40bf1da51" }, "require": { "doctrine/doctrine-bundle": "^2.0.8|^2.1", @@ -1186,7 +1186,7 @@ "\"vendor/bin/phpcs\" --config-set installed_paths vendor/phpcompatibility/php-compatibility" ], "phpcs-compatibility-test": [ - "vendor/bin/phpcs src/ tests/ --standard=PHPCompatibility --runtime-set testVersion 7.2-8.1" + "vendor/bin/phpcs src/ tests/ --standard=PHPCompatibility --runtime-set testVersion 8.1-8.3" ] }, "license": [ From a1ca49624119f0cdc3e656504adf077fe9bb86be Mon Sep 17 00:00:00 2001 From: r3hp1c Date: Sun, 3 Mar 2024 11:30:54 +0000 Subject: [PATCH 27/44] Added phpcompatibility/php-compatibility version 8.2 in an attempt to fix the 8.1 lowest error. 'php-compatibility handling the post-update-cmd event returned with error code 255' --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index ad62bc5e..fde27804 100644 --- a/composer.json +++ b/composer.json @@ -19,7 +19,7 @@ "defuse/php-encryption": "^2.1", "doctrine/cache": "^1.11", "phpstan/phpstan": "^1.4", - "phpcompatibility/php-compatibility": "^9.3", + "phpcompatibility/php-compatibility": "^8.2|^9.3", "symfony/phpunit-bridge": "^7.0", "symfony/expression-language": "^5.4|^6.0|^7.0" }, From d1137a8cd0aefca0c0e25e2a2671cc101c9fb50b Mon Sep 17 00:00:00 2001 From: r3hp1c Date: Sun, 3 Mar 2024 11:34:06 +0000 Subject: [PATCH 28/44] 8.1 lowest attempt to fix: 'php-compatibility handling the post-update-cmd event returned with error code 255' --- composer.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index fde27804..0d15192d 100644 --- a/composer.json +++ b/composer.json @@ -19,7 +19,8 @@ "defuse/php-encryption": "^2.1", "doctrine/cache": "^1.11", "phpstan/phpstan": "^1.4", - "phpcompatibility/php-compatibility": "^8.2|^9.3", + "phpcompatibility/php-compatibility": "^9.3", + "squizlabs/php_codesniffer": "^3.8", "symfony/phpunit-bridge": "^7.0", "symfony/expression-language": "^5.4|^6.0|^7.0" }, From c1ef83d099eba7cf55d15557afd3d2395753b773 Mon Sep 17 00:00:00 2001 From: r3hp1c Date: Sun, 3 Mar 2024 12:39:51 +0000 Subject: [PATCH 29/44] Fix 8.1 lowest tests --- .travis.yml | 13 +++++-------- composer.json | 4 ++-- demo/symfony5.4/composer.json | 2 +- demo/symfony6.x/composer.json | 2 +- demo/symfony7.x/composer.json | 2 +- demo/symfony7.x/composer.lock | 9 +++++---- phpunit.xml.dist | 2 +- tests/Functional/AbstractFunctionalTestCase.php | 2 -- 8 files changed, 16 insertions(+), 20 deletions(-) diff --git a/.travis.yml b/.travis.yml index feddc2d9..939918d3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,10 +8,10 @@ matrix: fast_finish: true include: # Minimum supported versions - - php: 7.2 + - php: 8.1 env: COMPOSER_FLAGS="--prefer-lowest" ## with sodium extension installed. - - php: 7.2 + - php: 8.1 env: COMPOSER_FLAGS="--prefer-lowest" before_install: - sudo add-apt-repository ppa:ondrej/php -y @@ -23,17 +23,14 @@ matrix: - printf "\n" | pecl install libsodium - composer update $COMPOSER_FLAGS --prefer-dist --no-interaction - - php: 7.3 + - php: 8.2 env: COVERAGE=true PHPUNIT_FLAGS="-v --coverage-text" - - php: 7.4 - env: COVERAGE=true PHPUNIT_FLAGS="-v --coverage-text" - - - php: 8.0 + - php: 8.3 env: COVERAGE=true PHPUNIT_FLAGS="-v --coverage-text" # Latest commit to master - - php: 7.3 + - php: 8.1 env: STABILITY="dev" allow_failures: diff --git a/composer.json b/composer.json index 0d15192d..004df45e 100644 --- a/composer.json +++ b/composer.json @@ -6,7 +6,7 @@ "description": "Encrypted symfony entity's by verified and standardized libraries", "require": { "php": "^8.1", - "doctrine/orm": "^2.5|^3.0", + "doctrine/orm": "^2.18|^3.0", "doctrine/doctrine-bundle": "^2.0.8|^2.1", "symfony/property-access": "^5.4|^6.0|^7.0", "symfony/dependency-injection": "^5.4|^6.0|^7.0", @@ -21,7 +21,7 @@ "phpstan/phpstan": "^1.4", "phpcompatibility/php-compatibility": "^9.3", "squizlabs/php_codesniffer": "^3.8", - "symfony/phpunit-bridge": "^7.0", + "symfony/phpunit-bridge": "^7.0.4", "symfony/expression-language": "^5.4|^6.0|^7.0" }, "suggest": { diff --git a/demo/symfony5.4/composer.json b/demo/symfony5.4/composer.json index 3f829a5a..f8033590 100644 --- a/demo/symfony5.4/composer.json +++ b/demo/symfony5.4/composer.json @@ -7,7 +7,7 @@ "php": "^8.1", "ext-ctype": "*", "ext-iconv": "*", - "doctrine/orm": "^2.5", + "doctrine/orm": "^2.18", "doctrineencryptbundle/doctrine-encrypt-bundle": "@dev", "doctrine/persistence": "^3.2", "paragonie/halite": "^4.6", diff --git a/demo/symfony6.x/composer.json b/demo/symfony6.x/composer.json index 091bcdd4..2124107b 100644 --- a/demo/symfony6.x/composer.json +++ b/demo/symfony6.x/composer.json @@ -7,7 +7,7 @@ "php": "^8.1", "ext-ctype": "*", "ext-iconv": "*", - "doctrine/orm": "^2.5", + "doctrine/orm": "^2.18", "doctrineencryptbundle/doctrine-encrypt-bundle": "@dev", "doctrine/persistence": "^3.2", "paragonie/halite": "^5.0", diff --git a/demo/symfony7.x/composer.json b/demo/symfony7.x/composer.json index bace50e2..cc0dd74a 100644 --- a/demo/symfony7.x/composer.json +++ b/demo/symfony7.x/composer.json @@ -7,7 +7,7 @@ "php": ">=8.2", "ext-ctype": "*", "ext-iconv": "*", - "doctrine/orm": "^2.5", + "doctrine/orm": "^2.18", "doctrineencryptbundle/doctrine-encrypt-bundle": "@dev", "doctrine/persistence": "^3.2", "paragonie/halite": "^5.0", diff --git a/demo/symfony7.x/composer.lock b/demo/symfony7.x/composer.lock index ba2d766d..4be0ba7b 100644 --- a/demo/symfony7.x/composer.lock +++ b/demo/symfony7.x/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "b607657f8bb963e1502c3194da36fb42", + "content-hash": "e99c69747ede75faeaa5d4d1457999d1", "packages": [ { "name": "doctrine/cache", @@ -1141,11 +1141,11 @@ "dist": { "type": "path", "url": "../..", - "reference": "e71725c3d94df5810c1d62520b843cc40bf1da51" + "reference": "d1137a8cd0aefca0c0e25e2a2671cc101c9fb50b" }, "require": { "doctrine/doctrine-bundle": "^2.0.8|^2.1", - "doctrine/orm": "^2.5|^3.0", + "doctrine/orm": "^2.18|^3.0", "php": "^8.1", "symfony/config": "^5.4|^6.0|^7.0", "symfony/dependency-injection": "^5.4|^6.0|^7.0", @@ -1159,8 +1159,9 @@ "paragonie/halite": "^4.6|^5.0", "phpcompatibility/php-compatibility": "^9.3", "phpstan/phpstan": "^1.4", + "squizlabs/php_codesniffer": "^3.8", "symfony/expression-language": "^5.4|^6.0|^7.0", - "symfony/phpunit-bridge": "^7.0" + "symfony/phpunit-bridge": "^7.0.4" }, "suggest": { "defuse/php-encryption": "Alternative for halite for use with older php-versions", diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 4b72e168..4db01306 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -30,7 +30,7 @@ - + diff --git a/tests/Functional/AbstractFunctionalTestCase.php b/tests/Functional/AbstractFunctionalTestCase.php index 89466342..727174a4 100644 --- a/tests/Functional/AbstractFunctionalTestCase.php +++ b/tests/Functional/AbstractFunctionalTestCase.php @@ -78,8 +78,6 @@ public function setUp(): void $cache, $reportFieldsWhereDeclared ); - $config->setLazyGhostObjectEnabled (true); - $config->setSchemaManagerFactory(new DefaultSchemaManagerFactory()); // obtaining the entity manager $conn = DriverManager::getConnection($connOptions, $config); $dbalConf = $conn->getConfiguration(); From c847ee557321b2c5e011da5a3ed25aeb85f87325 Mon Sep 17 00:00:00 2001 From: r3hp1c Date: Sun, 3 Mar 2024 12:43:38 +0000 Subject: [PATCH 30/44] Symfony 5.4 remove enable_lazy_ghost_objects --- demo/symfony5.4/config/packages/doctrine.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demo/symfony5.4/config/packages/doctrine.yaml b/demo/symfony5.4/config/packages/doctrine.yaml index 56f7e5d9..705b25eb 100644 --- a/demo/symfony5.4/config/packages/doctrine.yaml +++ b/demo/symfony5.4/config/packages/doctrine.yaml @@ -6,7 +6,7 @@ doctrine: # either here or in the DATABASE_URL env var (see .env file) #server_version: '15' orm: - enable_lazy_ghost_objects: true + # enable_lazy_ghost_objects: true auto_generate_proxy_classes: true naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware auto_mapping: true From f41a38012c21ccbf7835f49507d0e36e07293af1 Mon Sep 17 00:00:00 2001 From: r3hp1c Date: Sun, 3 Mar 2024 12:57:52 +0000 Subject: [PATCH 31/44] Add lowest doctrine/annotations 1.18 --- demo/symfony5.4/composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demo/symfony5.4/composer.json b/demo/symfony5.4/composer.json index f8033590..9b92cd33 100644 --- a/demo/symfony5.4/composer.json +++ b/demo/symfony5.4/composer.json @@ -18,7 +18,7 @@ "symfony/runtime": "5.4.*", "symfony/twig-bundle": "5.4.*", "symfony/yaml": "5.4.*", - "doctrine/annotations": "^2.0" + "doctrine/annotations": "^1.18|^2.0" }, "require-dev": { "symfony/phpunit-bridge": "^7.0" From 5a81556a8aca778f0fa4d4b9db81f2fc87dfbc8c Mon Sep 17 00:00:00 2001 From: r3hp1c Date: Sun, 3 Mar 2024 13:32:22 +0000 Subject: [PATCH 32/44] Attempt to fix lowest test error: Attempted to call an undefined method named registerLoader of class DoctrineCommonAnnotationsAnnotationRegistry. --- demo/symfony5.4/composer.json | 2 +- .../src/Repository/Annotation/SecretRepository.php | 11 ++--------- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/demo/symfony5.4/composer.json b/demo/symfony5.4/composer.json index 9b92cd33..f8033590 100644 --- a/demo/symfony5.4/composer.json +++ b/demo/symfony5.4/composer.json @@ -18,7 +18,7 @@ "symfony/runtime": "5.4.*", "symfony/twig-bundle": "5.4.*", "symfony/yaml": "5.4.*", - "doctrine/annotations": "^1.18|^2.0" + "doctrine/annotations": "^2.0" }, "require-dev": { "symfony/phpunit-bridge": "^7.0" diff --git a/demo/symfony5.4/src/Repository/Annotation/SecretRepository.php b/demo/symfony5.4/src/Repository/Annotation/SecretRepository.php index ce2edcc2..51427a94 100644 --- a/demo/symfony5.4/src/Repository/Annotation/SecretRepository.php +++ b/demo/symfony5.4/src/Repository/Annotation/SecretRepository.php @@ -4,14 +4,7 @@ use App\Entity\Annotation\Secret; use App\Repository\AbstractSecretRepository; - -// Alias is needed because of test with both php 7.2, 7.4 and 8.0 -if (!interface_exists('\Doctrine\Common\Persistence\ManagerRegistry')) { - class_alias( - '\Doctrine\Persistence\ManagerRegistry', - '\Doctrine\Common\Persistence\ManagerRegistry' - ); -} +use Doctrine\Persistence\ManagerRegistry; /** * @method Secret|null find($id, $lockMode = null, $lockVersion = null) @@ -20,7 +13,7 @@ class_alias( */ class SecretRepository extends AbstractSecretRepository { - public function __construct(\Doctrine\Common\Persistence\ManagerRegistry $registry) + public function __construct(ManagerRegistry $registry) { parent::__construct($registry, Secret::class); } From f131cc4a4b71d0018ae26ac8a0468b7abe20f741 Mon Sep 17 00:00:00 2001 From: r3hp1c Date: Sun, 3 Mar 2024 13:46:27 +0000 Subject: [PATCH 33/44] Add lowest doctrine/annotations 1.13 --- demo/symfony5.4/composer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/demo/symfony5.4/composer.json b/demo/symfony5.4/composer.json index f8033590..81108556 100644 --- a/demo/symfony5.4/composer.json +++ b/demo/symfony5.4/composer.json @@ -7,7 +7,7 @@ "php": "^8.1", "ext-ctype": "*", "ext-iconv": "*", - "doctrine/orm": "^2.18", + "doctrine/orm": "^2.13", "doctrineencryptbundle/doctrine-encrypt-bundle": "@dev", "doctrine/persistence": "^3.2", "paragonie/halite": "^4.6", @@ -18,7 +18,7 @@ "symfony/runtime": "5.4.*", "symfony/twig-bundle": "5.4.*", "symfony/yaml": "5.4.*", - "doctrine/annotations": "^2.0" + "doctrine/annotations": "^1.13|^2.0" }, "require-dev": { "symfony/phpunit-bridge": "^7.0" From cc4eb766977ba221ee4ed501126c0376917a06c6 Mon Sep 17 00:00:00 2001 From: r3hp1c Date: Sun, 3 Mar 2024 13:49:01 +0000 Subject: [PATCH 34/44] symfony/phpunit-bridge to 7.0.4 --- demo/symfony5.4/composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demo/symfony5.4/composer.json b/demo/symfony5.4/composer.json index 81108556..4e2c09f7 100644 --- a/demo/symfony5.4/composer.json +++ b/demo/symfony5.4/composer.json @@ -21,7 +21,7 @@ "doctrine/annotations": "^1.13|^2.0" }, "require-dev": { - "symfony/phpunit-bridge": "^7.0" + "symfony/phpunit-bridge": "^7.0.4" }, "config": { "allow-plugins": { From f13b8cb14d1aa32bcbf7bdb9af5356fdb1f8245e Mon Sep 17 00:00:00 2001 From: r3hp1c Date: Sun, 3 Mar 2024 13:58:23 +0000 Subject: [PATCH 35/44] symfony flex minimum version 2.2 --- demo/symfony5.4/composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demo/symfony5.4/composer.json b/demo/symfony5.4/composer.json index 4e2c09f7..062aedf3 100644 --- a/demo/symfony5.4/composer.json +++ b/demo/symfony5.4/composer.json @@ -13,7 +13,7 @@ "paragonie/halite": "^4.6", "symfony/console": "5.4.*", "symfony/dotenv": "5.4.*", - "symfony/flex": "^1.21|^2", + "symfony/flex": "^2.2", "symfony/framework-bundle": "5.4.*", "symfony/runtime": "5.4.*", "symfony/twig-bundle": "5.4.*", From 55a080976ca4ffbdbca1d4f868e7137364eeda5c Mon Sep 17 00:00:00 2001 From: r3hp1c Date: Sun, 3 Mar 2024 14:01:01 +0000 Subject: [PATCH 36/44] symfony flex minimum version 2.2 --- demo/symfony6.x/composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demo/symfony6.x/composer.json b/demo/symfony6.x/composer.json index 2124107b..99eaee25 100644 --- a/demo/symfony6.x/composer.json +++ b/demo/symfony6.x/composer.json @@ -13,7 +13,7 @@ "paragonie/halite": "^5.0", "symfony/console": "6.0.*", "symfony/dotenv": "6.0.*", - "symfony/flex": "^2", + "symfony/flex": "^2.2", "symfony/framework-bundle": "6.0.*", "symfony/runtime": "6.0.*", "symfony/twig-bundle": "6.0.*", From 966ba2aa189468c7aa757e51f1fd47f5712b695d Mon Sep 17 00:00:00 2001 From: r3hp1c Date: Sun, 3 Mar 2024 14:04:37 +0000 Subject: [PATCH 37/44] Symfony 6.4 remove enable_lazy_ghost_objects --- demo/symfony6.x/config/packages/doctrine.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demo/symfony6.x/config/packages/doctrine.yaml b/demo/symfony6.x/config/packages/doctrine.yaml index a82625fe..76db7da6 100644 --- a/demo/symfony6.x/config/packages/doctrine.yaml +++ b/demo/symfony6.x/config/packages/doctrine.yaml @@ -6,7 +6,7 @@ doctrine: # either here or in the DATABASE_URL env var (see .env file) #server_version: '13' orm: - enable_lazy_ghost_objects: true + # enable_lazy_ghost_objects: true auto_generate_proxy_classes: true naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware auto_mapping: true From c0e4211082c1dd75c26bb986a9cc810ad4f6a0fe Mon Sep 17 00:00:00 2001 From: r3hp1c Date: Sun, 3 Mar 2024 14:08:57 +0000 Subject: [PATCH 38/44] Updated composer.json versions --- demo/symfony6.x/composer.json | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/demo/symfony6.x/composer.json b/demo/symfony6.x/composer.json index 99eaee25..ccc73c71 100644 --- a/demo/symfony6.x/composer.json +++ b/demo/symfony6.x/composer.json @@ -7,21 +7,21 @@ "php": "^8.1", "ext-ctype": "*", "ext-iconv": "*", - "doctrine/orm": "^2.18", + "doctrine/orm": "^2.13", "doctrineencryptbundle/doctrine-encrypt-bundle": "@dev", "doctrine/persistence": "^3.2", "paragonie/halite": "^5.0", - "symfony/console": "6.0.*", - "symfony/dotenv": "6.0.*", + "symfony/console": "6.4.*", + "symfony/dotenv": "6.4.*", "symfony/flex": "^2.2", - "symfony/framework-bundle": "6.0.*", - "symfony/runtime": "6.0.*", - "symfony/twig-bundle": "6.0.*", - "doctrine/annotations": "^2.0" + "symfony/framework-bundle": "6.4.*", + "symfony/runtime": "6.4.*", + "symfony/twig-bundle": "6.4.*", + "symfony/yaml": "6.4.*", + "doctrine/annotations": "^1.13|^2.0" }, "require-dev": { - "symfony/maker-bundle": "^1.0", - "symfony/phpunit-bridge": "^7.0" + "symfony/phpunit-bridge": "^7.0.4" }, "config": { "allow-plugins": { @@ -71,7 +71,7 @@ "extra": { "symfony": { "allow-contrib": false, - "require": "6.0.*" + "require": "6.4.*" } }, "repositories": [ From 75a63e1192f968173c0b5aab81219765e82bc244 Mon Sep 17 00:00:00 2001 From: r3hp1c Date: Sun, 3 Mar 2024 14:12:51 +0000 Subject: [PATCH 39/44] added maker bundle back --- demo/symfony5.4/composer.json | 1 + 1 file changed, 1 insertion(+) diff --git a/demo/symfony5.4/composer.json b/demo/symfony5.4/composer.json index 062aedf3..a051ba58 100644 --- a/demo/symfony5.4/composer.json +++ b/demo/symfony5.4/composer.json @@ -21,6 +21,7 @@ "doctrine/annotations": "^1.13|^2.0" }, "require-dev": { + "symfony/maker-bundle": "^1.0", "symfony/phpunit-bridge": "^7.0.4" }, "config": { From e02069f06032faac38ab8ef9a4f0b834b3c4fe66 Mon Sep 17 00:00:00 2001 From: r3hp1c Date: Sun, 3 Mar 2024 14:16:52 +0000 Subject: [PATCH 40/44] symfony 7.x phpunit.xml.dist for symfony 6.x --- demo/symfony6.x/phpunit.xml.dist | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/demo/symfony6.x/phpunit.xml.dist b/demo/symfony6.x/phpunit.xml.dist index af3f1474..61f479af 100644 --- a/demo/symfony6.x/phpunit.xml.dist +++ b/demo/symfony6.x/phpunit.xml.dist @@ -6,7 +6,6 @@ backupGlobals="false" colors="true" bootstrap="tests/bootstrap.php" - convertDeprecationsToExceptions="false" > @@ -23,20 +22,8 @@ - - - src - + - - - - - - - From 29e2c8a54c09a0fa504ee24c208f7761154c5005 Mon Sep 17 00:00:00 2001 From: r3hp1c Date: Sun, 3 Mar 2024 14:18:27 +0000 Subject: [PATCH 41/44] Moved maker-bundle to the symfony 6.x composer.json --- demo/symfony5.4/composer.json | 1 - demo/symfony6.x/composer.json | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/demo/symfony5.4/composer.json b/demo/symfony5.4/composer.json index a051ba58..062aedf3 100644 --- a/demo/symfony5.4/composer.json +++ b/demo/symfony5.4/composer.json @@ -21,7 +21,6 @@ "doctrine/annotations": "^1.13|^2.0" }, "require-dev": { - "symfony/maker-bundle": "^1.0", "symfony/phpunit-bridge": "^7.0.4" }, "config": { diff --git a/demo/symfony6.x/composer.json b/demo/symfony6.x/composer.json index ccc73c71..d0c7d3bc 100644 --- a/demo/symfony6.x/composer.json +++ b/demo/symfony6.x/composer.json @@ -21,6 +21,7 @@ "doctrine/annotations": "^1.13|^2.0" }, "require-dev": { + "symfony/maker-bundle": "^1.0", "symfony/phpunit-bridge": "^7.0.4" }, "config": { From 8ac43bb0d9af62d0bf9c5fac00b513498cc68945 Mon Sep 17 00:00:00 2001 From: r3hp1c Date: Sun, 3 Mar 2024 14:38:19 +0000 Subject: [PATCH 42/44] symfony 5.x phpunit.xml.dist for symfony 6.x --- demo/symfony6.x/phpunit.xml.dist | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/demo/symfony6.x/phpunit.xml.dist b/demo/symfony6.x/phpunit.xml.dist index 61f479af..01574f0e 100644 --- a/demo/symfony6.x/phpunit.xml.dist +++ b/demo/symfony6.x/phpunit.xml.dist @@ -6,6 +6,7 @@ backupGlobals="false" colors="true" bootstrap="tests/bootstrap.php" + convertDeprecationsToExceptions="false" > @@ -13,7 +14,6 @@ - @@ -22,8 +22,16 @@ - + + + src + + + + + + + + From 7dd62a6027fd2ea8028d025bf4cabdb8d2146a61 Mon Sep 17 00:00:00 2001 From: r3hp1c Date: Sun, 3 Mar 2024 14:47:46 +0000 Subject: [PATCH 43/44] Set KERNEL_CLASS --- demo/symfony6.x/phpunit.xml.dist | 1 + demo/symfony7.x/phpunit.xml.dist | 1 + 2 files changed, 2 insertions(+) diff --git a/demo/symfony6.x/phpunit.xml.dist b/demo/symfony6.x/phpunit.xml.dist index 01574f0e..875a9706 100644 --- a/demo/symfony6.x/phpunit.xml.dist +++ b/demo/symfony6.x/phpunit.xml.dist @@ -11,6 +11,7 @@ + diff --git a/demo/symfony7.x/phpunit.xml.dist b/demo/symfony7.x/phpunit.xml.dist index 61f479af..ba1bd023 100644 --- a/demo/symfony7.x/phpunit.xml.dist +++ b/demo/symfony7.x/phpunit.xml.dist @@ -10,6 +10,7 @@ + From baa82b4e5978cbe5d4cb60208c2045b9639e7abd Mon Sep 17 00:00:00 2001 From: r3hp1c Date: Sun, 3 Mar 2024 15:08:38 +0000 Subject: [PATCH 44/44] symfony/flex to version 2.3 for symfony 6.x --- demo/symfony6.x/composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demo/symfony6.x/composer.json b/demo/symfony6.x/composer.json index d0c7d3bc..5c507435 100644 --- a/demo/symfony6.x/composer.json +++ b/demo/symfony6.x/composer.json @@ -13,7 +13,7 @@ "paragonie/halite": "^5.0", "symfony/console": "6.4.*", "symfony/dotenv": "6.4.*", - "symfony/flex": "^2.2", + "symfony/flex": "^2.3", "symfony/framework-bundle": "6.4.*", "symfony/runtime": "6.4.*", "symfony/twig-bundle": "6.4.*",