vendor/symfony/form/Extension/Core/DataAccessor/PropertyPathAccessor.php line 54

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of the Symfony package.
  4.  *
  5.  * (c) Fabien Potencier <fabien@symfony.com>
  6.  *
  7.  * For the full copyright and license information, please view the LICENSE
  8.  * file that was distributed with this source code.
  9.  */
  10. namespace Symfony\Component\Form\Extension\Core\DataAccessor;
  11. use Symfony\Component\Form\DataAccessorInterface;
  12. use Symfony\Component\Form\Exception\AccessException;
  13. use Symfony\Component\Form\FormInterface;
  14. use Symfony\Component\PropertyAccess\Exception\AccessException as PropertyAccessException;
  15. use Symfony\Component\PropertyAccess\Exception\NoSuchIndexException;
  16. use Symfony\Component\PropertyAccess\Exception\UninitializedPropertyException;
  17. use Symfony\Component\PropertyAccess\PropertyAccess;
  18. use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
  19. use Symfony\Component\PropertyAccess\PropertyPathInterface;
  20. /**
  21.  * Writes and reads values to/from an object or array using property path.
  22.  *
  23.  * @author Yonel Ceruto <yonelceruto@gmail.com>
  24.  * @author Bernhard Schussek <bschussek@gmail.com>
  25.  */
  26. class PropertyPathAccessor implements DataAccessorInterface
  27. {
  28.     private PropertyAccessorInterface $propertyAccessor;
  29.     public function __construct(PropertyAccessorInterface $propertyAccessor null)
  30.     {
  31.         $this->propertyAccessor $propertyAccessor ?? PropertyAccess::createPropertyAccessor();
  32.     }
  33.     /**
  34.      * {@inheritdoc}
  35.      */
  36.     public function getValue(object|array $dataFormInterface $form): mixed
  37.     {
  38.         if (null === $propertyPath $form->getPropertyPath()) {
  39.             throw new AccessException('Unable to read from the given form data as no property path is defined.');
  40.         }
  41.         return $this->getPropertyValue($data$propertyPath);
  42.     }
  43.     /**
  44.      * {@inheritdoc}
  45.      */
  46.     public function setValue(object|array &$datamixed $valueFormInterface $form): void
  47.     {
  48.         if (null === $propertyPath $form->getPropertyPath()) {
  49.             throw new AccessException('Unable to write the given value as no property path is defined.');
  50.         }
  51.         // If the field is of type DateTimeInterface and the data is the same skip the update to
  52.         // keep the original object hash
  53.         if ($value instanceof \DateTimeInterface && $value == $this->getPropertyValue($data$propertyPath)) {
  54.             return;
  55.         }
  56.         // If the data is identical to the value in $data, we are
  57.         // dealing with a reference
  58.         if (!\is_object($data) || !$form->getConfig()->getByReference() || $value !== $this->getPropertyValue($data$propertyPath)) {
  59.             $this->propertyAccessor->setValue($data$propertyPath$value);
  60.         }
  61.     }
  62.     /**
  63.      * {@inheritdoc}
  64.      */
  65.     public function isReadable(object|array $dataFormInterface $form): bool
  66.     {
  67.         return null !== $form->getPropertyPath();
  68.     }
  69.     /**
  70.      * {@inheritdoc}
  71.      */
  72.     public function isWritable(object|array $dataFormInterface $form): bool
  73.     {
  74.         return null !== $form->getPropertyPath();
  75.     }
  76.     private function getPropertyValue(object|array $dataPropertyPathInterface $propertyPath)
  77.     {
  78.         try {
  79.             return $this->propertyAccessor->getValue($data$propertyPath);
  80.         } catch (PropertyAccessException $e) {
  81.             if (\is_array($data) && $e instanceof NoSuchIndexException) {
  82.                 return null;
  83.             }
  84.             if (!$e instanceof UninitializedPropertyException
  85.                 // For versions without UninitializedPropertyException check the exception message
  86.                 && (class_exists(UninitializedPropertyException::class) || !str_contains($e->getMessage(), 'You should initialize it'))
  87.             ) {
  88.                 throw $e;
  89.             }
  90.             return null;
  91.         }
  92.     }
  93. }