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
12 changes: 6 additions & 6 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,24 +29,24 @@
"codeception/module-asserts": "^3.0",
"codeception/module-doctrine": "^3.1",
"codeception/module-symfony": "*",
"doctrine/dbal": "^3.4",
"doctrine/dbal": "^3.4|^4.0",
"doctrine/doctrine-bundle": "^2.4",
"doctrine/lexer": "^1.2|^2.0|^3.0",
"doctrine/orm": "^2.13|^3.0",
"doctrine/persistence": "^2.0|^3.0",
"doctrine/persistence": "^2.0|^3.0|^4.0",
"fsi/files": "^2.0.4|^3.0",
"guzzlehttp/psr7": "^2.0",
"monolog/monolog": "^1.25",
"nyholm/psr7": "^1.4",
"oneup/flysystem-bundle": "^4.4",
"php-http/guzzle7-adapter": "^1.0",
"php-http/httplug-bundle": "^1.20",
"phpstan/phpstan": "^1.10.39",
"phpstan/phpstan-beberlei-assert": "^1.0",
"phpstan/phpstan-phpunit": "^1.3",
"phpstan/phpstan": "^2.1.46",
"phpstan/phpstan-beberlei-assert": "^2.0",
"phpstan/phpstan-phpunit": "^2.0",
"phpunit/phpunit": "^9.5",
"psr/http-client": "^1.0",
"squizlabs/php_codesniffer": "^3.7",
"squizlabs/php_codesniffer": "^4.0",
"symfony/asset": "^4.4.30|^5.4|^6.0|^7.0",
"symfony/clock": "^6.4|^7.0",
"symfony/config": "^4.4.30|^5.4|^6.0|^7.0",
Expand Down
21 changes: 21 additions & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ parameters:
excludePaths:
- 'tests/_support/_generated'
- 'tests/_support/project/var'
- 'tests/_support/project/config'
- 'tests/_support/UnitTester.php'
ignoreErrors:
-
Expand All @@ -26,7 +27,27 @@ parameters:
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: '#.*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
49 changes: 35 additions & 14 deletions src/Integration/Doctrine/ORM/Entity/EmptyEmbeddableVerifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\Mapping\EmbeddedClassMapping;
use Symfony\Component\PropertyAccess\PropertyAccessor;
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;

Expand All @@ -21,6 +22,9 @@
use function mb_strlen;
use function uksort;

