Executes a detach operation on the given document.

@param object $document
@param array  $visited
198693
private function doDetach($document, array &$visited)
    {
        $oid = spl_object_hash($document);
        if (isset($visited[$oid])) {
            return; // Prevent infinite recursion
        }

        $visited[$oid] = $document; // mark visited

        $class = $this->dm->getClassMetadata(get_class($document));
        $this->cascadeDetach($class, $document, $visited);

        $state = $this->getDocumentState($document);
        switch ($state) {
            case self::STATE_MANAGED:
                $this->unregisterDocument($document);
                break;
            case self::STATE_NEW:
            case self::STATE_DETACHED:
                return;
        }
    }
25782
public function unlock($document)
    {
        if ($this->getDocumentState($document) != self::STATE_MANAGED) {
            throw new \InvalidArgumentException("Document is not MANAGED.");
        }
        $documentName = get_class($document);
        $this->getDocumentPersister($documentName)->unlock($document);
    }
26786
public function getVisitedCollections($document)
    {
        $oid = spl_object_hash($document);

        return isset($this->visitedCollections[$oid])
            ? $this->visitedCollections[$oid]
            : [];
    }
1215621
public function delete($docs)
    {
        if($docs instanceof Document) {
            $this->obj_gateway->delete([$docs->getId()]);
        } elseif (is_string($docs)) {
            $this->obj_gateway->delete([$docs]);
        } elseif (is_array($docs)) {
            $arr_doc_ids = [];
            foreach($docs as $doc){
                if($doc instanceof Document) {
                    $arr_doc_ids[] = $doc->getId();
                } elseif (is_string($doc)) {
                    $arr_doc_ids[] = $doc;
                } else {
                    throw new \InvalidArgumentException('Parameter must be one or more \Search\Document objects or ID strings');
                }
            }
            $this->obj_gateway->delete($arr_doc_ids);
        } else {
            throw new \InvalidArgumentException('Parameter must be one or more \Search\Document objects or ID strings');
        }
    }
418317
private function recursivelyRemoveRoutes(RouteBehavior $document)
    {
        $referrers = $this->documentInspector->getReferrers($document);

        foreach ($referrers as $referrer) {
            if (!$referrer instanceof RouteBehavior) {
                continue;
            }

            $this->recursivelyRemoveRoutes($referrer);
            $this->documentManager->remove($referrer);
        }
    }
998674
public function postRemove(ClassMetadata $class, $document)
    {
        $class->invokeLifecycleCallbacks(Event::postRemove, $document, [new LifecycleEventArgs($document, $this->dm)]);
        $this->evm->dispatchEvent(Event::postRemove, new LifecycleEventArgs($document, $this->dm));
    }
194442
public function handleCollections($document)
    {
        // Collection deletions (deletions of complete collections)
        foreach ($this->uow->getScheduledCollections($document) as $coll) {
            if (!$this->uow->isCollectionScheduledForDeletion($coll)) {
                continue;
            }

            $this->cp->delete($coll);
        }

        // Collection updates (deleteRows, updateRows, insertRows)
        foreach ($this->uow->getScheduledCollections($document) as $coll) {
            if (!$this->uow->isCollectionScheduledForUpdate($coll)) {
                continue;
            }

            $this->cp->update($coll);
        }

        // Take new snapshots from visited collections
        foreach ($this->uow->getVisitedCollections($document) as $coll) {
            $coll->takeSnapshot();
        }
    }
1166850
private function cascadeDetach($document, array &$visited)
    {
        $class = $this->dm->getClassMetadata(get_class($document));
        foreach ($class->propertyMetadata as $mapping) {
            if (!$mapping->isCascadeDetach) {
                continue;
            }
            $relatedDocuments = $class->getPropertyMetadata($mapping->name)->getValue($document);
            if (($relatedDocuments instanceof Collection || is_array($relatedDocuments))) {
                if ($relatedDocuments instanceof PersistentCollectionInterface) {
                    // Unwrap so that foreach() does not initialize
                    $relatedDocuments = $relatedDocuments->unwrap();
                }
                foreach ($relatedDocuments as $relatedDocument) {
                    $this->doDetach($relatedDocument, $visited);
                }
            } elseif ($relatedDocuments !== null) {
                $this->doDetach($relatedDocuments, $visited);
            }
        }
    }
1274230
private function cascadeRemove($entity, array &$visited)
    {
        $class = $this->em->getClassMetadata(get_class($entity));

        $associationMappings = array_filter(
            $class->associationMappings,
            function ($assoc) { return $assoc['isCascadeRemove']; }
        );

        $entitiesToCascade = array();

        foreach ($associationMappings as $assoc) {
            if ($entity instanceof Proxy && !$entity->__isInitialized__) {
                $entity->__load();
            }

            $relatedEntities = $class->reflFields[$assoc['fieldName']]->getValue($entity);

            switch (true) {
                case ($relatedEntities instanceof Collection):
                case (is_array($relatedEntities)):
                    // If its a PersistentCollection initialization is intended! No unwrap!
                    foreach ($relatedEntities as $relatedEntity) {
                        $entitiesToCascade[] = $relatedEntity;
                    }
                    break;

                case ($relatedEntities !== null):
                    $entitiesToCascade[] = $relatedEntities;
                    break;

                default:
                    // Do nothing
            }
        }

        foreach ($entitiesToCascade as $relatedEntity) {
            $this->doRemove($relatedEntity, $visited);
        }
    }
