Skip to content

Commit

Permalink
FIX Improve non-inline validation
Browse files Browse the repository at this point in the history
  • Loading branch information
emteknetnz committed Apr 30, 2024
1 parent e5cc486 commit 4045901
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 13 deletions.
79 changes: 66 additions & 13 deletions src/Forms/ElementalAreaField.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,14 @@
use SilverStripe\Forms\CompositeField;
use SilverStripe\Forms\FieldGroup;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\Form;
use SilverStripe\Forms\FormField;
use SilverStripe\Forms\GridField\GridField;
use SilverStripe\Forms\TabSet;
use SilverStripe\ORM\DataObjectInterface;
use Symbiote\GridFieldExtensions\GridFieldAddNewMultiClass;
use SilverStripe\Forms\GridField\GridFieldDetailForm;
use SilverStripe\Forms\GridField\GridFieldDetailForm_ItemRequest;

class ElementalAreaField extends GridField
{
Expand Down Expand Up @@ -214,33 +217,83 @@ public function setSubmittedValue($value, $data = null)
return $this->setValue(json_decode($value ?? '', true));
}

/**
* This will perform FormField validation
* DataObject validation will happen in saveInto() as part of $element->write()
*/
public function validate($validator)
{
foreach ($this->getElementData() as $arr) {
/** @var BaseElement $element */
/** @var array $data */
$element = $arr['element'];
$data = $arr['data'];
$elementForm = $this->getElementForm($element);
if (!$elementForm) {
continue;
}
$elementForm->loadDataFrom($data);
$formValidatorResult = $elementForm->validationResult();
if (!$formValidatorResult->isValid()) {
$validator->getResult()->combineAnd($formValidatorResult);
}
}
return $validator;
}

public function saveInto(DataObjectInterface $dataObject)
{
parent::saveInto($dataObject);

$elementData = $this->Value();
$idPrefixLength = strlen(sprintf(ElementalAreaController::FORM_NAME_TEMPLATE ?? '', ''));

if (!$elementData) {
return;
foreach ($this->getElementData() as $arr) {
/** @var BaseElement $element */
/** @var array $data */
$element = $arr['element'];
$data = $arr['data'];
$element->updateFromFormData($data);
$element->write();
}
}

foreach ($elementData as $form => $data) {
private function getElementData(): array
{
$elementData = [];
$value = $this->Value();
if (!$value) {
return [];
}
$idPrefixLength = strlen(sprintf(ElementalAreaController::FORM_NAME_TEMPLATE ?? '', ''));
foreach ($value as $form => $data) {
// Extract the ID
$elementId = (int) substr($form ?? '', $idPrefixLength ?? 0);

/** @var BaseElement $element */
$element = $this->getArea()->Elements()->byID($elementId);

if (!$element) {
// Ignore invalid elements
continue;
}

$data = ElementalAreaController::removeNamespacesFromFields($data, $element->ID);

$element->updateFromFormData($data);
$element->write();
$elementData[] = ['element' => $element, 'data' => $data];
}
return $elementData;
}

private function getElementForm(BaseElement $element): ?Form
{
// This is essentially the same method used to generate a form to edit an element
// that a non-inline edit for will use - see GridFieldDetailForm::handleItem()
$requestHandler = $requestHandler = $this->getForm()->getController();
$gridFieldDetailForm = new GridFieldDetailForm();
// The validator need to be explicitly copied from the element to the form
$validator = $element->getCMSCompositeValidator();
$gridFieldDetailForm->setValidator($validator);
$gridFieldDetailFormItemRequest = new GridFieldDetailForm_ItemRequest(
$this,
$gridFieldDetailForm,
$element,
$requestHandler,
''
);
$form = $gridFieldDetailFormItemRequest->ItemEditForm();
return $form;
}
}
52 changes: 52 additions & 0 deletions src/Forms/TextCheckboxGroupField.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,58 @@ public function __construct($title = null)
$this->setTitle($title);
}

/**
* @return string
*/
public function getMessage()
{
$message = parent::getMessage();
if ($message) {
return $message;
}
foreach ($this->getChildren() as $field) {
$message = $field->getMessage();
if ($message) {
return $message;
}
}
return '';
}

/**
* @return string
*/
public function getMessageType()
{
$message = parent::getMessage();
if ($message) {
return parent::getMessageType();
}
foreach ($this->getChildren() as $field) {
if ($field->getMessage()) {
return $field->getMessageType();
}
}
return '';
}

/**
* @return string
*/
public function getMessageCast()
{
$message = parent::getMessage();
if ($message) {
return parent::getMessageCast();
}
foreach ($this->getChildren() as $field) {
if ($field->getMessage()) {
return $field->getMessageCast();
}
}
return '';
}

/**
* Don't use the custom template for readonly states
*
Expand Down
2 changes: 2 additions & 0 deletions src/Models/BaseElement.php
Original file line number Diff line number Diff line change
Expand Up @@ -654,6 +654,7 @@ public function getRenderTemplates($suffix = '')
*/
public function updateFromFormData($data)
{
/** @var FieldList $cmsFields */
$cmsFields = $this->getCMSFields();

foreach ($data as $field => $datum) {
Expand All @@ -664,6 +665,7 @@ public function updateFromFormData($data)
}

$field->setSubmittedValue($datum);
// $field->validate();
$field->saveInto($this);
}
}
Expand Down

0 comments on commit 4045901

Please sign in to comment.