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

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of the Symfony package.
  4.  *
  5.  * (c) Fabien Potencier <[email protected]>
  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\DataMapperInterface;
  13. use Symfony\Component\Form\Exception\AccessException;
  14. use Symfony\Component\Form\Extension\Core\DataMapper\DataMapper;
  15. use Symfony\Component\Form\FormInterface;
  16. use Symfony\Component\PropertyAccess\Exception\AccessException as PropertyAccessException;
  17. use Symfony\Component\PropertyAccess\Exception\NoSuchIndexException;
  18. use Symfony\Component\PropertyAccess\Exception\UninitializedPropertyException;
  19. use Symfony\Component\PropertyAccess\PropertyAccess;
  20. use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
  21. use Symfony\Component\PropertyAccess\PropertyPathInterface;
  22. /**
  23.  * Writes and reads values to/from an object or array using property path.
  24.  *
  25.  * @author Yonel Ceruto <[email protected]>
  26.  * @author Bernhard Schussek <[email protected]>
  27.  */
  28. class PropertyPathAccessor implements DataAccessorInterface
  29. {
  30.     private $propertyAccessor;
  31.     public function __construct(?PropertyAccessorInterface $propertyAccessor null)
  32.     {
  33.         $this->propertyAccessor $propertyAccessor ?? PropertyAccess::createPropertyAccessor();
  34.     }
  35.     /**
  36.      * {@inheritdoc}
  37.      */
  38.     public function getValue($dataFormInterface $form)
  39.     {
  40.         if (null === $propertyPath $form->getPropertyPath()) {
  41.             throw new AccessException('Unable to read from the given form data as no property path is defined.');
  42.         }
  43.         return $this->getPropertyValue($data$propertyPath);
  44.     }
  45.     /**
  46.      * {@inheritdoc}
  47.      */
  48.     public function setValue(&$data$propertyValueFormInterface $form): void
  49.     {
  50.         if (null === $propertyPath $form->getPropertyPath()) {
  51.             throw new AccessException('Unable to write the given value as no property path is defined.');
  52.         }
  53.         $getValue = function () use ($data$form$propertyPath) {
  54.             $dataMapper $this->getDataMapper($form);
  55.             if ($dataMapper instanceof DataMapper && null !== $dataAccessor $dataMapper->getDataAccessor()) {
  56.                 return $dataAccessor->getValue($data$form);
  57.             }
  58.             return $this->getPropertyValue($data$propertyPath);
  59.         };
  60.         // If the field is of type DateTimeInterface and the data is the same skip the update to
  61.         // keep the original object hash
  62.         if ($propertyValue instanceof \DateTimeInterface && $propertyValue == $getValue()) {
  63.             return;
  64.         }
  65.         // If the data is identical to the value in $data, we are
  66.         // dealing with a reference
  67.         if (!\is_object($data) || !$form->getConfig()->getByReference() || $propertyValue !== $getValue()) {
  68.             $this->propertyAccessor->setValue($data$propertyPath$propertyValue);
  69.         }
  70.     }
  71.     /**
  72.      * {@inheritdoc}
  73.      */
  74.     public function isReadable($dataFormInterface $form): bool
  75.     {
  76.         return null !== $form->getPropertyPath();
  77.     }
  78.     /**
  79.      * {@inheritdoc}
  80.      */
  81.     public function isWritable($dataFormInterface $form): bool
  82.     {
  83.         return null !== $form->getPropertyPath();
  84.     }
  85.     private function getPropertyValue($dataPropertyPathInterface $propertyPath)
  86.     {
  87.         try {
  88.             return $this->propertyAccessor->getValue($data$propertyPath);
  89.         } catch (PropertyAccessException $e) {
  90.             if (\is_array($data) && $e instanceof NoSuchIndexException) {
  91.                 return null;
  92.             }
  93.             if (!$e instanceof UninitializedPropertyException
  94.                 // For versions without UninitializedPropertyException check the exception message
  95.                 && (class_exists(UninitializedPropertyException::class) || false === strpos($e->getMessage(), 'You should initialize it'))
  96.             ) {
  97.                 throw $e;
  98.             }
  99.             return null;
  100.         }
  101.     }
  102.     private function getDataMapper(FormInterface $form): ?DataMapperInterface
  103.     {
  104.         do {
  105.             $dataMapper $form->getConfig()->getDataMapper();
  106.         } while (null === $dataMapper && null !== $form $form->getParent());
  107.         return $dataMapper;
  108.     }
  109. }