Skip to content

Commit

Permalink
NEW DBField validation
Browse files Browse the repository at this point in the history
  • Loading branch information
emteknetnz committed Sep 24, 2024
1 parent e2e3231 commit 1b74cac
Show file tree
Hide file tree
Showing 12 changed files with 597 additions and 450 deletions.
2 changes: 2 additions & 0 deletions _config/model.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ SilverStripe\Core\Injector\Injector:
class: SilverStripe\ORM\FieldType\DBDecimal
Double:
class: SilverStripe\ORM\FieldType\DBDouble
Email:
class: SilverStripe\ORM\FieldType\DBEmail
Enum:
class: SilverStripe\ORM\FieldType\DBEnum
Float:
Expand Down
25 changes: 11 additions & 14 deletions src/Forms/EmailField.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

namespace SilverStripe\Forms;

use SilverStripe\Core\Validation\ConstraintValidator;
use Symfony\Component\Validator\Constraints;

/**
* Text input field with validation for correct email format according to RFC 2822.
*/
Expand All @@ -18,32 +21,26 @@ public function Type()
}

/**
* Validates for RFC 2822 compliant email addresses.
*
* @see http://www.regular-expressions.info/email.html
* @see http://www.ietf.org/rfc/rfc2822.txt
*
* @param Validator $validator
*
* @return string
*/
public function validate($validator)
{
$result = true;
$this->value = trim($this->value ?? '');

$pattern = '^[a-z0-9!#$%&\'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&\'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$';

// Escape delimiter characters.
$safePattern = str_replace('/', '\\/', $pattern ?? '');
$result = true;
$message = _t('SilverStripe\\Forms\\EmailField.VALIDATION', 'Please enter an email address');
$validationResult = ConstraintValidator::validate(
$this->value,
new Constraints\Email(message: $message)
);

if ($this->value && !preg_match('/' . $safePattern . '/i', $this->value ?? '')) {
if (!$validationResult->isValid()) {
$validator->validationError(
$this->name,
_t('SilverStripe\\Forms\\EmailField.VALIDATION', 'Please enter an email address'),
'validation'
$validationResult->getMessages()[0]['message'],
);

$result = false;
}

Expand Down
38 changes: 35 additions & 3 deletions src/Forms/FormField.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
use SilverStripe\View\AttributesHTML;
use SilverStripe\View\SSViewer;
use SilverStripe\Model\ModelData;
use SilverStripe\Model\ModelFields\ModelField;
use SilverStripe\Core\Injector\Injector;

/**
* Represents a field in a form.
Expand All @@ -40,7 +42,7 @@
* including both structure (name, id, attributes, etc.) and state (field value).
* Can be used by for JSON data which is consumed by a front-end application.
*/
class FormField extends RequestHandler
abstract class FormField extends RequestHandler
{
use AttributesHTML;
use FormMessage;
Expand Down Expand Up @@ -87,6 +89,28 @@ class FormField extends RequestHandler
/** @see $schemaDataType */
const SCHEMA_DATA_TYPE_STRUCTURAL = 'Structural';

/**
* Class of the ModelField to instantiate for this form field
* Intentionally does not have getters or setters
*/
protected string $modelFieldClass;

/**
* The instance of the ModelField for this form field
*/
protected ModelField $modelField;

public function getModelField(): ModelField
{
return $this->modelField;
}

public function setModelField(ModelField $modelField): static
{
$this->modelField = $modelField;
return $this;
}

/**
* @var Form
*/
Expand Down Expand Up @@ -330,6 +354,11 @@ public static function name_to_label($fieldName)
*/
public function __construct($name, $title = null, $value = null)
{
// TODO: should remove the check for modelFieldClass and just assume everything has it
if (isset($this->modelFieldClass)) {
$this->modelField = Injector::inst()->createWithArgs($this->modelFieldClass, [$name]);
}

$this->setName($name);

if ($title === null) {
Expand Down Expand Up @@ -929,7 +958,7 @@ public function Field($properties = [])
// Trim whitespace from the result, so that trailing newlines are suppressed. Works for strings and HTMLText values
if (is_string($result)) {
$result = trim($result ?? '');
} elseif ($result instanceof DBField) {
} elseif ($result instanceof ModelField) {
$result->setValue(trim($result->getValue() ?? ''));
}

Expand Down Expand Up @@ -1231,9 +1260,12 @@ protected function extendValidationResult(bool $result, Validator $validator): b
}

/**
* Abstract method each {@link FormField} subclass must implement, determines whether the field
* Method each {@link FormField} subclass can implement, determines whether the field
* is valid or not based on the value.
*
* Subclass methods should call $this->extendValidationResult(true, $validator)
* at the end of the method
*
* @param Validator $validator
* @return bool
*/
Expand Down
8 changes: 4 additions & 4 deletions src/Forms/FormRequestHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -216,10 +216,10 @@ public function httpSubmission($request)
// Action handlers may throw ValidationExceptions.
try {
// Or we can use the Validator attached to the form
$result = $this->form->validationResult();
if (!$result->isValid()) {
return $this->getValidationErrorResponse($result);
}
// $result = $this->form->validationResult();
// if (!$result->isValid()) {
// return $this->getValidationErrorResponse($result);
// }

// First, try a handler method on the controller (has been checked for allowed_actions above already)
$controller = $this->form->getController();
Expand Down
4 changes: 4 additions & 0 deletions src/Forms/TextField.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,15 @@

namespace SilverStripe\Forms;

use SilverStripe\Model\ModelFields\StringModelField;

/**
* Text input field.
*/
class TextField extends FormField implements TippableFieldInterface
{
protected string $modelFieldClass = StringModelField::class;

/**
* @var int
*/
Expand Down
15 changes: 8 additions & 7 deletions src/Model/ModelData.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@
use SilverStripe\Dev\Debug;
use SilverStripe\Core\ArrayLib;
use SilverStripe\Model\List\ArrayList;
use SilverStripe\ORM\FieldType\DBField;
use SilverStripe\ORM\FieldType\DBHTMLText;
use SilverStripe\Model\ArrayData;
use SilverStripe\View\SSViewer;
use UnexpectedValueException;
use SilverStripe\Model\ModelField;
use SilverStripe\Core\Validation\ValidationResult;

/**
* A ModelData object is any object that can be rendered into a template/view.
Expand Down Expand Up @@ -327,7 +328,7 @@ public function setCustomisedObj(ModelData $object)

/**
* Return the "casting helper" (a piece of PHP code that when evaluated creates a casted value object)
* for a field on this object. This helper will be a subclass of DBField.
* for a field on this object. This helper will be a subclass of ModelField.
*
* @param bool $useFallback If true, fall back on the default casting helper if there isn't an explicit one.
* @return string|null Casting helper As a constructor pattern, and may include arguments.
Expand Down Expand Up @@ -361,7 +362,7 @@ public function castingHelper(string $field, bool $useFallback = true): ?string

/**
* Return the default "casting helper" for use when no explicit casting helper is defined.
* This helper will be a subclass of DBField. See castingHelper()
* This helper will be a subclass of ModelField. See castingHelper()
*/
protected function defaultCastingHelper(string $field): string
{
Expand Down Expand Up @@ -402,7 +403,7 @@ public function escapeTypeForField(string $field): string
{
$class = $this->castingClass($field) ?: $this->config()->get('default_cast');

/** @var DBField $type */
/** @var ModelField $type */
$type = Injector::inst()->get($class, true);
return $type->config()->get('escape_type');
}
Expand Down Expand Up @@ -495,9 +496,9 @@ protected function objCacheClear()
* Get the value of a field on this object, automatically inserting the value into any available casting objects
* that have been specified.
*
* @return object|DBField|null The specific object representing the field, or null if there is no
* @return object|ModelField|null The specific object representing the field, or null if there is no
* property, method, or dynamic data available for that field.
* Note that if there is a property or method that returns null, a relevant DBField instance will
* Note that if there is a property or method that returns null, a relevant ModelField instance will
* be returned.
*/
public function obj(
Expand Down Expand Up @@ -568,7 +569,7 @@ public function obj(
* A simple wrapper around {@link ModelData::obj()} that automatically caches the result so it can be used again
* without re-running the method.
*
* @return Object|DBField
* @return Object|ModelField
*/
public function cachedCall(string $fieldName, array $arguments = [], ?string $cacheName = null): object
{
Expand Down
Loading

0 comments on commit 1b74cac

Please sign in to comment.