Пример #1
0
 /**
  * Save referenced model
  * @param AnnotatedInterface $referenced
  * @param DbRef $dbRef
  */
 public static function save(AnnotatedInterface $referenced, DbRef $dbRef)
 {
     // Ensure ref is same as referenced model
     PkManager::applyToModel($referenced, $dbRef->pk);
     $em = new EntityManager($referenced);
     $em->save();
 }
Пример #2
0
 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);
             }
         }
     }
 }
Пример #3
0
 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);
 }
Пример #4
0
 /**
  * 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));
 }
Пример #5
0
 /**
  * Validates the attribute of the object.
  * If there is any error, the error message is added to the object.
  * @param AnnotatedInterface $model the object being validated
  * @param string $attribute the attribute being validated
  */
 public function isValid(AnnotatedInterface $model, $attribute)
 {
     $value = $model->{$attribute};
     if ($this->allowEmpty && empty($value)) {
         return true;
     }
     $className = empty($this->className) ? get_class($model) : $this->className;
     $compareModel = new $className();
     $criteria = (new Criteria())->decorateWith($compareModel);
     $criteria->addCond($attribute, '==', $value);
     if ($this->criteria !== []) {
         $criteria->mergeWith($this->criteria);
     }
     ScenarioManager::setScenario($compareModel, ValidatorInterface::ScenarioValidate);
     $finder = new Finder($compareModel);
     $found = $finder->find($criteria);
     // Not found entirely
     if (null === $found) {
         return true;
     }
     // Same pk
     if (PkManager::compare($found, $model)) {
         return true;
     }
     $label = ManganMeta::create($model)->field($attribute)->label;
     $this->addError('msgTaken', ['{attribute}' => $label, '{value}' => $value]);
     return false;
 }
Пример #6
0
 /**
  * Deletes documents with the specified primary keys.
  * See {@link find()} for detailed explanation about $condition and $params.
  * @param mixed[] $pkValues Primary keys array
  * @param array|CriteriaInterface $criteria query criteria.
  * @since v1.0
  */
 public function deleteAllByPk($pkValues, $criteria = null)
 {
     if ($this->_beforeDelete()) {
         $criteria = $this->sm->apply($criteria);
         $criteria->mergeWith(PkManager::prepareAll($this->model, $pkValues, $criteria));
         $result = $this->getCollection()->remove($criteria->getConditions(), $this->options->getSaveOptions(['justOne' => false]));
         return $this->_result($result);
     }
     return false;
 }
Пример #7
0
 /**
  * Finds all documents with the specified primary keys.
  * In MongoDB world every document has '_id' unique field, so with this method that
  * field is in use as PK by default.
  * See {@link find()} for detailed explanation about $condition.
  *
  * @param mixed $pkValues primary key value(s). Use array for multiple primary keys. For composite key, each key value must be an array (column name=>column value).
  * @param array|CriteriaInterface $criteria query criteria.
  * @return AnnotatedInterface[]|Cursor - Array or cursor of Documents
  * @since v1.0
  */
 public function findAllByPk($pkValues, $criteria = null)
 {
     $pkCriteria = new Criteria($criteria);
     $pkCriteria->decorateWith($this->model);
     PkManager::prepareAll($this->model, $pkValues, $pkCriteria);
     return $this->findAll($pkCriteria);
 }
Пример #8
0
 public function read($model, $name, &$dbValues, $transformatorClass = TransformatorInterface::class)
 {
     if (!$dbValues) {
         $fieldMeta = ManganMeta::create($model)->field($name);
         $model->{$name} = $fieldMeta->default;
         return;
     }
     /**
      * NOTE: Documents must be sorted as $dbRefs,
      * however mongo does not guarantiee sorting by list of id's.
      * This require sorting in php.
      * If document has composite key this must be taken care too
      * while comparision for sorting is made.
      */
     $refs = [];
     $unsortedRefs = [];
     $pks = [];
     $sort = [];
     // Collect primary keys
     foreach ($dbValues as $key => $dbValue) {
         $dbValue['_class'] = DbRef::class;
         $dbRef = $transformatorClass::toModel($dbValue);
         // Collect keys separatelly for each type
         $pks[$dbRef->class][$key] = $dbRef->pk;
         $sort[$key] = $dbRef->pk;
     }
     // Fetch all types of db ref's en masse
     $i = 0;
     $unsortedPks = [];
     foreach ($pks as $referenced => $pkValues) {
         if (empty($referenced)) {
             continue;
         }
         // Find all referenced documents
         $refModel = new $referenced();
         $found = (new RawFinder($refModel))->findAllByPk($pkValues);
         if (!$found) {
             continue;
         }
         foreach ($found as $document) {
             // Collect unsorted documents
             $unsortedRefs[$i] = $document;
             // Collect pk's
             $unsortedPks[$i] = PkManager::getFromArray($document, $refModel);
             $i++;
         }
     }
     // Find existing documents
     $existing = [];
     foreach ($model->{$name} as $key => $document) {
         foreach ($sort as $i => $pk) {
             if (PkManager::compare($pk, $document)) {
                 // Set existing document with key same as in sort
                 $existing[$i] = $document;
             }
         }
     }
     // Sort as stored ref
     foreach ($sort as $key => $pk) {
         foreach ($unsortedRefs as $i => $document) {
             if (PkManager::compare($pk, $unsortedPks[$i])) {
                 if (array_key_exists($key, $existing)) {
                     // Update existing instance
                     $refs[$key] = $transformatorClass::toModel($document, $existing[$key], $existing[$key]);
                 } else {
                     // Create new instance
                     $refs[$key] = $transformatorClass::toModel($document);
                 }
             }
         }
     }
     $model->{$name} = $refs;
 }