Completed
Pull Request — master (#1462)
by Maciej
11:31
created

PersistentCollectionTrait::__sleep()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 4
ccs 2
cts 2
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\PersistentCollection;
21
22
use Doctrine\Common\Collections\Collection as BaseCollection;
23
use Doctrine\ODM\MongoDB\DocumentManager;
24
use Doctrine\ODM\MongoDB\Mapping\ClassMetadata;
25
use Doctrine\ODM\MongoDB\MongoDBException;
26
use Doctrine\ODM\MongoDB\UnitOfWork;
27
use Doctrine\ODM\MongoDB\Utility\CollectionHelper;
28
29
/**
30
 * Trait with methods needed to implement PersistentCollectionInterface.
31
 *
32
 * @since 1.1
33
 */
34
trait PersistentCollectionTrait
35
{
36
    /**
37
     * A snapshot of the collection at the moment it was fetched from the database.
38
     * This is used to create a diff of the collection at commit time.
39
     *
40
     * @var array
41
     */
42
    private $snapshot = array();
43
44
    /**
45
     * Collection's owning entity
46
     *
47
     * @var object
48
     */
49
    private $owner;
50
51
    /**
52
     * @var array
53
     */
54
    private $mapping;
55
56
    /**
57
     * Whether the collection is dirty and needs to be synchronized with the database
58
     * when the UnitOfWork that manages its persistent state commits.
59
     *
60
     * @var boolean
61
     */
62
    private $isDirty = false;
63
64
    /**
65
     * Whether the collection has already been initialized.
66
     *
67
     * @var boolean
68
     */
69
    private $initialized = true;
70
71
    /**
72
     * The wrapped Collection instance.
73
     *
74
     * @var BaseCollection
75
     */
76
    private $coll;
77
78
    /**
79
     * The DocumentManager that manages the persistence of the collection.
80
     *
81
     * @var DocumentManager
82
     */
83
    private $dm;
84
85
    /**
86
     * The UnitOfWork that manages the persistence of the collection.
87
     *
88
     * @var UnitOfWork
89
     */
90
    private $uow;
91
92
    /**
93
     * The raw mongo data that will be used to initialize this collection.
94
     *
95
     * @var array
96
     */
97
    private $mongoData = array();
98
99
    /**
100
     * Any hints to account for during reconstitution/lookup of the documents.
101
     *
102
     * @var array
103
     */
104
    private $hints = array();
105
106
    /** {@inheritdoc} */
107 2
    public function setDocumentManager(DocumentManager $dm)
108
    {
109 2
        $this->dm = $dm;
110 2
        $this->uow = $dm->getUnitOfWork();
111 2
    }
112
113
    /** {@inheritdoc} */
114 180
    public function setMongoData(array $mongoData)
115
    {
116 180
        $this->mongoData = $mongoData;
117 180
    }
118
119
    /** {@inheritdoc} */
120 156
    public function getMongoData()
121
    {
122 156
        return $this->mongoData;
123
    }
124
125
    /** {@inheritdoc} */
126 265
    public function setHints(array $hints)
127
    {
128 265
        $this->hints = $hints;
129 265
    }
130
131
    /** {@inheritdoc} */
132 170
    public function getHints()
133
    {
134 170
        return $this->hints;
135
    }
136
137
    /** {@inheritdoc} */
138 389
    public function initialize()
139
    {
140 389
        if ($this->initialized || ! $this->mapping) {
141 382
            return;
142
        }
143
144 168
        $newObjects = array();
145
146 168
        if ($this->isDirty) {
147
            // Remember any NEW objects added through add()
148 22
            $newObjects = $this->coll->toArray();
149
        }
150
151 168
        $this->initialized = true;
152
153 168
        $this->coll->clear();
154 168
        $this->uow->loadCollection($this);
155 168
        $this->takeSnapshot();
156
157 168
        $this->mongoData = array();
158
159
        // Reattach any NEW objects added through add()
160 168
        if ($newObjects) {
161 22
            foreach ($newObjects as $key => $obj) {
162 22
                if (CollectionHelper::isHash($this->mapping['strategy'])) {
163
                    $this->coll->set($key, $obj);
164
                } else {
165 22
                    $this->coll->add($obj);
166
                }
167
            }
168
169 22
            $this->isDirty = true;
170
        }
171 168
    }
172
173
    /**
174
     * Marks this collection as changed/dirty.
175
     */
176 199
    private function changed()
177
    {
178 199
        if ($this->isDirty) {
179 128
            return;
180
        }
181
182 199
        $this->isDirty = true;
183
184 199
        if ($this->needsSchedulingForDirtyCheck()) {
185 2
            $this->uow->scheduleForDirtyCheck($this->owner);
186
        }
187 199
    }
188
189
    /** {@inheritdoc} */
190 402
    public function isDirty()
191
    {
192 402
        if ($this->isDirty) {
193 258
            return true;
194
        }
195 350
        if (! $this->initialized && count($this->coll)) {
196
            // not initialized collection with added elements
197
            return true;
198
        }
199 350
        if ($this->initialized) {
200
            // if initialized let's check with last known snapshot
201 343
            return $this->coll->toArray() !== $this->snapshot;
202
        }
203 95
        return false;
204
    }
205
206
    /** {@inheritdoc} */
207 391
    public function setDirty($dirty)
208
    {
209 391
        $this->isDirty = $dirty;
210 391
    }
211
212
    /** {@inheritdoc} */
213 412
    public function setOwner($document, array $mapping)
214
    {
215 412
        $this->owner = $document;
216 412
        $this->mapping = $mapping;
217 412
    }
218
219
    /** {@inheritdoc} */
220 281
    public function takeSnapshot()
221
    {
222 281
        if (CollectionHelper::isList($this->mapping['strategy'])) {
223 267
            $array = $this->coll->toArray();
224 267
            $this->coll->clear();
225 267
            foreach ($array as $document) {
226 242
                $this->coll->add($document);
227
            }
228
        }
229 281
        $this->snapshot = $this->coll->toArray();
230 281
        $this->isDirty = false;
231 281
    }
232
233
    /** {@inheritdoc} */
234 23
    public function clearSnapshot()
235
    {
236 23
        $this->snapshot = array();
237 23
        $this->isDirty = $this->coll->count() ? true : false;
238 23
    }
239
240
    /** {@inheritdoc} */
241
    public function getSnapshot()
242
    {
243
        return $this->snapshot;
244
    }
245
246
    /** {@inheritdoc} */
247 89 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...
248
    {
249 89
        return array_udiff_assoc(
250 89
            $this->snapshot,
251 89
            $this->coll->toArray(),
252
            function ($a, $b) { return $a === $b ? 0 : 1; }
253
        );
254
    }
255
256
    /** {@inheritdoc} */
257 151 View Code Duplication
    public function getDeletedDocuments()
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...
258
    {
259
        $compare = function ($a, $b) {
260 104
            $compareA = is_object($a) ? spl_object_hash($a) : $a;
261 104
            $compareb = is_object($b) ? spl_object_hash($b) : $b;
262 104
            return $compareA === $compareb ? 0 : ($compareA > $compareb ? 1 : -1);
263 151
        };
264 151
        return array_values(array_udiff(
265 151
            $this->snapshot,
266 151
            $this->coll->toArray(),
267
            $compare
268
        ));
269
    }
270
271
    /** {@inheritdoc} */
272 89 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...
273
    {
274 89
        return array_udiff_assoc(
275 89
            $this->coll->toArray(),
276 89
            $this->snapshot,
277
            function ($a, $b) { return $a === $b ? 0 : 1; }
278
        );
279
    }
280
281
    /** {@inheritdoc} */
282 View Code Duplication
    public function getInsertedDocuments()
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...
283
    {
284 4
        $compare = function ($a, $b) {
285 4
            $compareA = is_object($a) ? spl_object_hash($a) : $a;
286 4
            $compareb = is_object($b) ? spl_object_hash($b) : $b;
287 4
            return $compareA === $compareb ? 0 : ($compareA > $compareb ? 1 : -1);
288 4
        };
289 4
        return array_values(array_udiff(
290 4
            $this->coll->toArray(),
291 4
            $this->snapshot,
292
            $compare
293
        ));
294
    }
295
296
    /** {@inheritdoc} */
297 401
    public function getOwner()
298
    {
299 401
        return $this->owner;
300
    }
301
302
    /** {@inheritdoc} */
303 274
    public function getMapping()
304
    {
305 274
        return $this->mapping;
306
    }
307
308
    /** {@inheritdoc} */
309 5
    public function getTypeClass()
310
    {
311
        switch (true) {
312 5
            case ($this->dm === null):
313 1
                throw new MongoDBException('No DocumentManager is associated with this PersistentCollection, please set one using setDocumentManager method.');
314
            case (empty($this->mapping)):
315 1
                throw new MongoDBException('No mapping is associated with this PersistentCollection, please set one using setOwner method.');
316 3
            case (empty($this->mapping['targetDocument'])):
317 1
                throw new MongoDBException('Specifying targetDocument is required for the ClassMetadata to be obtained.');
318
            default:
319 2
                return $this->dm->getClassMetadata($this->mapping['targetDocument']);
320
        }
321
    }
322
323
    /** {@inheritdoc} */
324 268
    public function setInitialized($bool)
325
    {
326 268
        $this->initialized = $bool;
327 268
    }
328
329
    /** {@inheritdoc} */
330 17
    public function isInitialized()
331
    {
332 17
        return $this->initialized;
333
    }
334
335
    /** {@inheritdoc} */
336 14
    public function first()
337
    {
338 14
        $this->initialize();
339 14
        return $this->coll->first();
340
    }
341
342
    /** {@inheritdoc} */
343 2
    public function last()
344
    {
345 2
        $this->initialize();
346 2
        return $this->coll->last();
347
    }
348
349
    /**
350
     * {@inheritdoc}
351
     */
352 4
    public function remove($key)
353
    {
354 4
        return $this->doRemove($key, false);
355
    }
356
357
    /**
358
     * {@inheritdoc}
359
     */
360 17
    public function removeElement($element)
361
    {
362 17
        $this->initialize();
363 17
        $removed = $this->coll->removeElement($element);
364
365 17
        if ( ! $removed) {
366
            return $removed;
367
        }
368
369 17
        $this->changed();
370
371 17
        return $removed;
372
    }
373
374
    /**
375
     * {@inheritdoc}
376
     */
377
    public function containsKey($key)
378
    {
379
        $this->initialize();
380
        return $this->coll->containsKey($key);
381
    }
382
383
    /**
384
     * {@inheritdoc}
385
     */
386 2
    public function contains($element)
387
    {
388 2
        $this->initialize();
389 2
        return $this->coll->contains($element);
390
    }
391
392
    /**
393
     * {@inheritdoc}
394
     */
395
    public function exists(\Closure $p)
396
    {
397
        $this->initialize();
398
        return $this->coll->exists($p);
399
    }
400
401
    /**
402
     * {@inheritdoc}
403
     */
404 2
    public function indexOf($element)
405
    {
406 2
        $this->initialize();
407 2
        return $this->coll->indexOf($element);
408
    }
409
410
    /**
411
     * {@inheritdoc}
412
     */
413 19
    public function get($key)
414
    {
415 19
        $this->initialize();
416 19
        return $this->coll->get($key);
417
    }
418
419
    /**
420
     * {@inheritdoc}
421
     */
422
    public function getKeys()
423
    {
424
        $this->initialize();
425
        return $this->coll->getKeys();
426
    }
427
428
    /**
429
     * {@inheritdoc}
430
     */
431
    public function getValues()
432
    {
433
        $this->initialize();
434
        return $this->coll->getValues();
435
    }
436
437
    /**
438
     * {@inheritdoc}
439
     */
440 117
    public function count()
441
    {
442 117
        $count = $this->coll->count();
443
444
        // If this collection is inversed and not initialized, add the count returned from the database
445 117
        if ($this->mapping['isInverseSide'] && ! $this->initialized) {
446 10
            $documentPersister = $this->uow->getDocumentPersister(get_class($this->owner));
447 10
            $count += empty($this->mapping['repositoryMethod'])
448 9
                ? $documentPersister->createReferenceManyInverseSideQuery($this)->count()
449 1
                : $documentPersister->createReferenceManyWithRepositoryMethodCursor($this)->count();
450
        }
451
452 117
        return $count + ($this->initialized ? 0 : count($this->mongoData));
453
    }
454
455
    /**
456
     * {@inheritdoc}
457
     */
458 35
    public function set($key, $value)
459
    {
460 35
        return $this->doSet($key, $value, false);
461
    }
462
463
    /**
464
     * {@inheritdoc}
465
     */
466 154
    public function add($value)
467
    {
468 154
        return $this->doAdd($value, false);
469
    }
470
471
    /**
472
     * {@inheritdoc}
473
     */
474 378
    public function isEmpty()
475
    {
476 378
        return $this->initialized ? $this->coll->isEmpty() : $this->count() === 0;
477
    }
478
479
    /**
480
     * {@inheritdoc}
481
     */
482 329
    public function getIterator()
483
    {
484 329
        $this->initialize();
485 329
        return $this->coll->getIterator();
486
    }
487
488
    /**
489
     * {@inheritdoc}
490
     */
491 221
    public function map(\Closure $func)
492
    {
493 221
        $this->initialize();
494 221
        return $this->coll->map($func);
495
    }
496
497
    /**
498
     * {@inheritdoc}
499
     */
500
    public function filter(\Closure $p)
501
    {
502
        $this->initialize();
503
        return $this->coll->filter($p);
504
    }
505
506
    /**
507
     * {@inheritdoc}
508
     */
509
    public function forAll(\Closure $p)
510
    {
511
        $this->initialize();
512
        return $this->coll->forAll($p);
513
    }
514
515
    /**
516
     * {@inheritdoc}
517
     */
518
    public function partition(\Closure $p)
519
    {
520
        $this->initialize();
521
        return $this->coll->partition($p);
522
    }
523
524
    /**
525
     * {@inheritdoc}
526
     */
527 23
    public function toArray()
528
    {
529 23
        $this->initialize();
530 23
        return $this->coll->toArray();
531
    }
532
533
    /**
534
     * {@inheritdoc}
535
     */
536 28
    public function clear()
537
    {
538 28
        if ($this->initialized && $this->isEmpty()) {
539
            return;
540
        }
541
542 28
        if ($this->isOrphanRemovalEnabled()) {
543 27
            foreach ($this->coll as $element) {
544 25
                $this->uow->scheduleOrphanRemoval($element);
545
            }
546
        }
547
548 28
        $this->mongoData = array();
549 28
        $this->coll->clear();
550
551
        // Nothing to do for inverse-side collections
552 28
        if ( ! $this->mapping['isOwningSide']) {
553
            return;
554
        }
555
556
        // Nothing to do if the collection was initialized but contained no data
557 28
        if ($this->initialized && empty($this->snapshot)) {
558 2
            return;
559
        }
560
561 26
        $this->changed();
562 26
        $this->uow->scheduleCollectionDeletion($this);
563 26
        $this->takeSnapshot();
564 26
    }
565
566
    /**
567
     * {@inheritdoc}
568
     */
569 1
    public function slice($offset, $length = null)
570
    {
571 1
        $this->initialize();
572 1
        return $this->coll->slice($offset, $length);
573
    }
574
575
    /**
576
     * Called by PHP when this collection is serialized. Ensures that only the
577
     * elements are properly serialized.
578
     *
579
     * @internal Tried to implement Serializable first but that did not work well
580
     *           with circular references. This solution seems simpler and works well.
581
     */
582 4
    public function __sleep()
583
    {
584 4
        return array('coll', 'initialized');
585
    }
586
587
    /* ArrayAccess implementation */
588
589
    /**
590
     * @see containsKey()
591
     */
592 2
    public function offsetExists($offset)
593
    {
594 2
        $this->initialize();
595 2
        return $this->coll->offsetExists($offset);
596
    }
597
598
    /**
599
     * @see get()
600
     */
601 81
    public function offsetGet($offset)
602
    {
603 81
        $this->initialize();
604 81
        return $this->coll->offsetGet($offset);
605
    }
606
607
    /**
608
     * @see add()
609
     * @see set()
610
     */
611 42
    public function offsetSet($offset, $value)
612
    {
613 42
        if ( ! isset($offset)) {
614 41
            return $this->doAdd($value, true);
615
        }
616
617 3
        return $this->doSet($offset, $value, true);
618
    }
619
620
    /**
621
     * @see remove()
622
     */
623 19
    public function offsetUnset($offset)
624
    {
625 19
        return $this->doRemove($offset, true);
626
    }
627
628
    public function key()
629
    {
630
        return $this->coll->key();
631
    }
632
633
    /**
634
     * Gets the element of the collection at the current iterator position.
635
     */
636 1
    public function current()
637
    {
638 1
        return $this->coll->current();
639
    }
640
641
    /**
642
     * Moves the internal iterator position to the next element.
643
     */
644
    public function next()
645
    {
646
        return $this->coll->next();
647
    }
648
649
    /**
650
     * {@inheritdoc}
651
     */
652 401
    public function unwrap()
653
    {
654 401
        return $this->coll;
655
    }
656
657
    /**
658
     * Cleanup internal state of cloned persistent collection.
659
     *
660
     * The following problems have to be prevented:
661
     * 1. Added documents are added to old PersistentCollection
662
     * 2. New collection is not dirty, if reused on other document nothing
663
     * changes.
664
     * 3. Snapshot leads to invalid diffs being generated.
665
     * 4. Lazy loading grabs entities from old owner object.
666
     * 5. New collection is connected to old owner and leads to duplicate keys.
667
     */
668 8
    public function __clone()
669
    {
670 8
        if (is_object($this->coll)) {
671 8
            $this->coll = clone $this->coll;
672
        }
673
674 8
        $this->initialize();
675
676 8
        $this->owner = null;
677 8
        $this->snapshot = array();
678
679 8
        $this->changed();
680 8
    }
681
682
    /**
683
     * Actual logic for adding an element to the collection.
684
     *
685
     * @param mixed $value
686
     * @param bool $arrayAccess
687
     * @return bool
688
     */
689 171
    private function doAdd($value, $arrayAccess)
690
    {
691
        /* Initialize the collection before calling add() so this append operation
692
         * uses the appropriate key. Otherwise, we risk overwriting original data
693
         * when $newObjects are re-added in a later call to initialize().
694
         */
695 171
        if (isset($this->mapping['strategy']) && CollectionHelper::isHash($this->mapping['strategy'])) {
696 12
            $this->initialize();
697
        }
698 171
        $arrayAccess ? $this->coll->offsetSet(null, $value) : $this->coll->add($value);
699 171
        $this->changed();
700
701 171 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...
702 97
            $this->uow->unscheduleOrphanRemoval($value);
703
        }
704
705 171
        return true;
706
    }
707
708
    /**
709
     * Actual logic for removing element by its key.
710
     *
711
     * @param mixed $offset
712
     * @param bool $arrayAccess
713
     * @return mixed|void
714
     */
715 23
    private function doRemove($offset, $arrayAccess)
716
    {
717 23
        $this->initialize();
718 23
        $removed = $arrayAccess ? $this->coll->offsetUnset($offset) : $this->coll->remove($offset);
719
720 23
        if ( ! $removed && ! $arrayAccess) {
721
            return $removed;
722
        }
723
724 23
        $this->changed();
725
726 23
        return $removed;
727
    }
728
729
    /**
730
     * Actual logic for setting an element in the collection.
731
     *
732
     * @param mixed $offset
733
     * @param mixed $value
734
     * @param bool $arrayAccess
735
     * @return bool
736
     */
737 36
    private function doSet($offset, $value, $arrayAccess)
738
    {
739 36
        $arrayAccess ? $this->coll->offsetSet($offset, $value) : $this->coll->set($offset, $value);
740
741
        // Handle orphanRemoval
742 36 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...
743 34
            $this->uow->unscheduleOrphanRemoval($value);
744
        }
745
746 36
        $this->changed();
747 36
    }
748
749
    /**
750
     * Returns whether or not this collection has orphan removal enabled.
751
     *
752
     * Embedded documents are automatically considered as "orphan removal enabled" because they might have references
753
     * that require to trigger cascade remove operations.
754
     *
755
     * @return boolean
756
     */
757 191
    private function isOrphanRemovalEnabled()
758
    {
759 191
        if ($this->mapping === null) {
760 11
            return false;
761
        }
762
763 180
        if (isset($this->mapping['embedded'])) {
764 108
            return true;
765
        }
766
767 78
        if (isset($this->mapping['reference']) && $this->mapping['isOwningSide'] && $this->mapping['orphanRemoval']) {
768 8
            return true;
769
        }
770
771 70
        return false;
772
    }
773
774
    /**
775
     * Checks whether collection owner needs to be scheduled for dirty change in case the collection is modified.
776
     *
777
     * @return bool
778
     */
779 199
    private function needsSchedulingForDirtyCheck()
780
    {
781 199
        return $this->owner && $this->dm && ! empty($this->mapping['isOwningSide'])
782 199
            && $this->dm->getClassMetadata(get_class($this->owner))->isChangeTrackingNotify();
783
    }
784
}
785