![]() Server : Apache System : Linux server2.corals.io 4.18.0-348.2.1.el8_5.x86_64 #1 SMP Mon Nov 15 09:17:08 EST 2021 x86_64 User : corals ( 1002) PHP Version : 7.4.33 Disable Function : exec,passthru,shell_exec,system Directory : /home/corals/mautic.corals.io/vendor/doctrine/orm/src/Internal/Hydration/ |
<?php declare(strict_types=1); namespace Doctrine\ORM\Internal\Hydration; use Doctrine\ORM\Mapping\ClassMetadata; use function count; use function end; use function is_array; use function key; use function reset; /** * The ArrayHydrator produces a nested array "graph" that is often (not always) * interchangeable with the corresponding object graph for read-only access. */ class ArrayHydrator extends AbstractHydrator { /** @var array<string,bool> */ private $rootAliases = []; /** @var bool */ private $isSimpleQuery = false; /** @var mixed[] */ private $identifierMap = []; /** @var mixed[] */ private $resultPointers = []; /** @var array<string,string> */ private $idTemplate = []; /** @var int */ private $resultCounter = 0; /** * {@inheritDoc} */ protected function prepare() { $this->isSimpleQuery = count($this->resultSetMapping()->aliasMap) <= 1; foreach ($this->resultSetMapping()->aliasMap as $dqlAlias => $className) { $this->identifierMap[$dqlAlias] = []; $this->resultPointers[$dqlAlias] = []; $this->idTemplate[$dqlAlias] = ''; } } /** * {@inheritDoc} */ protected function hydrateAllData() { $result = []; while ($data = $this->statement()->fetchAssociative()) { $this->hydrateRowData($data, $result); } return $result; } /** * {@inheritDoc} */ protected function hydrateRowData(array $row, array &$result) { // 1) Initialize $id = $this->idTemplate; // initialize the id-memory $nonemptyComponents = []; $rowData = $this->gatherRowData($row, $id, $nonemptyComponents); // 2) Now hydrate the data found in the current row. foreach ($rowData['data'] as $dqlAlias => $data) { $index = false; if (isset($this->resultSetMapping()->parentAliasMap[$dqlAlias])) { // It's a joined result $parent = $this->resultSetMapping()->parentAliasMap[$dqlAlias]; $path = $parent . '.' . $dqlAlias; // missing parent data, skipping as RIGHT JOIN hydration is not supported. if (! isset($nonemptyComponents[$parent])) { continue; } // Get a reference to the right element in the result tree. // This element will get the associated element attached. if ($this->resultSetMapping()->isMixed && isset($this->rootAliases[$parent])) { $first = reset($this->resultPointers); // TODO: Exception if $key === null ? $baseElement =& $this->resultPointers[$parent][key($first)]; } elseif (isset($this->resultPointers[$parent])) { $baseElement =& $this->resultPointers[$parent]; } else { unset($this->resultPointers[$dqlAlias]); // Ticket #1228 continue; } $relationAlias = $this->resultSetMapping()->relationMap[$dqlAlias]; $parentClass = $this->_metadataCache[$this->resultSetMapping()->aliasMap[$parent]]; $relation = $parentClass->associationMappings[$relationAlias]; // Check the type of the relation (many or single-valued) if (! ($relation['type'] & ClassMetadata::TO_ONE)) { $oneToOne = false; if (! isset($baseElement[$relationAlias])) { $baseElement[$relationAlias] = []; } if (isset($nonemptyComponents[$dqlAlias])) { $indexExists = isset($this->identifierMap[$path][$id[$parent]][$id[$dqlAlias]]); $index = $indexExists ? $this->identifierMap[$path][$id[$parent]][$id[$dqlAlias]] : false; $indexIsValid = $index !== false ? isset($baseElement[$relationAlias][$index]) : false; if (! $indexExists || ! $indexIsValid) { $element = $data; if (isset($this->resultSetMapping()->indexByMap[$dqlAlias])) { $baseElement[$relationAlias][$row[$this->resultSetMapping()->indexByMap[$dqlAlias]]] = $element; } else { $baseElement[$relationAlias][] = $element; } end($baseElement[$relationAlias]); $this->identifierMap[$path][$id[$parent]][$id[$dqlAlias]] = key($baseElement[$relationAlias]); } } } else { $oneToOne = true; if ( ! isset($nonemptyComponents[$dqlAlias]) && ( ! isset($baseElement[$relationAlias])) ) { $baseElement[$relationAlias] = null; } elseif (! isset($baseElement[$relationAlias])) { $baseElement[$relationAlias] = $data; } } $coll =& $baseElement[$relationAlias]; if (is_array($coll)) { $this->updateResultPointer($coll, $index, $dqlAlias, $oneToOne); } } else { // It's a root result element $this->rootAliases[$dqlAlias] = true; // Mark as root $entityKey = $this->resultSetMapping()->entityMappings[$dqlAlias] ?: 0; // if this row has a NULL value for the root result id then make it a null result. if (! isset($nonemptyComponents[$dqlAlias])) { $result[] = $this->resultSetMapping()->isMixed ? [$entityKey => null] : null; $resultKey = $this->resultCounter; ++$this->resultCounter; continue; } // Check for an existing element if ($this->isSimpleQuery || ! isset($this->identifierMap[$dqlAlias][$id[$dqlAlias]])) { $element = $this->resultSetMapping()->isMixed ? [$entityKey => $data] : $data; if (isset($this->resultSetMapping()->indexByMap[$dqlAlias])) { $resultKey = $row[$this->resultSetMapping()->indexByMap[$dqlAlias]]; $result[$resultKey] = $element; } else { $resultKey = $this->resultCounter; $result[] = $element; ++$this->resultCounter; } $this->identifierMap[$dqlAlias][$id[$dqlAlias]] = $resultKey; } else { $index = $this->identifierMap[$dqlAlias][$id[$dqlAlias]]; $resultKey = $index; } $this->updateResultPointer($result, $index, $dqlAlias, false); } } if (! isset($resultKey)) { $this->resultCounter++; } // Append scalar values to mixed result sets if (isset($rowData['scalars'])) { if (! isset($resultKey)) { // this only ever happens when no object is fetched (scalar result only) $resultKey = isset($this->resultSetMapping()->indexByMap['scalars']) ? $row[$this->resultSetMapping()->indexByMap['scalars']] : $this->resultCounter - 1; } foreach ($rowData['scalars'] as $name => $value) { $result[$resultKey][$name] = $value; } } // Append new object to mixed result sets if (isset($rowData['newObjects'])) { if (! isset($resultKey)) { $resultKey = $this->resultCounter - 1; } $scalarCount = (isset($rowData['scalars']) ? count($rowData['scalars']) : 0); foreach ($rowData['newObjects'] as $objIndex => $newObject) { $class = $newObject['class']; $args = $newObject['args']; $obj = $class->newInstanceArgs($args); if (count($args) === $scalarCount || ($scalarCount === 0 && count($rowData['newObjects']) === 1)) { $result[$resultKey] = $obj; continue; } $result[$resultKey][$objIndex] = $obj; } } } /** * Updates the result pointer for an Entity. The result pointers point to the * last seen instance of each Entity type. This is used for graph construction. * * @param mixed[]|null $coll The element. * @param bool|int $index Index of the element in the collection. * @param bool $oneToOne Whether it is a single-valued association or not. */ private function updateResultPointer( ?array &$coll, $index, string $dqlAlias, bool $oneToOne ): void { if ($coll === null) { unset($this->resultPointers[$dqlAlias]); // Ticket #1228 return; } if ($oneToOne) { $this->resultPointers[$dqlAlias] =& $coll; return; } if ($index !== false) { $this->resultPointers[$dqlAlias] =& $coll[$index]; return; } if (! $coll) { return; } end($coll); $this->resultPointers[$dqlAlias] =& $coll[key($coll)]; } }