vendor/doctrine/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php
author ymh <ymh.work@gmail.com>
Sat, 24 Sep 2011 15:40:41 +0200
changeset 0 7f95f8617b0b
permissions -rwxr-xr-x
first commit
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     1
<?php
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     2
/*
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     3
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     4
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     5
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     6
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     7
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     8
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     9
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    10
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    11
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    12
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    13
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    14
 *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    15
 * This software consists of voluntary contributions made by many individuals
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    16
 * and is licensed under the LGPL. For more information, see
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    17
 * <http://www.doctrine-project.org>.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    18
 */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    19
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    20
namespace Doctrine\ORM\Internal\Hydration;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    21
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    22
use PDO,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    23
    Doctrine\ORM\Mapping\ClassMetadata,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    24
    Doctrine\ORM\PersistentCollection,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    25
    Doctrine\ORM\Query,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    26
    Doctrine\Common\Collections\ArrayCollection,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    27
    Doctrine\Common\Collections\Collection;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    28
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    29
/**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    30
 * The ObjectHydrator constructs an object graph out of an SQL result set.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    31
 *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    32
 * @author Roman Borschel <roman@code-factory.org>
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    33
 * @since 2.0
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    34
 * @internal Highly performance-sensitive code.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    35
 */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    36
class ObjectHydrator extends AbstractHydrator
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    37
{
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    38
    /* Local ClassMetadata cache to avoid going to the EntityManager all the time.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    39
     * This local cache is maintained between hydration runs and not cleared.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    40
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    41
    private $_ce = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    42
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    43
    /* The following parts are reinitialized on every hydration run. */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    44
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    45
    private $_identifierMap;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    46
    private $_resultPointers;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    47
    private $_idTemplate;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    48
    private $_resultCounter;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    49
    private $_rootAliases = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    50
    private $_initializedCollections = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    51
    private $_existingCollections = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    52
    //private $_createdEntities;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    53
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    54
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    55
    /** @override */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    56
    protected function _prepare()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    57
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    58
        $this->_identifierMap =
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    59
        $this->_resultPointers =
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    60
        $this->_idTemplate = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    61
        $this->_resultCounter = 0;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    62
        if (!isset($this->_hints['deferEagerLoad'])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    63
            $this->_hints['deferEagerLoad'] = true;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    64
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    65
        
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    66
        foreach ($this->_rsm->aliasMap as $dqlAlias => $className) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    67
            $this->_identifierMap[$dqlAlias] = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    68
            $this->_idTemplate[$dqlAlias] = '';
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    69
            $class = $this->_em->getClassMetadata($className);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    70
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    71
            if ( ! isset($this->_ce[$className])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    72
                $this->_ce[$className] = $class;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    73
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    74
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    75
            // Remember which associations are "fetch joined", so that we know where to inject
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    76
            // collection stubs or proxies and where not.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    77
            if (isset($this->_rsm->relationMap[$dqlAlias])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    78
                if ( ! isset($this->_rsm->aliasMap[$this->_rsm->parentAliasMap[$dqlAlias]])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    79
                    throw HydrationException::parentObjectOfRelationNotFound($dqlAlias, $this->_rsm->parentAliasMap[$dqlAlias]);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    80
                }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    81
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    82
                $sourceClassName = $this->_rsm->aliasMap[$this->_rsm->parentAliasMap[$dqlAlias]];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    83
                $sourceClass = $this->_getClassMetadata($sourceClassName);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    84
                $assoc = $sourceClass->associationMappings[$this->_rsm->relationMap[$dqlAlias]];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    85
                $this->_hints['fetched'][$sourceClassName][$assoc['fieldName']] = true;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    86
                if ($sourceClass->subClasses) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    87
                    foreach ($sourceClass->subClasses as $sourceSubclassName) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    88
                        $this->_hints['fetched'][$sourceSubclassName][$assoc['fieldName']] = true;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    89
                    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    90
                }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    91
                if ($assoc['type'] != ClassMetadata::MANY_TO_MANY) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    92
                    // Mark any non-collection opposite sides as fetched, too.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    93
                    if ($assoc['mappedBy']) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    94
                        $this->_hints['fetched'][$className][$assoc['mappedBy']] = true;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    95
                    } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    96
                        if ($assoc['inversedBy']) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    97
                            $inverseAssoc = $class->associationMappings[$assoc['inversedBy']];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    98
                            if ($inverseAssoc['type'] & ClassMetadata::TO_ONE) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    99
                                $this->_hints['fetched'][$className][$inverseAssoc['fieldName']] = true;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   100
                                if ($class->subClasses) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   101
                                    foreach ($class->subClasses as $targetSubclassName) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   102
                                        $this->_hints['fetched'][$targetSubclassName][$inverseAssoc['fieldName']] = true;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   103
                                    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   104
                                }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   105
                            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   106
                        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   107
                    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   108
                }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   109
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   110
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   111
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   112
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   113
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   114
     * {@inheritdoc}
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   115
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   116
    protected function _cleanup()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   117
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   118
        $eagerLoad = (isset($this->_hints['deferEagerLoad'])) && $this->_hints['deferEagerLoad'] == true;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   119
        
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   120
        parent::_cleanup();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   121
        $this->_identifierMap =
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   122
        $this->_initializedCollections =
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   123
        $this->_existingCollections =
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   124
        $this->_resultPointers = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   125
        
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   126
        if ($eagerLoad) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   127
            $this->_em->getUnitOfWork()->triggerEagerLoads();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   128
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   129
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   130
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   131
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   132
     * {@inheritdoc}
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   133
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   134
    protected function _hydrateAll()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   135
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   136
        $result = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   137
        $cache = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   138
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   139
        while ($row = $this->_stmt->fetch(PDO::FETCH_ASSOC)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   140
            $this->_hydrateRow($row, $cache, $result);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   141
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   142
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   143
        // Take snapshots from all newly initialized collections
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   144
        foreach ($this->_initializedCollections as $coll) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   145
            $coll->takeSnapshot();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   146
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   147
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   148
        return $result;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   149
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   150
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   151
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   152
     * Initializes a related collection.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   153
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   154
     * @param object $entity The entity to which the collection belongs.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   155
     * @param string $name The name of the field on the entity that holds the collection.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   156
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   157
    private function _initRelatedCollection($entity, $class, $fieldName)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   158
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   159
        $oid = spl_object_hash($entity);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   160
        $relation = $class->associationMappings[$fieldName];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   161
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   162
        $value = $class->reflFields[$fieldName]->getValue($entity);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   163
        if ($value === null) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   164
            $value = new ArrayCollection;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   165
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   166
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   167
        if ( ! $value instanceof PersistentCollection) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   168
            $value = new PersistentCollection(
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   169
                $this->_em,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   170
                $this->_ce[$relation['targetEntity']],
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   171
                $value
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   172
            );
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   173
            $value->setOwner($entity, $relation);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   174
            $class->reflFields[$fieldName]->setValue($entity, $value);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   175
            $this->_uow->setOriginalEntityProperty($oid, $fieldName, $value);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   176
            $this->_initializedCollections[$oid . $fieldName] = $value;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   177
        } else if (isset($this->_hints[Query::HINT_REFRESH]) ||
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   178
                isset($this->_hints['fetched'][$class->name][$fieldName]) &&
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   179
                ! $value->isInitialized()) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   180
            // Is already PersistentCollection, but either REFRESH or FETCH-JOIN and UNINITIALIZED!
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   181
            $value->setDirty(false);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   182
            $value->setInitialized(true);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   183
            $value->unwrap()->clear();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   184
            $this->_initializedCollections[$oid . $fieldName] = $value;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   185
        } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   186
            // Is already PersistentCollection, and DON'T REFRESH or FETCH-JOIN!
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   187
            $this->_existingCollections[$oid . $fieldName] = $value;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   188
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   189
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   190
        return $value;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   191
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   192
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   193
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   194
     * Gets an entity instance.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   195
     * 
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   196
     * @param $data The instance data.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   197
     * @param $dqlAlias The DQL alias of the entity's class.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   198
     * @return object The entity.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   199
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   200
    private function _getEntity(array $data, $dqlAlias)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   201
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   202
        $className = $this->_rsm->aliasMap[$dqlAlias];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   203
        if (isset($this->_rsm->discriminatorColumns[$dqlAlias])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   204
            $discrColumn = $this->_rsm->metaMappings[$this->_rsm->discriminatorColumns[$dqlAlias]];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   205
            $className = $this->_ce[$className]->discriminatorMap[$data[$discrColumn]];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   206
            unset($data[$discrColumn]);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   207
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   208
        
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   209
        if (isset($this->_hints[Query::HINT_REFRESH_ENTITY]) && isset($this->_rootAliases[$dqlAlias])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   210
            $class = $this->_ce[$className];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   211
            $this->registerManaged($class, $this->_hints[Query::HINT_REFRESH_ENTITY], $data);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   212
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   213
        
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   214
        return $this->_uow->createEntity($className, $data, $this->_hints);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   215
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   216
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   217
    private function _getEntityFromIdentityMap($className, array $data)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   218
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   219
        // TODO: Abstract this code and UnitOfWork::createEntity() equivalent?
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   220
        $class = $this->_ce[$className];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   221
        /* @var $class ClassMetadata */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   222
        if ($class->isIdentifierComposite) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   223
            $idHash = '';
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   224
            foreach ($class->identifier as $fieldName) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   225
                if (isset($class->associationMappings[$fieldName])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   226
                    $idHash .= $data[$class->associationMappings[$fieldName]['joinColumns'][0]['name']] . ' ';
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   227
                } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   228
                    $idHash .= $data[$fieldName] . ' ';
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   229
                }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   230
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   231
            return $this->_uow->tryGetByIdHash(rtrim($idHash), $class->rootEntityName);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   232
        } else if (isset($class->associationMappings[$class->identifier[0]])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   233
            return $this->_uow->tryGetByIdHash($data[$class->associationMappings[$class->identifier[0]]['joinColumns'][0]['name']], $class->rootEntityName);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   234
        } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   235
            return $this->_uow->tryGetByIdHash($data[$class->identifier[0]], $class->rootEntityName);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   236
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   237
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   238
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   239
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   240
     * Gets a ClassMetadata instance from the local cache.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   241
     * If the instance is not yet in the local cache, it is loaded into the
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   242
     * local cache.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   243
     * 
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   244
     * @param string $className The name of the class.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   245
     * @return ClassMetadata
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   246
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   247
    private function _getClassMetadata($className)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   248
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   249
        if ( ! isset($this->_ce[$className])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   250
            $this->_ce[$className] = $this->_em->getClassMetadata($className);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   251
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   252
        return $this->_ce[$className];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   253
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   254
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   255
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   256
     * Hydrates a single row in an SQL result set.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   257
     * 
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   258
     * @internal
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   259
     * First, the data of the row is split into chunks where each chunk contains data
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   260
     * that belongs to a particular component/class. Afterwards, all these chunks
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   261
     * are processed, one after the other. For each chunk of class data only one of the
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   262
     * following code paths is executed:
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   263
     * 
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   264
     * Path A: The data chunk belongs to a joined/associated object and the association
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   265
     *         is collection-valued.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   266
     * Path B: The data chunk belongs to a joined/associated object and the association
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   267
     *         is single-valued.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   268
     * Path C: The data chunk belongs to a root result element/object that appears in the topmost
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   269
     *         level of the hydrated result. A typical example are the objects of the type
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   270
     *         specified by the FROM clause in a DQL query. 
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   271
     * 
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   272
     * @param array $data The data of the row to process.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   273
     * @param array $cache The cache to use.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   274
     * @param array $result The result array to fill.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   275
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   276
    protected function _hydrateRow(array $data, array &$cache, array &$result)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   277
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   278
        // Initialize
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   279
        $id = $this->_idTemplate; // initialize the id-memory
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   280
        $nonemptyComponents = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   281
        // Split the row data into chunks of class data.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   282
        $rowData = $this->_gatherRowData($data, $cache, $id, $nonemptyComponents);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   283
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   284
        // Extract scalar values. They're appended at the end.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   285
        if (isset($rowData['scalars'])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   286
            $scalars = $rowData['scalars'];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   287
            unset($rowData['scalars']);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   288
            if (empty($rowData)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   289
                ++$this->_resultCounter;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   290
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   291
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   292
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   293
        // Hydrate the data chunks
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   294
        foreach ($rowData as $dqlAlias => $data) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   295
            $entityName = $this->_rsm->aliasMap[$dqlAlias];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   296
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   297
            if (isset($this->_rsm->parentAliasMap[$dqlAlias])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   298
                // It's a joined result
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   299
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   300
                $parentAlias = $this->_rsm->parentAliasMap[$dqlAlias];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   301
                // we need the $path to save into the identifier map which entities were already
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   302
                // seen for this parent-child relationship
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   303
                $path = $parentAlias . '.' . $dqlAlias;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   304
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   305
                // Get a reference to the parent object to which the joined element belongs.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   306
                if ($this->_rsm->isMixed && isset($this->_rootAliases[$parentAlias])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   307
                    $first = reset($this->_resultPointers);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   308
                    $parentObject = $this->_resultPointers[$parentAlias][key($first)];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   309
                } else if (isset($this->_resultPointers[$parentAlias])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   310
                    $parentObject = $this->_resultPointers[$parentAlias];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   311
                } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   312
                    // Parent object of relation not found, so skip it.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   313
                    continue;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   314
                }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   315
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   316
                $parentClass = $this->_ce[$this->_rsm->aliasMap[$parentAlias]];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   317
                $oid = spl_object_hash($parentObject);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   318
                $relationField = $this->_rsm->relationMap[$dqlAlias];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   319
                $relation = $parentClass->associationMappings[$relationField];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   320
                $reflField = $parentClass->reflFields[$relationField];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   321
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   322
                // Check the type of the relation (many or single-valued)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   323
                if ( ! ($relation['type'] & ClassMetadata::TO_ONE)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   324
                    // PATH A: Collection-valued association
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   325
                    if (isset($nonemptyComponents[$dqlAlias])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   326
                        $collKey = $oid . $relationField;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   327
                        if (isset($this->_initializedCollections[$collKey])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   328
                            $reflFieldValue = $this->_initializedCollections[$collKey];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   329
                        } else if ( ! isset($this->_existingCollections[$collKey])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   330
                            $reflFieldValue = $this->_initRelatedCollection($parentObject, $parentClass, $relationField);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   331
                        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   332
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   333
                        $indexExists = isset($this->_identifierMap[$path][$id[$parentAlias]][$id[$dqlAlias]]);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   334
                        $index = $indexExists ? $this->_identifierMap[$path][$id[$parentAlias]][$id[$dqlAlias]] : false;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   335
                        $indexIsValid = $index !== false ? isset($reflFieldValue[$index]) : false;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   336
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   337
                        if ( ! $indexExists || ! $indexIsValid) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   338
                            if (isset($this->_existingCollections[$collKey])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   339
                                // Collection exists, only look for the element in the identity map.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   340
                                if ($element = $this->_getEntityFromIdentityMap($entityName, $data)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   341
                                    $this->_resultPointers[$dqlAlias] = $element;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   342
                                } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   343
                                    unset($this->_resultPointers[$dqlAlias]);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   344
                                }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   345
                            } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   346
                                $element = $this->_getEntity($data, $dqlAlias);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   347
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   348
                                if (isset($this->_rsm->indexByMap[$dqlAlias])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   349
                                    $field = $this->_rsm->indexByMap[$dqlAlias];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   350
                                    $indexValue = $this->_ce[$entityName]->reflFields[$field]->getValue($element);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   351
                                    $reflFieldValue->hydrateSet($indexValue, $element);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   352
                                    $this->_identifierMap[$path][$id[$parentAlias]][$id[$dqlAlias]] = $indexValue;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   353
                                } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   354
                                    $reflFieldValue->hydrateAdd($element);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   355
                                    $reflFieldValue->last();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   356
                                    $this->_identifierMap[$path][$id[$parentAlias]][$id[$dqlAlias]] = $reflFieldValue->key();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   357
                                }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   358
                                // Update result pointer
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   359
                                $this->_resultPointers[$dqlAlias] = $element;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   360
                            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   361
                        } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   362
                            // Update result pointer
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   363
                            $this->_resultPointers[$dqlAlias] = $reflFieldValue[$index];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   364
                        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   365
                    } else if ( ! $reflField->getValue($parentObject)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   366
                        $coll = new PersistentCollection($this->_em, $this->_ce[$entityName], new ArrayCollection);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   367
                        $coll->setOwner($parentObject, $relation);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   368
                        $reflField->setValue($parentObject, $coll);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   369
                        $this->_uow->setOriginalEntityProperty($oid, $relationField, $coll);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   370
                    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   371
                } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   372
                    // PATH B: Single-valued association
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   373
                    $reflFieldValue = $reflField->getValue($parentObject);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   374
                    if ( ! $reflFieldValue || isset($this->_hints[Query::HINT_REFRESH])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   375
                        if (isset($nonemptyComponents[$dqlAlias])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   376
                            $element = $this->_getEntity($data, $dqlAlias);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   377
                            $reflField->setValue($parentObject, $element);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   378
                            $this->_uow->setOriginalEntityProperty($oid, $relationField, $element);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   379
                            $targetClass = $this->_ce[$relation['targetEntity']];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   380
                            if ($relation['isOwningSide']) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   381
                                //TODO: Just check hints['fetched'] here?
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   382
                                // If there is an inverse mapping on the target class its bidirectional
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   383
                                if ($relation['inversedBy']) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   384
                                    $inverseAssoc = $targetClass->associationMappings[$relation['inversedBy']];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   385
                                    if ($inverseAssoc['type'] & ClassMetadata::TO_ONE) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   386
                                        $targetClass->reflFields[$inverseAssoc['fieldName']]->setValue($element, $parentObject);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   387
                                        $this->_uow->setOriginalEntityProperty(spl_object_hash($element), $inverseAssoc['fieldName'], $parentObject);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   388
                                    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   389
                                } else if ($parentClass === $targetClass && $relation['mappedBy']) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   390
                                    // Special case: bi-directional self-referencing one-one on the same class
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   391
                                    $targetClass->reflFields[$relationField]->setValue($element, $parentObject);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   392
                                }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   393
                            } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   394
                                // For sure bidirectional, as there is no inverse side in unidirectional mappings
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   395
                                $targetClass->reflFields[$relation['mappedBy']]->setValue($element, $parentObject);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   396
                                $this->_uow->setOriginalEntityProperty(spl_object_hash($element), $relation['mappedBy'], $parentObject);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   397
                            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   398
                            // Update result pointer
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   399
                            $this->_resultPointers[$dqlAlias] = $element;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   400
                        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   401
                        // else leave $reflFieldValue null for single-valued associations
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   402
                    } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   403
                        // Update result pointer
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   404
                        $this->_resultPointers[$dqlAlias] = $reflFieldValue;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   405
                    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   406
                }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   407
            } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   408
                // PATH C: Its a root result element
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   409
                $this->_rootAliases[$dqlAlias] = true; // Mark as root alias
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   410
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   411
                if ( ! isset($this->_identifierMap[$dqlAlias][$id[$dqlAlias]])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   412
                    $element = $this->_getEntity($rowData[$dqlAlias], $dqlAlias);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   413
                    if (isset($this->_rsm->indexByMap[$dqlAlias])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   414
                        $field = $this->_rsm->indexByMap[$dqlAlias];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   415
                        $key = $this->_ce[$entityName]->reflFields[$field]->getValue($element);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   416
                        if ($this->_rsm->isMixed) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   417
                            $element = array($key => $element);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   418
                            $result[] = $element;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   419
                            $this->_identifierMap[$dqlAlias][$id[$dqlAlias]] = $this->_resultCounter;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   420
                            ++$this->_resultCounter;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   421
                        } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   422
                            $result[$key] = $element;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   423
                            $this->_identifierMap[$dqlAlias][$id[$dqlAlias]] = $key;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   424
                        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   425
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   426
                        if (isset($this->_hints['collection'])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   427
                            $this->_hints['collection']->hydrateSet($key, $element);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   428
                        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   429
                    } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   430
                        if ($this->_rsm->isMixed) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   431
                            $element = array(0 => $element);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   432
                        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   433
                        $result[] = $element;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   434
                        $this->_identifierMap[$dqlAlias][$id[$dqlAlias]] = $this->_resultCounter;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   435
                        ++$this->_resultCounter;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   436
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   437
                        if (isset($this->_hints['collection'])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   438
                            $this->_hints['collection']->hydrateAdd($element);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   439
                        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   440
                    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   441
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   442
                    // Update result pointer
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   443
                    $this->_resultPointers[$dqlAlias] = $element;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   444
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   445
                } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   446
                    // Update result pointer
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   447
                    $index = $this->_identifierMap[$dqlAlias][$id[$dqlAlias]];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   448
                    $this->_resultPointers[$dqlAlias] = $result[$index];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   449
                    /*if ($this->_rsm->isMixed) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   450
                        $result[] = $result[$index];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   451
                        ++$this->_resultCounter;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   452
                    }*/
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   453
                }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   454
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   455
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   456
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   457
        // Append scalar values to mixed result sets
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   458
        if (isset($scalars)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   459
            foreach ($scalars as $name => $value) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   460
                $result[$this->_resultCounter - 1][$name] = $value;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   461
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   462
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   463
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   464
}