public function write($model, $name, &$dbValues, $transformatorClass = TransformatorInterface::class) { if (!empty($model->{$name})) { // Store empty field to trigger decorator read $dbValues[$name] = null; $fieldMeta = ManganMeta::create($model)->field($name); $relMeta = $fieldMeta->related; if ($relMeta->single) { $models = [$model->{$name}]; } else { $models = $model->{$name}; } $order = 0; foreach ($models as $relModel) { $fields = []; foreach ($relMeta->join as $source => $rel) { $fields[] = $rel; assert(isset($model->{$source})); $relModel->{$rel} = $model->{$source}; } if (!empty($relMeta->orderField)) { $fields[] = $relMeta->orderField; $fields = array_unique($fields); $relModel->order = $order; $order++; } $em = new EntityManager($relModel); if ($relMeta->updatable) { // Update whole model $em->upsert(); } else { // Update only relation info $criteria = PkManager::prepareFromModel($relModel); $em->updateOne($criteria, $fields); } } } }
public function testIfWillResolveNotFoundClass() { define('BogusClass', 'SomeClass'); $model = new WithPlainEmbedded(); $model->_id = new MongoId(); $model->stats = new SimplePlainEmbedded(); $em = new EntityManager($model); $em->save(); $pkCriteria = PkManager::prepareFromModel($model)->getConditions(); $set = ['$set' => ['stats._class' => BogusClass]]; $em->getCollection()->update($pkCriteria, $set); $finder = new Finder($model); try { $finder->findByPk($model->_id); $this->assertFalse(true); } catch (ManganException $ex) { $this->assertTrue(true); } // Attach class not found handlers new NotFoundResolver($model, [BogusClass => SimplePlainEmbedded::class]); $found = $finder->findByPk($model->_id); $this->assertInstanceOf(WithPlainEmbedded::class, $found); $this->assertInstanceOf(SimplePlainEmbedded::class, $found->stats); }
/** * Restore trashed item * @return boolean * @throws Exception * @Ignored */ public function restore() { if (!$this instanceof TrashInterface) { // When trying to restore normal document instead of trash item throw new Exception(sprintf('Restore can be performed only on `%s` instance', TrashInterface::class)); } $em = new EntityManager($this->data); // Set scenario to `restore` for model, which is just about to be restored ScenarioManager::setScenario($this->data, TrashInterface::ScenarioRestore); if (!Event::valid($this->data, TrashInterface::EventBeforeRestore)) { return false; } $saved = $em->save(); if (!$saved) { return false; } $finder = new Finder($this->data); $model = $finder->find(PkManager::prepareFromModel($this->data)); if (!$model) { return false; } $eventAfter = new RestoreEvent(); $eventAfter->setTrashed($this->data); $eventAfter->setTrash($this); if (!Event::valid($model, TrashInterface::EventAfterRestore, $eventAfter)) { return false; } $trashEm = new EntityManager($this); $this->data = null; // Use deleteOne, to avoid beforeDelete event, // which should be raised only when really removing document: // when emtying trash return $trashEm->deleteOne(PkManager::prepareFromModel($this)); }
/** * Deletes the document from database. * @return boolean whether the deletion is successful. * @throws ManganException if the record is new */ public function delete() { if ($this->_beforeDelete()) { $result = $this->deleteOne(PkManager::prepareFromModel($this->model)); if ($result !== false) { $this->_afterDelete(); return true; } else { return false; } } else { return false; } }