Complex classes like DocumentPersister often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use DocumentPersister, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 63 | class DocumentPersister |
||
| 64 | { |
||
| 65 | /** @var PersistenceBuilder */ |
||
| 66 | private $pb; |
||
| 67 | |||
| 68 | /** @var DocumentManager */ |
||
| 69 | private $dm; |
||
| 70 | |||
| 71 | /** @var UnitOfWork */ |
||
| 72 | private $uow; |
||
| 73 | |||
| 74 | /** @var ClassMetadata */ |
||
| 75 | private $class; |
||
| 76 | |||
| 77 | /** @var Collection */ |
||
| 78 | private $collection; |
||
| 79 | |||
| 80 | /** @var Bucket|null */ |
||
| 81 | private $bucket; |
||
| 82 | |||
| 83 | /** |
||
| 84 | * Array of queued inserts for the persister to insert. |
||
| 85 | * |
||
| 86 | * @var array |
||
| 87 | */ |
||
| 88 | private $queuedInserts = []; |
||
| 89 | |||
| 90 | /** |
||
| 91 | * Array of queued inserts for the persister to insert. |
||
| 92 | * |
||
| 93 | * @var array |
||
| 94 | */ |
||
| 95 | private $queuedUpserts = []; |
||
| 96 | |||
| 97 | /** @var CriteriaMerger */ |
||
| 98 | private $cm; |
||
| 99 | |||
| 100 | /** @var CollectionPersister */ |
||
| 101 | private $cp; |
||
| 102 | |||
| 103 | /** @var HydratorFactory */ |
||
| 104 | private $hydratorFactory; |
||
| 105 | |||
| 106 | 1121 | public function __construct( |
|
| 129 | |||
| 130 | public function getInserts() : array |
||
| 134 | |||
| 135 | public function isQueuedForInsert(object $document) : bool |
||
| 139 | |||
| 140 | /** |
||
| 141 | * Adds a document to the queued insertions. |
||
| 142 | * The document remains queued until {@link executeInserts} is invoked. |
||
| 143 | */ |
||
| 144 | 512 | public function addInsert(object $document) : void |
|
| 148 | |||
| 149 | public function getUpserts() : array |
||
| 153 | |||
| 154 | public function isQueuedForUpsert(object $document) : bool |
||
| 158 | |||
| 159 | /** |
||
| 160 | * Adds a document to the queued upserts. |
||
| 161 | * The document remains queued until {@link executeUpserts} is invoked. |
||
| 162 | */ |
||
| 163 | 85 | public function addUpsert(object $document) : void |
|
| 167 | |||
| 168 | /** |
||
| 169 | * Gets the ClassMetadata instance of the document class this persister is used for. |
||
| 170 | */ |
||
| 171 | public function getClassMetadata() : ClassMetadata |
||
| 175 | |||
| 176 | /** |
||
| 177 | * Executes all queued document insertions. |
||
| 178 | * |
||
| 179 | * Queued documents without an ID will inserted in a batch and queued |
||
| 180 | * documents with an ID will be upserted individually. |
||
| 181 | * |
||
| 182 | * If no inserts are queued, invoking this method is a NOOP. |
||
| 183 | * |
||
| 184 | * @throws DriverException |
||
| 185 | */ |
||
| 186 | 512 | public function executeInserts(array $options = []) : void |
|
| 234 | |||
| 235 | /** |
||
| 236 | * Executes all queued document upserts. |
||
| 237 | * |
||
| 238 | * Queued documents with an ID are upserted individually. |
||
| 239 | * |
||
| 240 | * If no upserts are queued, invoking this method is a NOOP. |
||
| 241 | */ |
||
| 242 | 85 | public function executeUpserts(array $options = []) : void |
|
| 260 | |||
| 261 | /** |
||
| 262 | * Executes a single upsert in {@link executeUpserts} |
||
| 263 | */ |
||
| 264 | 85 | private function executeUpsert(object $document, array $options) : void |
|
| 330 | |||
| 331 | /** |
||
| 332 | * Updates the already persisted document if it has any new changesets. |
||
| 333 | * |
||
| 334 | * @throws LockException |
||
| 335 | */ |
||
| 336 | 221 | public function update(object $document, array $options = []) : void |
|
| 394 | |||
| 395 | /** |
||
| 396 | * Removes document from mongo |
||
| 397 | * |
||
| 398 | * @throws LockException |
||
| 399 | */ |
||
| 400 | 36 | public function delete(object $document, array $options = []) : void |
|
| 425 | |||
| 426 | /** |
||
| 427 | * Refreshes a managed document. |
||
| 428 | */ |
||
| 429 | 23 | public function refresh(object $document) : void |
|
| 436 | |||
| 437 | /** |
||
| 438 | * Finds a document by a set of criteria. |
||
| 439 | * |
||
| 440 | * If a scalar or MongoDB\BSON\ObjectId is provided for $criteria, it will |
||
| 441 | * be used to match an _id value. |
||
| 442 | * |
||
| 443 | * @param mixed $criteria Query criteria |
||
| 444 | * |
||
| 445 | * @throws LockException |
||
| 446 | * |
||
| 447 | * @todo Check identity map? loadById method? Try to guess whether $criteria is the id? |
||
| 448 | */ |
||
| 449 | 359 | public function load($criteria, ?object $document = null, array $hints = [], int $lockMode = 0, ?array $sort = null) : ?object |
|
| 450 | { |
||
| 451 | // TODO: remove this |
||
| 452 | 359 | if ($criteria === null || is_scalar($criteria) || $criteria instanceof ObjectId) { |
|
| 453 | $criteria = ['_id' => $criteria]; |
||
| 454 | } |
||
| 455 | |||
| 456 | 359 | $criteria = $this->prepareQueryOrNewObj($criteria); |
|
| 457 | 359 | $criteria = $this->addDiscriminatorToPreparedQuery($criteria); |
|
| 458 | 359 | $criteria = $this->addFilterToPreparedQuery($criteria); |
|
| 459 | |||
| 460 | 359 | $options = []; |
|
| 461 | 359 | if ($sort !== null) { |
|
| 462 | 95 | $options['sort'] = $this->prepareSort($sort); |
|
| 463 | } |
||
| 464 | 359 | $result = $this->collection->findOne($criteria, $options); |
|
| 465 | |||
| 466 | 359 | if ($this->class->isLockable) { |
|
| 467 | 1 | $lockMapping = $this->class->fieldMappings[$this->class->lockField]; |
|
| 468 | 1 | if (isset($result[$lockMapping['name']]) && $result[$lockMapping['name']] === LockMode::PESSIMISTIC_WRITE) { |
|
| 469 | 1 | throw LockException::lockFailed($document); |
|
| 470 | } |
||
| 471 | } |
||
| 472 | |||
| 473 | 358 | if ($result === null) { |
|
| 474 | 115 | return null; |
|
| 475 | } |
||
| 476 | |||
| 477 | 314 | return $this->createDocument($result, $document, $hints); |
|
| 478 | } |
||
| 479 | |||
| 480 | /** |
||
| 481 | * Finds documents by a set of criteria. |
||
| 482 | */ |
||
| 483 | 22 | public function loadAll(array $criteria = [], ?array $sort = null, ?int $limit = null, ?int $skip = null) : Iterator |
|
| 484 | { |
||
| 485 | 22 | $criteria = $this->prepareQueryOrNewObj($criteria); |
|
| 486 | 22 | $criteria = $this->addDiscriminatorToPreparedQuery($criteria); |
|
| 487 | 22 | $criteria = $this->addFilterToPreparedQuery($criteria); |
|
| 488 | |||
| 489 | 22 | $options = []; |
|
| 490 | 22 | if ($sort !== null) { |
|
| 491 | 11 | $options['sort'] = $this->prepareSort($sort); |
|
| 492 | } |
||
| 493 | |||
| 494 | 22 | if ($limit !== null) { |
|
| 495 | 10 | $options['limit'] = $limit; |
|
| 496 | } |
||
| 497 | |||
| 498 | 22 | if ($skip !== null) { |
|
| 499 | 1 | $options['skip'] = $skip; |
|
| 500 | } |
||
| 501 | |||
| 502 | 22 | $baseCursor = $this->collection->find($criteria, $options); |
|
| 503 | 22 | return $this->wrapCursor($baseCursor); |
|
| 504 | } |
||
| 505 | |||
| 506 | /** |
||
| 507 | * @throws MongoDBException |
||
| 508 | */ |
||
| 509 | 301 | private function getShardKeyQuery(object $document) : array |
|
| 510 | { |
||
| 511 | 301 | if (! $this->class->isSharded()) { |
|
| 512 | 291 | return []; |
|
| 513 | } |
||
| 514 | |||
| 515 | 10 | $shardKey = $this->class->getShardKey(); |
|
| 516 | 10 | $keys = array_keys($shardKey['keys']); |
|
| 517 | 10 | $data = $this->uow->getDocumentActualData($document); |
|
| 518 | |||
| 519 | 10 | $shardKeyQueryPart = []; |
|
| 520 | 10 | foreach ($keys as $key) { |
|
| 521 | 10 | $mapping = $this->class->getFieldMappingByDbFieldName($key); |
|
| 522 | 10 | $this->guardMissingShardKey($document, $key, $data); |
|
| 523 | |||
| 524 | 8 | if (isset($mapping['association']) && $mapping['association'] === ClassMetadata::REFERENCE_ONE) { |
|
| 525 | 1 | $reference = $this->prepareReference( |
|
| 526 | 1 | $key, |
|
| 527 | 1 | $data[$mapping['fieldName']], |
|
| 528 | 1 | $mapping, |
|
| 529 | 1 | false |
|
| 530 | ); |
||
| 531 | 1 | foreach ($reference as $keyValue) { |
|
| 532 | 1 | $shardKeyQueryPart[$keyValue[0]] = $keyValue[1]; |
|
| 533 | } |
||
| 534 | } else { |
||
| 535 | 7 | $value = Type::getType($mapping['type'])->convertToDatabaseValue($data[$mapping['fieldName']]); |
|
| 536 | 8 | $shardKeyQueryPart[$key] = $value; |
|
| 537 | } |
||
| 538 | } |
||
| 539 | |||
| 540 | 8 | return $shardKeyQueryPart; |
|
| 541 | } |
||
| 542 | |||
| 543 | /** |
||
| 544 | * Wraps the supplied base cursor in the corresponding ODM class. |
||
| 545 | */ |
||
| 546 | 22 | private function wrapCursor(Cursor $baseCursor) : Iterator |
|
| 547 | { |
||
| 548 | 22 | return new CachingIterator(new HydratingIterator($baseCursor, $this->dm->getUnitOfWork(), $this->class)); |
|
| 549 | } |
||
| 550 | |||
| 551 | /** |
||
| 552 | * Checks whether the given managed document exists in the database. |
||
| 553 | */ |
||
| 554 | 3 | public function exists(object $document) : bool |
|
| 555 | { |
||
| 556 | 3 | $id = $this->class->getIdentifierObject($document); |
|
| 557 | 3 | return (bool) $this->collection->findOne(['_id' => $id], ['_id']); |
|
| 558 | } |
||
| 559 | |||
| 560 | /** |
||
| 561 | * Locks document by storing the lock mode on the mapped lock field. |
||
| 562 | */ |
||
| 563 | 5 | public function lock(object $document, int $lockMode) : void |
|
| 564 | { |
||
| 565 | 5 | $id = $this->uow->getDocumentIdentifier($document); |
|
| 566 | 5 | $criteria = ['_id' => $this->class->getDatabaseIdentifierValue($id)]; |
|
| 567 | 5 | $lockMapping = $this->class->fieldMappings[$this->class->lockField]; |
|
| 568 | 5 | $this->collection->updateOne($criteria, ['$set' => [$lockMapping['name'] => $lockMode]]); |
|
| 569 | 5 | $this->class->reflFields[$this->class->lockField]->setValue($document, $lockMode); |
|
| 570 | 5 | } |
|
| 571 | |||
| 572 | /** |
||
| 573 | * Releases any lock that exists on this document. |
||
| 574 | */ |
||
| 575 | 1 | public function unlock(object $document) : void |
|
| 576 | { |
||
| 577 | 1 | $id = $this->uow->getDocumentIdentifier($document); |
|
| 578 | 1 | $criteria = ['_id' => $this->class->getDatabaseIdentifierValue($id)]; |
|
| 579 | 1 | $lockMapping = $this->class->fieldMappings[$this->class->lockField]; |
|
| 580 | 1 | $this->collection->updateOne($criteria, ['$unset' => [$lockMapping['name'] => true]]); |
|
| 581 | 1 | $this->class->reflFields[$this->class->lockField]->setValue($document, null); |
|
| 582 | 1 | } |
|
| 583 | |||
| 584 | /** |
||
| 585 | * Creates or fills a single document object from an query result. |
||
| 586 | * |
||
| 587 | * @param array $result The query result. |
||
| 588 | * @param object $document The document object to fill, if any. |
||
| 589 | * @param array $hints Hints for document creation. |
||
| 590 | * |
||
| 591 | * @return object The filled and managed document object or NULL, if the query result is empty. |
||
| 592 | */ |
||
| 593 | 314 | private function createDocument(array $result, ?object $document = null, array $hints = []) : ?object |
|
| 594 | { |
||
| 595 | 314 | if ($document !== null) { |
|
| 596 | 26 | $hints[Query::HINT_REFRESH] = true; |
|
| 597 | 26 | $id = $this->class->getPHPIdentifierValue($result['_id']); |
|
| 598 | 26 | $this->uow->registerManaged($document, $id, $result); |
|
| 599 | } |
||
| 600 | |||
| 601 | 314 | return $this->uow->getOrCreateDocument($this->class->name, $result, $hints, $document); |
|
| 602 | } |
||
| 603 | |||
| 604 | /** |
||
| 605 | * Loads a PersistentCollection data. Used in the initialize() method. |
||
| 606 | */ |
||
| 607 | 178 | public function loadCollection(PersistentCollectionInterface $collection) : void |
|
| 628 | |||
| 629 | 126 | private function loadEmbedManyCollection(PersistentCollectionInterface $collection) : void |
|
| 630 | { |
||
| 631 | 126 | $embeddedDocuments = $collection->getMongoData(); |
|
| 632 | 126 | if (! $embeddedDocuments) { |
|
| 633 | 75 | return; |
|
| 634 | } |
||
| 635 | 97 | $mapping = $collection->getMapping(); |
|
| 636 | 97 | $owner = $collection->getOwner(); |
|
| 637 | 97 | $isHash = CollectionHelper::isHash($mapping['strategy']); |
|
| 638 | 97 | $classMetadataMap = []; |
|
| 639 | |||
| 640 | 97 | foreach ($embeddedDocuments as $key => $embeddedDocument) { |
|
| 641 | 97 | $className = $this->uow->getClassNameForAssociation($mapping, $embeddedDocument); |
|
| 642 | 97 | if (empty($classMetadataMap[$className])) { |
|
| 643 | 97 | $classMetadataMap[$className] = $this->dm->getClassMetadata($className); |
|
| 644 | } |
||
| 645 | 97 | $embeddedMetadata = $classMetadataMap[$className]; |
|
| 646 | 97 | $embeddedDocumentObject = $embeddedMetadata->newInstance(); |
|
| 647 | |||
| 648 | 97 | $this->uow->setParentAssociation($embeddedDocumentObject, $mapping, $owner, $mapping['name'] . '.' . $key); |
|
| 649 | |||
| 650 | 97 | $data = $this->hydratorFactory->hydrate($embeddedDocumentObject, $embeddedDocument, $collection->getHints()); |
|
| 651 | 97 | $id = $data[$embeddedMetadata->identifier] ?? null; |
|
| 652 | |||
| 653 | 97 | if (empty($collection->getHints()[Query::HINT_READ_ONLY])) { |
|
| 654 | 96 | $this->uow->registerManaged($embeddedDocumentObject, $id, $data); |
|
| 655 | } |
||
| 656 | 97 | if ($isHash) { |
|
| 657 | 25 | $collection->set($key, $embeddedDocumentObject); |
|
| 658 | } else { |
||
| 659 | 97 | $collection->add($embeddedDocumentObject); |
|
| 660 | } |
||
| 661 | } |
||
| 662 | 97 | } |
|
| 663 | |||
| 664 | 59 | private function loadReferenceManyCollectionOwningSide(PersistentCollectionInterface $collection) : void |
|
| 665 | { |
||
| 666 | 59 | $hints = $collection->getHints(); |
|
| 667 | 59 | $mapping = $collection->getMapping(); |
|
| 668 | 59 | $groupedIds = []; |
|
| 669 | |||
| 670 | 59 | $sorted = isset($mapping['sort']) && $mapping['sort']; |
|
| 671 | |||
| 672 | 59 | foreach ($collection->getMongoData() as $key => $reference) { |
|
| 673 | 53 | $className = $this->uow->getClassNameForAssociation($mapping, $reference); |
|
| 674 | 53 | $identifier = ClassMetadata::getReferenceId($reference, $mapping['storeAs']); |
|
| 675 | 53 | $id = $this->dm->getClassMetadata($className)->getPHPIdentifierValue($identifier); |
|
| 676 | |||
| 677 | // create a reference to the class and id |
||
| 678 | 53 | $reference = $this->dm->getReference($className, $id); |
|
| 679 | |||
| 680 | // no custom sort so add the references right now in the order they are embedded |
||
| 681 | 53 | if (! $sorted) { |
|
| 682 | 52 | if (CollectionHelper::isHash($mapping['strategy'])) { |
|
| 683 | 2 | $collection->set($key, $reference); |
|
| 684 | } else { |
||
| 685 | 50 | $collection->add($reference); |
|
| 686 | } |
||
| 687 | } |
||
| 688 | |||
| 689 | // only query for the referenced object if it is not already initialized or the collection is sorted |
||
| 690 | 53 | if (! (($reference instanceof GhostObjectInterface && ! $reference->isProxyInitialized())) && ! $sorted) { |
|
| 691 | 22 | continue; |
|
| 692 | } |
||
| 693 | |||
| 694 | 38 | $groupedIds[$className][] = $identifier; |
|
| 695 | } |
||
| 696 | 59 | foreach ($groupedIds as $className => $ids) { |
|
| 697 | 38 | $class = $this->dm->getClassMetadata($className); |
|
| 698 | 38 | $mongoCollection = $this->dm->getDocumentCollection($className); |
|
| 699 | 38 | $criteria = $this->cm->merge( |
|
| 700 | 38 | ['_id' => ['$in' => array_values($ids)]], |
|
| 701 | 38 | $this->dm->getFilterCollection()->getFilterCriteria($class), |
|
| 702 | 38 | $mapping['criteria'] ?? [] |
|
| 703 | ); |
||
| 704 | 38 | $criteria = $this->uow->getDocumentPersister($className)->prepareQueryOrNewObj($criteria); |
|
| 705 | |||
| 706 | 38 | $options = []; |
|
| 707 | 38 | if (isset($mapping['sort'])) { |
|
| 708 | 38 | $options['sort'] = $this->prepareSort($mapping['sort']); |
|
| 709 | } |
||
| 710 | 38 | if (isset($mapping['limit'])) { |
|
| 711 | $options['limit'] = $mapping['limit']; |
||
| 712 | } |
||
| 713 | 38 | if (isset($mapping['skip'])) { |
|
| 714 | $options['skip'] = $mapping['skip']; |
||
| 715 | } |
||
| 716 | 38 | if (! empty($hints[Query::HINT_READ_PREFERENCE])) { |
|
| 717 | $options['readPreference'] = $hints[Query::HINT_READ_PREFERENCE]; |
||
| 718 | } |
||
| 719 | |||
| 720 | 38 | $cursor = $mongoCollection->find($criteria, $options); |
|
| 721 | 38 | $documents = $cursor->toArray(); |
|
| 722 | 38 | foreach ($documents as $documentData) { |
|
| 723 | 37 | $document = $this->uow->getById($documentData['_id'], $class); |
|
| 724 | 37 | if ($document instanceof GhostObjectInterface && ! $document->isProxyInitialized()) { |
|
| 725 | 37 | $data = $this->hydratorFactory->hydrate($document, $documentData); |
|
| 726 | 37 | $this->uow->setOriginalDocumentData($document, $data); |
|
| 727 | } |
||
| 728 | |||
| 729 | 37 | if (! $sorted) { |
|
| 730 | 36 | continue; |
|
| 731 | } |
||
| 732 | |||
| 733 | 38 | $collection->add($document); |
|
| 734 | } |
||
| 735 | } |
||
| 736 | 59 | } |
|
| 737 | |||
| 738 | 17 | private function loadReferenceManyCollectionInverseSide(PersistentCollectionInterface $collection) : void |
|
| 739 | { |
||
| 740 | 17 | $query = $this->createReferenceManyInverseSideQuery($collection); |
|
| 741 | 17 | $documents = $query->execute()->toArray(); |
|
| 742 | 17 | foreach ($documents as $key => $document) { |
|
| 743 | 16 | $collection->add($document); |
|
| 744 | } |
||
| 745 | 17 | } |
|
| 746 | |||
| 747 | 17 | public function createReferenceManyInverseSideQuery(PersistentCollectionInterface $collection) : Query |
|
| 786 | |||
| 787 | 5 | private function loadReferenceManyWithRepositoryMethod(PersistentCollectionInterface $collection) : void |
|
| 800 | |||
| 801 | 5 | public function createReferenceManyWithRepositoryMethodCursor(PersistentCollectionInterface $collection) : Iterator |
|
| 822 | |||
| 823 | /** |
||
| 824 | * Prepare a projection array by converting keys, which are PHP property |
||
| 825 | * names, to MongoDB field names. |
||
| 826 | */ |
||
| 827 | 14 | public function prepareProjection(array $fields) : array |
|
| 837 | |||
| 838 | /** |
||
| 839 | * @param int|string|null $sort |
||
| 840 | * |
||
| 841 | * @return int|string|null |
||
| 842 | */ |
||
| 843 | 25 | private function getSortDirection($sort) |
|
| 855 | |||
| 856 | /** |
||
| 857 | * Prepare a sort specification array by converting keys to MongoDB field |
||
| 858 | * names and changing direction strings to int. |
||
| 859 | */ |
||
| 860 | 143 | public function prepareSort(array $fields) : array |
|
| 870 | |||
| 871 | /** |
||
| 872 | * Prepare a mongodb field name and convert the PHP property names to MongoDB field names. |
||
| 873 | */ |
||
| 874 | 436 | public function prepareFieldName(string $fieldName) : string |
|
| 880 | |||
| 881 | /** |
||
| 882 | * Adds discriminator criteria to an already-prepared query. |
||
| 883 | * |
||
| 884 | * This method should be used once for query criteria and not be used for |
||
| 885 | * nested expressions. It should be called before |
||
| 886 | * {@link DocumentPerister::addFilterToPreparedQuery()}. |
||
| 887 | */ |
||
| 888 | 513 | public function addDiscriminatorToPreparedQuery(array $preparedQuery) : array |
|
| 904 | |||
| 905 | /** |
||
| 906 | * Adds filter criteria to an already-prepared query. |
||
| 907 | * |
||
| 908 | * This method should be used once for query criteria and not be used for |
||
| 909 | * nested expressions. It should be called after |
||
| 910 | * {@link DocumentPerister::addDiscriminatorToPreparedQuery()}. |
||
| 911 | */ |
||
| 912 | 514 | public function addFilterToPreparedQuery(array $preparedQuery) : array |
|
| 927 | |||
| 928 | /** |
||
| 929 | * Prepares the query criteria or new document object. |
||
| 930 | * |
||
| 931 | * PHP field names and types will be converted to those used by MongoDB. |
||
| 932 | */ |
||
| 933 | 546 | public function prepareQueryOrNewObj(array $query, bool $isNewObj = false) : array |
|
| 961 | |||
| 962 | /** |
||
| 963 | * Prepares a query value and converts the PHP value to the database value |
||
| 964 | * if it is an identifier. |
||
| 965 | * |
||
| 966 | * It also handles converting $fieldName to the database name if they are different. |
||
| 967 | * |
||
| 968 | * @param mixed $value |
||
| 969 | */ |
||
| 970 | 901 | private function prepareQueryElement(string $fieldName, $value = null, ?ClassMetadata $class = null, bool $prepareValue = true, bool $inNewObj = false) : array |
|
| 1165 | |||
| 1166 | /** |
||
| 1167 | * Prepares a query expression. |
||
| 1168 | * |
||
| 1169 | * @param array|object $expression |
||
| 1170 | */ |
||
| 1171 | 77 | private function prepareQueryExpression($expression, ClassMetadata $class) : array |
|
| 1198 | |||
| 1199 | /** |
||
| 1200 | * Checks whether the value has DBRef fields. |
||
| 1201 | * |
||
| 1202 | * This method doesn't check if the the value is a complete DBRef object, |
||
| 1203 | * although it should return true for a DBRef. Rather, we're checking that |
||
| 1204 | * the value has one or more fields for a DBref. In practice, this could be |
||
| 1205 | * $elemMatch criteria for matching a DBRef. |
||
| 1206 | * |
||
| 1207 | * @param mixed $value |
||
| 1208 | */ |
||
| 1209 | 78 | private function hasDBRefFields($value) : bool |
|
| 1227 | |||
| 1228 | /** |
||
| 1229 | * Checks whether the value has query operators. |
||
| 1230 | * |
||
| 1231 | * @param mixed $value |
||
| 1232 | */ |
||
| 1233 | 82 | private function hasQueryOperators($value) : bool |
|
| 1251 | |||
| 1252 | /** |
||
| 1253 | * Gets the array of discriminator values for the given ClassMetadata |
||
| 1254 | */ |
||
| 1255 | 27 | private function getClassDiscriminatorValues(ClassMetadata $metadata) : array |
|
| 1274 | |||
| 1275 | 574 | private function handleCollections(object $document, array $options) : void |
|
| 1298 | |||
| 1299 | /** |
||
| 1300 | * If the document is new, ignore shard key field value, otherwise throw an exception. |
||
| 1301 | * Also, shard key field should be present in actual document data. |
||
| 1302 | * |
||
| 1303 | * @throws MongoDBException |
||
| 1304 | */ |
||
| 1305 | 10 | private function guardMissingShardKey(object $document, string $shardKeyField, array $actualDocumentData) : void |
|
| 1321 | |||
| 1322 | /** |
||
| 1323 | * Get shard key aware query for single document. |
||
| 1324 | */ |
||
| 1325 | 297 | private function getQueryForDocument(object $document) : array |
|
| 1333 | |||
| 1334 | 585 | private function getWriteOptions(array $options = []) : array |
|
| 1344 | |||
| 1345 | 15 | private function prepareReference(string $fieldName, $value, array $mapping, bool $inNewObj) : array |
|
| 1385 | } |
||
| 1386 |
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.