121988
private function doMerge($object, array &$visited)
    {
        $oid = spl_object_hash($object);

        if (isset($visited[$oid])) {
            return $visited[$oid];
        }

        $visited[$oid] = $object;

        /** @var DocumentMetadata $class */
        $class = $this->manager->getClassMetadata(get_class($object));
        $managedCopy = $object;

        if (self::STATE_MANAGED !== $this->getDocumentState($object, self::STATE_DETACHED)) {
            $this->manager->initializeObject($object);

            $id = $class->getSingleIdentifier($object);
            $managedCopy = null;

            if (null !== $id) {
                $managedCopy = $this->manager->find($class->name, $id);

                if (null !== $managedCopy && self::STATE_REMOVED === $this->getDocumentState($managedCopy)) {
                    throw new \InvalidArgumentException('Removed document detected during merge.');
                }

                $this->manager->initializeObject($managedCopy);
            }

            if (null === $managedCopy) {
                $managedCopy = $this->newInstance($class);
                if (null !== $id) {
                    $class->setIdentifierValue($managedCopy, $id);
                }

                $this->persistNew($class, $managedCopy);
            }

            foreach ($class->getReflectionClass()->getProperties() as $property) {
                $name = $property->name;
                $property->setAccessible(true);

                if (! isset($class->associationMappings[$name])) {
                    if (! $class->isIdentifier($name)) {
                        $property->setValue($managedCopy, $property->getValue($object));
                    }
                } else {
                    // @todo
                }
            }
        }

        $visited[spl_object_hash($managedCopy)] = $managedCopy;
        $this->cascadeMerge($object, $managedCopy, $visited);

        return $managedCopy;
    }
461451
private function cascadeRefresh($entity, array &$visited)
    {
        $class = $this->entityManager->getClassMetadata(get_class($entity));

        foreach ($class->getRelationships() as $relationship) {
            $value = $relationship->getValue($entity);

            switch (true) {
                case $value instanceof Collection:
                case is_array($value):
                    foreach ($value as $relatedEntity) {
                        $this->doRefresh($relatedEntity, $visited);
                    }
                    break;
                case $value !== null:
                    $this->doRefresh($value, $visited);
                    break;
                default:
                    // Do nothing
            }
        }
    }
687750
public function detach($entity)
    {
        $this->entityRegistry->deregisterEntity($entity);
        $objectHashId = $this->entityRegistry->getObjectHashId($entity);
        unset($this->scheduledForInsertion[$objectHashId]);
        unset($this->scheduledForUpdate[$objectHashId]);
        unset($this->scheduledForDeletion[$objectHashId]);
    }
391640
private function doRefresh($entity, array &$visited)
    {
        $oid = spl_object_id($entity);

        if (isset($visited[$oid])) {
            return; // Prevent infinite recursion
        }

        $visited[$oid] = $entity; // mark visited

        $class = $this->em->getClassMetadata(get_class($entity));

        if ($this->getEntityState($entity) !== self::STATE_MANAGED) {
            throw ORMInvalidArgumentException::entityNotManaged($entity);
        }

        $this->getEntityPersister($class->getClassName())->refresh(
            array_combine($class->getIdentifierFieldNames(), $this->entityIdentifiers[$oid]),
            $entity
        );

        $this->cascadeRefresh($entity, $visited);
    }
850173
public function detach($observer)
	{
		$retval = false;

		$key = array_search($observer, $this->_observers);

		if ($key !== false)
		{
			unset($this->_observers[$key]);
			$retval = true;

			foreach ($this->_methods as &$method)
			{
				$k = array_search($key, $method);

				if ($k !== false)
				{
					unset($method[$k]);
				}
			}
		}

		return $retval;
	}
449836
public function lock($document, $lockMode)
    {
        $id = $this->uow->getDocumentIdentifier($document);
        $criteria = array('_id' => $this->class->getDatabaseIdentifierValue($id));
        $lockMapping = $this->class->fieldMappings[$this->class->lockField];
        $this->collection->update($criteria, array('$set' => array($lockMapping['name'] => $lockMode)));
        $this->class->reflFields[$this->class->lockField]->setValue($document, $lockMode);
    }
840513
public function offsetUnset($offset) {
        $detach = NULL;

        if(parent::offsetExists($offset)) {
            $child = parent::offsetGet($offset);
            if($child instanceof Element && $child->__parent === $this) {
                $detach = $child;
            }
        }

        parent::offsetUnset($offset);

        if($detach) {
            $detach->detach();
        }
    }
224133
private function cascadeDetach(object $document, array &$visited) : void
    {
        $class = $this->dm->getClassMetadata(get_class($document));
        foreach ($class->fieldMappings as $mapping) {
            if (! $mapping['isCascadeDetach']) {
                continue;
            }
            $relatedDocuments = $class->reflFields[$mapping['fieldName']]->getValue($document);
            if ($relatedDocuments instanceof Collection || is_array($relatedDocuments)) {
                if ($relatedDocuments instanceof PersistentCollectionInterface) {
                    // Unwrap so that foreach() does not initialize
                    $relatedDocuments = $relatedDocuments->unwrap();
                }
                foreach ($relatedDocuments as $relatedDocument) {
                    $this->doDetach($relatedDocument, $visited);
                }
            } elseif ($relatedDocuments !== null) {
                $this->doDetach($relatedDocuments, $visited);
            }
        }
    }