-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathProductProvider.php
109 lines (93 loc) · 3.99 KB
/
ProductProvider.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
<?php
/*
* This file is part of the ESQL project.
*
* (c) Antoine Bluchet <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Soyuka\ESQL\Tests\Fixtures\TestBundle\State;
use ApiPlatform\Metadata\Operation;
use ApiPlatform\State\Pagination\PartialPaginatorInterface;
use ApiPlatform\State\ProviderInterface;
use Doctrine\DBAL\Platforms\SQLServerPlatform;
use Doctrine\Persistence\ManagerRegistry;
use Soyuka\ESQL\ESQLInterface;
use Soyuka\ESQL\ESQLMapperInterface;
use Soyuka\ESQL\Tests\Fixtures\TestBundle\Entity\Category;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
final class ProductProvider implements ProviderInterface
{
private readonly ESQLMapperInterface $mapper;
public function __construct(private readonly RequestStack $requestStack, private readonly ManagerRegistry $managerRegistry, private readonly ESQLInterface $esql, private readonly ProviderInterface $decorated)
{
}
private function getCategories(): array
{
/** @var array|string */
$categoryParameter = null === ($request = $this->requestStack->getCurrentRequest()) ? null : $request->query->get('category');
if (\is_array($categoryParameter)) {
throw new BadRequestHttpException();
}
$connection = $this->managerRegistry->getConnection();
$categoryPredicate = $categoryParameter ? 'c.identifier = :category' : 'c.parent_id IS NULL';
$category = $this->esql->__invoke(Category::class);
$recursive = $connection->getDriver()->getDatabasePlatform() instanceof SQLServerPlatform ? '' : ' RECURSIVE ';
$query = <<<SQL
WITH{$recursive}
ancestors(identifier, name, parent_id) AS (
SELECT c.identifier, c.name, c.parent_id FROM category c WHERE {$categoryPredicate}
UNION ALL
SELECT c.identifier, c.name, c.parent_id FROM ancestors, category c WHERE c.identifier = ancestors.parent_id
),
descendants(identifier, name, parent_id) AS (
SELECT c.identifier, c.name, c.parent_id FROM category c WHERE {$categoryPredicate}
UNION ALL
SELECT c.identifier, c.name, c.parent_id FROM descendants, category c WHERE c.parent_id = descendants.identifier
)
SELECT {$category->columns()} FROM ancestors {$category->alias()}
UNION
SELECT {$category->columns()} FROM descendants {$category->alias()}
SQL;
$stmt = $connection->executeQuery($query, $categoryParameter ? ['category' => $categoryParameter] : []);
$data = $stmt->fetchAllAssociative();
$categories = $category->map($data);
foreach ($categories as $category) {
if (null === $category->parent) {
continue;
}
foreach ($categories as $parent) {
if ($parent->identifier === $category->parent->identifier) {
$category->parent = $parent;
}
}
}
return $categories;
}
/**
* {@inheritDoc}
*/
public function provide(Operation $operation, array $uriVariables = [], array $context = []): object|array|null
{
/** @var array */
$data = $this->decorated->provide($operation, $uriVariables, $context);
if ($data instanceof PartialPaginatorInterface && !\count($data)) {
return $data;
}
$categories = $this->getCategories();
foreach ($data as $product) {
foreach ($categories as $category) {
if ($product->categoryRelation->identifier === $category->identifier) {
$product->categoryRelation = $category;
}
if ($product->categoryRelation->parent && $product->categoryRelation->parent->identifier === $category->identifier) {
$product->categoryRelation->parent = $category;
}
}
}
return $data;
}
}