2018-05-08 07:02:01 +02:00
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace SilverStripe\UserForms\Form;
|
|
|
|
|
2020-01-10 05:36:04 +01:00
|
|
|
use InvalidArgumentException;
|
2018-05-08 07:02:01 +02:00
|
|
|
use SilverStripe\Dev\Debug;
|
|
|
|
use SilverStripe\Forms\FileField;
|
|
|
|
use SilverStripe\Forms\FormField;
|
|
|
|
use SilverStripe\Forms\RequiredFields;
|
2024-09-23 04:40:23 +02:00
|
|
|
use SilverStripe\Core\ArrayLib;
|
2018-05-08 07:02:01 +02:00
|
|
|
use SilverStripe\UserForms\Model\EditableFormField;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* An extension of RequiredFields which handles conditionally required fields.
|
|
|
|
*
|
|
|
|
* A conditionally required is a field that is required, but can be hidden by display rules.
|
|
|
|
* When it is visible, (according to the submitted form data) it will be validated as required.
|
|
|
|
* When it is hidden, it will skip required validation.
|
|
|
|
*
|
|
|
|
* Required fields will be validated as usual.
|
|
|
|
* Conditionally required fields will be validated IF the display rules are satisfied in the submitted dataset.
|
|
|
|
*/
|
|
|
|
class UserFormsRequiredFields extends RequiredFields
|
|
|
|
{
|
|
|
|
/**
|
|
|
|
* Allows validation of fields via specification of a php function for
|
|
|
|
* validation which is executed after the form is submitted.
|
|
|
|
*
|
|
|
|
* @param array $data
|
|
|
|
*
|
2020-01-10 05:36:04 +01:00
|
|
|
* @return bool
|
2018-05-08 07:02:01 +02:00
|
|
|
*/
|
|
|
|
public function php($data)
|
|
|
|
{
|
|
|
|
$valid = true;
|
|
|
|
$fields = $this->form->Fields();
|
|
|
|
|
|
|
|
foreach ($fields as $field) {
|
|
|
|
$valid = ($field->validate($this) && $valid);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (empty($this->required)) {
|
|
|
|
return $valid;
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach ($this->required as $fieldName) {
|
|
|
|
if (!$fieldName) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// get form field
|
|
|
|
if ($fieldName instanceof FormField) {
|
|
|
|
$formField = $fieldName;
|
|
|
|
$fieldName = $fieldName->getName();
|
|
|
|
} else {
|
|
|
|
$formField = $fields->dataFieldByName($fieldName);
|
|
|
|
}
|
|
|
|
|
|
|
|
// get editable form field - owns display rules for field
|
|
|
|
$editableFormField = $this->getEditableFormFieldByName($fieldName);
|
|
|
|
|
2020-01-10 05:36:04 +01:00
|
|
|
// Validate if the field is displayed
|
|
|
|
$error =
|
|
|
|
$editableFormField->isDisplayed($data) &&
|
|
|
|
$this->validateRequired($formField, $data);
|
2018-05-08 07:02:01 +02:00
|
|
|
|
|
|
|
// handle error case
|
|
|
|
if ($formField && $error) {
|
|
|
|
$this->handleError($formField, $fieldName);
|
|
|
|
$valid = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $valid;
|
|
|
|
}
|
|
|
|
|
2020-01-10 05:36:04 +01:00
|
|
|
/**
|
|
|
|
* Retrieve an Editable Form field by its name.
|
|
|
|
* @param string $name
|
|
|
|
* @return EditableFormField
|
|
|
|
*/
|
2018-05-08 07:02:01 +02:00
|
|
|
private function getEditableFormFieldByName($name)
|
|
|
|
{
|
2020-01-10 05:36:04 +01:00
|
|
|
$field = EditableFormField::get()->filter(['Name' => $name])->first();
|
2018-05-08 07:02:01 +02:00
|
|
|
|
2020-01-10 05:36:04 +01:00
|
|
|
if ($field) {
|
|
|
|
return $field;
|
2018-05-08 07:02:01 +02:00
|
|
|
}
|
|
|
|
|
2020-01-10 05:36:04 +01:00
|
|
|
// This should happen if form field data got corrupted
|
|
|
|
throw new InvalidArgumentException(sprintf(
|
|
|
|
'Could not find EditableFormField with name `%s`',
|
|
|
|
$name
|
|
|
|
));
|
2018-05-08 07:02:01 +02:00
|
|
|
}
|
|
|
|
|
2020-01-10 05:36:04 +01:00
|
|
|
/**
|
|
|
|
* Check if the validation rules for the specified field are met by the provided data.
|
|
|
|
*
|
|
|
|
* @note Logic replicated from php() method of parent class `SilverStripe\Forms\RequiredFields`
|
|
|
|
* @param EditableFormField $field
|
|
|
|
* @param array $data
|
|
|
|
* @return bool
|
|
|
|
*/
|
|
|
|
private function validateRequired(FormField $field, array $data)
|
2018-05-08 07:02:01 +02:00
|
|
|
{
|
|
|
|
$error = false;
|
|
|
|
$fieldName = $field->getName();
|
|
|
|
// submitted data for file upload fields come back as an array
|
|
|
|
$value = isset($data[$fieldName]) ? $data[$fieldName] : null;
|
|
|
|
|
|
|
|
if (is_array($value)) {
|
|
|
|
if ($field instanceof FileField && isset($value['error']) && $value['error']) {
|
|
|
|
$error = true;
|
|
|
|
} else {
|
2022-04-13 03:52:56 +02:00
|
|
|
$error = (count($value ?? [])) ? false : true;
|
2018-05-08 07:02:01 +02:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// assume a string or integer
|
2022-04-13 03:52:56 +02:00
|
|
|
$error = (strlen($value ?? '')) ? false : true;
|
2018-05-08 07:02:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return $error;
|
|
|
|
}
|
|
|
|
|
2020-01-13 00:14:11 +01:00
|
|
|
/**
|
|
|
|
* Register an error for the provided field.
|
|
|
|
* @param FormField $formField
|
|
|
|
* @param string $fieldName
|
|
|
|
* @return void
|
|
|
|
*/
|
|
|
|
private function handleError(FormField $formField, $fieldName)
|
2018-05-08 07:02:01 +02:00
|
|
|
{
|
|
|
|
$errorMessage = _t(
|
|
|
|
'SilverStripe\\Forms\\Form.FIELDISREQUIRED',
|
|
|
|
'{name} is required',
|
2020-01-14 00:28:04 +01:00
|
|
|
[
|
2018-05-08 07:02:01 +02:00
|
|
|
'name' => strip_tags(
|
|
|
|
'"' . ($formField->Title() ? $formField->Title() : $fieldName) . '"'
|
|
|
|
)
|
2020-01-14 00:28:04 +01:00
|
|
|
]
|
2018-05-08 07:02:01 +02:00
|
|
|
);
|
|
|
|
|
|
|
|
if ($msg = $formField->getCustomValidationMessage()) {
|
|
|
|
$errorMessage = $msg;
|
|
|
|
}
|
|
|
|
|
2020-01-14 00:28:04 +01:00
|
|
|
$this->validationError($fieldName, $errorMessage, "required");
|
2018-05-08 07:02:01 +02:00
|
|
|
}
|
|
|
|
}
|