From dabd99539e39adf6271c264c8bfbb92d318e4116 Mon Sep 17 00:00:00 2001
From: Michael Babker <michael@happydog.digital>
Date: Tue, 19 Mar 2024 08:56:10 -0400
Subject: [PATCH 1/4] Add a test build with doctrine/annotations uninstalled

---
 .github/workflows/continuous-integration.yml      | 15 ++++++++++++++-
 .../Mapping/Fixture/Unmapped/Timestampable.php    |  1 +
 .../Mapping/MetadataFactory/CustomDriverTest.php  | 10 +++++++++-
 tests/Gedmo/Mapping/ORMMappingTestCase.php        |  2 +-
 tests/bootstrap.php                               |  6 +++---
 5 files changed, 28 insertions(+), 6 deletions(-)

diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml
index a41da06561..e891bdfd34 100644
--- a/.github/workflows/continuous-integration.yml
+++ b/.github/workflows/continuous-integration.yml
@@ -11,7 +11,7 @@ env:
 
 jobs:
   phpunit:
-    name: "PHPUnit ${{ matrix.php-version }} (${{ matrix.deps }})"
+    name: "PHPUnit ${{ matrix.php-version }} (${{ matrix.deps }})${{ matrix.no-annotations == true && ' - Without Annotations' || '' }}"
     runs-on: "ubuntu-20.04"
 
     services:
@@ -30,11 +30,19 @@ jobs:
           - "8.3"
         deps:
           - "highest"
+        no-annotations:
+          - false
         include:
           - deps: "lowest"
             php-version: "7.4"
           - deps: "highest"
             php-version: "8.3"
+          - deps: "highest"
+            php-version: "7.4"
+            no-annotations: true
+          - deps: "highest"
+            php-version: "8.3"
+            no-annotations: true
 
     steps:
       - name: "Checkout"
@@ -53,6 +61,11 @@ jobs:
       - name: "Remove PHP-CS-Fixer"
         run: "composer remove --dev --no-update friendsofphp/php-cs-fixer"
 
+      # Remove doctrine/annotations if configured to do so
+      - name: "Remove doctrine/annotations"
+        if: "${{ matrix.no-annotations }}"
+        run: "composer remove --dev --no-update doctrine/annotations"
+
       - name: "Install dependencies with Composer"
         uses: "ramsey/composer-install@v3"
         with:
diff --git a/tests/Gedmo/Mapping/Fixture/Unmapped/Timestampable.php b/tests/Gedmo/Mapping/Fixture/Unmapped/Timestampable.php
index 5128ee4d97..08f921f5db 100644
--- a/tests/Gedmo/Mapping/Fixture/Unmapped/Timestampable.php
+++ b/tests/Gedmo/Mapping/Fixture/Unmapped/Timestampable.php
@@ -25,5 +25,6 @@ class Timestampable
      *
      * @Tmsp(on="create")
      */
+    #[Tmsp(on: 'create')]
     private $created;
 }
diff --git a/tests/Gedmo/Mapping/MetadataFactory/CustomDriverTest.php b/tests/Gedmo/Mapping/MetadataFactory/CustomDriverTest.php
index 00301821b3..024101d135 100644
--- a/tests/Gedmo/Mapping/MetadataFactory/CustomDriverTest.php
+++ b/tests/Gedmo/Mapping/MetadataFactory/CustomDriverTest.php
@@ -11,6 +11,7 @@
 
 namespace Gedmo\Tests\Mapping\MetadataFactory;
 
+use Doctrine\Common\Annotations\AnnotationReader;
 use Doctrine\Common\EventManager;
 use Doctrine\DBAL\DriverManager;
 use Doctrine\ORM\Configuration;
@@ -19,6 +20,7 @@
 use Doctrine\ORM\Tools\SchemaTool;
 use Doctrine\Persistence\Mapping\ClassMetadata;
 use Doctrine\Persistence\Mapping\Driver\MappingDriver;
+use Gedmo\Mapping\Driver\AttributeReader;
 use Gedmo\Tests\Mapping\Fixture\Unmapped\Timestampable;
 use Gedmo\Timestampable\TimestampableListener;
 use PHPUnit\Framework\TestCase;
@@ -48,7 +50,13 @@ protected function setUp(): void
 
         $evm = new EventManager();
         $this->timestampable = new TimestampableListener();
