Completed
Pull Request — 1.0.x (#1281)
by Maciej
06:42
created

PersistentCollection::next()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1
Metric Value
dl 0
loc 4
ccs 1
cts 1
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 0
crap 1
1
<?php
2
/*
3
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14
 *
15
 * This software consists of voluntary contributions made by many individuals
16
 * and is licensed under the MIT license. For more information, see
17
 * <http://www.doctrine-project.org>.
18
 */
19
20
namespace Doctrine\ODM\MongoDB;
21
22
use Doctrine\Common\Collections\Collection as BaseCollection;
23
use Doctrine\ODM\MongoDB\Mapping\ClassMetadata;
24
use Doctrine\ODM\MongoDB\Utility\CollectionHelper;
25
26
/**
27
 * A PersistentCollection represents a collection of elements that have persistent state.
28
 *
29
 * @since       1.0
30
 * @author      Jonathan H. Wage <[email protected]>
31
 * @author      Roman Borschel <[email protected]>
32
 */
33
class PersistentCollection implements BaseCollection
34
{
35
    /**
36
     * A snapshot of the collection at the moment it was fetched from the database.
37
     * This is used to create a diff of the collection at commit time.
38
     *
39
     * @var array
40
     */
41
    private $snapshot = array();
42
43
    /**
44
     * Collection's owning entity
45
     *
46
     * @var object
47
     */
48
    private $owner;
49
50
    /**
51
     * @var array
52
     */
53
    private $mapping;
54
55
    /**
56
     * Whether the collection is dirty and needs to be synchronized with the database
57
     * when the UnitOfWork that manages its persistent state commits.
58
     *
59
     * @var boolean
60
     */
61
    private $isDirty = false;
62
63
    /**
64
     * Whether the collection has already been initialized.
65
     *
66
     * @var boolean
67
     */
68
    private $initialized = true;
69
70
    /**
71
     * The wrapped Collection instance.
72
     *
73
     * @var BaseCollection
74
     */
75
    private $coll;
76
77
    /**
78
     * The DocumentManager that manages the persistence of the collection.
79
     *
80
     * @var DocumentManager
81
     */
82
    private $dm;
83
84
    /**
85
     * The UnitOfWork that manages the persistence of the collection.
86
     *
87
     * @var UnitOfWork
88
     */
89
    private $uow;
90
91
    /**
92
     * The raw mongo data that will be used to initialize this collection.
93
     *
94
     * @var array
95
     */
96
    private $mongoData = array();
97
98
    /**
99
     * Any hints to account for during reconstitution/lookup of the documents.
100
     *
101
     * @var array
102
     */
103
    private $hints = array();
104
105
    /**
106
     * @var ClassMetadata
107
     */
108
    private $typeClass;
109
110
    /**
111
     * @param BaseCollection $coll
112
     * @param DocumentManager $dm
113
     * @param UnitOfWork $uow
114
     */
115 372
    public function __construct(BaseCollection $coll, DocumentManager $dm, UnitOfWork $uow)
116
    {
117 372
        $this->coll = $coll;
118 372
        $this->dm = $dm;
119 372
        $this->uow = $uow;
120 372
    }
121
122
    /**
123
     * Sets the document manager and unit of work (used during merge operations).
124
     *
125
     * @param DocumentManager $dm
126
     */
127
    public function setDocumentManager(DocumentManager $dm)
128
    {
129
        $this->dm = $dm;
130
        $this->uow = $dm->getUnitOfWork();
131
    }
132
133
    /**
134
     * Sets the array of raw mongo data that will be used to initialize this collection.
135
     *
136
     * @param array $mongoData
137
     */
138 158
    public function setMongoData(array $mongoData)
139
    {
140 158
        $this->mongoData = $mongoData;
141 158
    }
142
143
    /**
144
     * Gets the array of raw mongo data that will be used to initialize this collection.
145
     *
146
     * @return array $mongoData
147
     */
148 137
    public function getMongoData()
149
    {
150 137
        return $this->mongoData;
151
    }
152
153
    /**
154
     * Set hints to account for during reconstitution/lookup of the documents.
155
     *
156
     * @param array $hints
157
     */
158 241
    public function setHints(array $hints)
159
    {
160 241
        $this->hints = $hints;
161 241
    }
162
163
    /**
164
     * Get hints to account for during reconstitution/lookup of the documents.
165
     *
166
     * @return array $hints
167
     */
168 79
    public function getHints()
169
    {
170 79
        return $this->hints;
171
    }
172
173
    /**
174
     * Initializes the collection by loading its contents from the database
175
     * if the collection is not yet initialized.
176
     */
177 345
    public function initialize()
178
    {
179 345
        if ($this->initialized || ! $this->mapping) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->mapping of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
180 339
            return;
181
        }
182
183 149
        $newObjects = array();
184
185 149
        if ($this->isDirty) {
186
            // Remember any NEW objects added through add()
187 20
            $newObjects = $this->coll->toArray();
188 20
        }
189
190 149
        $this->initialized = true;
191
192 149
        $this->coll->clear();
193 149
        $this->uow->loadCollection($this);
194 149
        $this->takeSnapshot();
195
196 149
        $this->mongoData = array();
197
198
        // Reattach any NEW objects added through add()
199 149
        if ($newObjects) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $newObjects of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
200 20
            foreach ($newObjects as $key => $obj) {
201 20
                if (CollectionHelper::isHash($this->mapping['strategy'])) {
202
                    $this->coll->set($key, $obj);
203
                } else {
204 20
                    $this->coll->add($obj);
205
                }
206 20
            }
207
208 20
            $this->isDirty = true;
209 20
        }
210 149
    }
