public function testWillSanitizeArraysOfAttributes() { $model = new WithSanitizedArrayValues(); $model->goals = ['1', 'a2', '2a']; $model->shots = [1, 0.2, '0', 'yes']; $model->title = [1, true, 1.2]; $sanitizer = new Sanitizer($model); $this->assertSame([1, 0, 2], $sanitizer->read('goals', $model->goals)); $this->assertSame([true, true, false, true], $sanitizer->read('shots', $model->shots)); $this->assertSame(['1', '1', '1.2'], $sanitizer->read('title', $model->title)); $this->assertSame([1, 0, 2], $sanitizer->write('goals', $model->goals)); $this->assertSame([true, true, false, true], $sanitizer->write('shots', $model->shots)); $this->assertSame(['1', '1', '1.2'], $sanitizer->write('title', $model->title)); }
/** * Returns the given object as an associative array * @param AnnotatedInterface|object $model * @param string[] $fields Fields to transform * @return array an associative array of the contents of this object */ public static function fromModel(AnnotatedInterface $model, $fields = []) { $meta = static::getMeta($model); $calledClass = get_called_class(); $decorator = new Decorator($model, $calledClass, $meta); $md = new ModelDecorator($model, $calledClass, $meta); $sanitizer = new Sanitizer($model, $calledClass, $meta); $filter = new Filter($model, $calledClass, $meta); $arr = []; foreach ($meta->fields() as $name => $fieldMeta) { if (!empty($fields) && !in_array($name, $fields)) { continue; } if (!$filter->fromModel($model, $fieldMeta)) { continue; } $model->{$name} = $sanitizer->write($name, $model->{$name}); $decorator->write($name, $arr); $model->{$name} = $sanitizer->read($name, $model->{$name}); } $md->write($arr); return FinalizingManager::fromModel($arr, static::class, $model); }
/** * Register event handlers for parent of parent-child relation. * * @param AnnotatedInterface $parent * @param string $childClass */ public function registerParent(AnnotatedInterface $parent, $childClass) { if (!ClassChecker::exists($childClass)) { throw new UnexpectedValueException(sprintf('Class `%s` not found', $childClass)); } // Delete all of this child items after removing from trash $beforeDelete = function (ModelEvent $event) use($parent, $childClass) { $model = $event->sender; $event->isValid = true; if ($model instanceof $parent) { $child = new $childClass(); $criteria = new Criteria(null, $child); $criteria->parentId = $model->_id; $event->isValid = $child->deleteAll($criteria); } }; Event::on($parent, EntityManagerInterface::EventBeforeDelete, $beforeDelete); // Trash all child items from parent item $afterTrash = function (ModelEvent $event) use($parent, $childClass) { $model = $event->sender; $event->isValid = true; if ($model instanceof $parent) { $child = new $childClass(); $criteria = new Criteria(null, $child); $criteria->parentId = $model->_id; $items = $child->findAll($criteria); // No items found, so skip if (empty($items)) { $event->isValid = true; return true; } // Trash in loop all items foreach ($items as $item) { if (!$item->trash()) { $event->isValid = false; return false; } } } }; Event::on($parent, TrashInterface::EventAfterTrash, $afterTrash); // Restore all child items from parent, but only those after it was trashed. // This will keep previously trashed items in trash $afterRestore = function (RestoreEvent $event) use($parent, $childClass) { $model = $event->sender; if ($model instanceof $parent) { $child = new $childClass(); $trash = $event->getTrash(); $criteria = new Criteria(null, $trash); // Conditions decorator do not work with dots so sanitize manually. $s = new Sanitizer($child); $id = $s->write('parentId', $model->_id); $criteria->addCond('data.parentId', '==', $id); // Restore only child items trashed when blog was trashed - skip earlier $criteria->addCond('createDate', 'gte', $trash->createDate); $trashedItems = $trash->findAll($criteria); if (empty($trashedItems)) { $event->isValid = true; return true; } // Restore all items foreach ($trashedItems as $trashedItem) { $trashedItem->restore(); } } $event->isValid = true; }; Event::on($parent, TrashInterface::EventAfterRestore, $afterRestore); }