-        $this->timestampable->setAnnotationReader($_ENV['annotation_reader']);
+
+        if (PHP_VERSION >= 80000) {
+            $this->timestampable->setAnnotationReader(new AttributeReader());
+        } elseif (class_exists(AnnotationReader::class)) {
+            $this->timestampable->setAnnotationReader($_ENV['annotation_reader']);
+        }
+
         $evm->addEventSubscriber($this->timestampable);
         $connection = DriverManager::getConnection($conn, $config);
         $this->em = new EntityManager($connection, $config, $evm);
diff --git a/tests/Gedmo/Mapping/ORMMappingTestCase.php b/tests/Gedmo/Mapping/ORMMappingTestCase.php
index 661e0275b1..021b6b3f22 100644
--- a/tests/Gedmo/Mapping/ORMMappingTestCase.php
+++ b/tests/Gedmo/Mapping/ORMMappingTestCase.php
@@ -78,7 +78,7 @@ final protected function createChainedMappingDriver(): MappingDriverChain
             $chain->addDriver(new AttributeDriver([]), 'Gedmo\Tests\Mapping\Fixture');
         }
 
-        if (class_exists(AnnotationDriver::class)) {
+        if (class_exists(AnnotationDriver::class) && class_exists(AnnotationReader::class)) {
             $chain->addDriver(new AnnotationDriver(new AnnotationReader()), 'Gedmo\Tests\Mapping\Fixture');
         }
 
diff --git a/tests/bootstrap.php b/tests/bootstrap.php
index 090f0e32f0..d378c5158b 100644
--- a/tests/bootstrap.php
+++ b/tests/bootstrap.php
@@ -29,8 +29,8 @@
 
 require dirname(__DIR__).'/vendor/autoload.php';
 
-$reader = new AnnotationReader();
-$reader = new PsrCachedReader($reader, new ArrayAdapter());
-$_ENV['annotation_reader'] = $reader;
+if (class_exists(AnnotationReader::class)) {
+    $_ENV['annotation_reader'] = new PsrCachedReader(new AnnotationReader(), new ArrayAdapter());
+}
 
 Type::addType('uuid', UuidType::class);

From b27b0c05e5d3db848ddc14cca6ca76bb51e848b2 Mon Sep 17 00:00:00 2001
From: Michael Babker <michael@happydog.digital>
Date: Mon, 19 Feb 2024 18:38:18 -0500
Subject: [PATCH 2/4] Update tests to only register either the annotation or
 attribute driver to avoid unintended overwrites due to namespaces

---
 tests/Gedmo/Mapping/LoggableORMMappingTest.php   | 16 ++++------------
 tests/Gedmo/Mapping/ORMMappingTestCase.php       |  4 +---
 tests/Gedmo/Mapping/SluggableMappingTest.php     |  4 +---
 .../Gedmo/Mapping/SoftDeleteableMappingTest.php  |  4 +---
 tests/Gedmo/Mapping/SortableMappingTest.php      |  4 +---
 tests/Gedmo/Mapping/TimestampableMappingTest.php |  4 +---
 tests/Gedmo/Mapping/TranslatableMappingTest.php  |  4 +---
 tests/Gedmo/Mapping/UploadableMappingTest.php    |  4 +---
 .../Gedmo/Timestampable/AttributeChangeTest.php  |  2 ++
 9 files changed, 13 insertions(+), 33 deletions(-)

diff --git a/tests/Gedmo/Mapping/LoggableORMMappingTest.php b/tests/Gedmo/Mapping/LoggableORMMappingTest.php
index 07fd5bf87f..f2d07801e2 100644
--- a/tests/Gedmo/Mapping/LoggableORMMappingTest.php
+++ b/tests/Gedmo/Mapping/LoggableORMMappingTest.php
@@ -59,9 +59,7 @@ public static function dataLoggableObject(): \Generator
     {
         if (PHP_VERSION_ID >= 80000) {
             yield 'Model with attributes' => [AnnotatedLoggable::class];
-        }
-
-        if (class_exists(AnnotationDriver::class)) {
+        } elseif (class_exists(AnnotationDriver::class)) {
             yield 'Model with annotations' => [AnnotatedLoggable::class];
         }
 
@@ -121,9 +119,7 @@ public static function dataLoggableObjectWithCompositeKey(): \Generator
 
         if (PHP_VERSION_ID >= 80000) {
             yield 'Model with attributes' => [AnnotatedLoggableComposite::class];
-        }
-
-        if (class_exists(AnnotationDriver::class)) {
+        } elseif (class_exists(AnnotationDriver::class)) {
             yield 'Model with annotations' => [AnnotatedLoggableComposite::class];
         }
 
@@ -166,9 +162,7 @@ public static function dataLoggableObjectWithCompositeKeyAndRelation(): \Generat
 
         if (PHP_VERSION_ID >= 80000) {
             yield 'Model with attributes' => [AnnotatedLoggableCompositeRelation::class];
-        }
-
-        if (class_exists(AnnotationDriver::class)) {
+        } elseif (class_exists(AnnotationDriver::class)) {
             yield 'Model with annotations' => [AnnotatedLoggableCompositeRelation::class];
         }
 
@@ -214,9 +208,7 @@ public static function dataLoggableObjectWithEmbedded(): \Generator
     {
         if (PHP_VERSION_ID >= 80000) {
             yield 'Model with attributes' => [AnnotatedLoggableWithEmbedded::class];
-        }
-
-        if (class_exists(AnnotationDriver::class)) {
+        } elseif (class_exists(AnnotationDriver::class)) {
             yield 'Model with annotations' => [AnnotatedLoggableWithEmbedded::class];
         }
     }
diff --git a/tests/Gedmo/Mapping/ORMMappingTestCase.php b/tests/Gedmo/Mapping/ORMMappingTestCase.php
index 021b6b3f22..cbccbd3896 100644
--- a/tests/Gedmo/Mapping/ORMMappingTestCase.php
+++ b/tests/Gedmo/Mapping/ORMMappingTestCase.php
@@ -76,9 +76,7 @@ final protected function createChainedMappingDriver(): MappingDriverChain
 
         if (PHP_VERSION_ID >= 80000) {
             $chain->addDriver(new AttributeDriver([]), 'Gedmo\Tests\Mapping\Fixture');
-        }
-
-        if (class_exists(AnnotationDriver::class) && class_exists(AnnotationReader::class)) {
+        } elseif (class_exists(AnnotationDriver::class) && class_exists(AnnotationReader::class)) {
             $chain->addDriver(new AnnotationDriver(new AnnotationReader()), 'Gedmo\Tests\Mapping\Fixture');
         }
 
diff --git a/tests/Gedmo/Mapping/SluggableMappingTest.php b/tests/Gedmo/Mapping/SluggableMappingTest.php
index 12ea9576f5..9b9ad8cce6 100644
--- a/tests/Gedmo/Mapping/SluggableMappingTest.php
+++ b/tests/Gedmo/Mapping/SluggableMappingTest.php
@@ -51,9 +51,7 @@ public static function dataSluggableObject(): \Generator
 
         if (PHP_VERSION_ID >= 80000) {
             yield 'Model with attributes' => [AnnotatedSluggable::class];
-        }
-
-        if (class_exists(AnnotationDriver::class)) {
+        } elseif (class_exists(AnnotationDriver::class)) {
             yield 'Model with annotations' => [AnnotatedSluggable::class];
         }
     }
diff --git a/tests/Gedmo/Mapping/SoftDeleteableMappingTest.php b/tests/Gedmo/Mapping/SoftDeleteableMappingTest.php
index 914e1528c5..0b868de5c2 100644
--- a/tests/Gedmo/Mapping/SoftDeleteableMappingTest.php
+++ b/tests/Gedmo/Mapping/SoftDeleteableMappingTest.php
@@ -50,9 +50,7 @@ public static function dataSoftDeleteableObject(): \Generator
 
         if (PHP_VERSION_ID >= 80000) {
             yield 'Model with attributes' => [AnnotatedSoftDeleteable::class];
-        }
-
-        if (class_exists(AnnotationDriver::class)) {
+        } elseif (class_exists(AnnotationDriver::class)) {
             yield 'Model with annotations' => [AnnotatedSoftDeleteable::class];
         }
 
diff --git a/tests/Gedmo/Mapping/SortableMappingTest.php b/tests/Gedmo/Mapping/SortableMappingTest.php
index 63a77c792b..f95c8150f9 100644
--- a/tests/Gedmo/Mapping/SortableMappingTest.php
+++ b/tests/Gedmo/Mapping/SortableMappingTest.php
@@ -49,9 +49,7 @@ public static function dataSortableObject(): \Generator
 
         if (PHP_VERSION_ID >= 80000) {
             yield 'Model with attributes' => [AnnotatedSortable::class];
-        }
-
-        if (class_exists(AnnotationDriver::class)) {
+        } elseif (class_exists(AnnotationDriver::class)) {
             yield 'Model with annotations' => [AnnotatedSortable::class];
         }
 
diff --git a/tests/Gedmo/Mapping/TimestampableMappingTest.php b/tests/Gedmo/Mapping/TimestampableMappingTest.php
index 2922652f35..91c3ec1d89 100644
--- a/tests/Gedmo/Mapping/TimestampableMappingTest.php
+++ b/tests/Gedmo/Mapping/TimestampableMappingTest.php
@@ -49,9 +49,7 @@ public static function dataTimestampableObject(): \Generator
     {
         if (PHP_VERSION_ID >= 80000) {
             yield 'Model with attributes' => [AnnotatedCategory::class];
-        }
-
-        if (class_exists(AnnotationDriver::class)) {
+        } elseif (class_exists(AnnotationDriver::class)) {
             yield 'Model with annotations' => [AnnotatedCategory::class];
         }
 
diff --git a/tests/Gedmo/Mapping/TranslatableMappingTest.php b/tests/Gedmo/Mapping/TranslatableMappingTest.php
index f63ed3cc88..4edec0a40e 100644
--- a/tests/Gedmo/Mapping/TranslatableMappingTest.php
+++ b/tests/Gedmo/Mapping/TranslatableMappingTest.php
@@ -51,9 +51,7 @@ public static function dataSortableObject(): \Generator
 
         if (PHP_VERSION_ID >= 80000) {
             yield 'Model with attributes' => [AnnotatedUser::class];
-        }
-
-        if (class_exists(AnnotationDriver::class)) {
+        } elseif (class_exists(AnnotationDriver::class)) {
             yield 'Model with annotations' => [AnnotatedUser::class];
         }
 
diff --git a/tests/Gedmo/Mapping/UploadableMappingTest.php b/tests/Gedmo/Mapping/UploadableMappingTest.php
index fb60c483dd..e76d13a6f0 100644
--- a/tests/Gedmo/Mapping/UploadableMappingTest.php
+++ b/tests/Gedmo/Mapping/UploadableMappingTest.php
@@ -54,9 +54,7 @@ public static function dataUploadableObject(): \Generator
 
         if (PHP_VERSION_ID >= 80000) {
             yield 'Model with attributes' => [AnnotatedUploadable::class];
-        }
-
-        if (class_exists(AnnotationDriver::class)) {
+        } elseif (class_exists(AnnotationDriver::class)) {
             yield 'Model with annotations' => [AnnotatedUploadable::class];
         }
 
diff --git a/tests/Gedmo/Timestampable/AttributeChangeTest.php b/tests/Gedmo/Timestampable/AttributeChangeTest.php
index c2c260d61a..261a2038dd 100644
--- a/tests/Gedmo/Timestampable/AttributeChangeTest.php
+++ b/tests/Gedmo/Timestampable/AttributeChangeTest.php
@@ -25,6 +25,8 @@
  * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
  *
  * @requires PHP >= 8.0
+ *
+ * @todo This test requires {@see ChangeTest} to have been run first to load the {@see TimestampableListenerStub}
  */
 final class AttributeChangeTest extends BaseTestCaseORM
 {

From ea4213284871f4a35420ce9554639f177d95a469 Mon Sep 17 00:00:00 2001
From: Michael Babker <michael@happydog.digital>
Date: Tue, 19 Mar 2024 09:08:38 -0400
Subject: [PATCH 3/4] Don't fail fast to let all jobs run

---
 .github/workflows/continuous-integration.yml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml
index e891bdfd34..e20efb8153 100644
--- a/.github/workflows/continuous-integration.yml
+++ b/.github/workflows/continuous-integration.yml
@@ -21,6 +21,7 @@ jobs:
           - 27017:27017
 
     strategy:
+      fail-fast: false
       matrix:
         php-version:
           - "7.4"

From 9837dfd2ec0446d75b05c63785cdac6f44e07bbb Mon Sep 17 00:00:00 2001
From: Michael Babker <michael@happydog.digital>
Date: Tue, 19 Mar 2024 09:17:50 -0400
Subject: [PATCH 4/4] Need new coverage artifact names for no-annotations
 builds

---
 .github/workflows/continuous-integration.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml
index e20efb8153..04df4aac47 100644
--- a/.github/workflows/continuous-integration.yml
+++ b/.github/workflows/continuous-integration.yml
@@ -78,7 +78,7 @@ jobs:
       - name: "Upload coverage file"
         uses: "actions/upload-artifact@v4"
         with:
-          name: "${{ github.job }}-${{ matrix.php-version }}-${{ matrix.deps }}-coverage"
+          name: "${{ github.job }}-${{ matrix.php-version }}-${{ matrix.deps }}-${{ matrix.no-annotations == true && 'no-annotations' || 'with-annotations' }}-coverage"
           path: "coverage.xml"
 
   lint-doctrine-xml-schema: