Completed
Pull Request — master (#9621)
by
unknown
13:40
created

ProductRepository::createShopListQueryBuilder()   B

Complexity

Conditions 3
Paths 4

Size

Total Lines 61

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 61
rs 8.8509
c 0
b 0
f 0
cc 3
nc 4
nop 5

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/*
4
 * This file is part of the Sylius package.
5
 *
6
 * (c) Paweł Jędrzejewski
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace Sylius\Bundle\CoreBundle\Doctrine\ORM;
15
16
use Doctrine\ORM\EntityManager;
17
use Doctrine\ORM\Mapping;
18
use Doctrine\ORM\QueryBuilder;
19
use Sylius\Bundle\ProductBundle\Doctrine\ORM\ProductRepository as BaseProductRepository;
20
use Sylius\Component\Core\Model\ChannelInterface;
21
use Sylius\Component\Core\Model\ProductInterface;
22
use Sylius\Component\Core\Model\TaxonInterface;
23
use Sylius\Component\Core\Repository\ProductRepositoryInterface;
24
use SyliusLabs\AssociationHydrator\AssociationHydrator;
25
26
class ProductRepository extends BaseProductRepository implements ProductRepositoryInterface
27
{
28
    /**
29
     * @var AssociationHydrator
30
     */
31
    private $associationHydrator;
32
33
    /**
34
     * {@inheritdoc}
35
     */
36
    public function __construct(EntityManager $entityManager, Mapping\ClassMetadata $class)
37
    {
38
        parent::__construct($entityManager, $class);
39
40
        $this->associationHydrator = new AssociationHydrator($entityManager, $class);
41
    }
42
43
    /**
44
     * {@inheritdoc}
45
     */
46
    public function createListQueryBuilder(string $locale, $taxonId = null): QueryBuilder
47
    {
48
        $queryBuilder = $this->createQueryBuilder('o')
49
            ->addSelect('translation')
50
            ->innerJoin('o.translations', 'translation', 'WITH', 'translation.locale = :locale')
51
            ->setParameter('locale', $locale)
52
        ;
53
54
        if (null !== $taxonId) {
55
            $queryBuilder
56
                ->innerJoin('o.productTaxons', 'productTaxon')
57
                ->andWhere('productTaxon.taxon = :taxonId')
58
                ->setParameter('taxonId', $taxonId)
59
            ;
60
        }
61
62
        return $queryBuilder;
63
    }
64
65
    /**
66
     * {@inheritdoc}
67
     */
68
    public function createShopListQueryBuilder(
69
        ChannelInterface $channel,
70
        TaxonInterface $taxon,
71
        string $locale,
72
        array $sorting = [],
73
        bool $includeAllDescendants = false
74
    ): QueryBuilder {
75
        $queryBuilder = $this->createQueryBuilder('o')
76
            ->addSelect('translation')
77
            ->innerJoin('o.translations', 'translation', 'WITH', 'translation.locale = :locale')
78
            ->innerJoin('o.productTaxons', 'productTaxon');
79
80
        if ($includeAllDescendants) {
81
            $queryBuilder
82
                ->innerJoin('productTaxon.taxon', 'taxon')
83
                ->andWhere('taxon.left >= :taxonLeft')
84
                ->andWhere('taxon.right <= :taxonRight')
85
                ->andWhere('taxon.root = :taxonRoot')
86
                ->setParameter('taxonLeft', $taxon->getLeft())
87
                ->setParameter('taxonRight', $taxon->getRight())
88
                ->setParameter('taxonRoot', $taxon->getRoot())
89
            ;
90
        } else {
91
            $queryBuilder
92
                ->andWhere('productTaxon.taxon = :taxon')
93
                ->setParameter('taxon', $taxon)
94
            ;
95
        }
96
97
        $queryBuilder
98
            ->andWhere(':channel MEMBER OF o.channels')
99
            ->andWhere('o.enabled = true')
100
            ->setParameter('locale', $locale)
101
            ->setParameter('channel', $channel)
102
        ;
103
104
        // Grid hack, we do not need to join these if we don't sort by price
105
        if (isset($sorting['price'])) {
106
            // Another hack, the subquery to get the first position variant
107
            $subQuery = $this->createQueryBuilder('m')
108
                 ->select('min(v.position)')
109
                 ->innerJoin('m.variants', 'v')
110
                 ->andWhere('m.id = :product_id')
111
             ;
112
113
            $queryBuilder
114
                ->innerJoin('o.variants', 'variant')
115
                ->innerJoin('variant.channelPricings', 'channelPricing')
116
                ->andWhere('channelPricing.channelCode = :channelCode')
117
                ->andWhere(
118
                    $queryBuilder->expr()->in(
119
                        'variant.position',
120
                        str_replace(':product_id', 'o.id', $subQuery->getDQL())
121
                    )
122
                )
123
                ->setParameter('channelCode', $channel->getCode())
124
            ;
125
        }
126
127
        return $queryBuilder;
128
    }
129
130
    /**
131
     * {@inheritdoc}
132
     */
133
    public function findLatestByChannel(ChannelInterface $channel, string $locale, int $count): array
134
    {
135
        return $this->createQueryBuilder('o')
136
            ->addSelect('translation')
137
            ->innerJoin('o.translations', 'translation', 'WITH', 'translation.locale = :locale')
138
            ->andWhere(':channel MEMBER OF o.channels')
139
            ->andWhere('o.enabled = true')
140
            ->addOrderBy('o.createdAt', 'DESC')
141
            ->setParameter('channel', $channel)
142
            ->setParameter('locale', $locale)
143
            ->setMaxResults($count)
144
            ->getQuery()
145
            ->getResult()
146
        ;
147
    }
148
149
    /**
150
     * {@inheritdoc}
151
     */
152
    public function findOneByChannelAndSlug(ChannelInterface $channel, string $locale, string $slug): ?ProductInterface
153
    {
154
        $product = $this->createQueryBuilder('o')
155
            ->addSelect('translation')
156
            ->innerJoin('o.translations', 'translation', 'WITH', 'translation.locale = :locale')
157
            ->andWhere('translation.slug = :slug')
158
            ->andWhere(':channel MEMBER OF o.channels')
159
            ->andWhere('o.enabled = true')
160
            ->setParameter('channel', $channel)
161
            ->setParameter('locale', $locale)
162
            ->setParameter('slug', $slug)
163
            ->getQuery()
164
            ->getOneOrNullResult()
165
        ;
166
167
        $this->associationHydrator->hydrateAssociations($product, [
168
            'images',
169
            'options',
170
            'options.translations',
171
            'variants',
172
            'variants.channelPricings',
173
            'variants.optionValues',
174
            'variants.optionValues.translations',
175
        ]);
176
177
        return $product;
178
    }
179
180
    /**
181
     * {@inheritdoc}
182
     */
183
    public function findOneByCode(string $code): ?ProductInterface
184
    {
185
        return $this->createQueryBuilder('o')
186
            ->where('o.code = :code')
187
            ->setParameter('code', $code)
188
            ->getQuery()
189
            ->getOneOrNullResult()
190
        ;
191
    }
192
}
193