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 98198a5
Show file tree
Hide file tree
Showing 15 changed files with 634 additions and 408 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
17 changes: 14 additions & 3 deletions src/Forms/FormField.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
use SilverStripe\View\AttributesHTML;
use SilverStripe\View\SSViewer;
use SilverStripe\Model\ModelData;
use SilverStripe\Model\ModelFields\ModelField;
use SilverStripe\Model\ModelFields\ModelFieldTrait;
use SilverStripe\Model\ModelFields\StringModelField;

/**
* Represents a field in a form.
Expand All @@ -40,10 +43,11 @@
* 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;
use ModelFieldTrait;

/** @see $schemaDataType */
const SCHEMA_DATA_TYPE_STRING = 'String';
Expand Down Expand Up @@ -87,6 +91,9 @@ class FormField extends RequestHandler
/** @see $schemaDataType */
const SCHEMA_DATA_TYPE_STRUCTURAL = 'Structural';

// TODO: this is wrong, though haven't yet created things like DateTimeModelField
protected string $modelFieldClass = StringModelField::class;

/**
* @var Form
*/
Expand Down Expand Up @@ -344,6 +351,7 @@ public function __construct($name, $title = null, $value = null)

parent::__construct();

$this->initModelField($name);
$this->setupDefaultClasses();
}

Expand Down Expand Up @@ -929,7 +937,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 +1239,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
2 changes: 2 additions & 0 deletions src/Forms/GridField/GridField.php
Original file line number Diff line number Diff line change
Expand Up @@ -543,6 +543,8 @@ public function FieldHolder($properties = [])
'footer' => '',
];

$_c = $this->getComponents();

foreach ($this->getComponents() as $item) {
if ($item instanceof GridField_HTMLProvider) {
$fragments = $item->getHTMLFragments($this);
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
31 changes: 22 additions & 9 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 All @@ -520,7 +521,13 @@ public function obj(
// Load value from record
if ($this->hasMethod($fieldName)) {
$hasObj = true;
$value = call_user_func_array([$this, $fieldName], $arguments ?: []);
// todo: remove try catch block
try {
$value = call_user_func_array([$this, $fieldName], $arguments ?: []);
} catch (Exception $e) {
$x=1;
throw $e;
}
} else {
$hasObj = $this->hasField($fieldName) || ($this->hasMethod("get{$fieldName}") && $this->isAccessibleMethod("get{$fieldName}"));
$value = $this->$fieldName;
Expand Down Expand Up @@ -568,7 +575,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 Expand Up @@ -599,7 +606,13 @@ public function XML_val(string $field, array $arguments = [], bool $cache = fals
return '';
}
// Might contain additional formatting over ->XML(). E.g. parse shortcodes, nl2br()
return $result->forTemplate();
// todo: remove try catch block
try {
return $result->forTemplate();
} catch (Exception $e) {
$x=1;
throw $e;
}
}

/**
Expand Down
Loading

0 comments on commit 98198a5

Please sign in to comment.