<?php
namespace FormBundle\Service;
use FormBundle\Event\FormBundleEvents;
use Pimcore\Log\Simple;
use Pimcore\Model\DataObject;
use Pimcore\Translation\Translator;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\ServiceLocator;
use Symfony\Component\EventDispatcher\GenericEvent;
use Symfony\Component\Form;
use Symfony\Component\Form\Extension\Core\Type;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Session\Flash\FlashBag;
class ObjectFormHandler {
private $successMessage;
private $failMessage;
private $invalidMessage;
protected Translator $translator;
protected ContainerInterface $container;
protected ObjectFormService $formService;
protected Form\FormBuilderInterface $builder;
protected Form\FormFactoryInterface $formfactory;
private $disableTranslation = false;
private DataObject\Concrete $object;
private $submitted = false;
private $success = false;
private Form\Form $form;
private $formview;
private array $formOptions = [];
private Request $request;
public function __construct(ContainerInterface $container) {
$this->container = $container;
$this->formService = $this->container->get('form.formservice');
$this->formfactory = $this->container->get('form.factory');
$this->translator = $this->container->get("translator");
$this->successMessage = $this->translator->trans("form.submit.success");
$this->failMessage = $this->translator->trans("form.submit.error");
$this->invalidMessage = $this->translator->trans("form.submit.error.invalid");
}
public function setRequest(Request $request) {
$this->request = $request;
}
public function disableTranslation() {
$this->disableTranslation = true;
}
/**
* @var DataObject\Concrete $object = null Insert object to save if not already provided in constructor
* @var array $options = []
*/
public function createForm(DataObject\Concrete $object = null, array $options = []) {
$eventSuffix = (isset($options["eventSuffix"]) ? ".".$options["eventSuffix"] : '');
$customLayoutId = $options["customLayoutId"] ?? null;
$this->object = $object;
$formAttr = ["enctype" => "multipart/form-data"];
if (isset($options["formAttrs"]) && is_array($options["formAttrs"])) {
$formAttr = array_merge($options["formAttrs"], $formAttr);
}
$object->setValues($_REQUEST);
$hasTranslation = !$this->disableTranslation && count(\Pimcore\Tool::getValidLanguages()) > 1;
$config = [
"method" => "POST",
"attr" => $formAttr,
"translation_domain" => $hasTranslation || array_key_exists("translationDomain", $options) ? ($options["translationDomain"] ?? 'messages') : false,
"allow_extra_fields" => true,
];
if (isset($options["action"])) {
$config["action"] = $options["action"];
} else {
$config["action"] = $this->request->getPathInfo();
}
$this->builder = $this->formfactory->createBuilder(Type\FormType::class, $object, $config);
$this->form = $this->formService->getForm($this->builder, $customLayoutId);
$this->form->handleRequest($this->request);
if (strtolower($object->getClassName()) == strtolower($_POST["form_id"] ?? "-")) {
if ($this->form->isSubmitted()) {
$eventData = new GenericEvent($object, [
"request" => $this->request,
"formHandler" => $this,
]);
\Pimcore::getEventDispatcher()->dispatch(
$eventData,
FormBundleEvents::REQUESTLISTENER_VALIDATION_EVENT.$eventSuffix
);
if (array_key_exists("validationEvent", $options)) {
\Pimcore::getEventDispatcher()->dispatch(
$eventData,
$options["validationEvent"]
);
}
$this->formService->validateFields($object, $this->form);
if (method_exists($this->object, "validateForm")) {
$this->object->validateForm($this->form, $this->container);
}
}
}
$this->formview = $this->form->createView();
$this->formview->customLayoutId = $customLayoutId;
}
public function handleRequest($addSuccessMessage = true) {
/** @var $bag FlashBag */
$bag = $this->container->get('session')->getFlashBag();
if ($this->form->isSubmitted()) {
$this->submitted = true;
if ($this->form->isValid()) {
try {
$this->object->save();
if ($addSuccessMessage && $this->successMessage) {
$bag->add("success", $this->successMessage);
}
$this->success = true;
} catch (\Exception $e) {
$this->success = false;
$bag->add("error", $this->invalidMessage);
if (\Pimcore::inDebugMode()) {
$bag->add("error", $e->getMessage());
}
if (stripos($e->getMessage(), "fieldname=") !== false) {
$m = [];
preg_match('/(.+)\sfieldname=(.+)/', $e->getMessage(), $m);
$this->addFormError($m[2], $m[1]);
// } else {
// $this->addFormError("General", $e->getMessage());
}
if (\Pimcore::inDebugMode()) {
$this->form->addError(new Form\FormError($e->getMessage()));
}
// Simple::log(date("Ym")."-WebFormularError", $e->getMessage().PHP_EOL.$e->getTraceAsString());
}
} else {
if (!$this->request || !$this->request->isXmlHttpRequest()) {
$bag->add("error", $this->failMessage);
if (\Pimcore::inDebugMode()) {
$debugMessage = ['<strong>Only Visible in Debugmode:</strong>'];
foreach ($this->getFormErrors() as $error) {
$debugMessage[] = $error->getOrigin()->getName().": ".$error->getMessage();
}
$bag->add("warning", join("<br/>", $debugMessage));
}
}
}
}
}
public function getFormOptions(): array {
return $this->formOptions;
}
public function getObject() {
return $this->object;
}
public function getContainer() {
return $this->container;
}
public function getForm(): Form\FormView {
return $this->formview;
}
public function getSymfonyForm(): Form\FormInterface {
return $this->form;
}
public function addFormError($fieldName, $message = null) {
if (empty($message)) {
$message = $this->translator->trans("form.validation.fieldempty");
}
if ($this->form == null) {
var_dump($message);
return;
}
if ($this->form->get($fieldName) == null) {
$this->form->addError(new Form\FormError($message." (".$fieldName.")"));
}
return $this->form->get($fieldName)->addError(new Form\FormError($message));
}
public function getFormErrors(): Form\FormErrorIterator {
return $this->form->getErrors(true);
}
public function isSuccess() {
return $this->success;
}
public function isSubmitted() {
return $this->form->isSubmitted();
}
}