211
212
    /**
213
     * Marks this collection as changed/dirty.
214
     */
215 164
    private function changed()
216
    {
217 164
        if ($this->isDirty) {
218 104
            return;
219
        }
220
221 164
        $this->isDirty = true;
222
223 164
        if ($this->dm &&
224 164
            $this->mapping !== null &&
225 164
            $this->mapping['isOwningSide'] &&
226 164
            $this->owner &&
227 164
            $this->dm->getClassMetadata(get_class($this->owner))->isChangeTrackingNotify()) {
228 1
            $this->uow->scheduleForDirtyCheck($this->owner);
229 1
        }
230 164
    }
231
232
    /**
233
     * Gets a boolean flag indicating whether this collection is dirty which means
234
     * its state needs to be synchronized with the database.
235
     *
236
     * @return boolean TRUE if the collection is dirty, FALSE otherwise.
237
     */
238 364
    public function isDirty()
239
    {
240 364
        return $this->isDirty;
241
    }
242
243
    /**
244
     * Sets a boolean flag, indicating whether this collection is dirty.
245
     *
246
     * @param boolean $dirty Whether the collection should be marked dirty or not.
247
     */
248 357
    public function setDirty($dirty)
249
    {
250 357
        $this->isDirty = $dirty;
251 357
    }
252
253
    /**
254
     * INTERNAL:
255
     * Sets the collection's owning entity together with the AssociationMapping that
256
     * describes the association between the owner and the elements of the collection.
257
     *
258
     * @param object $document
259
     * @param array $mapping
260
     */
261 371
    public function setOwner($document, array $mapping)
262
    {
263 371
        $this->owner = $document;
264 371
        $this->mapping = $mapping;
265
266 371
        if ( ! empty($this->mapping['targetDocument'])) {
267 359
            $this->typeClass = $this->dm->getClassMetadata($this->mapping['targetDocument']);
268 359
        }
269 371
    }
270
271
    /**
272
     * INTERNAL:
273
     * Tells this collection to take a snapshot of its current state reindexing
274
     * itself numerically if using save strategy that is enforcing BSON array.
275
     * Reindexing is safe as snapshot is taken only after synchronizing collection
276
     * with database or clearing it.
277
     */
278 241
    public function takeSnapshot()
279
    {
280 241
        if (CollectionHelper::isList($this->mapping['strategy'])) {
281 228
            $array = $this->coll->toArray();
282 228
            $this->coll->clear();
283 228
            foreach ($array as $document) {
284 206
                $this->coll->add($document);
285 228
            }
286 228
        }
287 241
        $this->snapshot = $this->coll->toArray();
288 241
        $this->isDirty = false;
289 241
    }
290
291
    /**
292
     * INTERNAL:
293
     * Clears the internal snapshot information and sets isDirty to true if the collection
294
     * has elements.
295
     */
296 22
    public function clearSnapshot()
297
    {
298 22
        $this->snapshot = array();
299 22
        $this->isDirty = $this->coll->count() ? true : false;
300 22
    }
301
302
    /**
303
     * INTERNAL:
304
     * Returns the last snapshot of the elements in the collection.
305
     *
306
     * @return array The last snapshot of the elements.
307
     */
308
    public function getSnapshot()
309
    {
310
        return $this->snapshot;
311
    }
