getEntity()->isLoaded() || $context->formSent() ) { if (method_exists($context, 'initializeEntity')) { $context->initializeEntity($this->getEntity()); } else { $this->assignContextToEntity($context); } } parent::initialize($context); } public function validate(FormContextInterface $context) : bool { # Context validates ContextField attributes containing properties on empty entity $this->validateContextFields($context); return $context->valid($this->getEntity()->isLoaded() ? $this->getEntity() : null); } public function execute(FormContextInterface $context) : mixed { $entity = $this->getEntity(); if ($entity->isLoaded()) { if (property_exists($entity, 'updatedAt') && $entity->repository()->generateDatasetDiff($entity) ) { $entity->updatedAt = new Datetime(); } } else { if (property_exists($entity, 'createdAt') && empty($entity->createdAt)) { $entity->createdAt = new Datetime(); } } try { $this->assignContextToEntity($context); if ( $saved = $entity::repository()->save($entity) ) { $context->pushMessage($this->message::generateSuccess( $this->lang('lean.api.form.save.success.save') )); } else { $context->pushMessage($this->message::generateWarning( $this->lang('lean.api.form.save.warning.entity', [ 'entity' => substr($this->entity::class, strrpos($this->entity::class, '\\') + 1) ]) )); } } catch(\PDOException $ex) { throw new \PDOException($this->lang('lean.api.form.save.error.pdo', [ 'error' => $ex->getMessage() ])); } catch(\Throwable $ex) { throw $ex; } return $saved; } protected function validateContextFields(FormContextInterface $context) : void { foreach ($this->reflectedProperties($context) as $name => $property) { $attribute = $property->getAttribute(ContextField::class); if ($attribute) { try { $attribute->object->assertValueSpecs($context->$name ?? null, $this->getEntity()->isLoaded()); } catch (MandatoryFieldException $e) { throw new MandatoryFieldException("An error occured with field '$name': " . $e->getMessage()); } } } } protected function assignContextToEntity(FormContextInterface $context) : void { $entity = $this->getEntity(); foreach($entity::resolveEntity()->fieldList() as $key => $property) { $field = $property->getAttribute(Field::class)->object; if (! $field->readonly || ! $entity->isLoaded()) { $apiField = $property->getAttribute(EntityField::class)->object ?? null; if ($apiField) { $var = $apiField->field ?: $key; if ( property_exists($context, $var) && ( new \ReflectionProperty($context, $var) )->isInitialized($context) ) { if ($apiField->setterMethod) { # Use a setter method call_user_func([ $entity, $apiField->setterMethod ], $context->{$var}); } else { # Direct property set $entity->$key = $context->{$var}; } } elseif (! $entity->isLoaded()) { # Applies 'default' value assigned to ContextField property $attr = $this->reflectedProperties($context)[$var] ?? null; if ($attr) { $contextField = $attr->getAttribute(ContextField::class); if ($contextField) { if (isset($contextField->object->default)) { $entity->$key = $contextField->object->default; } } } } } } } } private function reflectedProperties(FormContextInterface $context) : array { $this->reflectedProperties ??= ObjectReflection::fromClass($context::class)->reflectProperties(\ReflectionProperty::IS_PUBLIC); return $this->reflectedProperties; } }