Skip to content

Commit

Permalink
fix(bundle): use map_private_properties when configuring ReflectionEx…
Browse files Browse the repository at this point in the history
…tractor (#129)

configuration `map_private_properties` was not used to configure service
`automapper.property_info.reflection_extractor` whereas without the
bundle, `\AutoMapper\Configuration::$mapPrivateProperties` is actually
used, this PR fixes this.

I had to introduce a way to have several configurations available for
the fixture bundle, I'm using `KernelTestCase::createKernel()` + an
additional config file path for this.

waiting for #137
  • Loading branch information
joelwurtz authored Jun 5, 2024
2 parents aad796a + 8afc811 commit 20c3beb
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ public function load(array $configs, ContainerBuilder $container): void
->setArgument('$allowReadOnlyTargetToPopulate', $config['allow_readonly_target_to_populate'])
;

$container->setParameter('automapper.map_private_properties', $config['map_private_properties']);

$container->registerForAutoconfiguration(PropertyTransformerInterface::class)->addTag('automapper.property_transformer');

if ($config['loader']['eval']) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ public function process(ContainerBuilder $container): void
return;
}

$flags = ReflectionExtractor::ALLOW_PUBLIC;

if ($container->getParameter('automapper.map_private_properties')) {
$flags |= ReflectionExtractor::ALLOW_PRIVATE | ReflectionExtractor::ALLOW_PROTECTED;
}

$container->setDefinition(
'automapper.property_info.reflection_extractor',
new Definition(
Expand All @@ -31,7 +37,7 @@ public function process(ContainerBuilder $container): void
'$accessorPrefixes' => null,
'$arrayMutatorPrefixes' => null,
'$enableConstructorExtraction' => true,
'$accessFlags' => ReflectionExtractor::ALLOW_PUBLIC | ReflectionExtractor::ALLOW_PROTECTED | ReflectionExtractor::ALLOW_PRIVATE,
'$accessFlags' => $flags,
]
)
);
Expand Down
25 changes: 25 additions & 0 deletions tests/Bundle/Resources/App/AppKernel.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,39 @@
namespace AutoMapper\Tests\Bundle\Resources\App;

use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Kernel;

class AppKernel extends Kernel
{
use MicroKernelTrait;

public function __construct(
string $environment,
bool $debug,
private ?string $additionalConfigFile = null
) {
parent::__construct($environment, $debug);
}

protected function buildContainer(): ContainerBuilder
{
$containerBuilder = parent::buildContainer();

if ($this->additionalConfigFile) {
$this->getContainerLoader($containerBuilder)->load($this->additionalConfigFile);
}

return $containerBuilder;
}

public function getProjectDir(): string
{
return __DIR__ . '/..';
}

public function getCacheDir(): string
{
return parent::getCacheDir() . '/' . md5($this->additionalConfigFile ?? '');
}
}
3 changes: 3 additions & 0 deletions tests/Bundle/Resources/config/with-private-properties.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
automapper:
class_prefix: "Symfony_Mapper_With_Private_Property"
map_private_properties: true
51 changes: 40 additions & 11 deletions tests/Bundle/ServiceInstantiationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use AutoMapper\Metadata\TargetPropertyMetadata;
use AutoMapper\Symfony\Bundle\CacheWarmup\CacheWarmer;
use AutoMapper\Symfony\Bundle\DataCollector\MetadataCollector;
use AutoMapper\Tests\Bundle\Resources\App\AppKernel;
use AutoMapper\Tests\Bundle\Resources\App\Entity\AddressDTO;
use AutoMapper\Tests\Bundle\Resources\App\Entity\ClassWithMapToContextAttribute;
use AutoMapper\Tests\Bundle\Resources\App\Entity\ClassWithPrivateProperty;
Expand All @@ -23,15 +24,14 @@
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\KernelInterface;

