mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 12:05:37 +00:00
Compare commits
8 Commits
e46db939b3
...
da474707fb
Author | SHA1 | Date | |
---|---|---|---|
|
da474707fb | ||
|
fe46daa04f | ||
|
c523022cb9 | ||
|
a81b7855de | ||
|
e93dafb2fe | ||
|
6287b6ebeb | ||
|
c7ba8d19c5 | ||
|
5fa88663b0 |
@ -20,6 +20,8 @@ SilverStripe\Core\Injector\Injector:
|
|||||||
class: SilverStripe\ORM\FieldType\DBDecimal
|
class: SilverStripe\ORM\FieldType\DBDecimal
|
||||||
Double:
|
Double:
|
||||||
class: SilverStripe\ORM\FieldType\DBDouble
|
class: SilverStripe\ORM\FieldType\DBDouble
|
||||||
|
Email:
|
||||||
|
class: SilverStripe\ORM\FieldType\DBEmail
|
||||||
Enum:
|
Enum:
|
||||||
class: SilverStripe\ORM\FieldType\DBEnum
|
class: SilverStripe\ORM\FieldType\DBEnum
|
||||||
Float:
|
Float:
|
||||||
|
@ -13,6 +13,7 @@ use SilverStripe\Core\Extensible;
|
|||||||
use SilverStripe\Core\Injector\Injectable;
|
use SilverStripe\Core\Injector\Injectable;
|
||||||
use SilverStripe\Core\Injector\Injector;
|
use SilverStripe\Core\Injector\Injector;
|
||||||
use SilverStripe\ORM\FieldType\DBField;
|
use SilverStripe\ORM\FieldType\DBField;
|
||||||
|
use SilverStripe\ORM\FieldType\DBFieldHelper;
|
||||||
use SilverStripe\Model\ArrayData;
|
use SilverStripe\Model\ArrayData;
|
||||||
use SilverStripe\View\Requirements;
|
use SilverStripe\View\Requirements;
|
||||||
use SilverStripe\View\SSViewer;
|
use SilverStripe\View\SSViewer;
|
||||||
@ -509,7 +510,7 @@ class Email extends SymfonyEmail
|
|||||||
// Plain render fallbacks to using the html render with html tags removed
|
// Plain render fallbacks to using the html render with html tags removed
|
||||||
if (!$plainRender && $htmlRender) {
|
if (!$plainRender && $htmlRender) {
|
||||||
// call html_entity_decode() to ensure any encoded HTML is also stripped inside ->Plain()
|
// call html_entity_decode() to ensure any encoded HTML is also stripped inside ->Plain()
|
||||||
$dbField = DBField::create_field('HTMLFragment', html_entity_decode($htmlRender));
|
$dbField = DBFieldHelper::create_field('HTMLFragment', html_entity_decode($htmlRender));
|
||||||
$plainRender = $dbField->Plain();
|
$plainRender = $dbField->Plain();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ class CliBypass implements Bypass
|
|||||||
{
|
{
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
Deprecation::withNoReplacement(function () {
|
Deprecation::withSuppressedNotice(function () {
|
||||||
Deprecation::notice(
|
Deprecation::notice(
|
||||||
'5.4.0',
|
'5.4.0',
|
||||||
'Will be removed without equivalent functionality to replace it',
|
'Will be removed without equivalent functionality to replace it',
|
||||||
|
@ -4,6 +4,7 @@ namespace SilverStripe\Control\RSS;
|
|||||||
|
|
||||||
use SilverStripe\Control\Director;
|
use SilverStripe\Control\Director;
|
||||||
use SilverStripe\ORM\FieldType\DBField;
|
use SilverStripe\ORM\FieldType\DBField;
|
||||||
|
use SilverStripe\ORM\FieldType\DBFieldHelper;
|
||||||
use SilverStripe\ORM\FieldType\DBHTMLText;
|
use SilverStripe\ORM\FieldType\DBHTMLText;
|
||||||
use SilverStripe\Model\ModelData;
|
use SilverStripe\Model\ModelData;
|
||||||
use BadMethodCallException;
|
use BadMethodCallException;
|
||||||
|
@ -96,7 +96,7 @@ abstract class BuildTask
|
|||||||
*/
|
*/
|
||||||
public function getDescription()
|
public function getDescription()
|
||||||
{
|
{
|
||||||
Deprecation::withNoReplacement(
|
Deprecation::withSuppressedNotice(
|
||||||
fn() => Deprecation::notice('5.4.0', 'Will be replaced with a static method with the same name')
|
fn() => Deprecation::notice('5.4.0', 'Will be replaced with a static method with the same name')
|
||||||
);
|
);
|
||||||
return $this->description;
|
return $this->description;
|
||||||
|
@ -53,7 +53,7 @@ class Deprecation
|
|||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
private static bool $insideWithNoReplacement = false;
|
private static bool $insideNoticeSuppression = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
@ -103,22 +103,32 @@ class Deprecation
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to wrap deprecated methods and deprecated config get()/set() that will be removed
|
* Used to wrap deprecated methods and deprecated config get()/set() called from the vendor
|
||||||
* in the next major version with no replacement. This is done to surpress deprecation notices
|
* dir that projects have no ability to change.
|
||||||
* by for calls from the vendor dir to deprecated code that projects have no ability to change
|
|
||||||
*
|
*
|
||||||
* @return mixed
|
* @return mixed
|
||||||
|
* @deprecated 5.4.0 Use withSuppressedNotice() instead
|
||||||
*/
|
*/
|
||||||
public static function withNoReplacement(callable $func)
|
public static function withNoReplacement(callable $func)
|
||||||
{
|
{
|
||||||
if (Deprecation::$insideWithNoReplacement) {
|
Deprecation::notice('5.4.0', 'Use withSuppressedNotice() instead');
|
||||||
|
return Deprecation::withSuppressedNotice($func);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to wrap deprecated methods and deprecated config get()/set() called from the vendor
|
||||||
|
* dir that projects have no ability to change.
|
||||||
|
*/
|
||||||
|
public static function withSuppressedNotice(callable $func): mixed
|
||||||
|
{
|
||||||
|
if (Deprecation::$insideNoticeSuppression) {
|
||||||
return $func();
|
return $func();
|
||||||
}
|
}
|
||||||
Deprecation::$insideWithNoReplacement = true;
|
Deprecation::$insideNoticeSuppression = true;
|
||||||
try {
|
try {
|
||||||
return $func();
|
return $func();
|
||||||
} finally {
|
} finally {
|
||||||
Deprecation::$insideWithNoReplacement = false;
|
Deprecation::$insideNoticeSuppression = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,8 +147,8 @@ class Deprecation
|
|||||||
$level = 1;
|
$level = 1;
|
||||||
}
|
}
|
||||||
$newLevel = $level;
|
$newLevel = $level;
|
||||||
// handle closures inside withNoReplacement()
|
// handle closures inside withSuppressedNotice()
|
||||||
if (Deprecation::$insideWithNoReplacement
|
if (Deprecation::$insideNoticeSuppression
|
||||||
&& substr($backtrace[$newLevel]['function'], -strlen('{closure}')) === '{closure}'
|
&& substr($backtrace[$newLevel]['function'], -strlen('{closure}')) === '{closure}'
|
||||||
) {
|
) {
|
||||||
$newLevel = $newLevel + 2;
|
$newLevel = $newLevel + 2;
|
||||||
@ -247,8 +257,8 @@ class Deprecation
|
|||||||
$count++;
|
$count++;
|
||||||
$arr = array_shift(Deprecation::$userErrorMessageBuffer);
|
$arr = array_shift(Deprecation::$userErrorMessageBuffer);
|
||||||
$message = $arr['message'];
|
$message = $arr['message'];
|
||||||
$calledInsideWithNoReplacement = $arr['calledInsideWithNoReplacement'];
|
$calledWithNoticeSuppression = $arr['calledWithNoticeSuppression'];
|
||||||
if ($calledInsideWithNoReplacement && !Deprecation::$showNoReplacementNotices) {
|
if ($calledWithNoticeSuppression && !Deprecation::$showNoReplacementNotices) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Deprecation::$isTriggeringError = true;
|
Deprecation::$isTriggeringError = true;
|
||||||
@ -284,7 +294,7 @@ class Deprecation
|
|||||||
$data = [
|
$data = [
|
||||||
'key' => sha1($string),
|
'key' => sha1($string),
|
||||||
'message' => $string,
|
'message' => $string,
|
||||||
'calledInsideWithNoReplacement' => Deprecation::$insideWithNoReplacement
|
'calledWithNoticeSuppression' => Deprecation::$insideNoticeSuppression
|
||||||
];
|
];
|
||||||
} else {
|
} else {
|
||||||
if (!Deprecation::isEnabled()) {
|
if (!Deprecation::isEnabled()) {
|
||||||
@ -310,7 +320,7 @@ class Deprecation
|
|||||||
$string .= ".";
|
$string .= ".";
|
||||||
}
|
}
|
||||||
|
|
||||||
$level = Deprecation::$insideWithNoReplacement ? 4 : 2;
|
$level = Deprecation::$insideNoticeSuppression ? 4 : 2;
|
||||||
$string .= " Called from " . Deprecation::get_called_method_from_trace($backtrace, $level) . '.';
|
$string .= " Called from " . Deprecation::get_called_method_from_trace($backtrace, $level) . '.';
|
||||||
|
|
||||||
if ($caller) {
|
if ($caller) {
|
||||||
@ -319,7 +329,7 @@ class Deprecation
|
|||||||
$data = [
|
$data = [
|
||||||
'key' => sha1($string),
|
'key' => sha1($string),
|
||||||
'message' => $string,
|
'message' => $string,
|
||||||
'calledInsideWithNoReplacement' => Deprecation::$insideWithNoReplacement
|
'calledWithNoticeSuppression' => Deprecation::$insideNoticeSuppression
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
if ($data && !array_key_exists($data['key'], Deprecation::$userErrorMessageBuffer)) {
|
if ($data && !array_key_exists($data['key'], Deprecation::$userErrorMessageBuffer)) {
|
||||||
|
@ -34,7 +34,7 @@ class DevBuildController extends Controller implements PermissionProvider
|
|||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
Deprecation::withNoReplacement(function () {
|
Deprecation::withSuppressedNotice(function () {
|
||||||
Deprecation::notice(
|
Deprecation::notice(
|
||||||
'5.4.0',
|
'5.4.0',
|
||||||
'Will be replaced with SilverStripe\Dev\Command\DbBuild',
|
'Will be replaced with SilverStripe\Dev\Command\DbBuild',
|
||||||
|
@ -47,7 +47,7 @@ class DevConfigController extends Controller implements PermissionProvider
|
|||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
Deprecation::withNoReplacement(function () {
|
Deprecation::withSuppressedNotice(function () {
|
||||||
Deprecation::notice(
|
Deprecation::notice(
|
||||||
'5.4.0',
|
'5.4.0',
|
||||||
'Will be replaced with SilverStripe\Dev\Command\ConfigDump',
|
'Will be replaced with SilverStripe\Dev\Command\ConfigDump',
|
||||||
|
@ -233,7 +233,7 @@ class DevelopmentAdmin extends Controller implements PermissionProvider
|
|||||||
*/
|
*/
|
||||||
public function buildDefaults()
|
public function buildDefaults()
|
||||||
{
|
{
|
||||||
Deprecation::withNoReplacement(function () {
|
Deprecation::withSuppressedNotice(function () {
|
||||||
Deprecation::notice(
|
Deprecation::notice(
|
||||||
'5.4.0',
|
'5.4.0',
|
||||||
'Will be replaced with SilverStripe\Dev\Command\DbDefaults'
|
'Will be replaced with SilverStripe\Dev\Command\DbDefaults'
|
||||||
@ -266,7 +266,7 @@ class DevelopmentAdmin extends Controller implements PermissionProvider
|
|||||||
*/
|
*/
|
||||||
public function generatesecuretoken()
|
public function generatesecuretoken()
|
||||||
{
|
{
|
||||||
Deprecation::withNoReplacement(function () {
|
Deprecation::withSuppressedNotice(function () {
|
||||||
Deprecation::notice(
|
Deprecation::notice(
|
||||||
'5.4.0',
|
'5.4.0',
|
||||||
'Will be replaced with SilverStripe\Dev\Command\GenerateSecureToken'
|
'Will be replaced with SilverStripe\Dev\Command\GenerateSecureToken'
|
||||||
|
@ -36,7 +36,7 @@ class CleanupTestDatabasesTask extends BuildTask
|
|||||||
|
|
||||||
public function canView(): bool
|
public function canView(): bool
|
||||||
{
|
{
|
||||||
Deprecation::withNoReplacement(function () {
|
Deprecation::withSuppressedNotice(function () {
|
||||||
Deprecation::notice(
|
Deprecation::notice(
|
||||||
'5.4.0',
|
'5.4.0',
|
||||||
'Will be replaced with canRunInBrowser()'
|
'Will be replaced with canRunInBrowser()'
|
||||||
|
@ -6,6 +6,7 @@ use LogicException;
|
|||||||
use SilverStripe\ORM\DataObject;
|
use SilverStripe\ORM\DataObject;
|
||||||
use SilverStripe\ORM\DataObjectInterface;
|
use SilverStripe\ORM\DataObjectInterface;
|
||||||
use SilverStripe\ORM\FieldType\DBField;
|
use SilverStripe\ORM\FieldType\DBField;
|
||||||
|
use SilverStripe\ORM\FieldType\DBFieldHelper;
|
||||||
use SilverStripe\Security\Authenticator;
|
use SilverStripe\Security\Authenticator;
|
||||||
use SilverStripe\Security\Security;
|
use SilverStripe\Security\Security;
|
||||||
use SilverStripe\View\HTML;
|
use SilverStripe\View\HTML;
|
||||||
@ -771,6 +772,6 @@ class ConfirmedPasswordField extends FormField
|
|||||||
if (strpos($attributes, 'required="required"') === false && $this->Required()) {
|
if (strpos($attributes, 'required="required"') === false && $this->Required()) {
|
||||||
$attributes .= ' required="required" aria-required="true"';
|
$attributes .= ' required="required" aria-required="true"';
|
||||||
}
|
}
|
||||||
return DBField::create_field('HTMLFragment', $attributes);
|
return DBFieldHelper::create_field('HTMLFragment', $attributes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,9 @@
|
|||||||
|
|
||||||
namespace SilverStripe\Forms;
|
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.
|
* Text input field with validation for correct email format according to RFC 2822.
|
||||||
*/
|
*/
|
||||||
@ -18,32 +21,27 @@ class EmailField extends TextField
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
* @param Validator $validator
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function validate($validator)
|
public function validate($validator)
|
||||||
{
|
{
|
||||||
$result = true;
|
|
||||||
$this->value = trim($this->value ?? '');
|
$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])?$';
|
$result = true;
|
||||||
|
// $message = _t('SilverStripe\\Forms\\EmailField.VALIDATION', 'Please enter an email address');
|
||||||
|
// $validationResult = ConstraintValidator::validate(
|
||||||
|
// $this->value,
|
||||||
|
// new Constraints\Email(message: $message)
|
||||||
|
// );
|
||||||
|
$validationResult = $this->getModelField()->validate();
|
||||||
|
|
||||||
// Escape delimiter characters.
|
if (!$validationResult->isValid()) {
|
||||||
$safePattern = str_replace('/', '\\/', $pattern ?? '');
|
|
||||||
|
|
||||||
if ($this->value && !preg_match('/' . $safePattern . '/i', $this->value ?? '')) {
|
|
||||||
$validator->validationError(
|
$validator->validationError(
|
||||||
$this->name,
|
$this->name,
|
||||||
_t('SilverStripe\\Forms\\EmailField.VALIDATION', 'Please enter an email address'),
|
$validationResult->getMessages()[0]['message'],
|
||||||
'validation'
|
|
||||||
);
|
);
|
||||||
|
|
||||||
$result = false;
|
$result = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,11 +10,16 @@ use SilverStripe\Core\ClassInfo;
|
|||||||
use SilverStripe\Core\Convert;
|
use SilverStripe\Core\Convert;
|
||||||
use SilverStripe\ORM\DataObjectInterface;
|
use SilverStripe\ORM\DataObjectInterface;
|
||||||
use SilverStripe\ORM\FieldType\DBField;
|
use SilverStripe\ORM\FieldType\DBField;
|
||||||
|
use SilverStripe\ORM\FieldType\DBFieldHelper;
|
||||||
use SilverStripe\ORM\FieldType\DBHTMLText;
|
use SilverStripe\ORM\FieldType\DBHTMLText;
|
||||||
use SilverStripe\Core\Validation\ValidationResult;
|
use SilverStripe\Core\Validation\ValidationResult;
|
||||||
use SilverStripe\View\AttributesHTML;
|
use SilverStripe\View\AttributesHTML;
|
||||||
use SilverStripe\View\SSViewer;
|
use SilverStripe\View\SSViewer;
|
||||||
use SilverStripe\Model\ModelData;
|
use SilverStripe\Model\ModelData;
|
||||||
|
use SilverStripe\Model\ModelFields\ModelField;
|
||||||
|
use SilverStripe\Model\ModelFields\ModelFieldTrait;
|
||||||
|
use SilverStripe\Model\ModelFields\StringModelField;
|
||||||
|
use SilverStripe\Core\Injector\Injector;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a field in a form.
|
* Represents a field in a form.
|
||||||
@ -40,11 +45,28 @@ use SilverStripe\Model\ModelData;
|
|||||||
* including both structure (name, id, attributes, etc.) and state (field value).
|
* 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.
|
* 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 AttributesHTML;
|
||||||
use FormMessage;
|
use FormMessage;
|
||||||
|
|
||||||
|
// todo: possibly should make this abstract
|
||||||
|
protected string $modelFieldClass = StringModelField::class;
|
||||||
|
|
||||||
|
private ModelField $modelField;
|
||||||
|
|
||||||
|
protected function getModelField(): ModelField
|
||||||
|
{
|
||||||
|
return $this->modelField;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function initModelField(): void
|
||||||
|
{
|
||||||
|
$name = $this->getName();
|
||||||
|
$modelField = Injector::inst()->createWithArgs($this->modelFieldClass, [$name]);
|
||||||
|
$this->modelField = $modelField;
|
||||||
|
}
|
||||||
|
|
||||||
/** @see $schemaDataType */
|
/** @see $schemaDataType */
|
||||||
const SCHEMA_DATA_TYPE_STRING = 'String';
|
const SCHEMA_DATA_TYPE_STRING = 'String';
|
||||||
|
|
||||||
@ -344,6 +366,7 @@ class FormField extends RequestHandler
|
|||||||
|
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
|
|
||||||
|
$this->initModelField($name);
|
||||||
$this->setupDefaultClasses();
|
$this->setupDefaultClasses();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -929,7 +952,7 @@ class FormField extends RequestHandler
|
|||||||
// Trim whitespace from the result, so that trailing newlines are suppressed. Works for strings and HTMLText values
|
// Trim whitespace from the result, so that trailing newlines are suppressed. Works for strings and HTMLText values
|
||||||
if (is_string($result)) {
|
if (is_string($result)) {
|
||||||
$result = trim($result ?? '');
|
$result = trim($result ?? '');
|
||||||
} elseif ($result instanceof DBField) {
|
} elseif ($result instanceof ModelField) {
|
||||||
$result->setValue(trim($result->getValue() ?? ''));
|
$result->setValue(trim($result->getValue() ?? ''));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1231,9 +1254,12 @@ class FormField extends RequestHandler
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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.
|
* 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
|
* @param Validator $validator
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
|
@ -216,10 +216,10 @@ class FormRequestHandler extends RequestHandler
|
|||||||
// Action handlers may throw ValidationExceptions.
|
// Action handlers may throw ValidationExceptions.
|
||||||
try {
|
try {
|
||||||
// Or we can use the Validator attached to the form
|
// Or we can use the Validator attached to the form
|
||||||
$result = $this->form->validationResult();
|
// $result = $this->form->validationResult();
|
||||||
if (!$result->isValid()) {
|
// if (!$result->isValid()) {
|
||||||
return $this->getValidationErrorResponse($result);
|
// return $this->getValidationErrorResponse($result);
|
||||||
}
|
// }
|
||||||
|
|
||||||
// First, try a handler method on the controller (has been checked for allowed_actions above already)
|
// First, try a handler method on the controller (has been checked for allowed_actions above already)
|
||||||
$controller = $this->form->getController();
|
$controller = $this->form->getController();
|
||||||
|
@ -22,6 +22,7 @@ use SilverStripe\Model\List\ArrayList;
|
|||||||
use SilverStripe\ORM\DataList;
|
use SilverStripe\ORM\DataList;
|
||||||
use SilverStripe\ORM\DataObjectInterface;
|
use SilverStripe\ORM\DataObjectInterface;
|
||||||
use SilverStripe\ORM\FieldType\DBField;
|
use SilverStripe\ORM\FieldType\DBField;
|
||||||
|
use SilverStripe\ORM\FieldType\DBFieldHelper;
|
||||||
use SilverStripe\Model\List\Filterable;
|
use SilverStripe\Model\List\Filterable;
|
||||||
use SilverStripe\Model\List\Limitable;
|
use SilverStripe\Model\List\Limitable;
|
||||||
use SilverStripe\Model\List\Sortable;
|
use SilverStripe\Model\List\Sortable;
|
||||||
@ -382,14 +383,14 @@ class GridField extends FormField
|
|||||||
|
|
||||||
if (strpos($castingDefinition ?? '', '->') === false) {
|
if (strpos($castingDefinition ?? '', '->') === false) {
|
||||||
$castingFieldType = $castingDefinition;
|
$castingFieldType = $castingDefinition;
|
||||||
$castingField = DBField::create_field($castingFieldType, $value);
|
$castingField = DBFieldHelper::create_field($castingFieldType, $value);
|
||||||
|
|
||||||
return call_user_func_array([$castingField, 'XML'], $castingParams ?? []);
|
return call_user_func_array([$castingField, 'XML'], $castingParams ?? []);
|
||||||
}
|
}
|
||||||
|
|
||||||
list($castingFieldType, $castingMethod) = explode('->', $castingDefinition ?? '');
|
list($castingFieldType, $castingMethod) = explode('->', $castingDefinition ?? '');
|
||||||
|
|
||||||
$castingField = DBField::create_field($castingFieldType, $value);
|
$castingField = DBFieldHelper::create_field($castingFieldType, $value);
|
||||||
|
|
||||||
return call_user_func_array([$castingField, $castingMethod], $castingParams ?? []);
|
return call_user_func_array([$castingField, $castingMethod], $castingParams ?? []);
|
||||||
}
|
}
|
||||||
@ -543,6 +544,8 @@ class GridField extends FormField
|
|||||||
'footer' => '',
|
'footer' => '',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
$_c = $this->getComponents();
|
||||||
|
|
||||||
foreach ($this->getComponents() as $item) {
|
foreach ($this->getComponents() as $item) {
|
||||||
if ($item instanceof GridField_HTMLProvider) {
|
if ($item instanceof GridField_HTMLProvider) {
|
||||||
$fragments = $item->getHTMLFragments($this);
|
$fragments = $item->getHTMLFragments($this);
|
||||||
|
@ -25,7 +25,7 @@ class GridFieldConfig_Base extends GridFieldConfig
|
|||||||
$this->addComponent(GridFieldPageCount::create('toolbar-header-right'));
|
$this->addComponent(GridFieldPageCount::create('toolbar-header-right'));
|
||||||
$this->addComponent($pagination = GridFieldPaginator::create($itemsPerPage));
|
$this->addComponent($pagination = GridFieldPaginator::create($itemsPerPage));
|
||||||
|
|
||||||
Deprecation::withNoReplacement(function () use ($sort, $filter, $pagination) {
|
Deprecation::withSuppressedNotice(function () use ($sort, $filter, $pagination) {
|
||||||
$sort->setThrowExceptionOnBadDataType(false);
|
$sort->setThrowExceptionOnBadDataType(false);
|
||||||
$filter->setThrowExceptionOnBadDataType(false);
|
$filter->setThrowExceptionOnBadDataType(false);
|
||||||
$pagination->setThrowExceptionOnBadDataType(false);
|
$pagination->setThrowExceptionOnBadDataType(false);
|
||||||
|
@ -32,7 +32,7 @@ class GridFieldConfig_RecordEditor extends GridFieldConfig
|
|||||||
$this->addComponent($pagination = GridFieldPaginator::create($itemsPerPage));
|
$this->addComponent($pagination = GridFieldPaginator::create($itemsPerPage));
|
||||||
$this->addComponent(GridFieldDetailForm::create(null, $showPagination, $showAdd));
|
$this->addComponent(GridFieldDetailForm::create(null, $showPagination, $showAdd));
|
||||||
|
|
||||||
Deprecation::withNoReplacement(function () use ($sort, $filter, $pagination) {
|
Deprecation::withSuppressedNotice(function () use ($sort, $filter, $pagination) {
|
||||||
$sort->setThrowExceptionOnBadDataType(false);
|
$sort->setThrowExceptionOnBadDataType(false);
|
||||||
$filter->setThrowExceptionOnBadDataType(false);
|
$filter->setThrowExceptionOnBadDataType(false);
|
||||||
$pagination->setThrowExceptionOnBadDataType(false);
|
$pagination->setThrowExceptionOnBadDataType(false);
|
||||||
|
@ -45,7 +45,7 @@ class GridFieldConfig_RelationEditor extends GridFieldConfig
|
|||||||
$this->addComponent($pagination = GridFieldPaginator::create($itemsPerPage));
|
$this->addComponent($pagination = GridFieldPaginator::create($itemsPerPage));
|
||||||
$this->addComponent(GridFieldDetailForm::create());
|
$this->addComponent(GridFieldDetailForm::create());
|
||||||
|
|
||||||
Deprecation::withNoReplacement(function () use ($sort, $filter, $pagination) {
|
Deprecation::withSuppressedNotice(function () use ($sort, $filter, $pagination) {
|
||||||
$sort->setThrowExceptionOnBadDataType(false);
|
$sort->setThrowExceptionOnBadDataType(false);
|
||||||
$filter->setThrowExceptionOnBadDataType(false);
|
$filter->setThrowExceptionOnBadDataType(false);
|
||||||
$pagination->setThrowExceptionOnBadDataType(false);
|
$pagination->setThrowExceptionOnBadDataType(false);
|
||||||
|
@ -5,6 +5,7 @@ namespace SilverStripe\Forms\GridField;
|
|||||||
use LogicException;
|
use LogicException;
|
||||||
use SilverStripe\ORM\DataObject;
|
use SilverStripe\ORM\DataObject;
|
||||||
use SilverStripe\ORM\FieldType\DBField;
|
use SilverStripe\ORM\FieldType\DBField;
|
||||||
|
use SilverStripe\ORM\FieldType\DBFieldHelper;
|
||||||
use SilverStripe\ORM\Hierarchy\Hierarchy;
|
use SilverStripe\ORM\Hierarchy\Hierarchy;
|
||||||
use SilverStripe\Model\ArrayData;
|
use SilverStripe\Model\ArrayData;
|
||||||
use SilverStripe\View\HTML;
|
use SilverStripe\View\HTML;
|
||||||
@ -91,7 +92,7 @@ class GridFieldLevelup extends AbstractGridFieldComponent implements GridField_H
|
|||||||
$linkTag = HTML::createTag('a', $attrs);
|
$linkTag = HTML::createTag('a', $attrs);
|
||||||
|
|
||||||
$forTemplate = new ArrayData([
|
$forTemplate = new ArrayData([
|
||||||
'UpLink' => DBField::create_field('HTMLFragment', $linkTag)
|
'UpLink' => DBFieldHelper::create_field('HTMLFragment', $linkTag)
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$template = SSViewer::get_templates_by_class($this, '', __CLASS__);
|
$template = SSViewer::get_templates_by_class($this, '', __CLASS__);
|
||||||
|
@ -6,6 +6,7 @@ use SilverStripe\Core\Convert;
|
|||||||
use SilverStripe\Core\ArrayLib;
|
use SilverStripe\Core\ArrayLib;
|
||||||
use SilverStripe\ORM\DataObjectInterface;
|
use SilverStripe\ORM\DataObjectInterface;
|
||||||
use SilverStripe\ORM\FieldType\DBField;
|
use SilverStripe\ORM\FieldType\DBField;
|
||||||
|
use SilverStripe\ORM\FieldType\DBFieldHelper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read-only complement of {@link MultiSelectField}.
|
* Read-only complement of {@link MultiSelectField}.
|
||||||
@ -58,7 +59,7 @@ class LookupField extends MultiSelectField
|
|||||||
}
|
}
|
||||||
|
|
||||||
$properties = array_merge($properties, [
|
$properties = array_merge($properties, [
|
||||||
'AttrValue' => DBField::create_field('HTMLFragment', $attrValue),
|
'AttrValue' => DBFieldHelper::create_field('HTMLFragment', $attrValue),
|
||||||
'InputValue' => $inputValue
|
'InputValue' => $inputValue
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ use SilverStripe\Core\Convert;
|
|||||||
use SilverStripe\Core\ArrayLib;
|
use SilverStripe\Core\ArrayLib;
|
||||||
use SilverStripe\ORM\DataObjectInterface;
|
use SilverStripe\ORM\DataObjectInterface;
|
||||||
use SilverStripe\ORM\FieldType\DBField;
|
use SilverStripe\ORM\FieldType\DBField;
|
||||||
|
use SilverStripe\ORM\FieldType\DBFieldHelper;
|
||||||
use SilverStripe\Model\List\ArrayList;
|
use SilverStripe\Model\List\ArrayList;
|
||||||
use SilverStripe\ORM\DataList;
|
use SilverStripe\ORM\DataList;
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ namespace SilverStripe\Forms;
|
|||||||
|
|
||||||
use SilverStripe\Model\List\ArrayList;
|
use SilverStripe\Model\List\ArrayList;
|
||||||
use SilverStripe\ORM\FieldType\DBField;
|
use SilverStripe\ORM\FieldType\DBField;
|
||||||
|
use SilverStripe\ORM\FieldType\DBFieldHelper;
|
||||||
use SilverStripe\View\HTML;
|
use SilverStripe\View\HTML;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -91,7 +92,7 @@ class SelectionGroup extends CompositeField
|
|||||||
|
|
||||||
$itemID = $this->ID() . '_' . (++$count);
|
$itemID = $this->ID() . '_' . (++$count);
|
||||||
$extra = [
|
$extra = [
|
||||||
"RadioButton" => DBField::create_field('HTMLFragment', HTML::createTag(
|
"RadioButton" => DBFieldHelper::create_field('HTMLFragment', HTML::createTag(
|
||||||
'input',
|
'input',
|
||||||
[
|
[
|
||||||
'class' => 'selector',
|
'class' => 'selector',
|
||||||
|
@ -6,6 +6,7 @@ use SilverStripe\Core\Convert;
|
|||||||
use SilverStripe\ORM\DataObjectInterface;
|
use SilverStripe\ORM\DataObjectInterface;
|
||||||
use SilverStripe\Model\List\Map;
|
use SilverStripe\Model\List\Map;
|
||||||
use SilverStripe\ORM\FieldType\DBField;
|
use SilverStripe\ORM\FieldType\DBField;
|
||||||
|
use SilverStripe\ORM\FieldType\DBFieldHelper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read-only complement of {@link DropdownField}.
|
* Read-only complement of {@link DropdownField}.
|
||||||
@ -125,7 +126,7 @@ class SingleLookupField extends SingleSelectField
|
|||||||
}
|
}
|
||||||
|
|
||||||
$properties = array_merge($properties, [
|
$properties = array_merge($properties, [
|
||||||
'AttrValue' => DBField::create_field('HTMLFragment', $attrValue),
|
'AttrValue' => DBFieldHelper::create_field('HTMLFragment', $attrValue),
|
||||||
'InputValue' => $inputValue
|
'InputValue' => $inputValue
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
@ -2,11 +2,15 @@
|
|||||||
|
|
||||||
namespace SilverStripe\Forms;
|
namespace SilverStripe\Forms;
|
||||||
|
|
||||||
|
use SilverStripe\Model\ModelFields\StringModelField;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Text input field.
|
* Text input field.
|
||||||
*/
|
*/
|
||||||
class TextField extends FormField implements TippableFieldInterface
|
class TextField extends FormField implements TippableFieldInterface
|
||||||
{
|
{
|
||||||
|
protected string $modelFieldClass = StringModelField::class;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var int
|
* @var int
|
||||||
*/
|
*/
|
||||||
|
@ -4,6 +4,7 @@ namespace SilverStripe\Logging;
|
|||||||
|
|
||||||
use Monolog\Formatter\FormatterInterface;
|
use Monolog\Formatter\FormatterInterface;
|
||||||
use Monolog\Handler\AbstractProcessingHandler;
|
use Monolog\Handler\AbstractProcessingHandler;
|
||||||
|
use Monolog\Level;
|
||||||
use Monolog\LogRecord;
|
use Monolog\LogRecord;
|
||||||
use SilverStripe\Control\Controller;
|
use SilverStripe\Control\Controller;
|
||||||
use SilverStripe\Control\Director;
|
use SilverStripe\Control\Director;
|
||||||
@ -34,10 +35,10 @@ class HTTPOutputHandler extends AbstractProcessingHandler
|
|||||||
*/
|
*/
|
||||||
private $cliFormatter = null;
|
private $cliFormatter = null;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct(int|string|Level $level = Level::Debug, bool $bubble = true)
|
||||||
{
|
{
|
||||||
parent::__construct();
|
parent::__construct($level, $bubble);
|
||||||
Deprecation::withNoReplacement(function () {
|
Deprecation::withSuppressedNotice(function () {
|
||||||
Deprecation::notice(
|
Deprecation::notice(
|
||||||
'5.4.0',
|
'5.4.0',
|
||||||
'Will be renamed to ErrorOutputHandler',
|
'Will be renamed to ErrorOutputHandler',
|
||||||
|
@ -720,7 +720,7 @@ class ArrayList extends ModelData implements SS_List, Filterable, Sortable, Limi
|
|||||||
|
|
||||||
// Apply default case sensitivity for backwards compatability
|
// Apply default case sensitivity for backwards compatability
|
||||||
if (!str_contains($filterKey, ':case') && !str_contains($filterKey, ':nocase')) {
|
if (!str_contains($filterKey, ':case') && !str_contains($filterKey, ':nocase')) {
|
||||||
$caseSensitive = Deprecation::withNoReplacement(fn() => static::config()->get('default_case_sensitive'));
|
$caseSensitive = Deprecation::withSuppressedNotice(fn() => static::config()->get('default_case_sensitive'));
|
||||||
if ($caseSensitive && in_array('case', $searchFilter->getSupportedModifiers())) {
|
if ($caseSensitive && in_array('case', $searchFilter->getSupportedModifiers())) {
|
||||||
$searchFilter->setModifiers($searchFilter->getModifiers() + ['case']);
|
$searchFilter->setModifiers($searchFilter->getModifiers() + ['case']);
|
||||||
} elseif (!$caseSensitive && in_array('nocase', $searchFilter->getSupportedModifiers())) {
|
} elseif (!$caseSensitive && in_array('nocase', $searchFilter->getSupportedModifiers())) {
|
||||||
|
@ -16,11 +16,12 @@ use SilverStripe\Core\Injector\Injector;
|
|||||||
use SilverStripe\Dev\Debug;
|
use SilverStripe\Dev\Debug;
|
||||||
use SilverStripe\Core\ArrayLib;
|
use SilverStripe\Core\ArrayLib;
|
||||||
use SilverStripe\Model\List\ArrayList;
|
use SilverStripe\Model\List\ArrayList;
|
||||||
use SilverStripe\ORM\FieldType\DBField;
|
|
||||||
use SilverStripe\ORM\FieldType\DBHTMLText;
|
use SilverStripe\ORM\FieldType\DBHTMLText;
|
||||||
use SilverStripe\Model\ArrayData;
|
use SilverStripe\Model\ArrayData;
|
||||||
use SilverStripe\View\SSViewer;
|
use SilverStripe\View\SSViewer;
|
||||||
use UnexpectedValueException;
|
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.
|
* A ModelData object is any object that can be rendered into a template/view.
|
||||||
@ -327,7 +328,7 @@ class ModelData
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the "casting helper" (a piece of PHP code that when evaluated creates a casted value 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.
|
* @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.
|
* @return string|null Casting helper As a constructor pattern, and may include arguments.
|
||||||
@ -361,7 +362,7 @@ class ModelData
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the default "casting helper" for use when no explicit casting helper is defined.
|
* 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
|
protected function defaultCastingHelper(string $field): string
|
||||||
{
|
{
|
||||||
@ -402,7 +403,7 @@ class ModelData
|
|||||||
{
|
{
|
||||||
$class = $this->castingClass($field) ?: $this->config()->get('default_cast');
|
$class = $this->castingClass($field) ?: $this->config()->get('default_cast');
|
||||||
|
|
||||||
/** @var DBField $type */
|
/** @var ModelField $type */
|
||||||
$type = Injector::inst()->get($class, true);
|
$type = Injector::inst()->get($class, true);
|
||||||
return $type->config()->get('escape_type');
|
return $type->config()->get('escape_type');
|
||||||
}
|
}
|
||||||
@ -495,9 +496,9 @@ class ModelData
|
|||||||
* Get the value of a field on this object, automatically inserting the value into any available casting objects
|
* Get the value of a field on this object, automatically inserting the value into any available casting objects
|
||||||
* that have been specified.
|
* 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.
|
* 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.
|
* be returned.
|
||||||
*/
|
*/
|
||||||
public function obj(
|
public function obj(
|
||||||
@ -520,7 +521,13 @@ class ModelData
|
|||||||
// Load value from record
|
// Load value from record
|
||||||
if ($this->hasMethod($fieldName)) {
|
if ($this->hasMethod($fieldName)) {
|
||||||
$hasObj = true;
|
$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 {
|
} else {
|
||||||
$hasObj = $this->hasField($fieldName) || ($this->hasMethod("get{$fieldName}") && $this->isAccessibleMethod("get{$fieldName}"));
|
$hasObj = $this->hasField($fieldName) || ($this->hasMethod("get{$fieldName}") && $this->isAccessibleMethod("get{$fieldName}"));
|
||||||
$value = $this->$fieldName;
|
$value = $this->$fieldName;
|
||||||
@ -568,7 +575,7 @@ class ModelData
|
|||||||
* A simple wrapper around {@link ModelData::obj()} that automatically caches the result so it can be used again
|
* A simple wrapper around {@link ModelData::obj()} that automatically caches the result so it can be used again
|
||||||
* without re-running the method.
|
* without re-running the method.
|
||||||
*
|
*
|
||||||
* @return Object|DBField
|
* @return Object|ModelField
|
||||||
*/
|
*/
|
||||||
public function cachedCall(string $fieldName, array $arguments = [], ?string $cacheName = null): object
|
public function cachedCall(string $fieldName, array $arguments = [], ?string $cacheName = null): object
|
||||||
{
|
{
|
||||||
@ -599,7 +606,13 @@ class ModelData
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
// Might contain additional formatting over ->XML(). E.g. parse shortcodes, nl2br()
|
// 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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
25
src/Model/ModelFields/EmailModelField.php
Normal file
25
src/Model/ModelFields/EmailModelField.php
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace SilverStripe\Model\ModelFields;
|
||||||
|
|
||||||
|
use SilverStripe\Core\Validation\ValidationResult;
|
||||||
|
use SilverStripe\Model\ModelFields\StringModelField;
|
||||||
|
use SilverStripe\Core\Validation\ConstraintValidator;
|
||||||
|
use Symfony\Component\Validator\Constraints;
|
||||||
|
|
||||||
|
class EmailModelField extends StringModelField
|
||||||
|
{
|
||||||
|
public function validate(): ValidationResult
|
||||||
|
{
|
||||||
|
$result = parent::validate();
|
||||||
|
$message = _t('SilverStripe\\Forms\\EmailField.VALIDATION', 'Please enter an email address');
|
||||||
|
|
||||||
|
$validationResult = ConstraintValidator::validate(
|
||||||
|
$this->getValue(),
|
||||||
|
new Constraints\Email(message: $message),
|
||||||
|
$this->getName()
|
||||||
|
);
|
||||||
|
|
||||||
|
return $result->combineAnd($validationResult);
|
||||||
|
}
|
||||||
|
}
|
249
src/Model/ModelFields/ModelField.php
Normal file
249
src/Model/ModelFields/ModelField.php
Normal file
@ -0,0 +1,249 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace SilverStripe\Model\ModelFields;
|
||||||
|
|
||||||
|
use SilverStripe\Core\Convert;
|
||||||
|
use SilverStripe\Forms\FormField;
|
||||||
|
use SilverStripe\Forms\TextField;
|
||||||
|
use SilverStripe\Model\ModelData;
|
||||||
|
use SilverStripe\Core\Validation\ValidationResult;
|
||||||
|
|
||||||
|
abstract class ModelField extends ModelData
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Raw value of this field
|
||||||
|
*/
|
||||||
|
protected mixed $value = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Name of this field
|
||||||
|
*/
|
||||||
|
protected ?string $name = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The escape type for this field when inserted into a template - either "xml" or "raw".
|
||||||
|
*/
|
||||||
|
private static string $escape_type = 'raw';
|
||||||
|
|
||||||
|
private static array $casting = [
|
||||||
|
'ATT' => 'HTMLFragment',
|
||||||
|
'CDATA' => 'HTMLFragment',
|
||||||
|
'HTML' => 'HTMLFragment',
|
||||||
|
'HTMLATT' => 'HTMLFragment',
|
||||||
|
'JS' => 'HTMLFragment',
|
||||||
|
'RAW' => 'HTMLFragment',
|
||||||
|
'RAWURLATT' => 'HTMLFragment',
|
||||||
|
'URLATT' => 'HTMLFragment',
|
||||||
|
'XML' => 'HTMLFragment',
|
||||||
|
'ProcessedRAW' => 'HTMLFragment',
|
||||||
|
];
|
||||||
|
|
||||||
|
public function __construct(?string $name = null)
|
||||||
|
{
|
||||||
|
$this->name = $name;
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setName(?string $name): static
|
||||||
|
{
|
||||||
|
$this->name = $name;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the name of this field.
|
||||||
|
*/
|
||||||
|
public function getName(): string
|
||||||
|
{
|
||||||
|
return $this->name ?? '';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value of this field.
|
||||||
|
*/
|
||||||
|
public function getValue(): mixed
|
||||||
|
{
|
||||||
|
return $this->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setValue(mixed $value): static
|
||||||
|
{
|
||||||
|
$this->value = $value;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine 'default' casting for this field.
|
||||||
|
*/
|
||||||
|
public function forTemplate(): string
|
||||||
|
{
|
||||||
|
// Default to XML encoding
|
||||||
|
return $this->XML();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the value appropriate for a HTML attribute string
|
||||||
|
*/
|
||||||
|
public function HTMLATT(): string
|
||||||
|
{
|
||||||
|
return Convert::raw2htmlatt($this->RAW());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* urlencode this string
|
||||||
|
*/
|
||||||
|
public function URLATT(): string
|
||||||
|
{
|
||||||
|
return urlencode($this->RAW() ?? '');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* rawurlencode this string
|
||||||
|
*/
|
||||||
|
public function RAWURLATT(): string
|
||||||
|
{
|
||||||
|
return rawurlencode($this->RAW() ?? '');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the value appropriate for a HTML attribute string
|
||||||
|
*/
|
||||||
|
public function ATT(): string
|
||||||
|
{
|
||||||
|
return Convert::raw2att($this->RAW());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the raw value for this field.
|
||||||
|
* Note: Skips processors implemented via forTemplate()
|
||||||
|
*/
|
||||||
|
public function RAW(): mixed
|
||||||
|
{
|
||||||
|
return $this->getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets javascript string literal value
|
||||||
|
*/
|
||||||
|
public function JS(): string
|
||||||
|
{
|
||||||
|
return Convert::raw2js($this->RAW());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return JSON encoded value
|
||||||
|
*/
|
||||||
|
public function JSON(): string
|
||||||
|
{
|
||||||
|
return json_encode($this->RAW());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias for {@see XML()}
|
||||||
|
*/
|
||||||
|
public function HTML(): string
|
||||||
|
{
|
||||||
|
return $this->XML();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* XML encode this value
|
||||||
|
*/
|
||||||
|
public function XML(): string
|
||||||
|
{
|
||||||
|
return Convert::raw2xml($this->RAW());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Safely escape for XML string
|
||||||
|
*/
|
||||||
|
public function CDATA(): string
|
||||||
|
{
|
||||||
|
return $this->XML();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves this field to the given data object.
|
||||||
|
*
|
||||||
|
* TODO: probably rename, it's just setting a field on a model
|
||||||
|
*/
|
||||||
|
public function saveInto(ModelData $model): void
|
||||||
|
{
|
||||||
|
$fieldName = $this->name;
|
||||||
|
if (empty($fieldName)) {
|
||||||
|
throw new \BadMethodCallException(
|
||||||
|
"ModelField::saveInto() Called on a nameless '" . static::class . "' object"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if ($this->value instanceof ModelField) {
|
||||||
|
$this->value->saveInto($model);
|
||||||
|
} else {
|
||||||
|
$model->__set($fieldName, $this->value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function validate(): ValidationResult
|
||||||
|
{
|
||||||
|
return ValidationResult::create();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a FormField instance used as a default
|
||||||
|
* for form scaffolding.
|
||||||
|
*
|
||||||
|
* Used by {@link SearchContext}, {@link ModelAdmin}, {@link DataObject::scaffoldFormFields()}
|
||||||
|
*
|
||||||
|
* @param string $title Optional. Localized title of the generated instance
|
||||||
|
*/
|
||||||
|
public function scaffoldFormField(?string $title = null, array $params = []): ?FormField
|
||||||
|
{
|
||||||
|
return TextField::create($this->name, $title);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a FormField instance used as a default
|
||||||
|
* for searchform scaffolding.
|
||||||
|
*
|
||||||
|
* Used by {@link SearchContext}, {@link ModelAdmin}, {@link DataObject::scaffoldFormFields()}.
|
||||||
|
*
|
||||||
|
* @param string $title Optional. Localized title of the generated instance
|
||||||
|
*/
|
||||||
|
public function scaffoldSearchField(?string $title = null): ?FormField
|
||||||
|
{
|
||||||
|
return $this->scaffoldFormField($title);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get formfield schema value for use in formschema response
|
||||||
|
*/
|
||||||
|
public function getSchemaValue(): mixed
|
||||||
|
{
|
||||||
|
return $this->RAW();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function debug(): string
|
||||||
|
{
|
||||||
|
return <<<DBG
|
||||||
|
<ul>
|
||||||
|
<li><b>Name:</b>{$this->name}</li>
|
||||||
|
<li><b>Table:</b>{$this->tableName}</li>
|
||||||
|
<li><b>Value:</b>{$this->value}</li>
|
||||||
|
</ul>
|
||||||
|
DBG;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __toString(): string
|
||||||
|
{
|
||||||
|
return (string)$this->forTemplate();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not this ModelField only accepts scalar values.
|
||||||
|
*
|
||||||
|
* Composite ModelFields can override this method and return `false` so they can accept arrays of values.
|
||||||
|
*/
|
||||||
|
public function scalarValueOnly(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
142
src/Model/ModelFields/StringModelField.php
Normal file
142
src/Model/ModelFields/StringModelField.php
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace SilverStripe\Model\ModelFields;
|
||||||
|
|
||||||
|
use SilverStripe\Model\ModelFields\ModelField;
|
||||||
|
use SilverStripe\ORM\FieldType\DBString;
|
||||||
|
|
||||||
|
class StringModelField extends ModelField
|
||||||
|
{
|
||||||
|
private static array $casting = [
|
||||||
|
'LimitCharacters' => 'Text',
|
||||||
|
'LimitCharactersToClosestWord' => 'Text',
|
||||||
|
'LimitWordCount' => 'Text',
|
||||||
|
'LowerCase' => 'Text',
|
||||||
|
'UpperCase' => 'Text',
|
||||||
|
'Plain' => 'Text',
|
||||||
|
];
|
||||||
|
|
||||||
|
public function forTemplate(): string
|
||||||
|
{
|
||||||
|
return nl2br(parent::forTemplate() ?? '');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Limit this field's content by a number of characters.
|
||||||
|
* This makes use of strip_tags() to avoid malforming the
|
||||||
|
* HTML tags in the string of text.
|
||||||
|
*
|
||||||
|
* @param int $limit Number of characters to limit by
|
||||||
|
* @param string|false $add Ellipsis to add to the end of truncated string
|
||||||
|
*/
|
||||||
|
public function LimitCharacters(int $limit = 20, string|false $add = false): string
|
||||||
|
{
|
||||||
|
$value = $this->Plain();
|
||||||
|
if (mb_strlen($value ?? '') <= $limit) {
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
return $this->addEllipsis(mb_substr($value ?? '', 0, $limit), $add);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Limit this field's content by a number of characters and truncate
|
||||||
|
* the field to the closest complete word. All HTML tags are stripped
|
||||||
|
* from the field.
|
||||||
|
*
|
||||||
|
* @param int $limit Number of characters to limit by
|
||||||
|
* @param string|false $add Ellipsis to add to the end of truncated string
|
||||||
|
* @return string Plain text value with limited characters
|
||||||
|
*/
|
||||||
|
public function LimitCharactersToClosestWord(int $limit = 20, string|false $add = false): string
|
||||||
|
{
|
||||||
|
// Safely convert to plain text
|
||||||
|
$value = $this->Plain();
|
||||||
|
|
||||||
|
// Determine if value exceeds limit before limiting characters
|
||||||
|
if (mb_strlen($value ?? '') <= $limit) {
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Limit to character limit
|
||||||
|
$value = mb_substr($value ?? '', 0, $limit);
|
||||||
|
|
||||||
|
// If value exceeds limit, strip punctuation off the end to the last space and apply ellipsis
|
||||||
|
$value = $this->addEllipsis(
|
||||||
|
preg_replace(
|
||||||
|
'/[^\w_]+$/',
|
||||||
|
'',
|
||||||
|
mb_substr($value ?? '', 0, mb_strrpos($value ?? '', " "))
|
||||||
|
),
|
||||||
|
$add
|
||||||
|
);
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Limit this field's content by a number of words.
|
||||||
|
*
|
||||||
|
* @param int $numWords Number of words to limit by.
|
||||||
|
* @param string|false $add Ellipsis to add to the end of truncated string.
|
||||||
|
*/
|
||||||
|
public function LimitWordCount(int $numWords = 26, string|false $add = false): string
|
||||||
|
{
|
||||||
|
$value = $this->Plain();
|
||||||
|
$words = explode(' ', $value ?? '');
|
||||||
|
if (count($words ?? []) <= $numWords) {
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Limit
|
||||||
|
$words = array_slice($words ?? [], 0, $numWords);
|
||||||
|
return $this->addEllipsis(implode(' ', $words), $add);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the current value for this StringField to lowercase.
|
||||||
|
*
|
||||||
|
* @return string Text with lowercase (HTML for some subclasses)
|
||||||
|
*/
|
||||||
|
public function LowerCase(): string
|
||||||
|
{
|
||||||
|
return mb_strtolower($this->RAW() ?? '');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the current value for this StringField to uppercase.
|
||||||
|
*
|
||||||
|
* @return string Text with uppercase (HTML for some subclasses)
|
||||||
|
*/
|
||||||
|
public function UpperCase(): string
|
||||||
|
{
|
||||||
|
return mb_strtoupper($this->RAW() ?? '');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plain text version of this string
|
||||||
|
*/
|
||||||
|
public function Plain(): string
|
||||||
|
{
|
||||||
|
return trim($this->RAW() ?? '');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Swap add for defaultEllipsis if need be
|
||||||
|
*/
|
||||||
|
private function addEllipsis(string $string, string|false $add): string
|
||||||
|
{
|
||||||
|
if ($add === false) {
|
||||||
|
$add = $this->defaultEllipsis();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $string . $add;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the default string to indicate that a string was cut off.
|
||||||
|
*/
|
||||||
|
public function defaultEllipsis(): string
|
||||||
|
{
|
||||||
|
// TODO: Change to translation key defined on StringModelField
|
||||||
|
return _t(DBString::class . '.ELLIPSIS', '…');
|
||||||
|
}
|
||||||
|
}
|
@ -10,6 +10,7 @@ use SilverStripe\Core\Injector\Injector;
|
|||||||
use SilverStripe\ORM\DataObject;
|
use SilverStripe\ORM\DataObject;
|
||||||
use SilverStripe\ORM\DB;
|
use SilverStripe\ORM\DB;
|
||||||
use SilverStripe\ORM\FieldType\DBField;
|
use SilverStripe\ORM\FieldType\DBField;
|
||||||
|
use SilverStripe\ORM\FieldType\DBFieldHelper;
|
||||||
use SilverStripe\ORM\FieldType\DBPrimaryKey;
|
use SilverStripe\ORM\FieldType\DBPrimaryKey;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -6,6 +6,7 @@ use mysqli;
|
|||||||
use mysqli_sql_exception;
|
use mysqli_sql_exception;
|
||||||
use mysqli_stmt;
|
use mysqli_stmt;
|
||||||
use SilverStripe\Core\Config\Config;
|
use SilverStripe\Core\Config\Config;
|
||||||
|
use SilverStripe\Core\Environment;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Connector for MySQL using the MySQLi method
|
* Connector for MySQL using the MySQLi method
|
||||||
@ -81,15 +82,21 @@ class MySQLiConnector extends DBConnector
|
|||||||
// Connection charset and collation
|
// Connection charset and collation
|
||||||
$connCharset = Config::inst()->get(MySQLDatabase::class, 'connection_charset');
|
$connCharset = Config::inst()->get(MySQLDatabase::class, 'connection_charset');
|
||||||
$connCollation = Config::inst()->get(MySQLDatabase::class, 'connection_collation');
|
$connCollation = Config::inst()->get(MySQLDatabase::class, 'connection_collation');
|
||||||
|
$socket = Environment::getEnv('SS_DATABASE_SOCKET');
|
||||||
|
$flags = Environment::getEnv('SS_DATABASE_FLAGS');
|
||||||
|
|
||||||
|
$flags = $flags ? array_reduce(explode(',', $flags), function ($carry, $item) {
|
||||||
|
$item = trim($item);
|
||||||
|
return $carry | constant($item);
|
||||||
|
}, 0) : $flags;
|
||||||
|
|
||||||
$this->dbConn = mysqli_init();
|
$this->dbConn = mysqli_init();
|
||||||
|
|
||||||
// Use native types (MysqlND only)
|
// Use native types (MysqlND only)
|
||||||
if (defined('MYSQLI_OPT_INT_AND_FLOAT_NATIVE')) {
|
if (defined('MYSQLI_OPT_INT_AND_FLOAT_NATIVE')) {
|
||||||
$this->dbConn->options(MYSQLI_OPT_INT_AND_FLOAT_NATIVE, true);
|
$this->dbConn->options(MYSQLI_OPT_INT_AND_FLOAT_NATIVE, true);
|
||||||
|
|
||||||
// The alternative is not ideal, throw a notice-level error
|
|
||||||
} else {
|
} else {
|
||||||
|
// The alternative is not ideal, throw a notice-level error
|
||||||
user_error(
|
user_error(
|
||||||
'mysqlnd PHP library is not available, numeric values will be fetched from the DB as strings',
|
'mysqlnd PHP library is not available, numeric values will be fetched from the DB as strings',
|
||||||
E_USER_NOTICE
|
E_USER_NOTICE
|
||||||
@ -117,7 +124,9 @@ class MySQLiConnector extends DBConnector
|
|||||||
$parameters['username'],
|
$parameters['username'],
|
||||||
$parameters['password'],
|
$parameters['password'],
|
||||||
$selectedDB,
|
$selectedDB,
|
||||||
!empty($parameters['port']) ? $parameters['port'] : ini_get("mysqli.default_port")
|
!empty($parameters['port']) ? $parameters['port'] : ini_get("mysqli.default_port"),
|
||||||
|
$socket ?? null,
|
||||||
|
$flags ?? 0
|
||||||
);
|
);
|
||||||
|
|
||||||
if ($this->dbConn->connect_error) {
|
if ($this->dbConn->connect_error) {
|
||||||
@ -126,8 +135,8 @@ class MySQLiConnector extends DBConnector
|
|||||||
|
|
||||||
// Set charset and collation if given and not null. Can explicitly set to empty string to omit
|
// Set charset and collation if given and not null. Can explicitly set to empty string to omit
|
||||||
$charset = isset($parameters['charset'])
|
$charset = isset($parameters['charset'])
|
||||||
? $parameters['charset']
|
? $parameters['charset']
|
||||||
: $connCharset;
|
: $connCharset;
|
||||||
|
|
||||||
if (!empty($charset)) {
|
if (!empty($charset)) {
|
||||||
$this->dbConn->set_charset($charset);
|
$this->dbConn->set_charset($charset);
|
||||||
|
@ -20,6 +20,7 @@ use SilverStripe\Forms\FormField;
|
|||||||
use SilverStripe\Forms\FormScaffolder;
|
use SilverStripe\Forms\FormScaffolder;
|
||||||
use SilverStripe\Forms\CompositeValidator;
|
use SilverStripe\Forms\CompositeValidator;
|
||||||
use SilverStripe\Forms\FieldsValidator;
|
use SilverStripe\Forms\FieldsValidator;
|
||||||
|
use SilverStripe\Forms\Form;
|
||||||
use SilverStripe\Forms\GridField\GridField;
|
use SilverStripe\Forms\GridField\GridField;
|
||||||
use SilverStripe\Forms\GridField\GridFieldConfig_RelationEditor;
|
use SilverStripe\Forms\GridField\GridFieldConfig_RelationEditor;
|
||||||
use SilverStripe\Forms\HiddenField;
|
use SilverStripe\Forms\HiddenField;
|
||||||
@ -33,6 +34,7 @@ use SilverStripe\ORM\FieldType\DBComposite;
|
|||||||
use SilverStripe\ORM\FieldType\DBDatetime;
|
use SilverStripe\ORM\FieldType\DBDatetime;
|
||||||
use SilverStripe\ORM\FieldType\DBEnum;
|
use SilverStripe\ORM\FieldType\DBEnum;
|
||||||
use SilverStripe\ORM\FieldType\DBField;
|
use SilverStripe\ORM\FieldType\DBField;
|
||||||
|
use SilverStripe\ORM\FieldType\DBFieldHelper;
|
||||||
use SilverStripe\ORM\FieldType\DBForeignKey;
|
use SilverStripe\ORM\FieldType\DBForeignKey;
|
||||||
use SilverStripe\ORM\Filters\PartialMatchFilter;
|
use SilverStripe\ORM\Filters\PartialMatchFilter;
|
||||||
use SilverStripe\ORM\Filters\SearchFilter;
|
use SilverStripe\ORM\Filters\SearchFilter;
|
||||||
@ -45,7 +47,13 @@ use SilverStripe\Security\Permission;
|
|||||||
use SilverStripe\Security\Security;
|
use SilverStripe\Security\Security;
|
||||||
use SilverStripe\View\SSViewer;
|
use SilverStripe\View\SSViewer;
|
||||||
use SilverStripe\Model\ModelData;
|
use SilverStripe\Model\ModelData;
|
||||||
|
use SilverStripe\ORM\FieldType\DBText;
|
||||||
|
use SilverStripe\ORM\FieldType\DBVarchar;
|
||||||
use stdClass;
|
use stdClass;
|
||||||
|
use SilverStripe\Control\Controller;
|
||||||
|
use SilverStripe\Control\HTTPRequest;
|
||||||
|
use SilverStripe\Control\Session;
|
||||||
|
use Symfony\Component\Validator\Constraints\Uuid;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A single database record & abstract class for the data-access-model.
|
* A single database record & abstract class for the data-access-model.
|
||||||
@ -1230,10 +1238,44 @@ class DataObject extends ModelData implements DataObjectInterface, i18nEntityPro
|
|||||||
public function validate()
|
public function validate()
|
||||||
{
|
{
|
||||||
$result = ValidationResult::create();
|
$result = ValidationResult::create();
|
||||||
|
// Call validate() on every DBField
|
||||||
|
$specs = static::getSchema()->fieldSpecs(static::class);
|
||||||
|
foreach (array_keys($specs) as $fieldName) {
|
||||||
|
// Call DBField::validate() on every DBField
|
||||||
|
$dbField = $this->dbObject($fieldName);
|
||||||
|
$result->combineAnd($dbField->validate());
|
||||||
|
}
|
||||||
|
// If it passed DBField::validate(), then call FormField::validate()
|
||||||
|
// on every field that would be scaffolded
|
||||||
|
// This isn't ideal and can lead to double validation, however it's to preserve
|
||||||
|
// any legacy FormField::validate() logic on projects that has not been
|
||||||
|
// migrated to use DBField::validate()
|
||||||
|
// TODO: don't call this when in FormRequestHandler::httpSubmission()
|
||||||
|
// as it means that calling FormField::validate() is called twice
|
||||||
|
if ($result->isValid()) {
|
||||||
|
$form = $this->getFormForValidation();
|
||||||
|
$result->combineAnd($form->validationResult());
|
||||||
|
}
|
||||||
|
// Call extension hook and return
|
||||||
$this->extend('updateValidate', $result);
|
$this->extend('updateValidate', $result);
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function getFormForValidation(): Form
|
||||||
|
{
|
||||||
|
$session = new Session([]);
|
||||||
|
$controller = new Controller();
|
||||||
|
$request = new HTTPRequest('GET', '/');
|
||||||
|
$request->setSession($session);
|
||||||
|
$controller->setRequest($request);
|
||||||
|
// Use getCMSFields rather than $dbField->scaffoldFormField()
|
||||||
|
// to ensure we get any CMS fields that were replaced by other fields
|
||||||
|
$fields = $this->getCMSFields();
|
||||||
|
$form = new Form($controller, sprintf('temp-%s', uniqid()), $fields, null, new FieldsValidator);
|
||||||
|
$form->loadDataFrom($this);
|
||||||
|
return $form;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Event handler called before writing to the database.
|
* Event handler called before writing to the database.
|
||||||
* You can overload this to clean up or otherwise process data before writing it to the
|
* You can overload this to clean up or otherwise process data before writing it to the
|
||||||
@ -1456,7 +1498,7 @@ class DataObject extends ModelData implements DataObjectInterface, i18nEntityPro
|
|||||||
// if database column doesn't correlate to a DBField instance...
|
// if database column doesn't correlate to a DBField instance...
|
||||||
$fieldObj = $this->dbObject($fieldName);
|
$fieldObj = $this->dbObject($fieldName);
|
||||||
if (!$fieldObj) {
|
if (!$fieldObj) {
|
||||||
$fieldObj = DBField::create_field('Varchar', $fieldValue, $fieldName);
|
$fieldObj = DBFieldHelper::create_field('Varchar', $fieldValue, $fieldName);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write to manipulation
|
// Write to manipulation
|
||||||
@ -1982,7 +2024,7 @@ class DataObject extends ModelData implements DataObjectInterface, i18nEntityPro
|
|||||||
if ($details['polymorphic']) {
|
if ($details['polymorphic']) {
|
||||||
$result = PolymorphicHasManyList::create($componentClass, $details['joinField'], static::class);
|
$result = PolymorphicHasManyList::create($componentClass, $details['joinField'], static::class);
|
||||||
if ($details['needsRelation']) {
|
if ($details['needsRelation']) {
|
||||||
Deprecation::withNoReplacement(fn () => $result->setForeignRelation($componentName));
|
Deprecation::withSuppressedNotice(fn () => $result->setForeignRelation($componentName));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$result = HasManyList::create($componentClass, $details['joinField']);
|
$result = HasManyList::create($componentClass, $details['joinField']);
|
||||||
@ -2422,16 +2464,15 @@ class DataObject extends ModelData implements DataObjectInterface, i18nEntityPro
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, use the database field's scaffolder
|
// Otherwise, use the database field's scaffolder
|
||||||
} elseif ($object = $this->relObject($fieldName)) {
|
} elseif ($dbField = $this->relObject($fieldName)) {
|
||||||
if (is_object($object) && $object->hasMethod('scaffoldSearchField')) {
|
if (!is_a($dbField, DBField::class)) {
|
||||||
$field = $object->scaffoldSearchField();
|
|
||||||
} else {
|
|
||||||
throw new Exception(sprintf(
|
throw new Exception(sprintf(
|
||||||
"SearchField '%s' on '%s' does not return a valid DBField instance.",
|
"SearchField '%s' on '%s' does not return a valid DBField instance.",
|
||||||
$fieldName,
|
$fieldName,
|
||||||
get_class($this)
|
get_class($this)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
$field = $dbField->scaffoldSearchField();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allow fields to opt out of search
|
// Allow fields to opt out of search
|
||||||
|
@ -16,6 +16,7 @@ use SilverStripe\Dev\TestOnly;
|
|||||||
use SilverStripe\ORM\Connect\DBSchemaManager;
|
use SilverStripe\ORM\Connect\DBSchemaManager;
|
||||||
use SilverStripe\ORM\FieldType\DBComposite;
|
use SilverStripe\ORM\FieldType\DBComposite;
|
||||||
use SilverStripe\ORM\FieldType\DBField;
|
use SilverStripe\ORM\FieldType\DBField;
|
||||||
|
use SilverStripe\ORM\FieldType\DBFieldHelper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides dataobject and database schema mapping functionality
|
* Provides dataobject and database schema mapping functionality
|
||||||
|
@ -67,7 +67,7 @@ class DatabaseAdmin extends Controller
|
|||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
Deprecation::withNoReplacement(function () {
|
Deprecation::withSuppressedNotice(function () {
|
||||||
Deprecation::notice(
|
Deprecation::notice(
|
||||||
'5.4.0',
|
'5.4.0',
|
||||||
'Will be replaced with SilverStripe\Dev\Command\DbBuild',
|
'Will be replaced with SilverStripe\Dev\Command\DbBuild',
|
||||||
@ -213,7 +213,7 @@ class DatabaseAdmin extends Controller
|
|||||||
*/
|
*/
|
||||||
public static function lastBuilt()
|
public static function lastBuilt()
|
||||||
{
|
{
|
||||||
Deprecation::withNoReplacement(function () {
|
Deprecation::withSuppressedNotice(function () {
|
||||||
Deprecation::notice(
|
Deprecation::notice(
|
||||||
'5.4.0',
|
'5.4.0',
|
||||||
'Will be replaced with SilverStripe\Dev\Command\DbBuild::lastBuilt()'
|
'Will be replaced with SilverStripe\Dev\Command\DbBuild::lastBuilt()'
|
||||||
|
@ -6,6 +6,7 @@ use SilverStripe\Dev\Debug;
|
|||||||
use SilverStripe\Model\ModelData;
|
use SilverStripe\Model\ModelData;
|
||||||
use SilverStripe\ORM\Connect\DatabaseException;
|
use SilverStripe\ORM\Connect\DatabaseException;
|
||||||
use SilverStripe\ORM\FieldType\DBField;
|
use SilverStripe\ORM\FieldType\DBField;
|
||||||
|
use SilverStripe\ORM\FieldType\DBFieldHelper;
|
||||||
use BadMethodCallException;
|
use BadMethodCallException;
|
||||||
use InvalidArgumentException;
|
use InvalidArgumentException;
|
||||||
use LogicException;
|
use LogicException;
|
||||||
|
@ -7,12 +7,17 @@ use SilverStripe\Forms\DropdownField;
|
|||||||
use SilverStripe\Forms\FormField;
|
use SilverStripe\Forms\FormField;
|
||||||
use SilverStripe\ORM\DB;
|
use SilverStripe\ORM\DB;
|
||||||
use SilverStripe\Model\ModelData;
|
use SilverStripe\Model\ModelData;
|
||||||
|
use SilverStripe\Model\ModelFields\ModelField;
|
||||||
|
use SilverStripe\ORM\FieldType\DBFieldTrait;
|
||||||
|
use SilverStripe\ORM\FieldType\DBField;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a boolean field.
|
* Represents a boolean field.
|
||||||
*/
|
*/
|
||||||
class DBBoolean extends DBField
|
class DBBoolean extends ModelField implements DBField
|
||||||
{
|
{
|
||||||
|
use DBFieldTrait;
|
||||||
|
|
||||||
public function __construct(?string $name = null, bool|int $defaultVal = 0)
|
public function __construct(?string $name = null, bool|int $defaultVal = 0)
|
||||||
{
|
{
|
||||||
$this->defaultVal = ($defaultVal) ? 1 : 0;
|
$this->defaultVal = ($defaultVal) ? 1 : 0;
|
||||||
|
@ -8,6 +8,9 @@ use SilverStripe\ORM\DataObject;
|
|||||||
use SilverStripe\ORM\DB;
|
use SilverStripe\ORM\DB;
|
||||||
use SilverStripe\ORM\Queries\SQLSelect;
|
use SilverStripe\ORM\Queries\SQLSelect;
|
||||||
use SilverStripe\Model\ModelData;
|
use SilverStripe\Model\ModelData;
|
||||||
|
use SilverStripe\Model\ModelFields\ModelField;
|
||||||
|
use SilverStripe\ORM\FieldType\DBFieldTrait;
|
||||||
|
use SilverStripe\ORM\FieldType\DBField;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extend this class when designing a {@link DBField} that doesn't have a 1-1 mapping with a database field.
|
* Extend this class when designing a {@link DBField} that doesn't have a 1-1 mapping with a database field.
|
||||||
@ -23,8 +26,10 @@ use SilverStripe\Model\ModelData;
|
|||||||
* }
|
* }
|
||||||
* </code>
|
* </code>
|
||||||
*/
|
*/
|
||||||
abstract class DBComposite extends DBField
|
abstract class DBComposite extends ModelField implements DBField
|
||||||
{
|
{
|
||||||
|
use DBFieldTrait;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Similar to {@link DataObject::$db},
|
* Similar to {@link DataObject::$db},
|
||||||
* holds an array of composite field names.
|
* holds an array of composite field names.
|
||||||
@ -85,8 +90,6 @@ abstract class DBComposite extends DBField
|
|||||||
*/
|
*/
|
||||||
public function addToQuery(SQLSelect &$query): void
|
public function addToQuery(SQLSelect &$query): void
|
||||||
{
|
{
|
||||||
parent::addToQuery($query);
|
|
||||||
|
|
||||||
foreach ($this->compositeDatabaseFields() as $field => $spec) {
|
foreach ($this->compositeDatabaseFields() as $field => $spec) {
|
||||||
$table = $this->getTable();
|
$table = $this->getTable();
|
||||||
$key = $this->getName() . $field;
|
$key = $this->getName() . $field;
|
||||||
|
@ -12,6 +12,9 @@ use SilverStripe\ORM\DB;
|
|||||||
use SilverStripe\Security\Member;
|
use SilverStripe\Security\Member;
|
||||||
use SilverStripe\Security\Security;
|
use SilverStripe\Security\Security;
|
||||||
use SilverStripe\Model\ModelData;
|
use SilverStripe\Model\ModelData;
|
||||||
|
use SilverStripe\ORM\FieldType\DBFieldTrait;
|
||||||
|
use SilverStripe\Model\ModelFields\ModelField;
|
||||||
|
use SilverStripe\ORM\FieldType\DBField;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a date field.
|
* Represents a date field.
|
||||||
@ -29,8 +32,10 @@ use SilverStripe\Model\ModelData;
|
|||||||
* Date formats all follow CLDR standard format codes
|
* Date formats all follow CLDR standard format codes
|
||||||
* @link https://unicode-org.github.io/icu/userguide/format_parse/datetime
|
* @link https://unicode-org.github.io/icu/userguide/format_parse/datetime
|
||||||
*/
|
*/
|
||||||
class DBDate extends DBField
|
class DBDate extends ModelField implements DBField
|
||||||
{
|
{
|
||||||
|
use DBFieldTrait;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Standard ISO format string for date in CLDR standard format
|
* Standard ISO format string for date in CLDR standard format
|
||||||
*/
|
*/
|
||||||
|
@ -260,7 +260,7 @@ class DBDatetime extends DBDate implements TemplateGlobalProvider
|
|||||||
$time = DBDatetime::$mock_now ? DBDatetime::$mock_now->Value : time();
|
$time = DBDatetime::$mock_now ? DBDatetime::$mock_now->Value : time();
|
||||||
|
|
||||||
/** @var DBDatetime $now */
|
/** @var DBDatetime $now */
|
||||||
$now = DBField::create_field('Datetime', $time);
|
$now = DBFieldHelper::create_field('Datetime', $time);
|
||||||
|
|
||||||
return $now;
|
return $now;
|
||||||
}
|
}
|
||||||
@ -277,7 +277,7 @@ class DBDatetime extends DBDate implements TemplateGlobalProvider
|
|||||||
{
|
{
|
||||||
if (!$datetime instanceof DBDatetime) {
|
if (!$datetime instanceof DBDatetime) {
|
||||||
$value = $datetime;
|
$value = $datetime;
|
||||||
$datetime = DBField::create_field('Datetime', $datetime);
|
$datetime = DBFieldHelper::create_field('Datetime', $datetime);
|
||||||
if ($datetime === false) {
|
if ($datetime === false) {
|
||||||
throw new InvalidArgumentException('DBDatetime::set_mock_now(): Wrong format: ' . $value);
|
throw new InvalidArgumentException('DBDatetime::set_mock_now(): Wrong format: ' . $value);
|
||||||
}
|
}
|
||||||
|
@ -6,12 +6,16 @@ use SilverStripe\Forms\FormField;
|
|||||||
use SilverStripe\Forms\NumericField;
|
use SilverStripe\Forms\NumericField;
|
||||||
use SilverStripe\ORM\DB;
|
use SilverStripe\ORM\DB;
|
||||||
use SilverStripe\Model\ModelData;
|
use SilverStripe\Model\ModelData;
|
||||||
|
use SilverStripe\ORM\FieldType\DBFieldTrait;
|
||||||
|
use SilverStripe\Model\ModelFields\ModelField;
|
||||||
|
use SilverStripe\ORM\FieldType\DBField;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a Decimal field.
|
* Represents a Decimal field.
|
||||||
*/
|
*/
|
||||||
class DBDecimal extends DBField
|
class DBDecimal extends ModelField implements DBField
|
||||||
{
|
{
|
||||||
|
use DBFieldTrait;
|
||||||
/**
|
/**
|
||||||
* Whole number size
|
* Whole number size
|
||||||
*/
|
*/
|
||||||
|
44
src/ORM/FieldType/DBEmail.php
Normal file
44
src/ORM/FieldType/DBEmail.php
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace SilverStripe\ORM\FieldType;
|
||||||
|
|
||||||
|
use SilverStripe\ORM\FieldType\DBVarchar;
|
||||||
|
use Symfony\Component\Validator\Constraints;
|
||||||
|
use SilverStripe\Core\Validation\ConstraintValidator;
|
||||||
|
use SilverStripe\Core\Validation\ValidationResult;
|
||||||
|
use SilverStripe\Forms\EmailField;
|
||||||
|
use SilverStripe\Forms\NullableField;
|
||||||
|
use SilverStripe\Forms\FormField;
|
||||||
|
|
||||||
|
class DBEmail extends DBVarchar
|
||||||
|
{
|
||||||
|
// public function validate(): ValidationResult
|
||||||
|
// {
|
||||||
|
// // https://symfony.com/doc/current/reference/constraints/Email.html
|
||||||
|
// $result = parent::validate();
|
||||||
|
// // $message = _t('SilverStripe\\Forms\\EmailField.VALIDATION', 'Please enter an email address');
|
||||||
|
// // $result = $result->combineAnd(
|
||||||
|
// // ConstraintValidator::validate(
|
||||||
|
// // $this->getValue(),
|
||||||
|
// // new Constraints\Email(message: $message),
|
||||||
|
// // $this->getName()
|
||||||
|
// // )
|
||||||
|
// // );
|
||||||
|
// $result = $result->combineAnd($this->validateEmail());
|
||||||
|
// $this->extend('updateValidate', $result);
|
||||||
|
// return $result;
|
||||||
|
// }
|
||||||
|
|
||||||
|
public function scaffoldFormField(?string $title = null, array $params = []): ?FormField
|
||||||
|
{
|
||||||
|
// Set field with appropriate size
|
||||||
|
$field = EmailField::create($this->name, $title);
|
||||||
|
$field->setMaxLength($this->getSize());
|
||||||
|
|
||||||
|
// Allow the user to select if it's null instead of automatically assuming empty string is
|
||||||
|
if (!$this->getNullifyEmpty()) {
|
||||||
|
return NullableField::create($field);
|
||||||
|
}
|
||||||
|
return $field;
|
||||||
|
}
|
||||||
|
}
|
@ -2,567 +2,9 @@
|
|||||||
|
|
||||||
namespace SilverStripe\ORM\FieldType;
|
namespace SilverStripe\ORM\FieldType;
|
||||||
|
|
||||||
use InvalidArgumentException;
|
|
||||||
use SilverStripe\Core\Convert;
|
|
||||||
use SilverStripe\Core\Injector\Injector;
|
|
||||||
use SilverStripe\Forms\FormField;
|
|
||||||
use SilverStripe\Forms\TextField;
|
|
||||||
use SilverStripe\ORM\Filters\SearchFilter;
|
|
||||||
use SilverStripe\ORM\Queries\SQLSelect;
|
|
||||||
use SilverStripe\Model\ModelData;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Single field in the database.
|
* This interface is exists basically so that $object instanceof DBField checks work
|
||||||
*
|
|
||||||
* Every field from the database is represented as a sub-class of DBField.
|
|
||||||
*
|
|
||||||
* <b>Multi-value DBField objects</b>
|
|
||||||
*
|
|
||||||
* Sometimes you will want to make DBField classes that don't have a 1-1 match
|
|
||||||
* to database fields. To do this, there are a number of fields for you to
|
|
||||||
* overload:
|
|
||||||
*
|
|
||||||
* - Overload {@link writeToManipulation} to add the appropriate references to
|
|
||||||
* the INSERT or UPDATE command
|
|
||||||
* - Overload {@link addToQuery} to add the appropriate items to a SELECT
|
|
||||||
* query's field list
|
|
||||||
* - Add appropriate accessor methods
|
|
||||||
*
|
|
||||||
* <b>Subclass Example</b>
|
|
||||||
*
|
|
||||||
* The class is easy to overload with custom types, e.g. the MySQL "BLOB" type
|
|
||||||
* (https://dev.mysql.com/doc/refman/8.4/en/blob.html).
|
|
||||||
*
|
|
||||||
* <code>
|
|
||||||
* class Blob extends DBField {
|
|
||||||
* function requireField(): void {
|
|
||||||
* DB::require_field($this->tableName, $this->name, "blob");
|
|
||||||
* }
|
|
||||||
* }
|
|
||||||
* </code>
|
|
||||||
*/
|
*/
|
||||||
abstract class DBField extends ModelData implements DBIndexable
|
interface DBField extends DBIndexable
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
|
||||||
* Raw value of this field
|
|
||||||
*/
|
|
||||||
protected mixed $value = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Table this field belongs to
|
|
||||||
*/
|
|
||||||
protected ?string $tableName = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Name of this field
|
|
||||||
*/
|
|
||||||
protected ?string $name = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used for generating DB schema. {@see DBSchemaManager}
|
|
||||||
* Despite its name, this seems to be a string
|
|
||||||
*/
|
|
||||||
protected $arrayValue;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Optional parameters for this field
|
|
||||||
*/
|
|
||||||
protected array $options = [];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The escape type for this field when inserted into a template - either "xml" or "raw".
|
|
||||||
*/
|
|
||||||
private static string $escape_type = 'raw';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Subclass of {@link SearchFilter} for usage in {@link defaultSearchFilter()}.
|
|
||||||
*/
|
|
||||||
private static string $default_search_filter_class = 'PartialMatchFilter';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The type of index to use for this field. Can either be a string (one of the DBIndexable type options) or a
|
|
||||||
* boolean. When a boolean is given, false will not index the field, and true will use the default index type.
|
|
||||||
*/
|
|
||||||
private static string|bool $index = false;
|
|
||||||
|
|
||||||
private static array $casting = [
|
|
||||||
'ATT' => 'HTMLFragment',
|
|
||||||
'CDATA' => 'HTMLFragment',
|
|
||||||
'HTML' => 'HTMLFragment',
|
|
||||||
'HTMLATT' => 'HTMLFragment',
|
|
||||||
'JS' => 'HTMLFragment',
|
|
||||||
'RAW' => 'HTMLFragment',
|
|
||||||
'RAWURLATT' => 'HTMLFragment',
|
|
||||||
'URLATT' => 'HTMLFragment',
|
|
||||||
'XML' => 'HTMLFragment',
|
|
||||||
'ProcessedRAW' => 'HTMLFragment',
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Default value in the database.
|
|
||||||
* Might be overridden on DataObject-level, but still useful for setting defaults on
|
|
||||||
* already existing records after a db-build.
|
|
||||||
*/
|
|
||||||
protected mixed $defaultVal = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provide the DBField name and an array of options, e.g. ['index' => true], or ['nullifyEmpty' => false]
|
|
||||||
*
|
|
||||||
* @throws InvalidArgumentException If $options was passed by not an array
|
|
||||||
*/
|
|
||||||
public function __construct(?string $name = null, array $options = [])
|
|
||||||
{
|
|
||||||
$this->name = $name;
|
|
||||||
|
|
||||||
if ($options) {
|
|
||||||
if (!is_array($options)) {
|
|
||||||
throw new InvalidArgumentException("Invalid options $options");
|
|
||||||
}
|
|
||||||
$this->setOptions($options);
|
|
||||||
}
|
|
||||||
|
|
||||||
parent::__construct();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a DBField object that's not bound to any particular field.
|
|
||||||
*
|
|
||||||
* Useful for accessing the classes behaviour for other parts of your code.
|
|
||||||
*
|
|
||||||
* @param string $spec Class specification to construct. May include both service name and additional
|
|
||||||
* constructor arguments in the same format as DataObject.db config.
|
|
||||||
* @param mixed $value value of field
|
|
||||||
* @param null|string $name Name of field
|
|
||||||
* @param mixed $args Additional arguments to pass to constructor if not using args in service $spec
|
|
||||||
* Note: Will raise a warning if using both
|
|
||||||
*/
|
|
||||||
public static function create_field(string $spec, mixed $value, ?string $name = null, mixed ...$args): static
|
|
||||||
{
|
|
||||||
// Raise warning if inconsistent with DataObject::dbObject() behaviour
|
|
||||||
// This will cause spec args to be shifted down by the number of provided $args
|
|
||||||
if ($args && strpos($spec ?? '', '(') !== false) {
|
|
||||||
trigger_error('Additional args provided in both $spec and $args', E_USER_WARNING);
|
|
||||||
}
|
|
||||||
// Ensure name is always first argument
|
|
||||||
array_unshift($args, $name);
|
|
||||||
|
|
||||||
/** @var DBField $dbField */
|
|
||||||
$dbField = Injector::inst()->createWithArgs($spec, $args);
|
|
||||||
$dbField->setValue($value, null, false);
|
|
||||||
return $dbField;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the name of this field.
|
|
||||||
*
|
|
||||||
* The name should never be altered, but it if was never given a name in
|
|
||||||
* the first place you can set a name.
|
|
||||||
*
|
|
||||||
* If you try an alter the name a warning will be thrown.
|
|
||||||
*/
|
|
||||||
public function setName(?string $name): static
|
|
||||||
{
|
|
||||||
if ($this->name && $this->name !== $name) {
|
|
||||||
user_error("DBField::setName() shouldn't be called once a DBField already has a name."
|
|
||||||
. "It's partially immutable - it shouldn't be altered after it's given a value.", E_USER_WARNING);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->name = $name;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the name of this field.
|
|
||||||
*/
|
|
||||||
public function getName(): string
|
|
||||||
{
|
|
||||||
return $this->name ?? '';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the value of this field.
|
|
||||||
*/
|
|
||||||
public function getValue(): mixed
|
|
||||||
{
|
|
||||||
return $this->value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the value of this field in various formats.
|
|
||||||
* Used by {@link DataObject->getField()}, {@link DataObject->setCastedField()}
|
|
||||||
* {@link DataObject->dbObject()} and {@link DataObject->write()}.
|
|
||||||
*
|
|
||||||
* As this method is used both for initializing the field after construction,
|
|
||||||
* and actually changing its values, it needs a {@link $markChanged}
|
|
||||||
* parameter.
|
|
||||||
*
|
|
||||||
* @param null|ModelData|array $record An array or object that this field is part of
|
|
||||||
* @param bool $markChanged Indicate whether this field should be marked changed.
|
|
||||||
* Set to FALSE if you are initializing this field after construction, rather
|
|
||||||
* than setting a new value.
|
|
||||||
*/
|
|
||||||
public function setValue(mixed $value, null|array|ModelData $record = null, bool $markChanged = true): static
|
|
||||||
{
|
|
||||||
$this->value = $value;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get default value assigned at the DB level
|
|
||||||
*/
|
|
||||||
public function getDefaultValue(): mixed
|
|
||||||
{
|
|
||||||
return $this->defaultVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set default value to use at the DB level
|
|
||||||
*/
|
|
||||||
public function setDefaultValue(mixed $defaultValue): static
|
|
||||||
{
|
|
||||||
$this->defaultVal = $defaultValue;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update the optional parameters for this field
|
|
||||||
*/
|
|
||||||
public function setOptions(array $options = []): static
|
|
||||||
{
|
|
||||||
$this->options = $options;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get optional parameters for this field
|
|
||||||
*/
|
|
||||||
public function getOptions(): array
|
|
||||||
{
|
|
||||||
return $this->options;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setIndexType($type): string|bool
|
|
||||||
{
|
|
||||||
if (!is_bool($type)
|
|
||||||
&& !in_array($type, [DBIndexable::TYPE_INDEX, DBIndexable::TYPE_UNIQUE, DBIndexable::TYPE_FULLTEXT])
|
|
||||||
) {
|
|
||||||
throw new \InvalidArgumentException(
|
|
||||||
"{$type} is not a valid index type or boolean. Please see DBIndexable."
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->options['index'] = $type;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getIndexType()
|
|
||||||
{
|
|
||||||
if (array_key_exists('index', $this->options ?? [])) {
|
|
||||||
$type = $this->options['index'];
|
|
||||||
} else {
|
|
||||||
$type = static::config()->get('index');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_bool($type)) {
|
|
||||||
if (!$type) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$type = DBIndexable::TYPE_DEFAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $type;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determines if the field has a value which is not considered to be 'null'
|
|
||||||
* in a database context.
|
|
||||||
*/
|
|
||||||
public function exists(): bool
|
|
||||||
{
|
|
||||||
return (bool)$this->value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the transformed value ready to be sent to the database. This value
|
|
||||||
* will be escaped automatically by the prepared query processor, so it
|
|
||||||
* should not be escaped or quoted at all.
|
|
||||||
*
|
|
||||||
* @param mixed $value The value to check
|
|
||||||
* @return mixed The raw value, or escaped parameterised details
|
|
||||||
*/
|
|
||||||
public function prepValueForDB(mixed $value): mixed
|
|
||||||
{
|
|
||||||
if ($value === null ||
|
|
||||||
$value === "" ||
|
|
||||||
$value === false ||
|
|
||||||
($this->scalarValueOnly() && !is_scalar($value))
|
|
||||||
) {
|
|
||||||
return null;
|
|
||||||
} else {
|
|
||||||
return $value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prepare the current field for usage in a
|
|
||||||
* database-manipulation (works on a manipulation reference).
|
|
||||||
*
|
|
||||||
* Make value safe for insertion into
|
|
||||||
* a SQL SET statement by applying addslashes() -
|
|
||||||
* can also be used to apply special SQL-commands
|
|
||||||
* to the raw value (e.g. for GIS functionality).
|
|
||||||
* {@see prepValueForDB}
|
|
||||||
*/
|
|
||||||
public function writeToManipulation(array &$manipulation): void
|
|
||||||
{
|
|
||||||
$manipulation['fields'][$this->name] = $this->exists()
|
|
||||||
? $this->prepValueForDB($this->value) : $this->nullValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add custom query parameters for this field,
|
|
||||||
* mostly SELECT statements for multi-value fields.
|
|
||||||
*
|
|
||||||
* By default, the ORM layer does a
|
|
||||||
* SELECT <tablename>.* which
|
|
||||||
* gets you the default representations
|
|
||||||
* of all columns.
|
|
||||||
*/
|
|
||||||
public function addToQuery(SQLSelect &$query)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Assign this DBField to a table
|
|
||||||
*/
|
|
||||||
public function setTable(string $tableName): static
|
|
||||||
{
|
|
||||||
$this->tableName = $tableName;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the table this field belongs to, if assigned
|
|
||||||
*/
|
|
||||||
public function getTable(): ?string
|
|
||||||
{
|
|
||||||
return $this->tableName;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determine 'default' casting for this field.
|
|
||||||
*/
|
|
||||||
public function forTemplate(): string
|
|
||||||
{
|
|
||||||
// Default to XML encoding
|
|
||||||
return $this->XML();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the value appropriate for a HTML attribute string
|
|
||||||
*/
|
|
||||||
public function HTMLATT(): string
|
|
||||||
{
|
|
||||||
return Convert::raw2htmlatt($this->RAW());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* urlencode this string
|
|
||||||
*/
|
|
||||||
public function URLATT(): string
|
|
||||||
{
|
|
||||||
return urlencode($this->RAW() ?? '');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* rawurlencode this string
|
|
||||||
*/
|
|
||||||
public function RAWURLATT(): string
|
|
||||||
{
|
|
||||||
return rawurlencode($this->RAW() ?? '');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the value appropriate for a HTML attribute string
|
|
||||||
*/
|
|
||||||
public function ATT(): string
|
|
||||||
{
|
|
||||||
return Convert::raw2att($this->RAW());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the raw value for this field.
|
|
||||||
* Note: Skips processors implemented via forTemplate()
|
|
||||||
*/
|
|
||||||
public function RAW(): mixed
|
|
||||||
{
|
|
||||||
return $this->getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets javascript string literal value
|
|
||||||
*/
|
|
||||||
public function JS(): string
|
|
||||||
{
|
|
||||||
return Convert::raw2js($this->RAW());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return JSON encoded value
|
|
||||||
*/
|
|
||||||
public function JSON(): string
|
|
||||||
{
|
|
||||||
return json_encode($this->RAW());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Alias for {@see XML()}
|
|
||||||
*/
|
|
||||||
public function HTML(): string
|
|
||||||
{
|
|
||||||
return $this->XML();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* XML encode this value
|
|
||||||
*/
|
|
||||||
public function XML(): string
|
|
||||||
{
|
|
||||||
return Convert::raw2xml($this->RAW());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Safely escape for XML string
|
|
||||||
*/
|
|
||||||
public function CDATA(): string
|
|
||||||
{
|
|
||||||
return $this->XML();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the value to be set in the database to blank this field.
|
|
||||||
* Usually it's a choice between null, 0, and ''
|
|
||||||
*/
|
|
||||||
public function nullValue(): mixed
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Saves this field to the given data object.
|
|
||||||
*/
|
|
||||||
public function saveInto(ModelData $model): void
|
|
||||||
{
|
|
||||||
$fieldName = $this->name;
|
|
||||||
if (empty($fieldName)) {
|
|
||||||
throw new \BadMethodCallException(
|
|
||||||
"DBField::saveInto() Called on a nameless '" . static::class . "' object"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if ($this->value instanceof DBField) {
|
|
||||||
$this->value->saveInto($model);
|
|
||||||
} else {
|
|
||||||
$model->__set($fieldName, $this->value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a FormField instance used as a default
|
|
||||||
* for form scaffolding.
|
|
||||||
*
|
|
||||||
* Used by {@link SearchContext}, {@link ModelAdmin}, {@link DataObject::scaffoldFormFields()}
|
|
||||||
*
|
|
||||||
* @param string $title Optional. Localized title of the generated instance
|
|
||||||
*/
|
|
||||||
public function scaffoldFormField(?string $title = null, array $params = []): ?FormField
|
|
||||||
{
|
|
||||||
return TextField::create($this->name, $title);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a FormField instance used as a default
|
|
||||||
* for searchform scaffolding.
|
|
||||||
*
|
|
||||||
* Used by {@link SearchContext}, {@link ModelAdmin}, {@link DataObject::scaffoldFormFields()}.
|
|
||||||
*
|
|
||||||
* @param string $title Optional. Localized title of the generated instance
|
|
||||||
*/
|
|
||||||
public function scaffoldSearchField(?string $title = null): ?FormField
|
|
||||||
{
|
|
||||||
return $this->scaffoldFormField($title);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $name Override name of this field
|
|
||||||
*/
|
|
||||||
public function defaultSearchFilter(?string $name = null): SearchFilter
|
|
||||||
{
|
|
||||||
$name = ($name) ? $name : $this->name;
|
|
||||||
$filterClass = static::config()->get('default_search_filter_class');
|
|
||||||
return Injector::inst()->create($filterClass, $name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add the field to the underlying database.
|
|
||||||
*/
|
|
||||||
abstract public function requireField(): void;
|
|
||||||
|
|
||||||
public function debug(): string
|
|
||||||
{
|
|
||||||
return <<<DBG
|
|
||||||
<ul>
|
|
||||||
<li><b>Name:</b>{$this->name}</li>
|
|
||||||
<li><b>Table:</b>{$this->tableName}</li>
|
|
||||||
<li><b>Value:</b>{$this->value}</li>
|
|
||||||
</ul>
|
|
||||||
DBG;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function __toString(): string
|
|
||||||
{
|
|
||||||
return (string)$this->forTemplate();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getArrayValue()
|
|
||||||
{
|
|
||||||
return $this->arrayValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setArrayValue($value): static
|
|
||||||
{
|
|
||||||
$this->arrayValue = $value;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get formfield schema value for use in formschema response
|
|
||||||
*/
|
|
||||||
public function getSchemaValue(): mixed
|
|
||||||
{
|
|
||||||
return $this->RAW();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getIndexSpecs(): ?array
|
|
||||||
{
|
|
||||||
$type = $this->getIndexType();
|
|
||||||
if ($type) {
|
|
||||||
return [
|
|
||||||
'type' => $type,
|
|
||||||
'columns' => [$this->getName()],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether or not this DBField only accepts scalar values.
|
|
||||||
*
|
|
||||||
* Composite DBFields can override this method and return `false` so they can accept arrays of values.
|
|
||||||
*/
|
|
||||||
public function scalarValueOnly(): bool
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
37
src/ORM/FieldType/DBFieldHelper.php
Normal file
37
src/ORM/FieldType/DBFieldHelper.php
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace SilverStripe\ORM\FieldType;
|
||||||
|
|
||||||
|
use SilverStripe\Core\Injector\Injector;
|
||||||
|
|
||||||
|
class DBFieldHelper
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Create a DBField object that's not bound to any particular field.
|
||||||
|
*
|
||||||
|
* Useful for accessing the classes behaviour for other parts of your code.
|
||||||
|
*
|
||||||
|
* @param string $spec Class specification to construct. May include both service name and additional
|
||||||
|
* constructor arguments in the same format as DataObject.db config.
|
||||||
|
* @param mixed $value value of field
|
||||||
|
* @param null|string $name Name of field
|
||||||
|
* @param mixed $args Additional arguments to pass to constructor if not using args in service $spec
|
||||||
|
* Note: Will raise a warning if using both
|
||||||
|
*/
|
||||||
|
public static function create_field(string $spec, mixed $value, ?string $name = null, mixed ...$args): DBField
|
||||||
|
{
|
||||||
|
// Raise warning if inconsistent with DataObject::dbObject() behaviour
|
||||||
|
// This will cause spec args to be shifted down by the number of provided $args
|
||||||
|
if ($args && strpos($spec ?? '', '(') !== false) {
|
||||||
|
trigger_error('Additional args provided in both $spec and $args', E_USER_WARNING);
|
||||||
|
}
|
||||||
|
// Ensure name is always first argument
|
||||||
|
array_unshift($args, $name);
|
||||||
|
|
||||||
|
$dbField = Injector::inst()->createWithArgs($spec, $args);
|
||||||
|
/** @var DBFieldTrait $dbField */
|
||||||
|
$dbField->setValue($value, null, false);
|
||||||
|
/** @var DBField $dbField */
|
||||||
|
return $dbField;
|
||||||
|
}
|
||||||
|
}
|
345
src/ORM/FieldType/DBFieldTrait.php
Normal file
345
src/ORM/FieldType/DBFieldTrait.php
Normal file
@ -0,0 +1,345 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace SilverStripe\ORM\FieldType;
|
||||||
|
|
||||||
|
use InvalidArgumentException;
|
||||||
|
use SilverStripe\Core\Injector\Injector;
|
||||||
|
use SilverStripe\Model\ModelData;
|
||||||
|
use SilverStripe\ORM\Queries\SQLSelect;
|
||||||
|
use SilverStripe\ORM\Filters\SearchFilter;
|
||||||
|
use SilverStripe\Model\ModelFields\ModelField;
|
||||||
|
use SilverStripe\Model\ModelFields\ModelFieldTrait;
|
||||||
|
use SilverStripe\Model\ModelFields\StringModelField;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Single field in the database.
|
||||||
|
*
|
||||||
|
* Every field from the database is represented as a sub-class of DBField.
|
||||||
|
*
|
||||||
|
* <b>Multi-value DBField objects</b>
|
||||||
|
*
|
||||||
|
* Sometimes you will want to make DBField classes that don't have a 1-1 match
|
||||||
|
* to database fields. To do this, there are a number of fields for you to
|
||||||
|
* overload:
|
||||||
|
*
|
||||||
|
* - Overload {@link writeToManipulation} to add the appropriate references to
|
||||||
|
* the INSERT or UPDATE command
|
||||||
|
* - Overload {@link addToQuery} to add the appropriate items to a SELECT
|
||||||
|
* query's field list
|
||||||
|
* - Add appropriate accessor methods
|
||||||
|
*
|
||||||
|
* <b>Subclass Example</b>
|
||||||
|
*
|
||||||
|
* The class is easy to overload with custom types, e.g. the MySQL "BLOB" type
|
||||||
|
* (https://dev.mysql.com/doc/refman/8.4/en/blob.html).
|
||||||
|
*
|
||||||
|
* <code>
|
||||||
|
* class Blob extends DBField {
|
||||||
|
* function requireField(): void {
|
||||||
|
* DB::require_field($this->tableName, $this->name, "blob");
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* </code>
|
||||||
|
*/
|
||||||
|
trait DBFieldTrait
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Raw value of this field
|
||||||
|
*/
|
||||||
|
protected mixed $value = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Name of this field
|
||||||
|
*/
|
||||||
|
protected ?string $name = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Table this field belongs to
|
||||||
|
*/
|
||||||
|
protected ?string $tableName = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used for generating DB schema. {@see DBSchemaManager}
|
||||||
|
* Despite its name, this seems to be a string
|
||||||
|
*/
|
||||||
|
protected $arrayValue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Optional parameters for this field
|
||||||
|
*/
|
||||||
|
protected array $options = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type of index to use for this field. Can either be a string (one of the DBIndexable type options) or a
|
||||||
|
* boolean. When a boolean is given, false will not index the field, and true will use the default index type.
|
||||||
|
*/
|
||||||
|
private static string|bool $index = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subclass of {@link SearchFilter} for usage in {@link defaultSearchFilter()}.
|
||||||
|
*/
|
||||||
|
private static string $default_search_filter_class = 'PartialMatchFilter';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default value in the database.
|
||||||
|
* Might be overridden on DataObject-level, but still useful for setting defaults on
|
||||||
|
* already existing records after a db-build.
|
||||||
|
*/
|
||||||
|
protected mixed $defaultVal = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide the DBField name and an array of options, e.g. ['index' => true], or ['nullifyEmpty' => false]
|
||||||
|
*
|
||||||
|
* @throws InvalidArgumentException If $options was passed by not an array
|
||||||
|
*/
|
||||||
|
public function __construct(?string $name = null, array $options = [])
|
||||||
|
{
|
||||||
|
if (!is_a(self::class, ModelField::class, true)) {
|
||||||
|
throw new InvalidArgumentException(
|
||||||
|
'DBFieldTrait can only be used on classes that extend ' . ModelField::class
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (!is_a(self::class, DBField::class, true)) {
|
||||||
|
throw new InvalidArgumentException(
|
||||||
|
'DBFieldTrait can only be used on classes that implement ' . DBField::class
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if ($options) {
|
||||||
|
if (!is_array($options)) {
|
||||||
|
throw new InvalidArgumentException("Invalid options $options");
|
||||||
|
}
|
||||||
|
$this->setOptions($options);
|
||||||
|
}
|
||||||
|
parent::__construct($name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the name of this field.
|
||||||
|
*
|
||||||
|
* The name should never be altered, but it if was never given a name in
|
||||||
|
* the first place you can set a name.
|
||||||
|
*
|
||||||
|
* If you try an alter the name a warning will be thrown.
|
||||||
|
*/
|
||||||
|
public function setName(?string $name): static
|
||||||
|
{
|
||||||
|
if ($this->name && $this->name !== $name) {
|
||||||
|
user_error("ModelField::setName() shouldn't be called once a ModelField already has a name."
|
||||||
|
. "It's partially immutable - it shouldn't be altered after it's given a value.", E_USER_WARNING);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->name = $name;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the value of this field in various formats.
|
||||||
|
* Used by {@link DataObject->getField()}, {@link DataObject->setCastedField()}
|
||||||
|
* {@link DataObject->dbObject()} and {@link DataObject->write()}.
|
||||||
|
*
|
||||||
|
* As this method is used both for initializing the field after construction,
|
||||||
|
* and actually changing its values, it needs a {@link $markChanged}
|
||||||
|
* parameter.
|
||||||
|
*
|
||||||
|
* @param null|ModelData|array $record An array or object that this field is part of
|
||||||
|
* @param bool $markChanged Indicate whether this field should be marked changed.
|
||||||
|
* Set to FALSE if you are initializing this field after construction, rather
|
||||||
|
* than setting a new value.
|
||||||
|
*/
|
||||||
|
public function setValue(mixed $value, null|array|ModelData $record = null, bool $markChanged = true): static
|
||||||
|
{
|
||||||
|
$this->value = $value;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the field to the underlying database.
|
||||||
|
*/
|
||||||
|
abstract public function requireField(): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get default value assigned at the DB level
|
||||||
|
*/
|
||||||
|
public function getDefaultValue(): mixed
|
||||||
|
{
|
||||||
|
return $this->defaultVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set default value to use at the DB level
|
||||||
|
*/
|
||||||
|
public function setDefaultValue(mixed $defaultValue): static
|
||||||
|
{
|
||||||
|
$this->defaultVal = $defaultValue;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the optional parameters for this field
|
||||||
|
*/
|
||||||
|
public function setOptions(array $options = []): static
|
||||||
|
{
|
||||||
|
$this->options = $options;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get optional parameters for this field
|
||||||
|
*/
|
||||||
|
public function getOptions(): array
|
||||||
|
{
|
||||||
|
return $this->options;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setIndexType($type): string|bool
|
||||||
|
{
|
||||||
|
if (!is_bool($type)
|
||||||
|
&& !in_array($type, [DBIndexable::TYPE_INDEX, DBIndexable::TYPE_UNIQUE, DBIndexable::TYPE_FULLTEXT])
|
||||||
|
) {
|
||||||
|
throw new \InvalidArgumentException(
|
||||||
|
"{$type} is not a valid index type or boolean. Please see DBIndexable."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->options['index'] = $type;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getIndexType()
|
||||||
|
{
|
||||||
|
if (array_key_exists('index', $this->options ?? [])) {
|
||||||
|
$type = $this->options['index'];
|
||||||
|
} else {
|
||||||
|
$type = static::config()->get('index');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_bool($type)) {
|
||||||
|
if (!$type) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$type = DBIndexable::TYPE_DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if the field has a value which is not considered to be 'null'
|
||||||
|
* in a database context.
|
||||||
|
*/
|
||||||
|
public function exists(): bool
|
||||||
|
{
|
||||||
|
return (bool)$this->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the transformed value ready to be sent to the database. This value
|
||||||
|
* will be escaped automatically by the prepared query processor, so it
|
||||||
|
* should not be escaped or quoted at all.
|
||||||
|
*
|
||||||
|
* @param mixed $value The value to check
|
||||||
|
* @return mixed The raw value, or escaped parameterised details
|
||||||
|
*/
|
||||||
|
public function prepValueForDB(mixed $value): mixed
|
||||||
|
{
|
||||||
|
if ($value === null ||
|
||||||
|
$value === "" ||
|
||||||
|
$value === false ||
|
||||||
|
($this->scalarValueOnly() && !is_scalar($value))
|
||||||
|
) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepare the current field for usage in a
|
||||||
|
* database-manipulation (works on a manipulation reference).
|
||||||
|
*
|
||||||
|
* Make value safe for insertion into
|
||||||
|
* a SQL SET statement by applying addslashes() -
|
||||||
|
* can also be used to apply special SQL-commands
|
||||||
|
* to the raw value (e.g. for GIS functionality).
|
||||||
|
* {@see prepValueForDB}
|
||||||
|
*/
|
||||||
|
public function writeToManipulation(array &$manipulation): void
|
||||||
|
{
|
||||||
|
$manipulation['fields'][$this->name] = $this->exists()
|
||||||
|
? $this->prepValueForDB($this->value) : $this->nullValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add custom query parameters for this field,
|
||||||
|
* mostly SELECT statements for multi-value fields.
|
||||||
|
*
|
||||||
|
* By default, the ORM layer does a
|
||||||
|
* SELECT <tablename>.* which
|
||||||
|
* gets you the default representations
|
||||||
|
* of all columns.
|
||||||
|
*/
|
||||||
|
public function addToQuery(SQLSelect &$query)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assign this DBField to a table
|
||||||
|
*/
|
||||||
|
public function setTable(string $tableName): static
|
||||||
|
{
|
||||||
|
$this->tableName = $tableName;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the table this field belongs to, if assigned
|
||||||
|
*/
|
||||||
|
public function getTable(): ?string
|
||||||
|
{
|
||||||
|
return $this->tableName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value to be set in the database to blank this field.
|
||||||
|
* Usually it's a choice between null, 0, and ''
|
||||||
|
*/
|
||||||
|
public function nullValue(): mixed
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $name Override name of this field
|
||||||
|
*/
|
||||||
|
public function defaultSearchFilter(?string $name = null): SearchFilter
|
||||||
|
{
|
||||||
|
$name = ($name) ? $name : $this->name;
|
||||||
|
$filterClass = static::config()->get('default_search_filter_class');
|
||||||
|
return Injector::inst()->create($filterClass, $name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getArrayValue()
|
||||||
|
{
|
||||||
|
return $this->arrayValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setArrayValue($value): static
|
||||||
|
{
|
||||||
|
$this->arrayValue = $value;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getIndexSpecs(): ?array
|
||||||
|
{
|
||||||
|
$type = $this->getIndexType();
|
||||||
|
if ($type) {
|
||||||
|
return [
|
||||||
|
'type' => $type,
|
||||||
|
'columns' => [$this->getName()],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -5,12 +5,17 @@ namespace SilverStripe\ORM\FieldType;
|
|||||||
use SilverStripe\Forms\FormField;
|
use SilverStripe\Forms\FormField;
|
||||||
use SilverStripe\Forms\NumericField;
|
use SilverStripe\Forms\NumericField;
|
||||||
use SilverStripe\ORM\DB;
|
use SilverStripe\ORM\DB;
|
||||||
|
use SilverStripe\ORM\FieldType\DBFieldTrait;
|
||||||
|
use SilverStripe\Model\ModelFields\ModelField;
|
||||||
|
use SilverStripe\ORM\FieldType\DBField;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a floating point field.
|
* Represents a floating point field.
|
||||||
*/
|
*/
|
||||||
class DBFloat extends DBField
|
class DBFloat extends ModelField implements DBField
|
||||||
{
|
{
|
||||||
|
use DBFieldTrait;
|
||||||
|
|
||||||
public function __construct(?string $name = null, float|int $defaultVal = 0)
|
public function __construct(?string $name = null, float|int $defaultVal = 0)
|
||||||
{
|
{
|
||||||
$this->defaultVal = is_float($defaultVal) ? $defaultVal : (float) 0;
|
$this->defaultVal = is_float($defaultVal) ? $defaultVal : (float) 0;
|
||||||
|
@ -8,12 +8,16 @@ use SilverStripe\Model\List\ArrayList;
|
|||||||
use SilverStripe\ORM\DB;
|
use SilverStripe\ORM\DB;
|
||||||
use SilverStripe\Model\List\SS_List;
|
use SilverStripe\Model\List\SS_List;
|
||||||
use SilverStripe\Model\ArrayData;
|
use SilverStripe\Model\ArrayData;
|
||||||
|
use SilverStripe\Model\ModelFields\ModelField;
|
||||||
|
use SilverStripe\ORM\FieldType\DBField;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a signed 32 bit integer field.
|
* Represents a signed 32 bit integer field.
|
||||||
*/
|
*/
|
||||||
class DBInt extends DBField
|
class DBInt extends ModelField implements DBField
|
||||||
{
|
{
|
||||||
|
use DBFieldTrait;
|
||||||
|
|
||||||
public function __construct(?string $name = null, int $defaultVal = 0)
|
public function __construct(?string $name = null, int $defaultVal = 0)
|
||||||
{
|
{
|
||||||
$this->defaultVal = is_int($defaultVal) ? $defaultVal : 0;
|
$this->defaultVal = is_int($defaultVal) ? $defaultVal : 0;
|
||||||
|
@ -2,19 +2,15 @@
|
|||||||
|
|
||||||
namespace SilverStripe\ORM\FieldType;
|
namespace SilverStripe\ORM\FieldType;
|
||||||
|
|
||||||
|
use SilverStripe\Model\ModelFields\StringModelField;
|
||||||
|
use SilverStripe\ORM\FieldType\DBFieldTrait;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An abstract base class for the string field types (i.e. Varchar and Text)
|
* An abstract base class for the string field types (i.e. Varchar and Text)
|
||||||
*/
|
*/
|
||||||
abstract class DBString extends DBField
|
abstract class DBString extends StringModelField implements DBField
|
||||||
{
|
{
|
||||||
private static array $casting = [
|
use DBFieldTrait;
|
||||||
'LimitCharacters' => 'Text',
|
|
||||||
'LimitCharactersToClosestWord' => 'Text',
|
|
||||||
'LimitWordCount' => 'Text',
|
|
||||||
'LowerCase' => 'Text',
|
|
||||||
'UpperCase' => 'Text',
|
|
||||||
'Plain' => 'Text',
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the default value for "nullify empty"
|
* Set the default value for "nullify empty"
|
||||||
@ -95,127 +91,4 @@ abstract class DBString extends DBField
|
|||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function forTemplate(): string
|
|
||||||
{
|
|
||||||
return nl2br(parent::forTemplate() ?? '');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Limit this field's content by a number of characters.
|
|
||||||
* This makes use of strip_tags() to avoid malforming the
|
|
||||||
* HTML tags in the string of text.
|
|
||||||
*
|
|
||||||
* @param int $limit Number of characters to limit by
|
|
||||||
* @param string|false $add Ellipsis to add to the end of truncated string
|
|
||||||
*/
|
|
||||||
public function LimitCharacters(int $limit = 20, string|false $add = false): string
|
|
||||||
{
|
|
||||||
$value = $this->Plain();
|
|
||||||
if (mb_strlen($value ?? '') <= $limit) {
|
|
||||||
return $value;
|
|
||||||
}
|
|
||||||
return $this->addEllipsis(mb_substr($value ?? '', 0, $limit), $add);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Limit this field's content by a number of characters and truncate
|
|
||||||
* the field to the closest complete word. All HTML tags are stripped
|
|
||||||
* from the field.
|
|
||||||
*
|
|
||||||
* @param int $limit Number of characters to limit by
|
|
||||||
* @param string|false $add Ellipsis to add to the end of truncated string
|
|
||||||
* @return string Plain text value with limited characters
|
|
||||||
*/
|
|
||||||
public function LimitCharactersToClosestWord(int $limit = 20, string|false $add = false): string
|
|
||||||
{
|
|
||||||
// Safely convert to plain text
|
|
||||||
$value = $this->Plain();
|
|
||||||
|
|
||||||
// Determine if value exceeds limit before limiting characters
|
|
||||||
if (mb_strlen($value ?? '') <= $limit) {
|
|
||||||
return $value;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Limit to character limit
|
|
||||||
$value = mb_substr($value ?? '', 0, $limit);
|
|
||||||
|
|
||||||
// If value exceeds limit, strip punctuation off the end to the last space and apply ellipsis
|
|
||||||
$value = $this->addEllipsis(
|
|
||||||
preg_replace(
|
|
||||||
'/[^\w_]+$/',
|
|
||||||
'',
|
|
||||||
mb_substr($value ?? '', 0, mb_strrpos($value ?? '', " "))
|
|
||||||
),
|
|
||||||
$add
|
|
||||||
);
|
|
||||||
return $value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Limit this field's content by a number of words.
|
|
||||||
*
|
|
||||||
* @param int $numWords Number of words to limit by.
|
|
||||||
* @param string|false $add Ellipsis to add to the end of truncated string.
|
|
||||||
*/
|
|
||||||
public function LimitWordCount(int $numWords = 26, string|false $add = false): string
|
|
||||||
{
|
|
||||||
$value = $this->Plain();
|
|
||||||
$words = explode(' ', $value ?? '');
|
|
||||||
if (count($words ?? []) <= $numWords) {
|
|
||||||
return $value;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Limit
|
|
||||||
$words = array_slice($words ?? [], 0, $numWords);
|
|
||||||
return $this->addEllipsis(implode(' ', $words), $add);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts the current value for this StringField to lowercase.
|
|
||||||
*
|
|
||||||
* @return string Text with lowercase (HTML for some subclasses)
|
|
||||||
*/
|
|
||||||
public function LowerCase(): string
|
|
||||||
{
|
|
||||||
return mb_strtolower($this->RAW() ?? '');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts the current value for this StringField to uppercase.
|
|
||||||
*
|
|
||||||
* @return string Text with uppercase (HTML for some subclasses)
|
|
||||||
*/
|
|
||||||
public function UpperCase(): string
|
|
||||||
{
|
|
||||||
return mb_strtoupper($this->RAW() ?? '');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Plain text version of this string
|
|
||||||
*/
|
|
||||||
public function Plain(): string
|
|
||||||
{
|
|
||||||
return trim($this->RAW() ?? '');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Swap add for defaultEllipsis if need be
|
|
||||||
*/
|
|
||||||
private function addEllipsis(string $string, string|false $add): string
|
|
||||||
{
|
|
||||||
if ($add === false) {
|
|
||||||
$add = $this->defaultEllipsis();
|
|
||||||
}
|
|
||||||
|
|
||||||
return $string . $add;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the default string to indicate that a string was cut off.
|
|
||||||
*/
|
|
||||||
public function defaultEllipsis(): string
|
|
||||||
{
|
|
||||||
return _t(DBString::class . '.ELLIPSIS', '…');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,9 @@ use SilverStripe\ORM\DB;
|
|||||||
use SilverStripe\Security\Member;
|
use SilverStripe\Security\Member;
|
||||||
use SilverStripe\Security\Security;
|
use SilverStripe\Security\Security;
|
||||||
use SilverStripe\Model\ModelData;
|
use SilverStripe\Model\ModelData;
|
||||||
|
use SilverStripe\ORM\FieldType\DBFieldTrait;
|
||||||
|
use SilverStripe\Model\ModelFields\ModelField;
|
||||||
|
use SilverStripe\ORM\FieldType\DBField;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a column in the database with the type 'Time'.
|
* Represents a column in the database with the type 'Time'.
|
||||||
@ -22,8 +25,10 @@ use SilverStripe\Model\ModelData;
|
|||||||
* );
|
* );
|
||||||
* </code>
|
* </code>
|
||||||
*/
|
*/
|
||||||
class DBTime extends DBField
|
class DBTime extends ModelField implements DBField
|
||||||
{
|
{
|
||||||
|
use DBFieldTrait;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Standard ISO format string for time in CLDR standard format
|
* Standard ISO format string for time in CLDR standard format
|
||||||
*/
|
*/
|
||||||
|
@ -5,12 +5,17 @@ namespace SilverStripe\ORM\FieldType;
|
|||||||
use SilverStripe\Forms\DropdownField;
|
use SilverStripe\Forms\DropdownField;
|
||||||
use SilverStripe\Forms\FormField;
|
use SilverStripe\Forms\FormField;
|
||||||
use SilverStripe\ORM\DB;
|
use SilverStripe\ORM\DB;
|
||||||
|
use SilverStripe\ORM\FieldType\DBFieldTrait;
|
||||||
|
use SilverStripe\Model\ModelFields\ModelField;
|
||||||
|
use SilverStripe\ORM\FieldType\DBField;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a single year field.
|
* Represents a single year field.
|
||||||
*/
|
*/
|
||||||
class DBYear extends DBField
|
class DBYear extends ModelField implements DBField
|
||||||
{
|
{
|
||||||
|
use DBFieldTrait;
|
||||||
|
|
||||||
public function requireField(): void
|
public function requireField(): void
|
||||||
{
|
{
|
||||||
$parts = ['datatype' => 'year', 'precision' => 4, 'arrayValue' => $this->arrayValue];
|
$parts = ['datatype' => 'year', 'precision' => 4, 'arrayValue' => $this->arrayValue];
|
||||||
|
@ -11,6 +11,7 @@ use InvalidArgumentException;
|
|||||||
use SilverStripe\Core\Config\Configurable;
|
use SilverStripe\Core\Config\Configurable;
|
||||||
use SilverStripe\ORM\DB;
|
use SilverStripe\ORM\DB;
|
||||||
use SilverStripe\ORM\FieldType\DBField;
|
use SilverStripe\ORM\FieldType\DBField;
|
||||||
|
use SilverStripe\ORM\FieldType\DBFieldHelper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for filtering implementations,
|
* Base class for filtering implementations,
|
||||||
|
@ -9,6 +9,7 @@ use SilverStripe\Core\ArrayLib;
|
|||||||
use SilverStripe\Model\List\ArrayList;
|
use SilverStripe\Model\List\ArrayList;
|
||||||
use SilverStripe\ORM\DataObject;
|
use SilverStripe\ORM\DataObject;
|
||||||
use SilverStripe\ORM\FieldType\DBField;
|
use SilverStripe\ORM\FieldType\DBField;
|
||||||
|
use SilverStripe\ORM\FieldType\DBFieldHelper;
|
||||||
use SilverStripe\Model\List\SS_List;
|
use SilverStripe\Model\List\SS_List;
|
||||||
use SilverStripe\Model\ArrayData;
|
use SilverStripe\Model\ArrayData;
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ use SilverStripe\ORM\FieldType\DBComposite;
|
|||||||
use InvalidArgumentException;
|
use InvalidArgumentException;
|
||||||
use Exception;
|
use Exception;
|
||||||
use SilverStripe\ORM\FieldType\DBField;
|
use SilverStripe\ORM\FieldType\DBField;
|
||||||
|
use SilverStripe\ORM\FieldType\DBFieldHelper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subclass of {@link DataList} representing a many_many relation.
|
* Subclass of {@link DataList} representing a many_many relation.
|
||||||
|
@ -7,6 +7,7 @@ use SilverStripe\Model\List\Limitable;
|
|||||||
use SilverStripe\Model\List\Sortable;
|
use SilverStripe\Model\List\Sortable;
|
||||||
use SilverStripe\Model\List\SS_List;
|
use SilverStripe\Model\List\SS_List;
|
||||||
use SilverStripe\ORM\FieldType\DBField;
|
use SilverStripe\ORM\FieldType\DBField;
|
||||||
|
use SilverStripe\ORM\FieldType\DBFieldHelper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract representation of a DB relation field, either saved or in memory
|
* Abstract representation of a DB relation field, either saved or in memory
|
||||||
|
@ -6,6 +6,7 @@ use InvalidArgumentException;
|
|||||||
use ArrayIterator;
|
use ArrayIterator;
|
||||||
use SilverStripe\Model\List\ArrayList;
|
use SilverStripe\Model\List\ArrayList;
|
||||||
use SilverStripe\ORM\FieldType\DBField;
|
use SilverStripe\ORM\FieldType\DBField;
|
||||||
|
use SilverStripe\ORM\FieldType\DBFieldHelper;
|
||||||
use Traversable;
|
use Traversable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -10,6 +10,7 @@ use SilverStripe\Control\HTTPResponse;
|
|||||||
use SilverStripe\Core\Convert;
|
use SilverStripe\Core\Convert;
|
||||||
use SilverStripe\Core\Manifest\ModuleLoader;
|
use SilverStripe\Core\Manifest\ModuleLoader;
|
||||||
use SilverStripe\ORM\FieldType\DBField;
|
use SilverStripe\ORM\FieldType\DBField;
|
||||||
|
use SilverStripe\ORM\FieldType\DBFieldHelper;
|
||||||
use SilverStripe\ORM\FieldType\DBHTMLText;
|
use SilverStripe\ORM\FieldType\DBHTMLText;
|
||||||
use SilverStripe\View\Requirements;
|
use SilverStripe\View\Requirements;
|
||||||
use SilverStripe\View\SSViewer;
|
use SilverStripe\View\SSViewer;
|
||||||
@ -197,7 +198,7 @@ PHP
|
|||||||
|
|
||||||
// Show login
|
// Show login
|
||||||
$controller = $controller->customise([
|
$controller = $controller->customise([
|
||||||
'Content' => DBField::create_field(DBHTMLText::class, _t(
|
'Content' => DBFieldHelper::create_field(DBHTMLText::class, _t(
|
||||||
__CLASS__ . '.SUCCESSCONTENT',
|
__CLASS__ . '.SUCCESSCONTENT',
|
||||||
'<p>Login success. If you are not automatically redirected ' . '<a target="_top" href="{link}">click here</a></p>',
|
'<p>Login success. If you are not automatically redirected ' . '<a target="_top" href="{link}">click here</a></p>',
|
||||||
'Login message displayed in the cms popup once a user has re-authenticated themselves',
|
'Login message displayed in the cms popup once a user has re-authenticated themselves',
|
||||||
|
@ -10,6 +10,7 @@ use SilverStripe\Control\RequestHandler;
|
|||||||
use SilverStripe\Core\Injector\Injector;
|
use SilverStripe\Core\Injector\Injector;
|
||||||
use SilverStripe\ORM\FieldType\DBDatetime;
|
use SilverStripe\ORM\FieldType\DBDatetime;
|
||||||
use SilverStripe\ORM\FieldType\DBField;
|
use SilverStripe\ORM\FieldType\DBField;
|
||||||
|
use SilverStripe\ORM\FieldType\DBFieldHelper;
|
||||||
use SilverStripe\Core\Validation\ValidationException;
|
use SilverStripe\Core\Validation\ValidationException;
|
||||||
use SilverStripe\Security\Authenticator;
|
use SilverStripe\Security\Authenticator;
|
||||||
use SilverStripe\Security\IdentityStore;
|
use SilverStripe\Security\IdentityStore;
|
||||||
@ -83,7 +84,7 @@ class ChangePasswordHandler extends RequestHandler
|
|||||||
|
|
||||||
$session = $this->getRequest()->getSession();
|
$session = $this->getRequest()->getSession();
|
||||||
if ($session->get('AutoLoginHash')) {
|
if ($session->get('AutoLoginHash')) {
|
||||||
$message = DBField::create_field(
|
$message = DBFieldHelper::create_field(
|
||||||
'HTMLFragment',
|
'HTMLFragment',
|
||||||
'<p>' . _t(
|
'<p>' . _t(
|
||||||
'SilverStripe\\Security\\Security.ENTERNEWPASSWORD',
|
'SilverStripe\\Security\\Security.ENTERNEWPASSWORD',
|
||||||
@ -100,7 +101,7 @@ class ChangePasswordHandler extends RequestHandler
|
|||||||
|
|
||||||
if (Security::getCurrentUser()) {
|
if (Security::getCurrentUser()) {
|
||||||
// Logged in user requested a password change form.
|
// Logged in user requested a password change form.
|
||||||
$message = DBField::create_field(
|
$message = DBFieldHelper::create_field(
|
||||||
'HTMLFragment',
|
'HTMLFragment',
|
||||||
'<p>' . _t(
|
'<p>' . _t(
|
||||||
'SilverStripe\\Security\\Security.CHANGEPASSWORDBELOW',
|
'SilverStripe\\Security\\Security.CHANGEPASSWORDBELOW',
|
||||||
@ -115,7 +116,7 @@ class ChangePasswordHandler extends RequestHandler
|
|||||||
}
|
}
|
||||||
// Show a friendly message saying the login token has expired
|
// Show a friendly message saying the login token has expired
|
||||||
if ($token !== null && $member && !$member->validateAutoLoginToken($token)) {
|
if ($token !== null && $member && !$member->validateAutoLoginToken($token)) {
|
||||||
$message = DBField::create_field(
|
$message = DBFieldHelper::create_field(
|
||||||
'HTMLFragment',
|
'HTMLFragment',
|
||||||
_t(
|
_t(
|
||||||
'SilverStripe\\Security\\Security.NOTERESETLINKINVALID',
|
'SilverStripe\\Security\\Security.NOTERESETLINKINVALID',
|
||||||
|
@ -176,7 +176,7 @@ class CookieAuthenticationHandler implements AuthenticationHandler
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Renew the token
|
// Renew the token
|
||||||
Deprecation::withNoReplacement(fn() => $rememberLoginHash->renew());
|
Deprecation::withSuppressedNotice(fn() => $rememberLoginHash->renew());
|
||||||
|
|
||||||
// Send the new token to the client if it was changed
|
// Send the new token to the client if it was changed
|
||||||
if ($rememberLoginHash->getToken()) {
|
if ($rememberLoginHash->getToken()) {
|
||||||
|
@ -11,6 +11,7 @@ use SilverStripe\Core\Convert;
|
|||||||
use SilverStripe\Core\Injector\Injector;
|
use SilverStripe\Core\Injector\Injector;
|
||||||
use SilverStripe\Forms\Form;
|
use SilverStripe\Forms\Form;
|
||||||
use SilverStripe\ORM\FieldType\DBField;
|
use SilverStripe\ORM\FieldType\DBField;
|
||||||
|
use SilverStripe\ORM\FieldType\DBFieldHelper;
|
||||||
use SilverStripe\Security\Member;
|
use SilverStripe\Security\Member;
|
||||||
use SilverStripe\Security\Security;
|
use SilverStripe\Security\Security;
|
||||||
use Symfony\Component\Mailer\Exception\TransportExceptionInterface;
|
use Symfony\Component\Mailer\Exception\TransportExceptionInterface;
|
||||||
@ -92,7 +93,7 @@ class LostPasswordHandler extends RequestHandler
|
|||||||
);
|
);
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'Content' => DBField::create_field('HTMLFragment', "<p>$message</p>"),
|
'Content' => DBFieldHelper::create_field('HTMLFragment', "<p>$message</p>"),
|
||||||
'Form' => $this->lostPasswordForm(),
|
'Form' => $this->lostPasswordForm(),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@ -115,7 +116,7 @@ class LostPasswordHandler extends RequestHandler
|
|||||||
'SilverStripe\\Security\\Security.PASSWORDRESETSENTHEADER',
|
'SilverStripe\\Security\\Security.PASSWORDRESETSENTHEADER',
|
||||||
"Password reset link sent"
|
"Password reset link sent"
|
||||||
),
|
),
|
||||||
'Content' => DBField::create_field('HTMLFragment', "<p>$message</p>"),
|
'Content' => DBFieldHelper::create_field('HTMLFragment', "<p>$message</p>"),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ use SilverStripe\Model\List\ArrayList;
|
|||||||
use SilverStripe\ORM\DataObject;
|
use SilverStripe\ORM\DataObject;
|
||||||
use SilverStripe\ORM\DB;
|
use SilverStripe\ORM\DB;
|
||||||
use SilverStripe\ORM\FieldType\DBField;
|
use SilverStripe\ORM\FieldType\DBField;
|
||||||
|
use SilverStripe\ORM\FieldType\DBFieldHelper;
|
||||||
use SilverStripe\ORM\FieldType\DBHTMLText;
|
use SilverStripe\ORM\FieldType\DBHTMLText;
|
||||||
use SilverStripe\Core\Validation\ValidationResult;
|
use SilverStripe\Core\Validation\ValidationResult;
|
||||||
use SilverStripe\Model\ArrayData;
|
use SilverStripe\Model\ArrayData;
|
||||||
@ -911,8 +912,8 @@ class Security extends Controller implements TemplateGlobalProvider
|
|||||||
$fragments = array_merge(['Title' => $title], $fragments);
|
$fragments = array_merge(['Title' => $title], $fragments);
|
||||||
if ($message) {
|
if ($message) {
|
||||||
$messageResult = [
|
$messageResult = [
|
||||||
'Content' => DBField::create_field('HTMLFragment', $message),
|
'Content' => DBFieldHelper::create_field('HTMLFragment', $message),
|
||||||
'Message' => DBField::create_field('HTMLFragment', $message),
|
'Message' => DBFieldHelper::create_field('HTMLFragment', $message),
|
||||||
'MessageType' => $messageType
|
'MessageType' => $messageType
|
||||||
];
|
];
|
||||||
$fragments = array_merge($fragments, $messageResult);
|
$fragments = array_merge($fragments, $messageResult);
|
||||||
|
@ -17,7 +17,7 @@ use SilverStripe\Core\Manifest\ResourceURLGenerator;
|
|||||||
use SilverStripe\Core\Path;
|
use SilverStripe\Core\Path;
|
||||||
use SilverStripe\Dev\Debug;
|
use SilverStripe\Dev\Debug;
|
||||||
use SilverStripe\i18n\i18n;
|
use SilverStripe\i18n\i18n;
|
||||||
use SilverStripe\ORM\FieldType\DBField;
|
use SilverStripe\ORM\FieldType\DBFieldHelper;
|
||||||
use Symfony\Component\Filesystem\Path as FilesystemPath;
|
use Symfony\Component\Filesystem\Path as FilesystemPath;
|
||||||
|
|
||||||
class Requirements_Backend
|
class Requirements_Backend
|
||||||
@ -1035,8 +1035,8 @@ class Requirements_Backend
|
|||||||
i18n::config()->get('default_locale'),
|
i18n::config()->get('default_locale'),
|
||||||
i18n::getData()->langFromLocale(i18n::get_locale()),
|
i18n::getData()->langFromLocale(i18n::get_locale()),
|
||||||
i18n::get_locale(),
|
i18n::get_locale(),
|
||||||
strtolower(DBField::create_field('Locale', i18n::get_locale())->RFC1766() ?? ''),
|
strtolower(DBFieldHelper::create_field('Locale', i18n::get_locale())->RFC1766() ?? ''),
|
||||||
strtolower(DBField::create_field('Locale', i18n::config()->get('default_locale'))->RFC1766() ?? '')
|
strtolower(DBFieldHelper::create_field('Locale', i18n::config()->get('default_locale'))->RFC1766() ?? '')
|
||||||
];
|
];
|
||||||
|
|
||||||
$candidates = array_map(
|
$candidates = array_map(
|
||||||
|
@ -11,7 +11,7 @@ use SilverStripe\Core\Flushable;
|
|||||||
use SilverStripe\Core\Injector\Injector;
|
use SilverStripe\Core\Injector\Injector;
|
||||||
use SilverStripe\Core\Injector\Injectable;
|
use SilverStripe\Core\Injector\Injectable;
|
||||||
use SilverStripe\Control\Director;
|
use SilverStripe\Control\Director;
|
||||||
use SilverStripe\ORM\FieldType\DBField;
|
use SilverStripe\ORM\FieldType\DBFieldHelper;
|
||||||
use SilverStripe\ORM\FieldType\DBHTMLText;
|
use SilverStripe\ORM\FieldType\DBHTMLText;
|
||||||
use SilverStripe\Security\Permission;
|
use SilverStripe\Security\Permission;
|
||||||
use InvalidArgumentException;
|
use InvalidArgumentException;
|
||||||
@ -670,7 +670,7 @@ PHP;
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @var DBHTMLText $html */
|
/** @var DBHTMLText $html */
|
||||||
$html = DBField::create_field('HTMLFragment', $output);
|
$html = DBFieldHelper::create_field('HTMLFragment', $output);
|
||||||
|
|
||||||
// Reset global state
|
// Reset global state
|
||||||
static::setRewriteHashLinksDefault($origRewriteDefault);
|
static::setRewriteHashLinksDefault($origRewriteDefault);
|
||||||
|
@ -6,6 +6,7 @@ use InvalidArgumentException;
|
|||||||
use SilverStripe\Core\ClassInfo;
|
use SilverStripe\Core\ClassInfo;
|
||||||
use SilverStripe\Model\ModelData;
|
use SilverStripe\Model\ModelData;
|
||||||
use SilverStripe\ORM\FieldType\DBField;
|
use SilverStripe\ORM\FieldType\DBField;
|
||||||
|
use SilverStripe\ORM\FieldType\DBFieldHelper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This extends SSViewer_Scope to mix in data on top of what the item provides. This can be "global"
|
* This extends SSViewer_Scope to mix in data on top of what the item provides. This can be "global"
|
||||||
@ -438,6 +439,6 @@ class SSViewer_DataPresenter extends SSViewer_Scope
|
|||||||
? ModelData::config()->uninherited('default_cast')
|
? ModelData::config()->uninherited('default_cast')
|
||||||
: $source['casting'];
|
: $source['casting'];
|
||||||
|
|
||||||
return DBField::create_field($casting, $value);
|
return DBFieldHelper::create_field($casting, $value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ namespace SilverStripe\View;
|
|||||||
|
|
||||||
use SilverStripe\Core\Config\Config;
|
use SilverStripe\Core\Config\Config;
|
||||||
use SilverStripe\ORM\FieldType\DBField;
|
use SilverStripe\ORM\FieldType\DBField;
|
||||||
|
use SilverStripe\ORM\FieldType\DBFieldHelper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Special SSViewer that will process a template passed as a string, rather than a filename.
|
* Special SSViewer that will process a template passed as a string, rather than a filename.
|
||||||
@ -72,7 +73,7 @@ class SSViewer_FromString extends SSViewer
|
|||||||
unlink($cacheFile ?? '');
|
unlink($cacheFile ?? '');
|
||||||
}
|
}
|
||||||
|
|
||||||
$html = DBField::create_field('HTMLFragment', $val);
|
$html = DBFieldHelper::create_field('HTMLFragment', $val);
|
||||||
|
|
||||||
return $html;
|
return $html;
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ use SilverStripe\ORM\FieldType\DBText;
|
|||||||
use SilverStripe\ORM\FieldType\DBFloat;
|
use SilverStripe\ORM\FieldType\DBFloat;
|
||||||
use SilverStripe\ORM\FieldType\DBInt;
|
use SilverStripe\ORM\FieldType\DBInt;
|
||||||
use SilverStripe\ORM\FieldType\DBField;
|
use SilverStripe\ORM\FieldType\DBField;
|
||||||
|
use SilverStripe\ORM\FieldType\DBFieldHelper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This tracks the current scope for an SSViewer instance. It has three goals:
|
* This tracks the current scope for an SSViewer instance. It has three goals:
|
||||||
|
@ -10,6 +10,7 @@ use SilverStripe\Core\Convert;
|
|||||||
use SilverStripe\Core\Injector\Injector;
|
use SilverStripe\Core\Injector\Injector;
|
||||||
use SilverStripe\Model\List\ArrayList;
|
use SilverStripe\Model\List\ArrayList;
|
||||||
use SilverStripe\ORM\FieldType\DBField;
|
use SilverStripe\ORM\FieldType\DBField;
|
||||||
|
use SilverStripe\ORM\FieldType\DBFieldHelper;
|
||||||
use SilverStripe\Model\ArrayData;
|
use SilverStripe\Model\ArrayData;
|
||||||
use SilverStripe\View\Embed\Embeddable;
|
use SilverStripe\View\Embed\Embeddable;
|
||||||
use SilverStripe\View\HTML;
|
use SilverStripe\View\HTML;
|
||||||
@ -197,7 +198,7 @@ class EmbedShortcodeProvider implements ShortcodeHandler
|
|||||||
$data = [
|
$data = [
|
||||||
'Arguments' => $arguments,
|
'Arguments' => $arguments,
|
||||||
'Attributes' => $attributes,
|
'Attributes' => $attributes,
|
||||||
'Content' => DBField::create_field('HTMLFragment', $content)
|
'Content' => DBFieldHelper::create_field('HTMLFragment', $content)
|
||||||
];
|
];
|
||||||
|
|
||||||
return ArrayData::create($data)->renderWith(EmbedShortcodeProvider::class . '_video')->forTemplate();
|
return ArrayData::create($data)->renderWith(EmbedShortcodeProvider::class . '_video')->forTemplate();
|
||||||
|
@ -116,72 +116,72 @@ class DeprecationTest extends SapphireTest
|
|||||||
Deprecation::outputNotices();
|
Deprecation::outputNotices();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testWithNoReplacementDefault()
|
public function testwithSuppressedNoticeDefault()
|
||||||
{
|
{
|
||||||
Deprecation::enable();
|
Deprecation::enable();
|
||||||
$ret = Deprecation::withNoReplacement(function () {
|
$ret = Deprecation::withSuppressedNotice(function () {
|
||||||
return $this->myDeprecatedMethod();
|
return $this->myDeprecatedMethod();
|
||||||
});
|
});
|
||||||
$this->assertSame('abc', $ret);
|
$this->assertSame('abc', $ret);
|
||||||
Deprecation::outputNotices();
|
Deprecation::outputNotices();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testWithNoReplacementTrue()
|
public function testwithSuppressedNoticeTrue()
|
||||||
{
|
{
|
||||||
$message = implode(' ', [
|
$message = implode(' ', [
|
||||||
'SilverStripe\Dev\Tests\DeprecationTest->myDeprecatedMethod is deprecated.',
|
'SilverStripe\Dev\Tests\DeprecationTest->myDeprecatedMethod is deprecated.',
|
||||||
'My message.',
|
'My message.',
|
||||||
'Called from SilverStripe\Dev\Tests\DeprecationTest->testWithNoReplacementTrue.'
|
'Called from SilverStripe\Dev\Tests\DeprecationTest->testwithSuppressedNoticeTrue.'
|
||||||
]);
|
]);
|
||||||
$this->expectException(DeprecationTestException::class);
|
$this->expectException(DeprecationTestException::class);
|
||||||
$this->expectExceptionMessage($message);
|
$this->expectExceptionMessage($message);
|
||||||
Deprecation::enable(true);
|
Deprecation::enable(true);
|
||||||
$ret = Deprecation::withNoReplacement(function () {
|
$ret = Deprecation::withSuppressedNotice(function () {
|
||||||
return $this->myDeprecatedMethod();
|
return $this->myDeprecatedMethod();
|
||||||
});
|
});
|
||||||
$this->assertSame('abc', $ret);
|
$this->assertSame('abc', $ret);
|
||||||
Deprecation::outputNotices();
|
Deprecation::outputNotices();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testWithNoReplacementTrueCallUserFunc()
|
public function testwithSuppressedNoticeTrueCallUserFunc()
|
||||||
{
|
{
|
||||||
$message = implode(' ', [
|
$message = implode(' ', [
|
||||||
'SilverStripe\Dev\Tests\DeprecationTest->myDeprecatedMethod is deprecated.',
|
'SilverStripe\Dev\Tests\DeprecationTest->myDeprecatedMethod is deprecated.',
|
||||||
'My message.',
|
'My message.',
|
||||||
'Called from SilverStripe\Dev\Tests\DeprecationTest->testWithNoReplacementTrueCallUserFunc.'
|
'Called from SilverStripe\Dev\Tests\DeprecationTest->testwithSuppressedNoticeTrueCallUserFunc.'
|
||||||
]);
|
]);
|
||||||
$this->expectException(DeprecationTestException::class);
|
$this->expectException(DeprecationTestException::class);
|
||||||
$this->expectExceptionMessage($message);
|
$this->expectExceptionMessage($message);
|
||||||
Deprecation::enable(true);
|
Deprecation::enable(true);
|
||||||
$ret = Deprecation::withNoReplacement(function () {
|
$ret = Deprecation::withSuppressedNotice(function () {
|
||||||
return call_user_func([$this, 'myDeprecatedMethod']);
|
return call_user_func([$this, 'myDeprecatedMethod']);
|
||||||
});
|
});
|
||||||
$this->assertSame('abc', $ret);
|
$this->assertSame('abc', $ret);
|
||||||
Deprecation::outputNotices();
|
Deprecation::outputNotices();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testNoticeWithNoReplacementTrue()
|
public function testNoticewithSuppressedNoticeTrue()
|
||||||
{
|
{
|
||||||
$message = implode(' ', [
|
$message = implode(' ', [
|
||||||
'SilverStripe\Dev\Tests\DeprecationTest->testNoticeWithNoReplacementTrue is deprecated.',
|
'SilverStripe\Dev\Tests\DeprecationTest->testNoticewithSuppressedNoticeTrue is deprecated.',
|
||||||
'My message.',
|
'My message.',
|
||||||
'Called from PHPUnit\Framework\TestCase->runTest.'
|
'Called from PHPUnit\Framework\TestCase->runTest.'
|
||||||
]);
|
]);
|
||||||
$this->expectException(DeprecationTestException::class);
|
$this->expectException(DeprecationTestException::class);
|
||||||
$this->expectExceptionMessage($message);
|
$this->expectExceptionMessage($message);
|
||||||
Deprecation::enable(true);
|
Deprecation::enable(true);
|
||||||
Deprecation::withNoReplacement(function () {
|
Deprecation::withSuppressedNotice(function () {
|
||||||
Deprecation::notice('123', 'My message.');
|
Deprecation::notice('123', 'My message.');
|
||||||
});
|
});
|
||||||
Deprecation::outputNotices();
|
Deprecation::outputNotices();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testClassWithNoReplacement()
|
public function testClasswithSuppressedNotice()
|
||||||
{
|
{
|
||||||
$message = implode(' ', [
|
$message = implode(' ', [
|
||||||
'SilverStripe\Dev\Tests\DeprecationTest\DeprecationTestObject is deprecated.',
|
'SilverStripe\Dev\Tests\DeprecationTest\DeprecationTestObject is deprecated.',
|
||||||
'Some class message.',
|
'Some class message.',
|
||||||
'Called from SilverStripe\Dev\Tests\DeprecationTest->testClassWithNoReplacement.'
|
'Called from SilverStripe\Dev\Tests\DeprecationTest->testClasswithSuppressedNotice.'
|
||||||
]);
|
]);
|
||||||
$this->expectException(DeprecationTestException::class);
|
$this->expectException(DeprecationTestException::class);
|
||||||
$this->expectExceptionMessage($message);
|
$this->expectExceptionMessage($message);
|
||||||
@ -193,12 +193,12 @@ class DeprecationTest extends SapphireTest
|
|||||||
Deprecation::outputNotices();
|
Deprecation::outputNotices();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testClassWithInjectorWithNoReplacement()
|
public function testClassWithInjectorwithSuppressedNotice()
|
||||||
{
|
{
|
||||||
$message = implode(' ', [
|
$message = implode(' ', [
|
||||||
'SilverStripe\Dev\Tests\DeprecationTest\DeprecationTestObject is deprecated.',
|
'SilverStripe\Dev\Tests\DeprecationTest\DeprecationTestObject is deprecated.',
|
||||||
'Some class message.',
|
'Some class message.',
|
||||||
'Called from SilverStripe\Dev\Tests\DeprecationTest->testClassWithInjectorWithNoReplacement.'
|
'Called from SilverStripe\Dev\Tests\DeprecationTest->testClassWithInjectorwithSuppressedNotice.'
|
||||||
]);
|
]);
|
||||||
$this->expectException(DeprecationTestException::class);
|
$this->expectException(DeprecationTestException::class);
|
||||||
$this->expectExceptionMessage($message);
|
$this->expectExceptionMessage($message);
|
||||||
|
@ -11,7 +11,7 @@ class DeprecationTestObject extends DataObject implements TestOnly
|
|||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
Deprecation::withNoReplacement(function () {
|
Deprecation::withSuppressedNotice(function () {
|
||||||
Deprecation::notice(
|
Deprecation::notice(
|
||||||
'1.2.3',
|
'1.2.3',
|
||||||
'Some class message',
|
'Some class message',
|
||||||
|
@ -6,6 +6,7 @@ use SilverStripe\Core\Config\Config;
|
|||||||
use SilverStripe\Dev\TestOnly;
|
use SilverStripe\Dev\TestOnly;
|
||||||
use SilverStripe\ORM\DB;
|
use SilverStripe\ORM\DB;
|
||||||
use SilverStripe\ORM\FieldType\DBField;
|
use SilverStripe\ORM\FieldType\DBField;
|
||||||
|
use SilverStripe\ORM\FieldType\DBFieldHelper;
|
||||||
use SilverStripe\Model\ModelData;
|
use SilverStripe\Model\ModelData;
|
||||||
|
|
||||||
class TestDbField extends DBField implements TestOnly
|
class TestDbField extends DBField implements TestOnly
|
||||||
|
@ -5,6 +5,7 @@ namespace SilverStripe\ORM\Tests\DataObjectTest;
|
|||||||
use SilverStripe\Dev\TestOnly;
|
use SilverStripe\Dev\TestOnly;
|
||||||
use SilverStripe\ORM\FieldType\DBBoolean;
|
use SilverStripe\ORM\FieldType\DBBoolean;
|
||||||
use SilverStripe\ORM\FieldType\DBField;
|
use SilverStripe\ORM\FieldType\DBField;
|
||||||
|
use SilverStripe\ORM\FieldType\DBFieldHelper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a fake DB field specifically design to test dynamic value assignment. You can set `scalarValueOnly` in
|
* This is a fake DB field specifically design to test dynamic value assignment. You can set `scalarValueOnly` in
|
||||||
|
@ -156,7 +156,7 @@ class PasswordEncryptorTest extends SapphireTest
|
|||||||
'encryptors',
|
'encryptors',
|
||||||
['test_sha1legacy' => [PasswordEncryptor_LegacyPHPHash::class => 'sha1']]
|
['test_sha1legacy' => [PasswordEncryptor_LegacyPHPHash::class => 'sha1']]
|
||||||
);
|
);
|
||||||
$e = Deprecation::withNoReplacement(fn() => PasswordEncryptor::create_for_algorithm('test_sha1legacy'));
|
$e = Deprecation::withSuppressedNotice(fn() => PasswordEncryptor::create_for_algorithm('test_sha1legacy'));
|
||||||
// precomputed hashes for 'mypassword' from different architectures
|
// precomputed hashes for 'mypassword' from different architectures
|
||||||
$amdHash = 'h1fj0a6m4o6k0sosks88oo08ko4gc4s';
|
$amdHash = 'h1fj0a6m4o6k0sosks88oo08ko4gc4s';
|
||||||
$intelHash = 'h1fj0a6m4o0g04ocg00o4kwoc4wowws';
|
$intelHash = 'h1fj0a6m4o0g04ocg00o4kwoc4wowws';
|
||||||
|
@ -111,7 +111,7 @@ class RememberLoginHashTest extends SapphireTest
|
|||||||
|
|
||||||
$member = $this->objFromFixture(Member::class, 'main');
|
$member = $this->objFromFixture(Member::class, 'main');
|
||||||
|
|
||||||
Deprecation::withNoReplacement(
|
Deprecation::withSuppressedNotice(
|
||||||
fn() => RememberLoginHash::config()->set('replace_token_during_session_renewal', $replaceToken)
|
fn() => RememberLoginHash::config()->set('replace_token_during_session_renewal', $replaceToken)
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -122,7 +122,7 @@ class RememberLoginHashTest extends SapphireTest
|
|||||||
// Fetch the token from the DB - otherwise we still have the token from when this was originally created
|
// Fetch the token from the DB - otherwise we still have the token from when this was originally created
|
||||||
$storedHash = RememberLoginHash::get()->find('ID', $hash->ID);
|
$storedHash = RememberLoginHash::get()->find('ID', $hash->ID);
|
||||||
|
|
||||||
Deprecation::withNoReplacement(fn() => $storedHash->renew());
|
Deprecation::withSuppressedNotice(fn() => $storedHash->renew());
|
||||||
|
|
||||||
if ($replaceToken) {
|
if ($replaceToken) {
|
||||||
$this->assertNotEquals($oldToken, $storedHash->getToken());
|
$this->assertNotEquals($oldToken, $storedHash->getToken());
|
||||||
|
Loading…
x
Reference in New Issue
Block a user