diff --git a/.github/workflows/backend-ci.yaml b/.github/workflows/backend-ci.yaml index 780c1ecb70..bf92458b4e 100644 --- a/.github/workflows/backend-ci.yaml +++ b/.github/workflows/backend-ci.yaml @@ -1,10 +1,11 @@ -name: CI +name: Backend CI on: push: branches: - '[0-9]+.[0-9]+' pull_request: ~ + workflow_dispatch: ~ jobs: cs-fix: @@ -19,13 +20,17 @@ jobs: - uses: ibexa/gh-workflows/actions/composer-install@main with: + php-version: ${{ matrix.php }} gh-client-id: ${{ secrets.AUTOMATION_CLIENT_ID }} gh-client-secret: ${{ secrets.AUTOMATION_CLIENT_SECRET }} satis-network-key: ${{ secrets.SATIS_NETWORK_KEY }} satis-network-token: ${{ secrets.SATIS_NETWORK_TOKEN }} - name: Run code style check - run: composer run-script check-cs -- --format=checkstyle | cs2pr + shell: bash + run: | + set -euo pipefail + composer run-script check-cs -- --format=checkstyle | cs2pr tests: name: Unit tests & SQLite integration tests @@ -44,6 +49,7 @@ jobs: - uses: ibexa/gh-workflows/actions/composer-install@main with: + php-version: ${{ matrix.php }} gh-client-id: ${{ secrets.AUTOMATION_CLIENT_ID }} gh-client-secret: ${{ secrets.AUTOMATION_CLIENT_SECRET }} satis-network-key: ${{ secrets.SATIS_NETWORK_KEY }} @@ -96,6 +102,7 @@ jobs: - uses: ibexa/gh-workflows/actions/composer-install@main with: + php-version: ${{ matrix.php }} gh-client-id: ${{ secrets.AUTOMATION_CLIENT_ID }} gh-client-secret: ${{ secrets.AUTOMATION_CLIENT_SECRET }} satis-network-key: ${{ secrets.SATIS_NETWORK_KEY }} @@ -148,6 +155,7 @@ jobs: - uses: ibexa/gh-workflows/actions/composer-install@main with: + php-version: ${{ matrix.php }} gh-client-id: ${{ secrets.AUTOMATION_CLIENT_ID }} gh-client-secret: ${{ secrets.AUTOMATION_CLIENT_SECRET }} satis-network-key: ${{ secrets.SATIS_NETWORK_KEY }} @@ -210,6 +218,7 @@ jobs: - name: Install Composer dependencies uses: ibexa/gh-workflows/actions/composer-install@main with: + php-version: ${{ matrix.php }} gh-client-id: ${{ secrets.AUTOMATION_CLIENT_ID }} gh-client-secret: ${{ secrets.AUTOMATION_CLIENT_SECRET }} satis-network-key: ${{ secrets.SATIS_NETWORK_KEY }} diff --git a/.github/workflows/gha-docker-solr.yaml b/.github/workflows/gha-docker-solr.yaml index f045fdf60f..525e7d61d1 100644 --- a/.github/workflows/gha-docker-solr.yaml +++ b/.github/workflows/gha-docker-solr.yaml @@ -66,7 +66,7 @@ jobs: CORES_SETUP: single - name: Log in to the Container registry - uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0 + uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0 with: registry: ghcr.io username: ${{ github.actor }} diff --git a/.github/workflows/rector.yaml b/.github/workflows/rector.yaml index 0d77808e71..6714134f5c 100644 --- a/.github/workflows/rector.yaml +++ b/.github/workflows/rector.yaml @@ -8,7 +8,10 @@ on: jobs: rector: + name: Run rector uses: ibexa/gh-workflows/.github/workflows/rector.yml@main + with: + php-version: '8.3' secrets: AUTOMATION_CLIENT_ID: ${{ secrets.AUTOMATION_CLIENT_ID }} AUTOMATION_CLIENT_SECRET: ${{ secrets.AUTOMATION_CLIENT_SECRET }} diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 7803cab242..976a6228b7 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -13,6 +13,13 @@ parameters: ignoreErrors: - message: "#^Cannot call method warning\\(\\) on Psr\\\\Log\\\\LoggerInterface\\|null\\.$#" + - + # ObjectManager::find() declares 2 parameters, but the runtime EntityManager + # supports $lockMode and $lockVersion, forwarded like Doctrine\ORM\Decorator\EntityManagerDecorator does + message: '#^Method Doctrine\\Persistence\\ObjectManager\:\:find\(\) invoked with 4 parameters, 2 required\.$#' + identifier: arguments.count + count: 1 + path: src/lib/Persistence/Doctrine/SiteAccessAwareEntityManager.php paths: - src - tests diff --git a/src/lib/Persistence/Doctrine/SiteAccessAwareEntityManager.php b/src/lib/Persistence/Doctrine/SiteAccessAwareEntityManager.php index 1cc0951fb2..12f3a44337 100644 --- a/src/lib/Persistence/Doctrine/SiteAccessAwareEntityManager.php +++ b/src/lib/Persistence/Doctrine/SiteAccessAwareEntityManager.php @@ -224,9 +224,22 @@ public function getCache(): ?Cache return $this->getWrapped()->getCache(); } - public function find($className, $id): ?object + /** + * @template T of object + * + * @phpstan-param class-string $className + * @phpstan-param \Doctrine\DBAL\LockMode::*|null $lockMode + * + * @param string $className + * @param mixed $id + * @param int|null $lockMode + * @param int|null $lockVersion + * + * @return T|null + */ + public function find($className, $id, ?int $lockMode = null, ?int $lockVersion = null): ?object { - return $this->getWrapped()->find($className, $id); + return $this->getWrapped()->find($className, $id, $lockMode, $lockVersion); } public function persist(object $object): void diff --git a/tests/lib/Persistence/Doctrine/SiteAccessAwareEntityManagerTest.php b/tests/lib/Persistence/Doctrine/SiteAccessAwareEntityManagerTest.php new file mode 100644 index 0000000000..6f00195cf6 --- /dev/null +++ b/tests/lib/Persistence/Doctrine/SiteAccessAwareEntityManagerTest.php @@ -0,0 +1,68 @@ +wrappedEntityManager = $this->createMock(EntityManagerInterface::class); + + $entityManagerFactory = $this->createMock(EntityManagerFactory::class); + $entityManagerFactory + ->method('getEntityManager') + ->willReturn($this->wrappedEntityManager); + + $this->entityManager = new SiteAccessAwareEntityManager($entityManagerFactory); + } + + public function testFindForwardsLockModeAndLockVersion(): void + { + $entity = new stdClass(); + + $this->wrappedEntityManager + ->expects(self::once()) + ->method('find') + ->with(stdClass::class, 1, LockMode::PESSIMISTIC_WRITE, 2) + ->willReturn($entity); + + self::assertSame( + $entity, + $this->entityManager->find(stdClass::class, 1, LockMode::PESSIMISTIC_WRITE, 2) + ); + } + + public function testFindWithoutLockArgumentsForwardsNullDefaults(): void + { + $entity = new stdClass(); + + $this->wrappedEntityManager + ->expects(self::once()) + ->method('find') + ->with(stdClass::class, 1, null, null) + ->willReturn($entity); + + self::assertSame( + $entity, + $this->entityManager->find(stdClass::class, 1) + ); + } +}