Skip to content

Commit

Permalink
Fix calss validation for elemental blocks
Browse files Browse the repository at this point in the history
  • Loading branch information
Maxime Rainville committed Aug 5, 2023
1 parent 02810ac commit b9a6c59
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 37 deletions.
22 changes: 14 additions & 8 deletions src/Form/AllowedClassesTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
use Psr\Container\NotFoundExceptionInterface;
use InvalidArgumentException;
use SilverStripe\AnyField\Services\AnyService;
use SilverStripe\Core\ClassInfo;
use SilverStripe\ORM\DataObject;
use SilverStripe\ORM\DataObjectInterface;

/**
* Encapsulate some shared logic between AnyField and ManyAnyField for tracking base classes
Expand All @@ -23,15 +23,16 @@ trait AllowedClassesTrait
* Retrieve the current BaseClass. If the BaseClass has not been explicitly set, try to guess what it is by looking
* at the relation the field is pointed at. Returns a blank string if the BaseClass can not be ascertained.
*/
public function getBaseClass(): string
public function getBaseClass(?DataObjectInterface $record = null): string
{
if ($this->baseClass) {
return $this->baseClass;
}

return (string)$this->guessBaseClass();
return (string)$this->guessBaseClass($record);
}


/**
* Explicitly set the BaseClass for this any Field
* @throws InvalidArgumentException If $className is not a valid DataObject class.
Expand Down Expand Up @@ -100,11 +101,16 @@ public function setRecursivelyAddChildClass(bool $recursivelyAddChildClass): sel
return $this;
}

abstract protected function guessBaseClass(): ?string;
/**
* Try to guess the base class for our any field
* @param null|DataObjectInterface $record
* @return null|string
*/
abstract protected function guessBaseClass(?DataObjectInterface $record = null): ?string;

public function getAllowedDataObjectClasses(): array
public function getAllowedDataObjectClasses(?DataObjectInterface $record = null): array
{
$baseClass = $this->getBaseClass();
$baseClass = $this->getBaseClass($record);

return AnyService::singleton()->getAllowedDataObjectClasses(
$baseClass,
Expand Down Expand Up @@ -135,9 +141,9 @@ public function getProps(): array
return $props;
}

protected function validClassName(string $className): void
protected function validClassName(string $className, ?DataObjectInterface $record = null): void
{
$valid = array_keys($this->getAllowedDataObjectClasses());
$valid = array_keys($this->getAllowedDataObjectClasses($record));
if (!in_array($className, $valid)) {
throw new \InvalidArgumentException(sprintf(
'%s is not a valid DataObject class for this field. Valid classes are: %s',
Expand Down
30 changes: 17 additions & 13 deletions src/Form/AnyField.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use DNADesign\Elemental\Controllers\ElementalAreaController;
use DNADesign\Elemental\Models\BaseElement;
use SilverStripe\ORM\DataObject;
use SilverStripe\ORM\DataObjectInterface;

/**
* Allows CMS users to edit a DataObject.
Expand All @@ -18,29 +19,32 @@ class AnyField extends JsonField
/**
* Try to guess what class we are editing
*/
private function guessBaseClass(): ?string
protected function guessBaseClass(?DataObjectInterface $record = null): ?string
{
$form = $this->getForm();
if (!$form) {
return null;
}

$record = $this->getForm()->getRecord();
if (!$record) {
return null;
if (empty($record)) {
$form = $this->getForm();
if (!$form) {
return null;
}

$record = $this->getForm()->getRecord();
if (!$record) {
return null;
}
}

$fieldname = $this->getName();
$class = DataObject::getSchema()->hasOneComponent(get_class($record), $fieldname);

// The name of Elemental block fields are rename with a prefix.
if ($record instanceof BaseElement) {
// Elemental sometimes rename our record field to something else.
// This bit figures out what the name is meant to be
if (empty($class) && $record instanceof BaseElement) {
$fakeData = ElementalAreaController::removeNamespacesFromFields([$fieldname => 0], $record->ID);
$fakeData = array_flip($fakeData);
$fieldname = $fakeData[0];
$class = DataObject::getSchema()->hasOneComponent(get_class($record), $fieldname);
};


$class = DataObject::getSchema()->hasOneComponent(get_class($record), $fieldname);
return $class;
}

Expand Down
6 changes: 3 additions & 3 deletions src/Form/JsonField.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public function saveInto(DataObjectInterface $record)
Controller::curr()->httpError(403);
}
$dataObject = $service->setData($dataObject, $value);
$this->validClassName($dataObject->ClassName);
$this->validClassName($dataObject->ClassName, $record);
$dataObject->write();
$record->{"{$fieldname}ID"} = $dataObject->ID;
} else {
Expand All @@ -87,7 +87,7 @@ public function saveInto(DataObjectInterface $record)
if (!$dataObject->canCreate()) {
Controller::curr()->httpError(403);
}
$this->validClassName($dataObject->ClassName);
$this->validClassName($dataObject->ClassName, $record);
$dataObject->write();
$record->{"{$fieldname}ID"} = $dataObject->ID;
} else {
Expand Down Expand Up @@ -148,5 +148,5 @@ public function InputValue(): string
*
* Should throw an exception if the class name is not valid.
*/
abstract protected function validClassName(string $className): void;
abstract protected function validClassName(string $className, ?DataObjectInterface $record): void;
}
30 changes: 17 additions & 13 deletions src/Form/ManyAnyField.php
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ public function saveInto(DataObjectInterface $record)
Controller::curr()->httpError(403);
}
$do = $service->setData($do, $data);
$this->validClassName($do->ClassName);
$this->validClassName($do->ClassName, $record);
$datalist->add($do);
$do->write();
} else {
Expand All @@ -129,7 +129,7 @@ public function saveInto(DataObjectInterface $record)
if (!$do->canCreate()) {
Controller::curr()->httpError(403);
}
$this->validClassName($do->ClassName);
$this->validClassName($do->ClassName, $record);
$datalist->add($do);
$do->write();
}
Expand All @@ -156,28 +156,32 @@ private function shiftRecordByID(array &$data, int $id): ?array
/**
* Try to guess what class we are editing
*/
private function guessBaseClass(): ?string
private function guessBaseClass(?DataObjectInterface $record = null): ?string
{
$form = $this->getForm();
if (!$form) {
return null;
}
if (empty($record)) {
$form = $this->getForm();
if (!$form) {
return null;
}

$record = $this->getForm()->getRecord();
if (!$record) {
return null;
$record = $this->getForm()->getRecord();
if (!$record) {
return null;
}
}

$fieldname = $this->getName();
$class = DataObject::getSchema()->hasManyComponent(get_class($record), $fieldname);

// The name of Elemental block fields are rename with a prefix.
if ($record instanceof BaseElement) {
// Elemental sometimes rename our record field to something else.
// This bit figures out what the name is meant to be
if (empty($class) && $record instanceof BaseElement) {
$fakeData = ElementalAreaController::removeNamespacesFromFields([$fieldname => 0], $record->ID);
$fakeData = array_flip($fakeData);
$fieldname = $fakeData[0];
$class = DataObject::getSchema()->hasManyComponent(get_class($record), $fieldname);
};

$class = DataObject::getSchema()->hasManyComponent(get_class($record), $fieldname);
return $class;
}

Expand Down

0 comments on commit b9a6c59

Please sign in to comment.