Issue #3298731 by alexpott, andypost, catch, longwave, Berdir, bbrala, Wim Leers: Using ConstraintViolation::$arrayPropertyPath bugs on PHP 8.2
(cherry picked from commit a8f48db663
)
merge-requests/2920/head
parent
eb5e3b550a
commit
f1de4134d1
|
@ -0,0 +1,133 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Drupal\Core\Field;
|
||||||
|
|
||||||
|
use Symfony\Component\Validator\ConstraintViolationInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wraps a violation to allow arrayPropertyPath to be deprecated.
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
* A BC shim for PHP 8.2.
|
||||||
|
*/
|
||||||
|
final class InternalViolation implements ConstraintViolationInterface {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The array property path.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private $arrayPropertyPath;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The violation being wrapped.
|
||||||
|
*
|
||||||
|
* @var \Symfony\Component\Validator\ConstraintViolationInterface
|
||||||
|
*/
|
||||||
|
private $violation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An array of dynamic properties.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private $properties = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a InternalViolation object.
|
||||||
|
*
|
||||||
|
* @param \Symfony\Component\Validator\ConstraintViolationInterface $violation
|
||||||
|
* The violation to wrap.
|
||||||
|
*/
|
||||||
|
public function __construct(ConstraintViolationInterface $violation) {
|
||||||
|
$this->violation = $violation;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function __get(string $name) {
|
||||||
|
if ($name === 'arrayPropertyPath') {
|
||||||
|
@trigger_error('Accessing the arrayPropertyPath property is deprecated in drupal:9.5.0 and is removed from drupal:11.0.0. Use \Symfony\Component\Validator\ConstraintViolationInterface::getPropertyPath() instead. See https://www.drupal.org/node/3307919', E_USER_DEPRECATED);
|
||||||
|
return $this->arrayPropertyPath;
|
||||||
|
}
|
||||||
|
@trigger_error('Accessing dynamic properties on violations is deprecated in drupal:9.5.0 and is removed from drupal:11.0.0. See https://www.drupal.org/node/3307919', E_USER_DEPRECATED);
|
||||||
|
return $this->properties[$name] ?? NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function __set(string $name, $value): void {
|
||||||
|
if ($name === 'arrayPropertyPath') {
|
||||||
|
$this->arrayPropertyPath = $value;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
@trigger_error('Setting dynamic properties on violations is deprecated in drupal:9.5.0 and is removed from drupal:11.0.0. See https://www.drupal.org/node/3307919', E_USER_DEPRECATED);
|
||||||
|
$this->properties[$name] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function __toString(): string {
|
||||||
|
return (string) $this->violation;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getMessage(): string|\Stringable {
|
||||||
|
return $this->violation->getMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getMessageTemplate(): string {
|
||||||
|
return $this->violation->getMessageTemplate();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getParameters(): array {
|
||||||
|
return $this->violation->getParameters();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getPlural(): ?int {
|
||||||
|
return $this->violation->getPlural();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getRoot(): mixed {
|
||||||
|
return $this->violation->getRoot();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getPropertyPath(): string {
|
||||||
|
return $this->violation->getPropertyPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getInvalidValue(): mixed {
|
||||||
|
return $this->violation->getInvalidValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getCode(): ?string {
|
||||||
|
return $this->violation->getCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -444,6 +444,7 @@ abstract class WidgetBase extends PluginSettingsBase implements WidgetInterface,
|
||||||
|
|
||||||
$violations_by_delta = $item_list_violations = [];
|
$violations_by_delta = $item_list_violations = [];
|
||||||
foreach ($violations as $violation) {
|
foreach ($violations as $violation) {
|
||||||
|
$violation = new InternalViolation($violation);
|
||||||
// Separate violations by delta.
|
// Separate violations by delta.
|
||||||
$property_path = explode('.', $violation->getPropertyPath());
|
$property_path = explode('.', $violation->getPropertyPath());
|
||||||
$delta = array_shift($property_path);
|
$delta = array_shift($property_path);
|
||||||
|
@ -454,6 +455,7 @@ abstract class WidgetBase extends PluginSettingsBase implements WidgetInterface,
|
||||||
else {
|
else {
|
||||||
$item_list_violations[] = $violation;
|
$item_list_violations[] = $violation;
|
||||||
}
|
}
|
||||||
|
// @todo Remove BC layer https://www.drupal.org/i/3307859 on PHP 8.2.
|
||||||
$violation->arrayPropertyPath = $property_path;
|
$violation->arrayPropertyPath = $property_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -470,7 +472,6 @@ abstract class WidgetBase extends PluginSettingsBase implements WidgetInterface,
|
||||||
$delta_element = $element[$original_delta];
|
$delta_element = $element[$original_delta];
|
||||||
}
|
}
|
||||||
foreach ($delta_violations as $violation) {
|
foreach ($delta_violations as $violation) {
|
||||||
// @todo: Pass $violation->arrayPropertyPath as property path.
|
|
||||||
$error_element = $this->errorElement($delta_element, $violation, $form, $form_state);
|
$error_element = $this->errorElement($delta_element, $violation, $form, $form_state);
|
||||||
if ($error_element !== FALSE) {
|
if ($error_element !== FALSE) {
|
||||||
$form_state->setError($error_element, $violation->getMessage());
|
$form_state->setError($error_element, $violation->getMessage());
|
||||||
|
|
|
@ -46,7 +46,7 @@ class TextareaWidget extends StringTextareaWidget {
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
public function errorElement(array $element, ConstraintViolationInterface $violation, array $form, FormStateInterface $form_state) {
|
public function errorElement(array $element, ConstraintViolationInterface $violation, array $form, FormStateInterface $form_state) {
|
||||||
if ($violation->arrayPropertyPath == ['format'] && isset($element['format']['#access']) && !$element['format']['#access']) {
|
if (isset($element['format']['#access']) && !$element['format']['#access'] && preg_match('/^[0-9]*\.format$/', $violation->getPropertyPath())) {
|
||||||
// Ignore validation errors for formats if formats may not be changed,
|
// Ignore validation errors for formats if formats may not be changed,
|
||||||
// such as when existing formats become invalid.
|
// such as when existing formats become invalid.
|
||||||
// See \Drupal\filter\Element\TextFormat::processFormat().
|
// See \Drupal\filter\Element\TextFormat::processFormat().
|
||||||
|
|
|
@ -100,7 +100,8 @@ class TextareaWithSummaryWidget extends TextareaWidget {
|
||||||
*/
|
*/
|
||||||
public function errorElement(array $element, ConstraintViolationInterface $violation, array $form, FormStateInterface $form_state) {
|
public function errorElement(array $element, ConstraintViolationInterface $violation, array $form, FormStateInterface $form_state) {
|
||||||
$element = parent::errorElement($element, $violation, $form, $form_state);
|
$element = parent::errorElement($element, $violation, $form, $form_state);
|
||||||
return ($element === FALSE) ? FALSE : $element[$violation->arrayPropertyPath[0]];
|
$property_path_array = explode('.', $violation->getPropertyPath());
|
||||||
|
return ($element === FALSE) ? FALSE : $element[$property_path_array[1]];
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@ class TextfieldWidget extends StringTextfieldWidget {
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
public function errorElement(array $element, ConstraintViolationInterface $violation, array $form, FormStateInterface $form_state) {
|
public function errorElement(array $element, ConstraintViolationInterface $violation, array $form, FormStateInterface $form_state) {
|
||||||
if ($violation->arrayPropertyPath == ['format'] && isset($element['format']['#access']) && !$element['format']['#access']) {
|
if (isset($element['format']['#access']) && !$element['format']['#access'] && preg_match('/^[0-9]*\.format$/', $violation->getPropertyPath())) {
|
||||||
// Ignore validation errors for formats that may not be changed,
|
// Ignore validation errors for formats that may not be changed,
|
||||||
// such as when existing formats become invalid.
|
// such as when existing formats become invalid.
|
||||||
// See \Drupal\filter\Element\TextFormat::processFormat().
|
// See \Drupal\filter\Element\TextFormat::processFormat().
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Drupal\Tests\Core\Field;
|
||||||
|
|
||||||
|
use Drupal\Core\Field\InternalViolation;
|
||||||
|
use Drupal\Tests\UnitTestCase;
|
||||||
|
use Symfony\Component\Validator\ConstraintViolationInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @coversDefaultClass \Drupal\Core\Field\InternalViolation
|
||||||
|
* @group legacy
|
||||||
|
*/
|
||||||
|
class InternalViolationTest extends UnitTestCase {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers ::__get
|
||||||
|
* @covers ::__set
|
||||||
|
*/
|
||||||
|
public function testSetGetDynamicProperties() {
|
||||||
|
$violation = new InternalViolation($this->prophesize(ConstraintViolationInterface::class)->reveal());
|
||||||
|
$this->expectDeprecation('Setting dynamic properties on violations is deprecated in drupal:9.5.0 and is removed from drupal:11.0.0. See https://www.drupal.org/node/3307919');
|
||||||
|
$this->expectDeprecation('Accessing dynamic properties on violations is deprecated in drupal:9.5.0 and is removed from drupal:11.0.0. See https://www.drupal.org/node/3307919');
|
||||||
|
$violation->foo = 'bar';
|
||||||
|
$this->assertSame('bar', $violation->foo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers ::__get
|
||||||
|
* @covers ::__set
|
||||||
|
*/
|
||||||
|
public function testSetGetArrayPropertyPath() {
|
||||||
|
$violation = new InternalViolation($this->prophesize(ConstraintViolationInterface::class)->reveal());
|
||||||
|
$this->expectDeprecation('Accessing the arrayPropertyPath property is deprecated in drupal:9.5.0 and is removed from drupal:11.0.0. Use \Symfony\Component\Validator\ConstraintViolationInterface::getPropertyPath() instead. See https://www.drupal.org/node/3307919');
|
||||||
|
$violation->arrayPropertyPath = ['bar'];
|
||||||
|
$this->assertSame(['bar'], $violation->arrayPropertyPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue