Skip to content

Commit 768a25c

Browse files
committed
Add configuration for ArrayAccess classes
1 parent 4484f61 commit 768a25c

9 files changed

+41
-19
lines changed

src/Configuration.php

+9
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44

55
namespace AutoMapper;
66

7+
use MongoDB\BSON\Document;
8+
use MongoDB\Model\BSONDocument;
9+
710
final readonly class Configuration
811
{
912
public function __construct(
@@ -36,6 +39,12 @@ public function __construct(
3639
* Does the mapper should throw an exception if the target is read-only.
3740
*/
3841
public bool $allowReadOnlyTargetToPopulate = false,
42+
/**
43+
* Classes with unknown properties, implemeting ArrayAccess.
44+
*
45+
* @var list<class-string<\ArrayAccess<string, mixed>>> $arrayAccessClasses
46+
*/
47+
public array $arrayAccessClasses = [\ArrayObject::class, Document::class, BSONDocument::class],
3948
) {
4049
}
4150
}

src/Extractor/MappingExtractor.php

+3-5
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@
55
namespace AutoMapper\Extractor;
66

77
use AutoMapper\Configuration;
8-
use MongoDB\BSON\Document;
9-
use MongoDB\Model\BSONDocument;
108
use Symfony\Component\PropertyInfo\PropertyInfoExtractorInterface;
119
use Symfony\Component\PropertyInfo\PropertyReadInfo;
1210
use Symfony\Component\PropertyInfo\PropertyReadInfoExtractorInterface;
@@ -33,7 +31,7 @@ public function __construct(
3331
*/
3432
public function getProperties(string $class): iterable
3533
{
36-
if ($class === 'array' || in_array($class, [\stdClass::class, Document::class, BSONDocument::class], true)) {
34+
if ($class === 'array' || $class === \stdClass::class || \in_array($class, $this->configuration->arrayAccessClasses, true)) {
3735
return [];
3836
}
3937

@@ -42,7 +40,7 @@ public function getProperties(string $class): iterable
4240

4341
public function getReadAccessor(string $class, string $property): ?ReadAccessor
4442
{
45-
if (in_array($class, ['array', Document::class, BSONDocument::class], true)) {
43+
if ('array' === $class || \in_array($class, $this->configuration->arrayAccessClasses, true)) {
4644
return new ReadAccessor(ReadAccessor::TYPE_ARRAY_DIMENSION, $property);
4745
}
4846

@@ -109,7 +107,7 @@ public function getWriteMutator(string $source, string $target, string $property
109107

110108
public function getCheckExists(string $class, string $property): bool
111109
{
112-
if (in_array($class, ['array', \stdClass::class, Document::class, BSONDocument::class], true)) {
110+
if ('array' === $class || \stdClass::class === $class || \in_array($class, $this->configuration->arrayAccessClasses, true)) {
113111
return true;
114112
}
115113

src/Generator/MapMethodStatementsGenerator.php

+3-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace AutoMapper\Generator;
66

7+
use AutoMapper\Configuration;
78
use AutoMapper\Exception\ReadOnlyTargetException;
89
use AutoMapper\Generator\Shared\CachedReflectionStatementsGenerator;
910
use AutoMapper\Generator\Shared\DiscriminatorStatementsGenerator;
@@ -27,6 +28,7 @@
2728
private PropertyStatementsGenerator $propertyStatementsGenerator;
2829

2930
public function __construct(
31+
Configuration $configuration,
3032
DiscriminatorStatementsGenerator $discriminatorStatementsGeneratorSource,
3133
DiscriminatorStatementsGenerator $discriminatorStatementsGeneratorTarget,
3234
CachedReflectionStatementsGenerator $cachedReflectionStatementsGenerator,
@@ -37,7 +39,7 @@ public function __construct(
3739
$discriminatorStatementsGeneratorTarget,
3840
$cachedReflectionStatementsGenerator,
3941
);
40-
$this->propertyStatementsGenerator = new PropertyStatementsGenerator($expressionLanguage);
42+
$this->propertyStatementsGenerator = new PropertyStatementsGenerator($configuration, $expressionLanguage);
4143
}
4244

4345
/**

src/Generator/MapperGenerator.php

+1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ public function __construct(
4444
);
4545

4646
$this->mapMethodStatementsGenerator = new MapMethodStatementsGenerator(
47+
$configuration,
4748
new DiscriminatorStatementsGenerator($classDiscriminatorResolver, true),
4849
new DiscriminatorStatementsGenerator($classDiscriminatorResolver, false),
4950
$cachedReflectionStatementsGenerator,

src/Generator/PropertyConditionsGenerator.php

+6-6
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,11 @@
44

55
namespace AutoMapper\Generator;
66

7+
use AutoMapper\Configuration;
78
use AutoMapper\Exception\CompileException;
89
use AutoMapper\MapperContext;
910
use AutoMapper\Metadata\GeneratorMetadata;
1011
use AutoMapper\Metadata\PropertyMetadata;
11-
use MongoDB\BSON\Document;
12-
use MongoDB\Model\BSONDocument;
1312
use PhpParser\Node\Arg;
1413
use PhpParser\Node\ArrayItem;
1514
use PhpParser\Node\Expr;
@@ -35,6 +34,7 @@ class_alias(Expr\ArrayItem::class, ArrayItem::class);
3534
private Parser $parser;
3635

3736
public function __construct(
37+
private Configuration $configuration,
3838
private ExpressionLanguage $expressionLanguage,
3939
Parser $parser = null,
4040
) {
@@ -47,7 +47,7 @@ public function generate(GeneratorMetadata $metadata, PropertyMetadata $property
4747

4848
$conditions[] = $this->propertyExistsForStdClass($metadata, $propertyMetadata);
4949
$conditions[] = $this->propertyExistsForArray($metadata, $propertyMetadata);
50-
$conditions[] = $this->propertyExistsForBSONDocument($metadata, $propertyMetadata);
50+
$conditions[] = $this->propertyExistsForArrayAccess($metadata, $propertyMetadata);
5151
$conditions[] = $this->isAllowedAttribute($metadata, $propertyMetadata);
5252

5353
if (!$propertyMetadata->disableGroupsCheck) {
@@ -127,15 +127,15 @@ private function propertyExistsForArray(GeneratorMetadata $metadata, PropertyMet
127127
}
128128

129129
/**
130-
* In case of source is an array we ensure that the key exists.
130+
* In case of source is an ArrayAccess implementation listed in the config.
131131
*
132132
* ```php
133133
* $source->offsetExists('propertyName').
134134
* ```
135135
*/
136-
private function propertyExistsForBSONDocument(GeneratorMetadata $metadata, PropertyMetadata $propertyMetadata): ?Expr
136+
private function propertyExistsForArrayAccess(GeneratorMetadata $metadata, PropertyMetadata $propertyMetadata): ?Expr
137137
{
138-
if (!$propertyMetadata->source->checkExists || !in_array($metadata->mapperMetadata->source, [Document::class, BSONDocument::class], true)) {
138+
if (!$propertyMetadata->source->checkExists || !\in_array($metadata->mapperMetadata->source, $this->configuration->arrayAccessClasses, true)) {
139139
return null;
140140
}
141141

src/Generator/PropertyStatementsGenerator.php

+3-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace AutoMapper\Generator;
66

7+
use AutoMapper\Configuration;
78
use AutoMapper\Extractor\WriteMutator;
89
use AutoMapper\Metadata\GeneratorMetadata;
910
use AutoMapper\Metadata\PropertyMetadata;
@@ -22,9 +23,10 @@
2223
private PropertyConditionsGenerator $propertyConditionsGenerator;
2324

2425
public function __construct(
26+
Configuration $configuration,
2527
ExpressionLanguage $expressionLanguage
2628
) {
27-
$this->propertyConditionsGenerator = new PropertyConditionsGenerator($expressionLanguage);
29+
$this->propertyConditionsGenerator = new PropertyConditionsGenerator($configuration, $expressionLanguage);
2830
}
2931

3032
/**

src/Metadata/MetadataFactory.php

+3-4
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,6 @@
4242
use AutoMapper\Transformer\TransformerFactoryInterface;
4343
use AutoMapper\Transformer\UniqueTypeTransformerFactory;
4444
use AutoMapper\Transformer\VoidTransformer;
45-
use MongoDB\BSON\Document;
46-
use MongoDB\Model\BSONDocument;
4745
use Symfony\Component\EventDispatcher\EventDispatcher;
4846
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
4947
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
@@ -174,11 +172,12 @@ private function createGeneratorMetadata(MapperMetadata $mapperMetadata): Genera
174172
{
175173
$extractor = $this->sourceTargetPropertiesMappingExtractor;
176174

177-
if (in_array($mapperMetadata->source, ['array', \stdClass::class, Document::class, BSONDocument::class], true)) {
175+
$classes = array_merge(['array', \stdClass::class], $this->configuration->arrayAccessClasses);
176+
if (\in_array($mapperMetadata->source, $classes, true)) {
178177
$extractor = $this->fromTargetPropertiesMappingExtractor;
179178
}
180179

181-
if (in_array($mapperMetadata->target, ['array', \stdClass::class, Document::class, BSONDocument::class], true)) {
180+
if (\in_array($mapperMetadata->target, $classes, true)) {
182181
$extractor = $this->fromSourcePropertiesMappingExtractor;
183182
}
184183

tools/phpstan/phpstan.neon

+4-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ parameters:
44
- ../../src/
55

66
tmpDir: cache
7+
scanFiles:
8+
- stubs/mongodb.php
79

810
ignoreErrors:
9-
- "#Instantiated class fromIteratorToArray not found#"
10-
- "#Instantiated class toArray not found#"
11+
- "#Instantiated class fromIteratorToArray not found#"
12+
- "#Instantiated class toArray not found#"

tools/phpstan/stubs/mongodb.php

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
namespace MongoDB\BSON {
4+
abstract class Document implements \ArrayAccess {}
5+
}
6+
7+
namespace MongoDB\Model {
8+
abstract class BSONDocument implements \ArrayAccess {}
9+
}

0 commit comments

Comments
 (0)