From dcc68634018ca9b8dd442cd74812addbf7b4988a Mon Sep 17 00:00:00 2001 From: Guy Sartorelli <36352093+GuySartorelli@users.noreply.github.com> Date: Fri, 19 Apr 2024 10:35:36 +1200 Subject: [PATCH] NEW Allow skipping validation on write (#11202) --- src/ORM/DataObject.php | 15 ++++++++++----- tests/php/ORM/DataObjectTest.php | 7 +++++++ tests/php/ORM/DataObjectTest/TreeNode.php | 4 ++-- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/ORM/DataObject.php b/src/ORM/DataObject.php index 42d016645..cf5e1f195 100644 --- a/src/ORM/DataObject.php +++ b/src/ORM/DataObject.php @@ -1345,7 +1345,7 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity * * @return ValidationException Exception generated by this write, or null if valid */ - protected function validateWrite() + protected function validateWrite(bool $skipValidation = false) { if ($this->ObsoleteClassName) { return new ValidationException( @@ -1354,6 +1354,10 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity ); } + if ($skipValidation) { + return null; + } + // Note: Validation can only be disabled at the global level, not per-model if (DataObject::config()->uninherited('validation_enabled')) { $result = $this->validate(); @@ -1369,10 +1373,10 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity * * @throws ValidationException */ - protected function preWrite() + protected function preWrite(bool $skipValidation = false) { // Validate this object - if ($writeException = $this->validateWrite()) { + if ($writeException = $this->validateWrite($skipValidation)) { // Used by DODs to clean up after themselves, eg, Versioned $this->invokeWithExtensions('onAfterSkippedWrite'); throw $writeException; @@ -1560,15 +1564,16 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity * {@link getManyManyComponents()}. Default to `false`. The parameter can also be provided in * the form of an array: `['recursive' => true, skip => ['Page'=>[1,2,3]]`. This avoid infinite * loops when one DataObject are components of each other. + * @param boolean $skipValidation Skip validation of data * @return int The ID of the record * @throws ValidationException Exception that can be caught and handled by the calling function */ - public function write($showDebug = false, $forceInsert = false, $forceWrite = false, $writeComponents = false) + public function write($showDebug = false, $forceInsert = false, $forceWrite = false, $writeComponents = false, bool $skipValidation = false) { $now = DBDatetime::now()->Rfc2822(); // Execute pre-write tasks - $this->preWrite(); + $this->preWrite($skipValidation); // Check if we are doing an update or an insert $isNewRecord = !$this->isInDB() || $forceInsert; diff --git a/tests/php/ORM/DataObjectTest.php b/tests/php/ORM/DataObjectTest.php index af99c2dec..b944ad34d 100644 --- a/tests/php/ORM/DataObjectTest.php +++ b/tests/php/ORM/DataObjectTest.php @@ -1519,6 +1519,13 @@ class DataObjectTest extends SapphireTest $this->assertTrue($validatedObject->isInDB(), "Validated object was not saved to database"); } + public function testWriteSkipValidation(): void + { + $validatedObject = new DataObjectTest\ValidatedObject(); + $validatedObject->write(skipValidation: true); + $this->assertTrue($validatedObject->isInDB(), "Validated object was not saved to database"); + } + public function testSubclassCreation() { /* Creating a new object of a subclass should set the ClassName field correctly */ diff --git a/tests/php/ORM/DataObjectTest/TreeNode.php b/tests/php/ORM/DataObjectTest/TreeNode.php index e497748b2..5a3370265 100644 --- a/tests/php/ORM/DataObjectTest/TreeNode.php +++ b/tests/php/ORM/DataObjectTest/TreeNode.php @@ -33,7 +33,7 @@ class TreeNode extends DataObject implements TestOnly 'Children' => self::class, ]; - public function write($showDebug = false, $forceInsert = false, $forceWrite = false, $writeComponents = false) + public function write($showDebug = false, $forceInsert = false, $forceWrite = false, $writeComponents = false, bool $skipValidation = false) { // Force the component to fetch its Parent and Cycle relation so we have components to recursively write $this->Parent; @@ -42,7 +42,7 @@ class TreeNode extends DataObject implements TestOnly // Count a write attempts $this->WriteCount++; - return parent::write($showDebug, $forceInsert, $forceWrite, $writeComponents); + return parent::write($showDebug, $forceInsert, $forceWrite, $writeComponents, $skipValidation); } /**