class ServiceInstantiationTest extends WebTestCase
{
protected function setUp(): void
public static function setUpBeforeClass(): void
{
static::$class = null;
$_SERVER['KERNEL_DIR'] = __DIR__ . '/Resources/App';
$_SERVER['KERNEL_CLASS'] = 'AutoMapper\Tests\Bundle\Resources\App\AppKernel';
$_SERVER['APP_DEBUG'] = false;

(new Filesystem())->remove(__DIR__ . '/Resources/var/cache/test');
}
Expand All @@ -47,13 +47,14 @@ public function testWarmup(): void
$service = static::$kernel->getContainer()->get(CacheWarmer::class);
$service->warmUp(__DIR__ . '/Resources/var/cache/test');

self::assertFileExists(__DIR__ . '/Resources/var/cache/test/automapper/Symfony_Mapper_AutoMapper_Tests_Bundle_Resources_App_Entity_NestedObject_array.php');
self::assertFileExists(__DIR__ . '/Resources/var/cache/test/automapper/Symfony_Mapper_AutoMapper_Tests_Bundle_Resources_App_Entity_User_array.php');
self::assertFileExists(__DIR__ . '/Resources/var/cache/test/automapper/Symfony_Mapper_AutoMapper_Tests_Bundle_Resources_App_Entity_AddressDTO_array.php');
self::assertFileExists(__DIR__ . '/Resources/var/cache/test/automapper/Symfony_Mapper_AutoMapper_Tests_Bundle_Resources_App_Entity_Pet_array.php');
self::assertFileExists(__DIR__ . '/Resources/var/cache/test/automapper/Symfony_Mapper_AutoMapper_Tests_Bundle_Resources_App_Entity_Dog_array.php');
self::assertFileExists(__DIR__ . '/Resources/var/cache/test/automapper/Symfony_Mapper_AutoMapper_Tests_Bundle_Resources_App_Entity_Cat_array.php');
self::assertFileExists(__DIR__ . '/Resources/var/cache/test/automapper/Symfony_Mapper_AutoMapper_Tests_Bundle_Resources_App_Api_Entity_Book_array.php');
$cacheDir = static::$kernel->getCacheDir();
self::assertFileExists("{$cacheDir}/automapper/Symfony_Mapper_AutoMapper_Tests_Bundle_Resources_App_Entity_NestedObject_array.php");
self::assertFileExists("{$cacheDir}/automapper/Symfony_Mapper_AutoMapper_Tests_Bundle_Resources_App_Entity_User_array.php");
self::assertFileExists("{$cacheDir}/automapper/Symfony_Mapper_AutoMapper_Tests_Bundle_Resources_App_Entity_AddressDTO_array.php");
self::assertFileExists("{$cacheDir}/automapper/Symfony_Mapper_AutoMapper_Tests_Bundle_Resources_App_Entity_Pet_array.php");
self::assertFileExists("{$cacheDir}/automapper/Symfony_Mapper_AutoMapper_Tests_Bundle_Resources_App_Entity_Dog_array.php");
self::assertFileExists("{$cacheDir}/automapper/Symfony_Mapper_AutoMapper_Tests_Bundle_Resources_App_Entity_Cat_array.php");
self::assertFileExists("{$cacheDir}/automapper/Symfony_Mapper_AutoMapper_Tests_Bundle_Resources_App_Api_Entity_Book_array.php");
}

public function testAutoMapper(): void
Expand Down Expand Up @@ -121,9 +122,10 @@ public function testItCanMapEnums(): void
/**
* This test validates that PropertyInfoPass is correctly applied.
*/
public function testMapClassWithPrivateProperty(): void
public function testMapToClassWithPrivateProperty(): void
{
static::bootKernel();

$container = static::$kernel->getContainer();
$autoMapper = $container->get(AutoMapperInterface::class);

Expand All @@ -133,6 +135,28 @@ public function testMapClassWithPrivateProperty(): void
);
}

/**
* This test validates that PropertyInfoPass is correctly applied.
*
* @dataProvider mapFromClassWithPrivatePropertyProvider
*/
public function testMapFromClassWithPrivateProperty(array $kernelOptions, array $expected): void
{
static::bootKernel($kernelOptions);
$autoMapper = self::getContainer()->get(AutoMapperInterface::class);

self::assertEquals(
$expected,
$autoMapper->map(new ClassWithPrivateProperty('foo'), 'array')
);
}

public static function mapFromClassWithPrivatePropertyProvider(): iterable
{
yield 'disallow private properties' => [[], []];
yield 'allow private properties' => [['additionalConfigFile' => __DIR__ . '/Resources/config/with-private-properties.yml'], ['foo' => 'foo', 'bar' => 'bar']];
}

/**
* We need to test that the mapToContext attribute is correctly used,
* because this behavior is dependent of the dependency injection.
Expand Down Expand Up @@ -253,4 +277,9 @@ public function getData(): array
}
}
}

protected static function createKernel(array $options = []): KernelInterface
{
return new AppKernel('test', false, $options['additionalConfigFile'] ?? null);
}
}

0 comments on commit 20c3beb

Please sign in to comment.