Completed
Push — master ( 96d434...f2324b )
by Daniel
04:52 queued 55s
created

bridge/doctrine-phpcr-odm/src/FieldMapper.php (5 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Psi\Bridge\ContentType\Doctrine\PhpcrOdm;
6
7
use Doctrine\ODM\PHPCR\Mapping\ClassMetadata;
8
use Psi\Component\ContentType\Field;
9
use Psi\Component\ContentType\FieldLoader;
10
use Psi\Component\ContentType\FieldOptions;
11
use Psi\Component\ContentType\Standard\Storage\CollectionType;
12
use Psi\Component\ContentType\Standard\Storage\DateTimeType;
13
use Psi\Component\ContentType\Standard\Storage\IntegerType;
14
use Psi\Component\ContentType\Standard\Storage\ObjectType;
15
use Psi\Component\ContentType\Standard\Storage\ReferenceType;
16
use Psi\Component\ContentType\Standard\Storage\StringType;
17
18
/**
19
 * The FieldMapper maps the correct PHPCR-ODM field for the given content-type
20
 * field.
21
 */
22
class FieldMapper
23
{
24
    private $encoder;
25
    private $fieldLoader;
26
27
    public function __construct(
28
        PropertyEncoder $encoder,
29
        FieldLoader $fieldLoader
30
    ) {
31
        $this->encoder = $encoder;
32
        $this->fieldLoader = $fieldLoader;
33
    }
34
35
    public function __invoke($fieldName, Field $field, ClassMetadata $metadata, array $extraOptions = [])
36
    {
37
        $type = $field->getStorageType();
38
        $options = array_merge([
39
            'multivalue' => false,
40
        ], $extraOptions);
41
42
        if ($type === ObjectType::class) {
43
            $options = $field->getStorageOptions();
44
            $this->unrestrictChildClass($options['class'], $metadata);
45
            $metadata->mapChild([
46
                'fieldName' => $fieldName,
47
                'nodeName' => $this->encoder->encode($fieldName),
48
                'nullable' => true,
49
            ]);
50
51
            return;
52
        }
53
54
        if ($type === CollectionType::class) {
55
            $this->mapCollectionType($fieldName, $field, $metadata);
56
57
            return;
58
        }
59
60 View Code Duplication
        if ($type === StringType::class) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
61
            $metadata->mapField([
62
                'fieldName' => $fieldName,
63
                'type' => 'string',
64
                'nullable' => true,
65
                'multivalue' => $options['multivalue'],
66
            ]);
67
68
            return;
69
        }
70
71 View Code Duplication
        if ($type === IntegerType::class) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
72
            $metadata->mapField([
73
                'fieldName' => $fieldName,
74
                'type' => 'long',
75
                'nullable' => true,
76
                'multivalue' => $options['multivalue'],
77
            ]);
78
79
            return;
80
        }
81
82 View Code Duplication
        if ($type === DateTimeType::class) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
83
            $metadata->mapField([
84
                'fieldName' => $fieldName,
85
                'type' => 'date',
86
                'nullable' => true,
87
                'multivalue' => $options['multivalue'],
88
            ]);
89
90
            return;
91
        }
92
93 View Code Duplication
        if ($type === ReferenceType::class) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
94
            $metadata->mapManyToOne([
95
                'fieldName' => $fieldName,
96
                'strategy' => 'hard',
97
98
                'nullable' => true,
99
                'cascade' => ClassMetadata::CASCADE_ALL,
100
                'multivalue' => $options['multivalue'],
101
            ]);
102
103
            return;
104
        }
105
106
        throw new \RuntimeException(sprintf(
107
            'Do not know how to map field of type "%s"',
108
            $type
109
        ));
110
    }
111
112
    private function mapCollectionType($fieldName, Field $field, ClassMetadata $metadata)
113
    {
114
        $options = $field->getOptions();
115
        $collectionField = $this->fieldLoader->load($options['field_type'], FieldOptions::create($options['field_options']));
116
117
        if ($collectionField->getStorageType() === ObjectType::class) {
118
            $options = $collectionField->getStorageOptions();
119
            $this->unrestrictChildClass($options['class'], $metadata);
120
121
            $metadata->mapChildren([
122
                'fieldName' => $fieldName,
123
                'fetchDepth' => 1,
124
                'filter' => $this->encoder->encode($fieldName) . '-*',
125
                'cascade' => ClassMetadata::CASCADE_ALL,
126
                'nullable' => true,
127
            ]);
128
129
            return;
130
        }
131
132 View Code Duplication
        if ($collectionField->getStorageType() === ReferenceType::class) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
133
            $metadata->mapManyToMany([
134
                'fieldName' => $fieldName,
135
                'strategy' => 'hard',
136
137
                'nullable' => true,
138
                'cascade' => ClassMetadata::CASCADE_ALL,
139
            ]);
140
141
            return;
142
        }
143
144
        // assume that other types are scalars...
145
        $this->__invoke($fieldName, $collectionField, $metadata, [
146
            'multivalue' => true,
147
        ]);
148
    }
149
150
    private function unrestrictChildClass(string $class, ClassMetadata $metadata)
151
    {
152
        if (!$class) {
153
            return;
154
        }
155
156
        if (!$childClasses = $metadata->getChildClasses()) {
157
            return;
158
        }
159
160
        $childClasses[] = $class;
161
        $metadata->setChildClasses($childClasses);
162
    }
163
}
164