Skip to content

Commit

Permalink
add HydrationFactory as extension point for tracking hydrations
Browse files Browse the repository at this point in the history
  • Loading branch information
kbond committed Feb 25, 2022
1 parent 7be96f6 commit ceb80da
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 33 deletions.
12 changes: 12 additions & 0 deletions lib/Doctrine/ORM/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
use Doctrine\ORM\Exception\ProxyClassesAlwaysRegenerating;
use Doctrine\ORM\Exception\UnknownEntityNamespace;
use Doctrine\ORM\Internal\Hydration\AbstractHydrator;
use Doctrine\ORM\Internal\Hydration\DefaultHydratorFactory;
use Doctrine\ORM\Internal\Hydration\HydratorFactory;
use Doctrine\ORM\Mapping\ClassMetadataFactory;
use Doctrine\ORM\Mapping\DefaultEntityListenerResolver;
use Doctrine\ORM\Mapping\DefaultNamingStrategy;
Expand Down Expand Up @@ -64,6 +66,16 @@ class Configuration extends \Doctrine\DBAL\Configuration
/** @var mixed[] */
protected $_attributes = [];

public function setHydratorFactory(HydratorFactory $factory): void
{
$this->_attributes['hydratorFactory'] = $factory;
}

public function getHydratorFactory(): HydratorFactory
{
return $this->_attributes['hydratorFactory'] ?? new DefaultHydratorFactory();
}

/**
* Sets the directory where Doctrine generates any necessary proxy class files.
*
Expand Down
39 changes: 10 additions & 29 deletions lib/Doctrine/ORM/EntityManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@
use Doctrine\DBAL\LockMode;
use Doctrine\Deprecations\Deprecation;
use Doctrine\ORM\Exception\EntityManagerClosed;
use Doctrine\ORM\Exception\InvalidHydrationMode;
use Doctrine\ORM\Exception\MismatchedEventManager;
use Doctrine\ORM\Exception\MissingIdentifierField;
use Doctrine\ORM\Exception\MissingMappingDriverImplementation;
use Doctrine\ORM\Exception\UnrecognizedIdentifierFields;
use Doctrine\ORM\Internal\Hydration\HydratorFactory;
use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\Mapping\ClassMetadataFactory;
use Doctrine\ORM\Proxy\ProxyFactory;
Expand Down Expand Up @@ -145,6 +145,13 @@
*/
private $cache;

/**
* The hydrator factory to use.
*
* @var HydratorFactory
*/
private $hydratorFactory;

/**
* Creates a new EntityManager that operates on the given database connection
* and uses the given Configuration and EventManager implementations.
Expand All @@ -162,6 +169,7 @@ protected function __construct(Connection $conn, Configuration $config, EventMan

$this->configureMetadataCache();

$this->hydratorFactory = $config->getHydratorFactory();
$this->repositoryFactory = $config->getRepositoryFactory();
$this->unitOfWork = new UnitOfWork($this);
$this->proxyFactory = new ProxyFactory(
Expand Down Expand Up @@ -856,34 +864,7 @@ public function getHydrator($hydrationMode)
*/
public function newHydrator($hydrationMode)
{
switch ($hydrationMode) {
case Query::HYDRATE_OBJECT:
return new Internal\Hydration\ObjectHydrator($this);

case Query::HYDRATE_ARRAY:
return new Internal\Hydration\ArrayHydrator($this);

case Query::HYDRATE_SCALAR:
return new Internal\Hydration\ScalarHydrator($this);

case Query::HYDRATE_SINGLE_SCALAR:
return new Internal\Hydration\SingleScalarHydrator($this);

case Query::HYDRATE_SIMPLEOBJECT:
return new Internal\Hydration\SimpleObjectHydrator($this);

case Query::HYDRATE_SCALAR_COLUMN:
return new Internal\Hydration\ScalarColumnHydrator($this);

default:
$class = $this->config->getCustomHydrationMode($hydrationMode);

if ($class !== null) {
return new $class($this);
}
}

throw InvalidHydrationMode::fromMode((string) $hydrationMode);
return $this->hydratorFactory->create($this, $this->config, $hydrationMode);
}

/**
Expand Down
49 changes: 49 additions & 0 deletions lib/Doctrine/ORM/Internal/Hydration/DefaultHydratorFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

declare(strict_types=1);

namespace Doctrine\ORM\Internal\Hydration;

use Doctrine\ORM\AbstractQuery;
use Doctrine\ORM\Configuration;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Exception\InvalidHydrationMode;

final class DefaultHydratorFactory implements HydratorFactory
{
/**
* @param string|int $hydrationMode
* @psalm-param string|AbstractQuery::HYDRATE_* $hydrationMode
*/
public function create(EntityManagerInterface $em, Configuration $config, $hydrationMode): AbstractHydrator
{
switch ($hydrationMode) {
case AbstractQuery::HYDRATE_OBJECT:
return new ObjectHydrator($em);

case AbstractQuery::HYDRATE_ARRAY:
return new ArrayHydrator($em);

case AbstractQuery::HYDRATE_SCALAR:
return new ScalarHydrator($em);

case AbstractQuery::HYDRATE_SINGLE_SCALAR:
return new SingleScalarHydrator($em);

case AbstractQuery::HYDRATE_SIMPLEOBJECT:
return new SimpleObjectHydrator($em);

case AbstractQuery::HYDRATE_SCALAR_COLUMN:
return new ScalarColumnHydrator($em);

default:
$class = $config->getCustomHydrationMode($hydrationMode);

if ($class !== null) {
return new $class($em);
}
}

throw InvalidHydrationMode::fromMode((string) $hydrationMode);
}
}
20 changes: 20 additions & 0 deletions lib/Doctrine/ORM/Internal/Hydration/HydratorFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

declare(strict_types=1);

namespace Doctrine\ORM\Internal\Hydration;

use Doctrine\ORM\AbstractQuery;
use Doctrine\ORM\Configuration;
use Doctrine\ORM\EntityManagerInterface;

interface HydratorFactory
{
/**
* Create a new instance for the given hydration mode.
*
* @param string|int $hydrationMode
* @psalm-param string|AbstractQuery::HYDRATE_* $hydrationMode
*/
public function create(EntityManagerInterface $em, Configuration $config, $hydrationMode): AbstractHydrator;
}
10 changes: 6 additions & 4 deletions psalm-baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -327,18 +327,20 @@
<PropertyTypeCoercion occurrences="1">
<code>new $metadataFactoryClassName()</code>
</PropertyTypeCoercion>
<RedundantCastGivenDocblockType occurrences="1">
<code>(string) $hydrationMode</code>
</RedundantCastGivenDocblockType>
<RedundantCondition occurrences="1">
<code>is_object($connection)</code>
</RedundantCondition>
<TypeDoesNotContainType occurrences="1">
<code>': "' . $connection . '"'</code>
</TypeDoesNotContainType>
</file>
<file src="lib/Doctrine/ORM/Internal/Hydration/DefaultHydratorFactory.php">
<UnsafeInstantiation occurrences="1">
<code>new $class($this)</code>
<code>new $class($em)</code>
</UnsafeInstantiation>
<RedundantCastGivenDocblockType occurrences="1">
<code>(string) $hydrationMode</code>
</RedundantCastGivenDocblockType>
</file>
<file src="lib/Doctrine/ORM/EntityRepository.php">
<InvalidReturnStatement occurrences="2">
Expand Down

0 comments on commit ceb80da

Please sign in to comment.