DocumentRegistry::isHydrated()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 5
Bugs 0 Features 1
Metric Value
c 5
b 0
f 1
dl 0
loc 10
rs 9.4286
cc 2
eloc 5
nc 2
nop 1
1
<?php
2
3
/*
4
 * This file is part of Sulu.
5
 *
6
 * (c) MASSIVE ART WebServices GmbH
7
 *
8
 * This source file is subject to the MIT license that is bundled
9
 * with this source code in the file LICENSE.
10
 */
11
12
namespace Sulu\Component\DocumentManager;
13
14
use PHPCR\NodeInterface;
15
use Sulu\Component\DocumentManager\Exception\DocumentManagerException;
16
17
/**
18
 * Handles the mapping between managed documents and nodes.
19
 */
20
class DocumentRegistry
21
{
22
    /**
23
     * @var array
24
     */
25
    private $documentMap = [];
26
27
    /**
28
     * @var array
29
     */
30
    private $documentNodeMap = [];
31
32
    /**
33
     * @var array
34
     */
35
    private $nodeMap = [];
36
37
    /**
38
     * @var array
39
     */
40
    private $nodeDocumentMap = [];
41
42
    /**
43
     * @var array
44
     */
45
    private $documentLocaleMap = [];
46
47
    /**
48
     * @var array
49
     */
50
    private $originalLocaleMap = [];
51
52
    /**
53
     * @var string
54
     */
55
    private $defaultLocale;
56
57
    /**
58
     * @var array
59
     */
60
    private $hydrationState = [];
61
62
    /**
63
     * @param $defaultLocale
64
     */
65
    public function __construct($defaultLocale)
66
    {
67
        $this->defaultLocale = $defaultLocale;
68
    }
69
70
    /**
71
     * Register a document.
72
     *
73
     * @param mixed $document
74
     * @param NodeInterface $node
75
     * @param NodeInterface $node
76
     * @param null|string $locale
77
     *
78
     * @throws DocumentManagerException
79
     */
80
    public function registerDocument($document, NodeInterface $node, $locale = null)
81
    {
82
        if (null === $locale) {
83
            $locale = $this->defaultLocale;
84
        }
85
86
        $oid = $this->getObjectIdentifier($document);
87
        $uuid = $node->getIdentifier();
88
89
        // do not allow nodes without UUIDs or reregistration of documents
90
        $this->validateDocumentRegistration($document, $node, $oid, $uuid);
91
92
        $this->documentMap[$oid] = $document;
93
        $this->documentNodeMap[$oid] = $uuid;
94
        $this->nodeMap[$node->getIdentifier()] = $node;
95
        $this->nodeDocumentMap[$node->getIdentifier()] = $document;
96
        $this->documentLocaleMap[$oid] = $locale;
97
    }
98
99
    /**
100
     * Update the locale of the given document and store the originally
101
     * requested locale.
102
     *
103
     * The originally requested locale should be reset when a HYDRATE event
104
     * is caused by the user (and not internally when loading dependencies).
105
     *
106
     * @param object $document
107
     * @param string $locale
108
     * @param null|string $originalLocale
109
     */
110
    public function updateLocale($document, $locale, $originalLocale = null)
111
    {
112
        $oid = $this->getObjectIdentifier($document);
113
        $this->originalLocaleMap[$oid] = $originalLocale;
114
        $this->documentLocaleMap[$oid] = $locale;
115
    }
116
117
    /**
118
     * Return true if the document is managed.
119
     *
120
     * @param object $document
121
     *
122
     * @return bool
123
     */
124
    public function hasDocument($document)
125
    {
126
        $oid = $this->getObjectIdentifier($document);
127
128
        return isset($this->documentMap[$oid]);
129
    }
130
131
    /**
132
     * Return true if the node is managed.
133
     *
134
     * @param NodeInterface $node
135
     *
136
     * @return bool
137
     */
138
    public function hasNode(NodeInterface $node)
139
    {
140
        return isset($this->nodeDocumentMap[$node->getIdentifier()]);
141
    }
142
143
    /**
144
     * Clear the registry (detach all documents).
145
     */
146
    public function clear()
147
    {
148
        $this->documentMap = [];
149
        $this->documentNodeMap = [];
150
        $this->nodeMap = [];
151
        $this->nodeDocumentMap = [];
152
        $this->documentLocaleMap = [];
153
        $this->originalLocaleMap = [];
154
        $this->hydrationState = [];
155
    }
156
157
    /**
158
     * Remove all references to the given document and its
159
     * associated node.
160
     *
161
     * @param object $document
162
     */
163
    public function deregisterDocument($document)
164
    {
165
        $oid = $this->getObjectIdentifier($document);
166
167
        $this->assertDocumentExists($document);
168
169
        $nodeIdentifier = $this->documentNodeMap[$oid];
170
171
        unset($this->nodeMap[$nodeIdentifier]);
172
        unset($this->nodeDocumentMap[$nodeIdentifier]);
173
        unset($this->documentMap[$oid]);
174
        unset($this->documentNodeMap[$oid]);
175
        unset($this->documentLocaleMap[$oid]);
176
        unset($this->originalLocaleMap[$oid]);
177
        unset($this->hydrationState[$oid]);
178
    }
179
180
    /**
181
     * Return the node for the given managed document.
182
     *
183
     * @param object $document
184
     *
185
     * @throws \RuntimeException If the node is not managed
186
     *
187
     * @return NodeInterface
188
     */
189
    public function getNodeForDocument($document)
190
    {
191
        $oid = $this->getObjectIdentifier($document);
192
        $this->assertDocumentExists($document);
193
194
        return $this->nodeMap[$this->documentNodeMap[$oid]];
195
    }
196
197
    /**
198
     * Return the current locale for the given document.
199
     *
200
     * @param object $document
201
     *
202
     * @return string
203
     */
204
    public function getLocaleForDocument($document)
205
    {
206
        $oid = $this->getObjectIdentifier($document);
207
        $this->assertDocumentExists($document);
208
209
        return $this->documentLocaleMap[$oid];
210
    }
211
212
    /**
213
     * Return the original locale for the document.
214
     *
215
     * @param object $document
216
     *
217
     * @return string
218
     */
219
    public function getOriginalLocaleForDocument($document)
220
    {
221
        $oid = $this->getObjectIdentifier($document);
222
        $this->assertDocumentExists($document);
223
224
        if (isset($this->originalLocaleMap[$oid])) {
225
            return $this->originalLocaleMap[$oid];
226
        }
227
228
        return $this->getLocaleForDocument($document);
229
    }
230
231
    /**
232
     * Return the document for the given managed node.
233
     *
234
     * @param NodeInterface $node
235
     *
236
     * @throws \RuntimeException If the node is not managed
237
     */
238
    public function getDocumentForNode(NodeInterface $node)
239
    {
240
        $identifier = $node->getIdentifier();
241
        $this->assertNodeExists($identifier);
242
243
        return $this->nodeDocumentMap[$identifier];
244
    }
245
246
    /**
247
     * Return the default locale.
248
     *
249
     * @return string
250
     */
251
    public function getDefaultLocale()
252
    {
253
        return $this->defaultLocale;
254
    }
255
256
    /**
257
     * @param object $document
258
     */
259
    private function assertDocumentExists($document)
260
    {
261
        $oid = spl_object_hash($document);
262
263
        if (!isset($this->documentMap[$oid])) {
264
            throw new \RuntimeException(sprintf(
265
                'Document "%s" with OID "%s" is not managed, there are "%s" managed objects,',
266
                get_class($document), $oid, count($this->documentMap)
267
            ));
268
        }
269
    }
270
271
    /**
272
     * @param mixed $identifier
273
     */
274
    private function assertNodeExists($identifier)
275
    {
276
        if (!isset($this->nodeDocumentMap[$identifier])) {
277
            throw new \RuntimeException(sprintf(
278
                'Node with identifier "%s" is not managed, there are "%s" managed objects,',
279
                $identifier, count($this->documentMap)
280
            ));
281
        }
282
    }
283
284
    /**
285
     * Get the spl object hash for the given object.
286
     *
287
     * @param object $document
288
     *
289
     * @return string
290
     */
291
    private function getObjectIdentifier($document)
292
    {
293
        return spl_object_hash($document);
294
    }
295
296
    /**
297
     * Ensure that the document is not already registered and that the node
298
     * has a UUID.
299
     *
300
     * @param object $document
301
     * @param NodeInterface $node
302
     * @param string $oid
303
     * @param string $uuid
304
     *
305
     * @throws DocumentManagerException
306
     */
307
    private function validateDocumentRegistration($document, NodeInterface $node, $oid, $uuid)
308
    {
309
        if (null === $uuid) {
310
            throw new DocumentManagerException(sprintf(
311
                'Node "%s" of type "%s" has no UUID. Only referencable nodes can be registered by the document manager',
312
                $node->getPath(), $node->getPrimaryNodeType()->getName()
313
            ));
314
        }
315
316
        if (isset($this->nodeMap[$uuid])) {
317
            $registeredDocument = $this->nodeDocumentMap[$uuid];
318
            throw new \RuntimeException(sprintf(
319
                'Document "%s" (%s) is already registered for node "%s" (%s) when trying to register document "%s" (%s)',
320
                spl_object_hash($registeredDocument),
321
                get_class($registeredDocument),
322
                $uuid,
323
                $node->getPath(),
324
                $oid,
325
                get_class($document)
326
            ));
327
        }
328
    }
329
330
    /**
331
     * Register that the document has been hydrated and that it should
332
     * not be hydrated again.
333
     *
334
     * @param object $document
335
     */
336
    public function markDocumentAsHydrated($document)
337
    {
338
        $oid = spl_object_hash($document);
339
        $this->hydrationState[$oid] = true;
340
    }
341
342
    /**
343
     * Unmark the document as being hydrated. It will then be
344
     * rehydrated the next time a HYDRATE event is fired for ot.
345
     *
346
     * @param object $document
347
     */
348
    public function unmarkDocumentAsHydrated($document)
349
    {
350
        $oid = spl_object_hash($document);
351
        unset($this->hydrationState[$oid]);
352
    }
353
354
    /**
355
     * Return true if the document is a candidate for hydration/re-hydration.
356
     *
357
     * @param object $document
358
     *
359
     * @return bool
360
     */
361
    public function isHydrated($document)
362
    {
363
        $oid = spl_object_hash($document);
364
365
        if (isset($this->hydrationState[$oid])) {
366
            return true;
367
        }
368
369
        return false;
370
    }
371
}
372