public function testIfWillDecorateWithCompoundDecorator() { $model = new WithPlainEmbedded(); $model->stats = new SimplePlainEmbedded(); $decorator = new Decorator($model, RawArray::class); $dbValue = ['stats' => []]; $decorator->write('stats', $dbValue); $this->assertSame($dbValue['stats']['_class'], get_class($model->stats)); $this->assertSame($dbValue['stats']['visits'], $model->stats->visits); }
/** * Create document from array * * @param mixed[] $data * @param string|object $className * @param AnnotatedInterface $instance * @return AnnotatedInterface * @throws TransformatorException */ public static function toModel($data, $className = null, AnnotatedInterface $instance = null) { $data = (array) $data; if (is_object($className)) { $className = get_class($className); } if (!$className) { if (array_key_exists('_class', $data)) { $className = $data['_class']; } else { if (null !== $instance) { $className = get_class($instance); } else { throw new TransformatorException('Could not determine document type'); } } } if ($instance) { $model = $instance; } else { $model = new $className(); } $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); foreach ($meta->fields() as $name => $fieldMeta) { /* @var $fieldMeta DocumentPropertyMeta */ if (array_key_exists($name, $data)) { // Value is available in passed data $value = $data[$name]; } elseif (!empty($instance)) { // Take value from existing instance // NOTE: We could `continue` here but value should be sanitized anyway $value = $model->{$name}; } else { // As a last resort set to default $value = $fieldMeta->default; } if (!$filter->toModel($model, $fieldMeta)) { continue; } $decorator->read($name, $value); $model->{$name} = $sanitizer->read($name, $model->{$name}); } $md->read($data); return FinalizingManager::toModel(static::class, $model); }