Skip to content

Commit

Permalink
NEW Validate DBFields
Browse files Browse the repository at this point in the history
  • Loading branch information
emteknetnz committed Sep 25, 2024
1 parent c523022 commit 6e464dc
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 38 deletions.
38 changes: 4 additions & 34 deletions src/Forms/EmailField.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@

namespace SilverStripe\Forms;

use SilverStripe\Validation\EmailValidator;

/**
* Text input field with validation for correct email format according to RFC 2822.
* Text input field with validation for correct email format
*/
class EmailField extends TextField
{
protected string $fieldValidatorClass = EmailValidator::class;

protected $inputType = 'email';
/**
Expand All @@ -17,39 +20,6 @@ public function Type()
return 'email text';
}

/**
* 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 ?? '');

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

$result = false;
}

return $this->extendValidationResult($result, $validator);
}

public function getSchemaValidation()
{
$rules = parent::getSchemaValidation();
Expand Down
25 changes: 21 additions & 4 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\Core\Injector\Injector;
use SilverStripe\Validation\FieldValidator;

/**
* Represents a field in a form.
Expand Down Expand Up @@ -87,6 +89,8 @@ class FormField extends RequestHandler
/** @see $schemaDataType */
const SCHEMA_DATA_TYPE_STRUCTURAL = 'Structural';

protected string $fieldValidatorClass;

/**
* @var Form
*/
Expand Down Expand Up @@ -1230,16 +1234,29 @@ protected function extendValidationResult(bool $result, Validator $validator): b
return $result;
}


/**
* Abstract method each {@link FormField} subclass must implement, determines whether the field
* is valid or not based on the value.
*
* Subclasses can define an existing FieldValidatorClass to validate the FormField value
* They may also override this method to provide custom validation logic
*
* @param Validator $validator
* @return bool
*/
public function validate($validator)
{
return $this->extendValidationResult(true, $validator);
$isValid = true;
if (!isset($this->fieldValidatorClass)) {
return;
}
$args = [$this->getName(), $this->getValue()];
/** @var FieldValidator $fieldValidator */
$fieldValidator = Injector::inst()->createWithArgs($this->fieldValidatorClass, $args);
$validationResult = $fieldValidator->validate();
if (!$validationResult->isValid()) {
$validator->getResult()->combineAnd($validationResult);
$isValid = false;
}
return $this->extendValidationResult($isValid, $validator);
}

/**
Expand Down
9 changes: 9 additions & 0 deletions src/ORM/FieldType/DBEmail.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

use SilverStripe\ORM\FieldType\DBVarchar;
use SilverStripe\Validation\EmailValidator;

class DBEmail extends DBVarchar
{
protected string $fieldValidatorClass = EmailValidator::class;
}
17 changes: 17 additions & 0 deletions src/ORM/FieldType/DBField.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use SilverStripe\ORM\Filters\SearchFilter;
use SilverStripe\ORM\Queries\SQLSelect;
use SilverStripe\Model\ModelData;
use SilverStripe\Core\Validation\ValidationResult;

/**
* Single field in the database.
Expand Down Expand Up @@ -43,6 +44,7 @@
*/
abstract class DBField extends ModelData implements DBIndexable
{
protected string $fieldValidatorClass;

/**
* Raw value of this field
Expand Down Expand Up @@ -468,6 +470,21 @@ public function saveInto(ModelData $model): void
}
}

public function validate(): ValidationResult
{
$result = ValidationResult::create();
if (!isset($this->fieldValidatorClass)) {
return $result;
}
$args = [$this->getName(), $this->getValue()];
$fieldValidator = Injector::inst()->createWithArgs($this->fieldValidatorClass, $args);
$validationResult = $fieldValidator->validate();
if (!$validationResult->isValid()) {
$result->combineAnd($validationResult);
}
return $result;
}

/**
* Returns a FormField instance used as a default
* for form scaffolding.
Expand Down
19 changes: 19 additions & 0 deletions src/Validation/EmailValidator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace SilverStripe\Validation;

use SilverStripe\Core\Validation\ValidationResult;
use SilverStripe\Validation\FieldValidator;

class EmailValidator extends FieldValidator
{
protected function validateValue(ValidationResult $result): ValidationResult
{
// Replace this with symfony constraint email validation
if (!filter_var($this->value, FILTER_VALIDATE_EMAIL)) {
$message = _t('SilverStripe\\Forms\\EmailField.VALIDATION', 'Please enter an email address');
$result->addFieldError($this->name, $message);
}
return $result;
}
}
27 changes: 27 additions & 0 deletions src/Validation/FieldValidator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

namespace SilverStripe\Validation;

use SilverStripe\Core\Validation\ValidationResult;

abstract class FieldValidator
{
protected string $name;

protected mixed $value;

public function __construct(string $name, mixed $value)
{
$this->name = $name;
$this->value = $value;
}

public function validate(): ValidationResult
{
$result = ValidationResult::create();
$result = $this->validateValue($result);
return $result;
}

abstract protected function validateValue(ValidationResult $result): ValidationResult;
}

0 comments on commit 6e464dc

Please sign in to comment.