312
313
    /**
314
     * INTERNAL:
315
     * getDeleteDiff
316
     *
317
     * @return array
318
     */
319 79 View Code Duplication
    public function getDeleteDiff()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
320
    {
321 79
        return array_udiff_assoc(
322 79
            $this->snapshot,
323 79
            $this->coll->toArray(),
324
            function ($a, $b) { return $a === $b ? 0 : 1; }
325 79
        );
326
    }
327
328
    /**
329
     * INTERNAL: get objects that were removed, unlike getDeleteDiff this doesn't care about indices.
330
     *
331
     * @return array
332
     */
333
    public function getDeletedDocuments()
334 79
    {
335
        $compare = function ($a, $b) {
336 79
            $compareA = is_object($a) ? spl_object_hash($a) : $a;
337 79
            $compareb = is_object($b) ? spl_object_hash($b) : $b;
338 79
            return $compareA === $compareb ? 0 : ($compareA > $compareb ? 1 : -1);
339
        };
340 79
341
        return array_udiff(
342
            $this->snapshot,
343
            $this->coll->toArray(),
344
            $compare
345
        );
346
    }
347
348
    /**
349 364
     * INTERNAL:
350
     * getInsertDiff
351 364
     *
352
     * @return array
353
     */
354 View Code Duplication
    public function getInsertDiff()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
355
    {
356
        return array_udiff_assoc(
357 244
            $this->coll->toArray(),
358
            $this->snapshot,
359 244
            function ($a, $b) { return $a === $b ? 0 : 1; }
360
        );
361
    }
362
363
    /**
364
     * INTERNAL:
365
     * Gets the collection owner.
366 2
     *
367
     * @return object
368 2
     */
369 1
    public function getOwner()
370
    {
371
        return $this->owner;
372 1
    }
373
374
    /**
375
     * @return array
376
     */
377
    public function getMapping()
378
    {
379
        return $this->mapping;
380 242
    }
381
382 242
    /**
383 242
     * @return ClassMetadata
384
     * @throws MongoDBException
385
     */
386
    public function getTypeClass()
387
    {
388
        if (empty($this->typeClass)) {
389
            throw new MongoDBException('Specifying targetDocument is required for the ClassMetadata to be obtained.');
390 15
        }
391
392 15
        return $this->typeClass;
393
    }
394
395
    /**
396 12
     * Sets the initialized flag of the collection, forcing it into that state.
397
     *
398 12
     * @param boolean $bool
399 12
     */
400
    public function setInitialized($bool)
401
    {
402
        $this->initialized = $bool;
403 1
    }
404
405 1
    /**
406 1
     * Checks whether this collection has been initialized.
407
     *
408
     * @return boolean
409
     */
410
    public function isInitialized()
411
    {
412 20
        return $this->initialized;
413
    }
414 20
415 20
    /** {@inheritdoc} */
416
    public function first()
417 20
    {
418
        $this->initialize();
419
        return $this->coll->first();
420
    }
421 20
422
    /** {@inheritdoc} */
423 20
    public function last()
424 12
    {
425 12
        $this->initialize();
426
        return $this->coll->last();
427 20
    }
428
429
    /**
430
     * {@inheritdoc}
431
     */
432 View Code Duplication
    public function remove($key)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
433 10
    {
434
        $this->initialize();
435 10
        $removed = $this->coll->remove($key);
436 10
437
        if ( ! $removed) {
438 10
            return $removed;
439
        }
440
441
        $this->changed();
442 10
443
        return $removed;
444 10
    }
445 8
446 8
    /**
447
     * {@inheritdoc}
448 10
     */
449 View Code Duplication
    public function removeElement($element)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
450
    {
451
        $this->initialize();
452
        $removed = $this->coll->removeElement($element);
453
454 1
        if ( ! $removed) {
455
            return $removed;
456 1
        }
457 1
458
        $this->changed();
459
460
        return $removed;
461
    }
462
463 2
    /**
464
     * {@inheritdoc}
465 2
     */
466 2
    public function containsKey($key)
467
    {
468
        $this->initialize();
469
        return $this->coll->containsKey($key);
470
    }
471
472
    /**
473
     * {@inheritdoc}
474
     */
475
    public function contains($element)
476
    {
477
        $this->initialize();
478
        return $this->coll->contains($element);
479
    }
480
481 1
    /**
482
     * {@inheritdoc}
483 1
     */
484 1
    public function exists(\Closure $p)
485
    {
486
        $this->initialize();
487
        return $this->coll->exists($p);
488
    }