/**
* @phpstan-type EmbeddedMappingArray array{class: class-string, declaredField?: string|null, originalField: string}
*/
final class EmptyEmbeddableVerifier
{
private static ?PropertyAccessorInterface $propertyAccessor = null;
Expand All @@ -36,27 +40,41 @@ public static function areAllEmpty(EntityManagerInterface $manager, object $tran
$allEmpty = true;
foreach ($embeddedClassesData as $fieldName => $embeddedData) {
/** @var class-string $embeddableClass */
$embeddableClass = $embeddedData['class'];
$embeddableClass = (true === $embeddedData instanceof EmbeddedClassMapping)
? $embeddedData->class
: $embeddedData['class'];
$embeddedMeta = $manager->getClassMetadata($embeddableClass);
$embeddedParentMeta = $classMetadata;
$embeddedParentObject = $translation;
$embeddedDeclaredField = (true === $embeddedData instanceof EmbeddedClassMapping)
? $embeddedData->declaredField
: ($embeddedData['declaredField'] ?? null);

if (true === isset($embeddedData['declaredField'])) {
if (null !== $embeddedDeclaredField) {
$embeddedParentObject = self::getPropertyAccessor()->getValue(
$translation,
$embeddedData['declaredField']
$embeddedDeclaredField
);

if (null === $embeddedParentObject) {
continue;
}

$embeddedParentData = $embeddedClassesData[$embeddedData['declaredField']];
$embeddedParentMeta = $manager->getClassMetadata($embeddedParentData['class']);
$fieldName = $embeddedData['originalField'];
$embeddedParentData = $embeddedClassesData[$embeddedDeclaredField];
/** @var class-string<object> $embeddedParentClass */
$embeddedParentClass = (true === $embeddedParentData instanceof EmbeddedClassMapping)
? $embeddedParentData->class
: $embeddedParentData['class'];
$embeddedParentMeta = $manager->getClassMetadata($embeddedParentClass);
$fieldName = (true === $embeddedData instanceof EmbeddedClassMapping)
? $embeddedData->originalField
: $embeddedData['originalField'];
}

$embeddedObject = $embeddedParentMeta->getFieldValue($embeddedParentObject, $fieldName);
$embeddedObject = null;
if (null !== $fieldName) {
$embeddedObject = $embeddedParentMeta->getFieldValue($embeddedParentObject, $fieldName);
}
if (null === $embeddedObject) {
continue;
}
Expand All @@ -78,11 +96,14 @@ public static function getEmbeddableClasses(EntityManagerInterface $manager, obj
$embeddedClassesData = self::getAndSortEmbeddedDataByNestingLevel(
self::getTranslationMetadata($manager, $translation)
);

return array_map(
static fn($embeddedData): string => $embeddedData['class'],
$embeddedClassesData
);
/** @var callable(EmbeddedClassMapping|EmbeddedMappingArray): class-string $embeddedMappingMapper */
$embeddedMappingMapper = static function (EmbeddedClassMapping|array $embeddedData): string {
return (true === $embeddedData instanceof EmbeddedClassMapping)
? $embeddedData->class
: $embeddedData['class'];
};

return array_map($embeddedMappingMapper, $embeddedClassesData);
}

/**
Expand All @@ -109,11 +130,11 @@ static function (bool $accumulator, string $fieldName) use ($classMetadata, $emb

/**
* @param ClassMetadata<object> $classMetadata
* @return array<string, array{ class: class-string, declaredField?: string|null, originalField: string }>
* @return array<string, EmbeddedClassMapping|EmbeddedMappingArray>
*/
private static function getAndSortEmbeddedDataByNestingLevel(ClassMetadata $classMetadata): array
{
/** @var array<string, array{ class: class-string, declaredField?: string|null, originalField: string }> $data */
/** @var array<string, EmbeddedClassMapping|EmbeddedMappingArray> $data */
$data = $classMetadata->embeddedClasses;
// Example data ["fieldName" => [], "fieldName.nestedFieldName" => []]
uksort(
Expand Down
2 changes: 1 addition & 1 deletion src/Integration/Symfony/TranslatableBundle.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public function build(ContainerBuilder $container): void
}
}

public function getContainerExtension(): ?ExtensionInterface
public function getContainerExtension(): ExtensionInterface
{
if (false === $this->extension instanceof TranslatableExtension) {
$this->extension = new TranslatableExtension();
Expand Down
9 changes: 1 addition & 8 deletions src/PropertyConfiguration.php
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,6 @@ private function getPropertyReflection(): ReflectionProperty
}

$this->propertyReflection = $reflectionClass->getProperty($this->propertyName);
if (PHP_VERSION_ID < 80500) {
$this->propertyReflection->setAccessible(true);
}
} while ($reflectionClass = $reflectionClass->getParentClass());
}

Expand All @@ -140,11 +137,7 @@ private function getPropertyReflection(): ReflectionProperty
*/
private function handleUninitializedProperty(ReflectionProperty $propertyReflection)
{
if (
true === method_exists($propertyReflection, 'hasDefaultValue')
&& true === method_exists($propertyReflection, 'getDefaultValue')
&& true === $propertyReflection->hasDefaultValue()
) {
if (true === $propertyReflection->hasDefaultValue()) {
return $propertyReflection->getDefaultValue();
}

Expand Down
2 changes: 1 addition & 1 deletion tests/_support/Module/DbModule.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public function _beforeSuite($settings = []): void
/** @var EntityManagerInterface $manager */
$manager = $symfony->_getEntityManager();

(new SchemaTool($manager))->createSchema($manager->getMetadataFactory()->getAllMetadata());
(new SchemaTool($manager))->createSchema(array_values($manager->getMetadataFactory()->getAllMetadata()));
}

/**
Expand Down
2 changes: 1 addition & 1 deletion tests/_support/project/src/Kernel.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ protected function configureContainer(ContainerBuilder $container, LoaderInterfa
{
$configDirectory = $this->getProjectDir() . '/config';
$container->addResource(new FileResource($configDirectory . '/bundles.php'));
$container->setParameter('container.dumper.inline_class_loader', PHP_VERSION_ID < 70400 || $this->debug);
$container->setParameter('container.dumper.inline_class_loader', $this->debug);
$container->setParameter('container.dumper.inline_factories', true);

if (InstalledVersions::getVersion('symfony/framework-bundle') >= '5.0.0') {
Expand Down
6 changes: 2 additions & 4 deletions tests/_support/project/templates/Form/formTheme.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,8 @@
{% endblock %}

{% block collection_prototype -%}
{% apply spaceless %}
{% set form = prototype %}
{{ block('collection_item') }}
{% endapply %}
{% set form = prototype %}
{{ block('collection_item') }}
{%- endblock %}

{% block collection_item %}
Expand Down