Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
vendor
composer.lock
.phpcs-cache
tests/_support/project/config/reference.php
tests/_support/project/public/files/*
!tests/_support/project/public/files/.gitkeep
tests/_support/project/var/cache/*
Expand Down
5 changes: 3 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
"codeception/module-doctrine": "^3.1",
"codeception/module-symfony": "*",
"doctrine/dbal": "^3.4|^4.0",
"doctrine/doctrine-bundle": "^2.4",
"doctrine/doctrine-bundle": "^2.4|^3.0",
"doctrine/lexer": "^1.2|^2.0|^3.0",
"doctrine/orm": "^2.13|^3.0",
"doctrine/persistence": "^2.0|^3.0|^4.0",
Expand All @@ -44,7 +44,7 @@
"phpstan/phpstan": "^2.1.46",
"phpstan/phpstan-beberlei-assert": "^2.0",
"phpstan/phpstan-phpunit": "^2.0",
"phpunit/phpunit": "^9.5",
"phpunit/phpunit": "^10.0",
"psr/http-client": "^1.0",
"squizlabs/php_codesniffer": "^4.0",
"symfony/asset": "^4.4.30|^5.4|^6.0|^7.0",
Expand All @@ -69,6 +69,7 @@
"twig/twig": "^3.7"
},
"conflict": {
"doctrine/collections": "<1.7",
"doctrine/persistence": "<2.0",
"symfony/property-info": ">=8.0"
},
Expand Down
13 changes: 4 additions & 9 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ parameters:
- src
- tests
inferPrivatePropertyTypeFromConstructor: true
reportUnmatchedIgnoredErrors: false
excludePaths:
- 'tests/_support/_generated'
- 'tests/_support/project/var'
Expand All @@ -18,36 +19,30 @@ parameters:
-
message: '#^Parameter \#1 \$errors of method Tests\\FSi\\App\\Controller\\[a-zA-z]{1,}Controller::formErrorsToMessage\(\).{1,}$#'
path: 'tests/_support/project/src/Controller'
reportUnmatched: false
-
message: '#^PHPDoc tag \@param for parameter \$event contains generic type Doctrine\\Persistence\\Event\\LifecycleEventArgs<Doctrine\\Persistence\\ObjectManager> but class Doctrine\\Persistence\\Event\\LifecycleEventArgs is not generic\.$#'
path: 'src/Integration/Doctrine/ORM/Subscriber/EntitySubscriber.php'
reportUnmatched: false
-
message: '#^Call to an undefined method Doctrine\\ORM\\Event\\\w+::getEntityManager\(\)\.$#'
path: 'src/Integration/Doctrine/ORM/Subscriber/EntitySubscriber.php'
reportUnmatched: false
-
message: '#^Call to function method_exists\(\) with Doctrine\\ORM\\Event\\\w+ and ''getObjectManager'' will always evaluate to true\.$#'
path: 'src/Integration/Doctrine/ORM/Subscriber/EntitySubscriber.php'
reportUnmatched: false
-
message: '#^Call to an undefined method ReflectionClass\<object\>::\w+\(\)\.$#'
path: 'src/Integration/Doctrine/ORM/Subscriber/EntitySubscriber.php'
-
message: '#.*Symfony\\Component\\Routing\\RouteCollectionBuilder.*#'
path: '%currentWorkingDirectory%/tests/_support/project/src/Kernel.php'
reportUnmatched: false
-
message: '#Doctrine\\ORM\\Mapping\\EmbeddedClassMapping( not found)?#'
path: '%currentWorkingDirectory%/src/Integration/Doctrine/ORM/Entity/EmptyEmbeddableVerifier.php'
reportUnmatched: false
-
identifier: 'trait.unused'
path: '%currentWorkingDirectory%/src/Integration/Doctrine/ORM/ProxyTrait.php'
reportUnmatched: false
-
identifier: 'property.unusedType'
path: 'tests/_support/project/src/Entity'
reportUnmatched: false
-
identifier: 'arrayValues.list'
path: 'tests/_support/Module/DbModule.php'
reportUnmatched: false
8 changes: 8 additions & 0 deletions src/Integration/Doctrine/ORM/Subscriber/EntitySubscriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,15 @@
use FSi\Component\Translatable\Entity\TranslationLoader;
use FSi\Component\Translatable\Entity\TranslationUpdater;
use FSi\Component\Translatable\LocaleProvider;
use ReflectionClass;

use function array_walk;
use function get_class;
use function in_array;
use function method_exists;

use const PHP_VERSION_ID;

final class EntitySubscriber
{
private LocaleProvider $localeProvider;
Expand Down Expand Up @@ -233,6 +236,11 @@ private function initializeProxy(object $object): void
{
if (true === $object instanceof Proxy && false === $object->__isInitialized()) {
$object->__load();
} elseif (PHP_VERSION_ID >= 80400) {
$reflector = new ReflectionClass($object);
if (true === $reflector->isUninitializedLazyObject($object)) {
$reflector->initializeLazyObject($object);
}
}
}
}
1 change: 0 additions & 1 deletion tests/_support/project/config/packages/doctrine.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ doctrine:
charset: UTF8
path: '%kernel.project_dir%/var/data.sqlite'
orm:
auto_generate_proxy_classes: true
naming_strategy: doctrine.orm.naming_strategy.underscore
auto_mapping: true
mappings:
Expand Down
13 changes: 13 additions & 0 deletions tests/_support/project/src/Entity/Article.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,17 @@ class Article
* @var Collection<int, Comment>
*/
private Collection $comments;
/**
* @var Collection<int,Post>
*/
private Collection $posts;

