Skip to content

Commit 0217900

Browse files
committed
LazyEntityGetter replaced with EntityFinderByPrimary
1 parent a978705 commit 0217900

File tree

4 files changed

+198
-0
lines changed

4 files changed

+198
-0
lines changed

src/DI/UtilityExtension.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use Utilitte\Doctrine\FetchByIdentifiers;
1212
use Utilitte\Doctrine\Query\RawQueryFactory;
1313
use Utilitte\Doctrine\QueryMetadataExtractor;
14+
use Utilitte\Nette\Doctrine\EntityFinderByPrimaryFactory;
1415
use Utilitte\Nette\Http\MaxUploadSize;
1516
use Utilitte\Nette\Latte\Macros;
1617
use Utilitte\Nette\UI\FlexibleMultiplierByIdentifierFactory;
@@ -44,6 +45,9 @@ public function loadConfiguration(): void
4445
$builder->addDefinition($this->prefix('flexibleTransferObjectMultiplier'))
4546
->setFactory(FlexibleTransferObjectMultiplier::class);
4647

48+
$builder->addFactoryDefinition($this->prefix('entityPresenterFinder'))
49+
->setImplement(EntityFinderByPrimaryFactory::class);
50+
4751
if (interface_exists(EntityManagerInterface::class) && class_exists(DoctrineIdentityExtractor::class)) {
4852
$builder->addDefinition($this->prefix('doctrine.identityExtractor'))
4953
->setType(DoctrineIdentityExtractor::class);
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace Utilitte\Nette\Doctrine;
4+
5+
use Doctrine\ORM\EntityManagerInterface;
6+
use LogicException;
7+
use Nette\Application\IPresenter;
8+
use Nette\Application\UI\Presenter;
9+
use Nette\Utils\Strings;
10+
use Utilitte\Nette\Exceptions\EntityIsNotValid;
11+
use Utilitte\Nette\Exceptions\EntityNotFound;
12+
use Utilitte\Nette\Exceptions\InvalidArgumentException;
13+
14+
final class EntityFinderByPrimary
15+
{
16+
17+
/** @var callable[] */
18+
private array $validators = [];
19+
20+
/** @var array{parameter:mixed, class:string, object:object}|null */
21+
private ?array $previous = null;
22+
23+
private Presenter $presenter;
24+
25+
private string|int|null $parameterValue;
26+
27+
private bool $parameterSet = false;
28+
29+
private string $parameterName = 'id';
30+
31+
public function __construct(
32+
IPresenter $presenter,
33+
private EntityManagerInterface $em,
34+
35+
)
36+
{
37+
if (!$presenter instanceof Presenter) {
38+
throw new \InvalidArgumentException(sprintf('Supported only %s.', Presenter::class));
39+
}
40+
41+
$this->presenter = $presenter;
42+
}
43+
44+
private function getParameterValue(): string|int|null
45+
{
46+
if (!$this->parameterSet) {
47+
$this->parameterValue = $this->presenter->getParameter($this->parameterName);
48+
}
49+
50+
return $this->parameterValue;
51+
}
52+
53+
public function setParameterValue(string|int|null $parameterValue): self
54+
{
55+
if ($this->parameterSet) {
56+
throw new LogicException('Cannot set parameter value, parameter value already set.');
57+
}
58+
59+
$this->parameterSet = true;
60+
$this->parameterValue = $parameterValue;
61+
62+
return $this;
63+
}
64+
65+
public function setParameterName(string $parameterName): self
66+
{
67+
if ($this->parameterSet) {
68+
throw new LogicException('Cannot set parameter name, parameter value already set.');
69+
}
70+
71+
$this->parameterName = $parameterName;
72+
73+
return $this;
74+
}
75+
76+
public function addValidator(callable $validator): self
77+
{
78+
$this->validators[] = $validator;
79+
80+
return $this;
81+
}
82+
83+
/**
84+
* @template T
85+
* @param class-string<T> $class
86+
* @param mixed[] $checkParameters
87+
* @return T|null
88+
*/
89+
public function getEntityIfParameterPresented(string $class): ?object
90+
{
91+
if ($this->getParameterValue() === null) {
92+
return null;
93+
}
94+
95+
return $this->getEntity($class);
96+
}
97+
98+
/**
99+
* @template T
100+
* @param class-string<T> $class
101+
* @param mixed[] $checkParameters
102+
* @return T|null
103+
*/
104+
public function getNullableEntity(string $class): ?object
105+
{
106+
$id = $this->getParameterValue();
107+
if ($this->previous === null) {
108+
if ($id === null) {
109+
return null;
110+
}
111+
112+
$object = $this->em->find($class, $id);
113+
114+
if (!$object) {
115+
return null;
116+
}
117+
118+
foreach ($this->validators as $validator) {
119+
if ($validator($object) === false) {
120+
throw new EntityIsNotValid($class, $id);
121+
}
122+
}
123+
124+
$this->previous = [
125+
'parameter' => $id,
126+
'class' => $class,
127+
'object' => $object,
128+
];
129+
} elseif ($this->previous['class'] !== $class) {
130+
throw new InvalidArgumentException(
131+
sprintf('Entity %s already requested, cannot request %s entity.', $this->previous['class'], $class)
132+
);
133+
} elseif ($this->previous['parameter'] !== $id) {
134+
throw new LogicException(
135+
sprintf(
136+
'Entity %s with id %s requested, cannot change id to %s.',
137+
$this->previous['class'],
138+
(string) $this->previous['parameter'],
139+
(string) $id,
140+
)
141+
);
142+
}
143+
144+
return $this->previous['object'];
145+
}
146+
147+
/**
148+
* @template T
149+
* @param class-string<T> $class
150+
* @param mixed[] $checkParameters
151+
* @return T
152+
*/
153+
public function getEntity(string $class): object
154+
{
155+
$object = $this->getNullableEntity($class);
156+
157+
if (!$object) {
158+
throw new EntityNotFound($class, $id);
159+
}
160+
161+
return $object;
162+
}
163+
164+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace Utilitte\Nette\Doctrine;
4+
5+
use Nette\Application\IPresenter;
6+
7+
interface EntityFinderByPrimaryFactory
8+
{
9+
10+
public function create(IPresenter $presenter): EntityFinderByPrimary;
11+
12+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace Utilitte\Nette\Traits\Application;
4+
5+
use Utilitte\Nette\Doctrine\EntityFinderByPrimary;
6+
use Utilitte\Nette\Doctrine\EntityFinderByPrimaryFactory;
7+
8+
trait EntityFinderByPrimaryTrait
9+
{
10+
11+
private EntityFinderByPrimary $entityFinderByPrimary;
12+
13+
final public function injectEntityFinderByPrimary(EntityFinderByPrimaryFactory $factory): void
14+
{
15+
$this->entityFinderByPrimary = $factory->create($this);
16+
}
17+
18+
}

0 commit comments

Comments
 (0)