/** * Datasource constructor, creates the Configuration, Connection and DocumentManager objects * * ### You can pass the following configuration options * * - server: name of the server that will be used to connect to Mongo (default: `localhost`) * - database: name of the database to use when connecting to Mongo (default: `cake`) * - documentPaths: array containing a list of full path names where Document classes can be located (default: `App::path('Model')`) * - proxyDir: full path to the directory that will contain the generated proxy classes for each document (default: `TMP . 'cache'`) * - proxyNamespace: string representing the namespace the proxy classes will reside in (default: `Proxies`) * - hydratorDir: directory well the hydrator classes will be generated in (default: `TMP . 'cache'`) * - hydratorNamespace: string representing the namespace the hydrator classes will reside in (default: `Hydrators`) * * @param arary $config * @param boolean $autoConnect whether this object should attempt connection on creation * @throws MissingConnectionException if it was not possible to connect to MongoDB */ public function __construct($config = array(), $autoConnect = true) { $modelPaths = $this->_cleanupPaths(App::path('Model')); $this->_baseConfig = array('proxyDir' => TMP . 'cache', 'proxyNamespace' => 'Proxies', 'hydratorDir' => TMP . 'cache', 'hydratorNamespace' => 'Hydrators', 'server' => 'localhost', 'database' => 'cake', 'documentPaths' => $modelPaths, 'prefix' => null); foreach (CakePlugin::loaded() as $plugin) { $this->_baseConfig['documentPaths'] = array_merge($this->_baseConfig['documentPaths'], $this->_cleanupPaths(App::path('Model', $plugin))); } parent::__construct($config); extract($this->config, EXTR_OVERWRITE); $configuration = new Configuration(); $configuration->setProxyDir($proxyDir); $configuration->setProxyNamespace($proxyNamespace); $configuration->setHydratorDir($hydratorDir); $configuration->setHydratorNamespace($hydratorNamespace); $configuration->setDefaultDB($database); $configuration->setMetadataDriverImpl($this->_getMetadataReader($documentPaths)); if (Configure::read('debug') === 0) { $configuration->setAutoGenerateHydratorClasses(false); $configuration->setAutoGenerateProxyClasses(false); $configuration->setMetadataCacheImpl(new ApcCache()); } $this->configuration = $configuration; $this->connection = new Connection($server, array(), $configuration); $this->documentManager = DocumentManager::create($this->connection, $configuration); $this->documentManager->getEventManager()->addEventListener(array(Events::prePersist, Events::preUpdate, Events::preRemove, Events::postPersist, Events::postUpdate, Events::postRemove), $this); try { if ($autoConnect) { $this->connect(); } } catch (Exception $e) { throw new MissingConnectionException(array('class' => get_class($this))); } $this->setupLogger(); }
public function testResolveTargetDocumentListenerCanResolveTargetDocument() { $evm = $this->dm->getEventManager(); $this->listener->addResolveTargetDocument('Doctrine\\ODM\\MongoDB\\Tests\\Tools\\ResolveTargetInterface', 'Doctrine\\ODM\\MongoDB\\Tests\\Tools\\ResolveTargetDocument', array()); $this->listener->addResolveTargetDocument('Doctrine\\ODM\\MongoDB\\Tests\\Tools\\TargetInterface', 'Doctrine\\ODM\\MongoDB\\Tests\\Tools\\TargetDocument', array()); $evm->addEventListener(Events::loadClassMetadata, $this->listener); $cm = $this->dm->getClassMetadata('Doctrine\\ODM\\MongoDB\\Tests\\Tools\\ResolveTargetDocument'); $meta = $cm->associationMappings; $this->assertSame('Doctrine\\ODM\\MongoDB\\Tests\\Tools\\ResolveTargetDocument', $meta['refOne']['targetDocument']); $this->assertSame('Doctrine\\ODM\\MongoDB\\Tests\\Tools\\TargetDocument', $meta['refMany']['targetDocument']); $this->assertSame('Doctrine\\ODM\\MongoDB\\Tests\\Tools\\ResolveTargetDocument', $meta['embedOne']['targetDocument']); $this->assertSame('Doctrine\\ODM\\MongoDB\\Tests\\Tools\\TargetDocument', $meta['embedMany']['targetDocument']); }
/** * Updates persisted document, using atomic operators * * @param mixed $document */ public function update($document) { $id = $this->_uow->getDocumentIdentifier($document); $update = $this->prepareUpdateData($document); if (!empty($update)) { if ($this->_dm->getEventManager()->hasListeners(ODMEvents::onUpdatePrepared)) { $this->_dm->getEventManager()->dispatchEvent(ODMEvents::onUpdatePrepared, new OnUpdatePreparedArgs($this->_dm, $document, $update)); } /** * temporary fix for @link http://jira.mongodb.org/browse/SERVER-1050 * atomic modifiers $pushAll and $pullAll, $push, $pop and $pull * are not allowed on the same field in one update */ $id = $this->_class->getDatabaseIdentifierValue($id); if (isset($update[$this->_cmd . 'pushAll']) && isset($update[$this->_cmd . 'pullAll'])) { $fields = array_intersect(array_keys($update[$this->_cmd . 'pushAll']), array_keys($update[$this->_cmd . 'pullAll'])); if (!empty($fields)) { $tempUpdate = array(); foreach ($fields as $field) { $tempUpdate[$field] = $update[$this->_cmd . 'pullAll'][$field]; unset($update[$this->_cmd . 'pullAll'][$field]); } if (empty($update[$this->_cmd . 'pullAll'])) { unset($update[$this->_cmd . 'pullAll']); } $tempUpdate = array($this->_cmd . 'pullAll' => $tempUpdate); $this->_collection->update(array('_id' => $id), $tempUpdate); } } $this->_collection->update(array('_id' => $id), $update); } }
/** * Create a new MongoCollection instance that wraps a PHP MongoCollection instance * for a given ClassMetadata instance. * * @param MongoCollection $mongoColleciton The MongoCollection instance. * @param ClassMetadata $class The ClassMetadata instance. * @param DocumentManager $dm The DocumentManager instance. */ public function __construct(\MongoCollection $mongoCollection, ClassMetadata $class, DocumentManager $dm) { $this->_mongoCollection = $mongoCollection; $this->_class = $class; $this->_loggerCallable = $dm->getConfiguration()->getLoggerCallable(); $this->_cmd = $dm->getConfiguration()->getMongoCmd(); $this->_eventManager = $dm->getEventManager(); }
/** * {@inheritdoc} */ public function getMetadataFor($className) { if (!isset($this->innerLoadedMetadata[$className])) { $evm = $this->documentManager->getEventManager(); if ($evm->hasListeners(Events::PRE_LOAD_CLASSMETADATA)) { $eventArgs = new PreLoadClassMetadataEventArgs($className, $this->documentManager); $evm->dispatchEvent(Events::PRE_LOAD_CLASSMETADATA, $eventArgs); } $classMetadata = parent::getMetadataFor($className); if ($evm->hasListeners(Events::POST_LOAD_CLASS_METADATA)) { $eventArgs = new LoadClassMetadataEventArgs($classMetadata, $this->documentManager); $evm->dispatchEvent(Events::POST_LOAD_CLASS_METADATA, $eventArgs); } $this->innerLoadedMetadata[$className] = $classMetadata; } return $this->innerLoadedMetadata[$className]; }
/** * Initializes a new instance of the <tt>ProxyFactory</tt> class that is * connected to the given <tt>DocumentManager</tt>. * * @param \Doctrine\ODM\MongoDB\DocumentManager $documentManager The DocumentManager the new factory works for. * @param string $proxyDir The directory to use for the proxy classes. It * must exist. * @param string $proxyNamespace The namespace to use for the proxy classes. * @param integer $autoGenerate Whether to automatically generate proxy classes. */ public function __construct(DocumentManager $documentManager, $proxyDir, $proxyNamespace, $autoGenerate = AbstractProxyFactory::AUTOGENERATE_NEVER) { $this->metadataFactory = $documentManager->getMetadataFactory(); $this->uow = $documentManager->getUnitOfWork(); $this->proxyNamespace = $proxyNamespace; $this->lifecycleEventManager = new LifecycleEventManager($documentManager, $this->uow, $documentManager->getEventManager()); $proxyGenerator = new ProxyGenerator($proxyDir, $proxyNamespace); $proxyGenerator->setPlaceholder('baseProxyInterface', Proxy::class); parent::__construct($proxyGenerator, $this->metadataFactory, $autoGenerate); }
/** * Updates the already persisted document if it has any new changesets. * * @param object $document * @param array $options Array of options to be used with update() */ public function update($document, array $options = array()) { $id = $this->uow->getDocumentIdentifier($document); $update = $this->dp->prepareUpdateData($document); if ( ! empty($update)) { $id = $this->class->getDatabaseIdentifierValue($id); $query = array('_id' => $id); // Include versioning updates if ($this->class->isVersioned) { $versionMapping = $this->class->fieldMappings[$this->class->versionField]; $currentVersion = $this->class->getFieldValue($document, $this->class->versionField); if ($versionMapping['type'] === 'int') { $nextVersion = $currentVersion + 1; $update[$this->cmd . 'inc'][$versionMapping['name']] = 1; $query[$versionMapping['name']] = $currentVersion; $this->class->setFieldValue($document, $this->class->versionField, $nextVersion); } elseif ($versionMapping['type'] === 'date') { $nextVersion = new \DateTime(); $update[$this->cmd . 'set'][$versionMapping['name']] = new \MongoDate($nextVersion->getTimestamp()); $query[$versionMapping['name']] = new \MongoDate($currentVersion->getTimestamp()); $this->class->setFieldValue($document, $this->class->versionField, $nextVersion); } $options['safe'] = true; } if ($this->class->isLockable) { $isLocked = $this->class->getFieldValue($document, $this->class->lockField); $lockMapping = $this->class->fieldMappings[$this->class->lockField]; if ($isLocked) { $update[$this->cmd . 'unset'] = array($lockMapping['name'] => true); } else { $query[$lockMapping['name']] = array($this->cmd . 'exists' => false); } } if ($this->dm->getEventManager()->hasListeners(Events::onUpdatePrepared)) { $this->dm->getEventManager()->dispatchEvent( Events::onUpdatePrepared, new OnUpdatePreparedArgs($this->dm, $document, $update) ); } $result = $this->collection->update($query, $update, $options); if (($this->class->isVersioned || $this->class->isLockable) && ! $result['n']) { throw LockException::lockFailed($document); } } }
/** * @return \Doctrine\ODM\MongoDB\DocumentManager */ public function dm() { if ($this->dm === null) { $this->dm = $this->createTestDocumentManager(); $this->uow = $this->dm->getUnitOfWork(); Type::addType('Phonenumber', PhonenumberType::class); Type::addType('Role', RoleType::class); $this->dm->getEventManager()->addEventSubscriber(new MetadataEventSubscriber()); $this->dm->getEventManager()->addEventSubscriber(new CollectionsEventSubscriber()); $this->dm->getEventManager()->addEventSubscriber(new ModelEventSubscriber()); $this->dm->getEventManager()->addEventSubscriber(new IdentityEventSubscriber()); $this->dm->getEventManager()->addEventSubscriber(new GeolocationEventSubscriber()); $this->dm->getEventManager()->addEventSubscriber(new SystemEventSubscriber()); } return $this->dm; }
/** * Initializes a new UnitOfWork instance, bound to the given DocumentManager. * * @param Doctrine\ODM\MongoDB\DocumentManager $dm */ public function __construct(DocumentManager $dm) { $this->_dm = $dm; $this->_evm = $dm->getEventManager(); $this->_hydrator = $dm->getHydrator(); }