489
490 87
    /**
491
     * {@inheritdoc}
492 87
     */
493 87
    public function indexOf($element)
494
    {
495
        $this->initialize();
496
        return $this->coll->indexOf($element);
497
    }
498
499
    /**
500
     * {@inheritdoc}
501
     */
502
    public function get($key)
503
    {
504
        $this->initialize();
505
        return $this->coll->get($key);
506
    }
507
508
    /**
509
     * {@inheritdoc}
510
     */
511
    public function getKeys()
512
    {
513
        $this->initialize();
514
        return $this->coll->getKeys();
515
    }
516
517 345
    /**
518
     * {@inheritdoc}
519 345
     */
520
    public function getValues()
521
    {
522 345
        $this->initialize();
523 10
        return $this->coll->getValues();
524 10
    }
525 10
526 10
    /**
527 10
     * {@inheritdoc}
528
     */
529 345
    public function count()
530
    {
531
        $count = $this->coll->count();
532
533
        // If this collection is inversed and not initialized, add the count returned from the database
534
        if ($this->mapping['isInverseSide'] && ! $this->initialized) {
535 27
            $documentPersister = $this->uow->getDocumentPersister(get_class($this->owner));
536
            $count += empty($this->mapping['repositoryMethod'])
537 27
                ? $documentPersister->createReferenceManyInverseSideQuery($this)->count()
538 27
                : $documentPersister->createReferenceManyWithRepositoryMethodCursor($this)->count();
539
        }
540
541 27
        return count($this->mongoData) + $count;
542 26
    }
543 2
544 2
    /**
545
     * {@inheritdoc}
546 26
     */
547 26
    public function set($key, $value)
548 26
    {
549 26
        $this->coll->set($key, $value);
550
551 27
        // Handle orphanRemoval
552 27 View Code Duplication
        if ($this->uow !== null && $this->isOrphanRemovalEnabled() && $value !== null) {
0 ignored issues
show
Duplication introduced by
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...
553
            $this->uow->unscheduleOrphanRemoval($value);
554
        }
555
556
        $this->changed();
557 140
    }
558
559
    /**
560
     * {@inheritdoc}
561
     */
562
    public function add($value)
563 140
    {
564 9
        /* Initialize the collection before calling add() so this append operation
565 9
         * uses the appropriate key. Otherwise, we risk overwriting original data
566 140
         * when $newObjects are re-added in a later call to initialize().
567 140
         */
568
        if (isset($this->mapping['strategy']) && CollectionHelper::isHash($this->mapping['strategy'])) {
569 140
            $this->initialize();
570 82
        }
571 82
        $this->coll->add($value);
572
        $this->changed();
573 140
574 View Code Duplication
        if ($this->uow !== null && $this->isOrphanRemovalEnabled() && $value !== null) {
0 ignored issues
show
Duplication introduced by
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...
575
            $this->uow->unscheduleOrphanRemoval($value);
576
        }
577
578
        return true;
579 338
    }
580
581 338
    /**
582
     * {@inheritdoc}
583
     */
584
    public function isEmpty()
585
    {
586
        return $this->count() === 0;
587 298
    }
588
589 298
    /**
590 298
     * {@inheritdoc}
591
     */
592
    public function getIterator()
593
    {
594
        $this->initialize();
595
        return $this->coll->getIterator();
596 198
    }
597
598 198
    /**
599 198
     * {@inheritdoc}
600
     */
601
    public function map(\Closure $func)
602
    {
603
        $this->initialize();
604
        return $this->coll->map($func);
605
    }
606
607
    /**
608
     * {@inheritdoc}
609
     */
610
    public function filter(\Closure $p)
611
    {
612
        $this->initialize();
613
        return $this->coll->filter($p);
614
    }
615
616
    /**
617
     * {@inheritdoc}
618
     */
619
    public function forAll(\Closure $p)
620
    {
621
        $this->initialize();
622
        return $this->coll->forAll($p);
623
    }
624
625
    /**
626
     * {@inheritdoc}
627
     */
628
    public function partition(\Closure $p)
629
    {
630
        $this->initialize();
631
        return $this->coll->partition($p);
632 15
    }
633
634 15
    /**
635 15
     * {@inheritdoc}
636
     */
637
    public function toArray()
638
    {
639
        $this->initialize();
640
        return $this->coll->toArray();
641 27
    }
642
643 27
    /**
644
     * {@inheritdoc}
645
     */
646
    public function clear()
