vendor/doctrine/orm/lib/Doctrine/ORM/Cache/DefaultEntityHydrator.php line 199

Open in your IDE?
  1. <?php
  2. /*
  3.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  4.  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  5.  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  6.  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  7.  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  8.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  9.  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  10.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  11.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  12.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  13.  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  14.  *
  15.  * This software consists of voluntary contributions made by many individuals
  16.  * and is licensed under the MIT license. For more information, see
  17.  * <http://www.doctrine-project.org>.
  18.  */
  19. namespace Doctrine\ORM\Cache;
  20. use Doctrine\Common\Util\ClassUtils;
  21. use Doctrine\ORM\Query;
  22. use Doctrine\ORM\Mapping\ClassMetadata;
  23. use Doctrine\ORM\EntityManagerInterface;
  24. use Doctrine\ORM\Utility\IdentifierFlattener;
  25. /**
  26.  * Default hydrator cache for entities
  27.  *
  28.  * @since   2.5
  29.  * @author  Fabio B. Silva <fabio.bat.silva@gmail.com>
  30.  */
  31. class DefaultEntityHydrator implements EntityHydrator
  32. {
  33.     /**
  34.      * @var \Doctrine\ORM\EntityManagerInterface
  35.      */
  36.     private $em;
  37.     /**
  38.      * @var \Doctrine\ORM\UnitOfWork
  39.      */
  40.     private $uow;
  41.     /**
  42.      * The IdentifierFlattener used for manipulating identifiers
  43.      *
  44.      * @var \Doctrine\ORM\Utility\IdentifierFlattener
  45.      */
  46.     private $identifierFlattener;
  47.     /**
  48.      * @var array
  49.      */
  50.     private static $hints = [Query::HINT_CACHE_ENABLED => true];
  51.     /**
  52.      * @param \Doctrine\ORM\EntityManagerInterface $em The entity manager.
  53.      */
  54.     public function __construct(EntityManagerInterface $em)
  55.     {
  56.         $this->em   $em;
  57.         $this->uow  $em->getUnitOfWork();
  58.         $this->identifierFlattener = new IdentifierFlattener($em->getUnitOfWork(), $em->getMetadataFactory());
  59.     }
  60.     /**
  61.      * {@inheritdoc}
  62.      */
  63.     public function buildCacheEntry(ClassMetadata $metadataEntityCacheKey $key$entity)
  64.     {
  65.         $data $this->uow->getOriginalEntityData($entity);
  66.         $data array_merge($data$metadata->getIdentifierValues($entity)); // why update has no identifier values ?
  67.         if ($metadata->isVersioned) {
  68.             $data[$metadata->versionField] = $metadata->getFieldValue($entity$metadata->versionField);
  69.         }
  70.         foreach ($metadata->associationMappings as $name => $assoc) {
  71.             if ( ! isset($data[$name])) {
  72.                 continue;
  73.             }
  74.             if ( ! ($assoc['type'] & ClassMetadata::TO_ONE)) {
  75.                 unset($data[$name]);
  76.                 continue;
  77.             }
  78.             if ( ! isset($assoc['cache'])) {
  79.                 $targetClassMetadata $this->em->getClassMetadata($assoc['targetEntity']);
  80.                 $owningAssociation   = ( ! $assoc['isOwningSide'])
  81.                     ? $targetClassMetadata->associationMappings[$assoc['mappedBy']]
  82.                     : $assoc;
  83.                 $associationIds      $this->identifierFlattener->flattenIdentifier(
  84.                     $targetClassMetadata,
  85.                     $targetClassMetadata->getIdentifierValues($data[$name])
  86.                 );
  87.                 unset($data[$name]);
  88.                 foreach ($associationIds as $fieldName => $fieldValue) {
  89.                     if (isset($targetClassMetadata->fieldMappings[$fieldName])) {
  90.                         $fieldMapping $targetClassMetadata->fieldMappings[$fieldName];
  91.                         $data[$owningAssociation['targetToSourceKeyColumns'][$fieldMapping['columnName']]] = $fieldValue;
  92.                         continue;
  93.                     }
  94.                     $targetAssoc $targetClassMetadata->associationMappings[$fieldName];
  95.                     foreach($assoc['targetToSourceKeyColumns'] as $referencedColumn => $localColumn) {
  96.                         if (isset($targetAssoc['sourceToTargetKeyColumns'][$referencedColumn])) {
  97.                             $data[$localColumn] = $fieldValue;
  98.                         }
  99.                     }
  100.                 }
  101.                 continue;
  102.             }
  103.             if ( ! isset($assoc['id'])) {
  104.                 $targetClass ClassUtils::getClass($data[$name]);
  105.                 $targetId    $this->uow->getEntityIdentifier($data[$name]);
  106.                 $data[$name] = new AssociationCacheEntry($targetClass$targetId);
  107.                 continue;
  108.             }
  109.             // handle association identifier
  110.             $targetId is_object($data[$name]) && $this->uow->isInIdentityMap($data[$name])
  111.                 ? $this->uow->getEntityIdentifier($data[$name])
  112.                 : $data[$name];
  113.             // @TODO - fix it !
  114.             // handle UnitOfWork#createEntity hash generation
  115.             if ( ! is_array($targetId)) {
  116.                 $data[reset($assoc['joinColumnFieldNames'])] = $targetId;
  117.                 $targetEntity $this->em->getClassMetadata($assoc['targetEntity']);
  118.                 $targetId     = [$targetEntity->identifier[0] => $targetId];
  119.             }
  120.             $data[$name] = new AssociationCacheEntry($assoc['targetEntity'], $targetId);
  121.         }
  122.         return new EntityCacheEntry($metadata->name$data);
  123.     }
  124.     /**
  125.      * {@inheritdoc}
  126.      */
  127.     public function loadCacheEntry(ClassMetadata $metadataEntityCacheKey $keyEntityCacheEntry $entry$entity null)
  128.     {
  129.         $data  $entry->data;
  130.         $hints self::$hints;
  131.         if ($entity !== null) {
  132.             $hints[Query::HINT_REFRESH]         = true;
  133.             $hints[Query::HINT_REFRESH_ENTITY]  = $entity;
  134.         }
  135.         foreach ($metadata->associationMappings as $name => $assoc) {
  136.             if ( ! isset($assoc['cache']) ||  ! isset($data[$name])) {
  137.                 continue;
  138.             }
  139.             $assocClass     $data[$name]->class;
  140.             $assocId        $data[$name]->identifier;
  141.             $isEagerLoad    = ($assoc['fetch'] === ClassMetadata::FETCH_EAGER || ($assoc['type'] === ClassMetadata::ONE_TO_ONE && ! $assoc['isOwningSide']));
  142.             if ( ! $isEagerLoad) {
  143.                 $data[$name] = $this->em->getReference($assocClass$assocId);
  144.                 continue;
  145.             }
  146.             $assocMetadata  $this->em->getClassMetadata($assoc['targetEntity']);
  147.             $assocKey       = new EntityCacheKey($assocMetadata->rootEntityName$assocId);
  148.             $assocPersister $this->uow->getEntityPersister($assoc['targetEntity']);
  149.             $assocRegion    $assocPersister->getCacheRegion();
  150.             $assocEntry     $assocRegion->get($assocKey);
  151.             if ($assocEntry === null) {
  152.                 return null;
  153.             }
  154.             $data[$name] = $this->uow->createEntity($assocEntry->class$assocEntry->resolveAssociationEntries($this->em), $hints);
  155.         }
  156.         if ($entity !== null) {
  157.             $this->uow->registerManaged($entity$key->identifier$data);
  158.         }
  159.         $result $this->uow->createEntity($entry->class$data$hints);
  160.         $this->uow->hydrationComplete();
  161.         return $result;
  162.     }
  163. }