public function __construct(?string $title = null, ?string $description = null)
{
$this->title = $title;
$this->description = $description;
$this->comments = new ArrayCollection();
$this->posts = new ArrayCollection();
}

public function getId(): ?int
Expand Down Expand Up @@ -141,4 +146,12 @@ public function removeComment(Comment $comment): void
{
$this->comments->removeElement($comment);
}

/**
* @return list<Post>
*/
public function getPosts(): array
{
return $this->posts->getValues();
}
}
6 changes: 6 additions & 0 deletions tests/_support/project/src/Entity/Post.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class Post
private ?string $locale;
private ?string $title;
private ?string $content;
private ?Article $article = null;

public function __construct(?string $title = null, ?string $content = null)
{
Expand Down Expand Up @@ -58,4 +59,9 @@ public function setContent(?string $content): void
{
$this->content = $content;
}

public function getArticle(): ?Article
{
return $this->article;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@

<field name="publicationDate" type="datetime_immutable" />

<one-to-many field="posts" target-entity="Tests\FSi\App\Entity\Post" mapped-by="page" fetch="EXTRA_LAZY" />

</entity>

</doctrine-mapping>
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
<generator strategy="AUTO"/>
</id>

<many-to-one field="article" target-entity="Tests\FSi\App\Entity\Article" inversed-by="posts" fetch="LAZY" />

</entity>

</doctrine-mapping>
44 changes: 44 additions & 0 deletions tests/functional/Entity/ProxyLoadingCest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

/**
* (c) FSi sp. z o.o. <info@fsi.pl>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace Tests\FSi\Component\Translatable\Entity;

use DateTimeImmutable;
use Tests\FSi\App\Entity\Article;
use Tests\FSi\App\Entity\Post;
use Tests\FSi\FunctionalTester;

final class ProxyLoadingCest
{
public function testProxyLoading(FunctionalTester $I): void
{
$articleId = $I->haveInRepository(Article::class, [
'locale' => 'en',
'publicationDate' => new DateTimeImmutable(),
'title' => 'Title',
'description' => 'Description',
]);
$article = $I->grabEntityFromRepository(Article::class, ['id' => $articleId]);

$postId = $I->haveInRepository(Post::class, [
'locale' => 'en',
'title' => 'Title',
'content' => 'Content',
'article' => $article,
]);

$I->clearEntityManager();

$post = $I->grabEntityFromRepository(Post::class, ['id' => $postId]);
$I->assertInstanceOf(Article::class, $post->getArticle());
$I->flushToDatabase();
}
}