647 27
    {
648 26
        if ($this->initialized && $this->isEmpty()) {
649 24
            return;
650 26
        }
651 26
652
        if ($this->isOrphanRemovalEnabled()) {
653 27
            foreach ($this->coll as $element) {
654 27
                $this->uow->scheduleOrphanRemoval($element);
655
            }
656
        }
657 27
658
        $this->mongoData = array();
659
        $this->coll->clear();
660
661
        // Nothing to do for inverse-side collections
662 27
        if ( ! $this->mapping['isOwningSide']) {
663 2
            return;
664
        }
665
666 25
        // Nothing to do if the collection was initialized but contained no data
667 25
        if ($this->initialized && empty($this->snapshot)) {
668 25
            return;
669 25
        }
670
671
        $this->changed();
672
        $this->uow->scheduleCollectionDeletion($this);
673
        $this->takeSnapshot();
674 1
    }
675
676 1
    /**
677 1
     * {@inheritdoc}
678
     */
679
    public function slice($offset, $length = null)
680
    {
681
        $this->initialize();
682
        return $this->coll->slice($offset, $length);
683
    }
684
685
    /**
686
     * Called by PHP when this collection is serialized. Ensures that only the
687 1
     * elements are properly serialized.
688
     *
689 1
     * @internal Tried to implement Serializable first but that did not work well
690
     *           with circular references. This solution seems simpler and works well.
691
     */
692
    public function __sleep()
693
    {
694
        return array('coll', 'initialized');
695
    }
696
697 1
    /* ArrayAccess implementation */
698
699 1
    /**
700
     * @see containsKey()
701
     */
702
    public function offsetExists($offset)
703
    {
704
        return $this->containsKey($offset);
705 75
    }
706
707 75
    /**
708
     * @see get()
709
     */
710
    public function offsetGet($offset)
711
    {
712
        return $this->get($offset);
713
    }
714 38
715
    /**
716 38
     * @see add()
717 37
     * @see set()
718
     */
719
    public function offsetSet($offset, $value)
720 2
    {
721
        if ( ! isset($offset)) {
722
            return $this->add($value);
723
        }
724
725
        return $this->set($offset, $value);
726 17
    }
727
728 17
    /**
729
     * @see remove()
730
     */
731
    public function offsetUnset($offset)
732
    {
733
        return $this->remove($offset);
734
    }
735
736
    public function key()
737
    {
738
        return $this->coll->key();
739 1
    }
740
741 1
    /**
742
     * Gets the element of the collection at the current iterator position.
743
     */
744
    public function current()
745
    {
746
        return $this->coll->current();
747
    }
748
749
    /**
750
     * Moves the internal iterator position to the next element.
751
     */
752
    public function next()
753
    {
754
        return $this->coll->next();
755 364
    }
756
757 364
    /**
758
     * Retrieves the wrapped Collection instance.
759
     */
760
    public function unwrap()
761
    {
762
        return $this->coll;
763
    }
764
765
    /**
766
     * Cleanup internal state of cloned persistent collection.
767
     *
768
     * The following problems have to be prevented:
769
     * 1. Added documents are added to old PersistentCollection
770
     * 2. New collection is not dirty, if reused on other document nothing
771 8
     * changes.
772
     * 3. Snapshot leads to invalid diffs being generated.
773 8
     * 4. Lazy loading grabs entities from old owner object.
774 8
     * 5. New collection is connected to old owner and leads to duplicate keys.
775 8
     */
776
    public function __clone()
777 8
    {
778
        if (is_object($this->coll)) {
779 8
            $this->coll = clone $this->coll;
780 8
        }
781
782 8
        $this->initialize();
783 8
784
        $this->owner = null;
785
        $this->snapshot = array();
786
787
        $this->changed();
788
    }
789
790
    /**
791
     * Returns whether or not this collection has orphan removal enabled.
792
     *
793 163
     * Embedded documents are automatically considered as "orphan removal enabled" because they might have references
794
     * that require to trigger cascade remove operations.
795 163
     *
796
     * @return boolean
797
     */
798
    private function isOrphanRemovalEnabled()
799 163
    {
800 97
        if ($this->mapping === null) {
801
            return false;
802
        }
803 72
804 6
        if (isset($this->mapping['embedded'])) {
805
            return true;
806
        }
807 66
808
        if (isset($this->mapping['reference']) && $this->mapping['isOwningSide'] && $this->mapping['orphanRemoval']) {
809
            return true;
810
        }
811
812
        return false;
813
    }
814
}
815