Completed
Push — master ( b4949b...b69366 )
by Kamil
10:51 queued 03:28
created

EventListener/ODMTranslatableListener.php (1 issue)

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
/*
4
 * This file is part of the Sylius package.
5
 *
6
 * (c) Paweł Jędrzejewski
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace Sylius\Bundle\ResourceBundle\EventListener;
15
16
use Doctrine\Common\EventSubscriber;
17
use Doctrine\ODM\MongoDB\Event\LifecycleEventArgs;
18
use Doctrine\ODM\MongoDB\Event\LoadClassMetadataEventArgs;
19
use Doctrine\ODM\MongoDB\Events;
20
use Doctrine\ODM\MongoDB\Mapping\ClassMetadata;
21
use Sylius\Component\Resource\Model\TranslatableInterface;
22
use Sylius\Component\Resource\Model\TranslationInterface;
23
24
final class ODMTranslatableListener implements EventSubscriber
25
{
26
    /**
27
     * @var string
28
     */
29
    private $currentLocale;
30
31
    /**
32
     * @var string
33
     */
34
    private $fallbackLocale;
35
36
    /**
37
     * @var array
38
     */
39
    private $mappings;
40
41
    /**
42
     * @param array $mappings
43
     * @param string $fallbackLocale
44
     */
45
    public function __construct(array $mappings, $fallbackLocale)
46
    {
47
        $this->mappings = $mappings;
48
        $this->fallbackLocale = $fallbackLocale;
49
    }
50
51
    /**
52
     * {@inheritdoc}
53
     */
54
    public function setCurrentLocale($currentLocale)
55
    {
56
        $this->currentLocale = $currentLocale;
57
58
        return $this;
59
    }
60
61
    /**
62
     * {@inheritdoc}
63
     */
64
    public function getSubscribedEvents()
65
    {
66
        return [
67
            Events::loadClassMetadata,
68
            Events::postLoad,
69
        ];
70
    }
71
72
    /**
73
     * Add mapping to translatable entities
74
     *
75
     * @param LoadClassMetadataEventArgs $eventArgs
76
     */
77
    public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs)
78
    {
79
        $classMetadata = $eventArgs->getClassMetadata();
80
        $reflection = $classMetadata->reflClass;
81
82
        if (!$reflection || $reflection->isAbstract()) {
83
            return;
84
        }
85
86
        if ($reflection->implementsInterface(TranslatableInterface::class)) {
87
            $this->mapTranslatable($classMetadata);
88
        }
89
90
        if ($reflection->implementsInterface(TranslationInterface::class)) {
91
            $this->mapTranslation($classMetadata);
92
        }
93
    }
94
95
    /**
96
     * Add mapping data to a translatable entity
97
     *
98
     * @param ClassMetadata $metadata
99
     */
100
    private function mapTranslatable(ClassMetadata $metadata)
101
    {
102
        // In the case A -> B -> TranslatableInterface, B might not have mapping defined as it
103
        // is probably defined in A, so in that case, we just return.
104
        if (!isset($this->mappings[$metadata->name])) {
105
            return;
106
        }
107
108
        $config = $this->mappings[$metadata->name];
109
        $mapping = $config['translation']['mapping'];
110
111
        $metadata->mapManyEmbedded([
112
            'fieldName' => $mapping['translatable']['translations'],
113
            'targetDocument' => $config['translation']['model'],
114
            'strategy' => 'set',
115
        ]);
116
    }
117
118
    /**
119
     * Add mapping data to a translation entity
120
     *
121
     * @param ClassMetadata $metadata
122
     */
123
    private function mapTranslation(ClassMetadata $metadata)
124
    {
125
        // In the case A -> B -> TranslationInterface, B might not have mapping defined as it
126
        // is probably defined in A, so in that case, we just return;
127
        if (!isset($this->mappings[$metadata->name])) {
128
            return;
129
        }
130
131
        $config = $this->mappings[$metadata->name];
132
        $mapping = $config['translation']['mapping'];
133
134
        $metadata->isEmbeddedDocument = true;
135
        $metadata->isMappedSuperclass = false;
136
        $metadata->setIdentifier(null);
137
138
        // Map locale field.
139
        if (!$metadata->hasField($mapping['translation']['locale'])) {
140
            $metadata->mapField([
141
                'fieldName' => $mapping['translation']['locale'],
142
                'type' => 'string',
143
            ]);
144
        }
145
146
        // Map unique index.
147
        $keys = [
148
            $mapping['translation']['translatable'] => 1,
149
            $mapping['translation']['locale'] => 1,
150
        ];
151
152
        if (!$this->hasUniqueIndex($metadata, $keys)) {
0 ignored issues
show
The method hasUniqueIndex() does not seem to exist on object<Sylius\Bundle\Res...DMTranslatableListener>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
153
            $metadata->addIndex($keys, [
154
                'unique' => true,
155
            ]);
156
        }
157
    }
158
159
    /**
160
     * Load translations
161
     *
162
     * @param LifecycleEventArgs $args
163
     */
164
    public function postLoad(LifecycleEventArgs $args)
165
    {
166
        $document = $args->getDocument();
167
168
        // Sometimes $document is a doctrine proxy class, we therefore need to retrieve it's real class
169
        $name = $args->getDocumentManager()->getClassMetadata(get_class($document))->getName();
170
171
        if (!isset($this->mappings[$name])) {
172
            return;
173
        }
174
175
        $metadata = $this->mappings[$name];
176
177
        if (isset($metadata['fallback_locale'])) {
178
            $setter = 'set' . ucfirst($metadata['fallback_locale']);
179
            $document->$setter($this->fallbackLocale);
180
        }
181
        if (isset($metadata['current_locale'])) {
182
            $setter = 'set' . ucfirst($metadata['current_locale']);
183
            $document->$setter($this->currentLocale);
184
        }
185
    }
186
}
187