Passed
Push — trunk ( 1df889...04e1b9 )
by Christian
29:44 queued 17:31
created

ProductPageLoader::load()   B

Complexity

Conditions 8
Paths 25

Size

Total Lines 58
Code Lines 35

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
eloc 35
nc 25
nop 2
dl 0
loc 58
rs 8.1155
c 0
b 0
f 0

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 declare(strict_types=1);
2
3
namespace Shopware\Storefront\Page\Product;
4
5
use Shopware\Core\Content\Category\Exception\CategoryNotFoundException;
6
use Shopware\Core\Content\Product\Aggregate\ProductMedia\ProductMediaCollection;
7
use Shopware\Core\Content\Product\Aggregate\ProductMedia\ProductMediaEntity;
0 ignored issues
show
Bug introduced by
The type Shopware\Core\Content\Pr...edia\ProductMediaEntity was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
8
use Shopware\Core\Content\Product\Exception\ProductNotFoundException;
9
use Shopware\Core\Content\Product\SalesChannel\CrossSelling\AbstractProductCrossSellingRoute;
10
use Shopware\Core\Content\Product\SalesChannel\Detail\AbstractProductDetailRoute;
11
use Shopware\Core\Content\Product\SalesChannel\SalesChannelProductEntity;
0 ignored issues
show
Bug introduced by
The type Shopware\Core\Content\Pr...lesChannelProductEntity was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
12
use Shopware\Core\Content\Property\Aggregate\PropertyGroupOption\PropertyGroupOptionCollection;
13
use Shopware\Core\Content\Property\PropertyGroupCollection;
14
use Shopware\Core\Framework\DataAbstractionLayer\Exception\InconsistentCriteriaIdsException;
15
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
16
use Shopware\Core\Framework\Feature;
17
use Shopware\Core\Framework\Routing\Exception\MissingRequestParameterException;
18
use Shopware\Core\System\SalesChannel\SalesChannelContext;
19
use Shopware\Storefront\Page\GenericPageLoaderInterface;
20
use Shopware\Storefront\Page\Product\Review\ProductReviewLoader;
21
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
22
use Symfony\Component\HttpFoundation\Request;
23
24
/**
25
 * @package storefront
26
 */
27
class ProductPageLoader
28
{
29
    private GenericPageLoaderInterface $genericLoader;
30
31
    private EventDispatcherInterface $eventDispatcher;
32
33
    private AbstractProductDetailRoute $productDetailRoute;
34
35
    private ProductReviewLoader $productReviewLoader;
36
37
    private AbstractProductCrossSellingRoute $crossSellingRoute;
38
39
    /**
40
     * @internal
41
     */
42
    public function __construct(
43
        GenericPageLoaderInterface $genericLoader,
44
        EventDispatcherInterface $eventDispatcher,
45
        AbstractProductDetailRoute $productDetailRoute,
46
        ProductReviewLoader $productReviewLoader,
47
        AbstractProductCrossSellingRoute $crossSellingRoute
48
    ) {
49
        $this->genericLoader = $genericLoader;
50
        $this->eventDispatcher = $eventDispatcher;
51
        $this->productDetailRoute = $productDetailRoute;
52
        $this->productReviewLoader = $productReviewLoader;
53
        $this->crossSellingRoute = $crossSellingRoute;
54
    }
55
56
    /**
57
     * @throws CategoryNotFoundException
58
     * @throws InconsistentCriteriaIdsException
59
     * @throws MissingRequestParameterException
60
     * @throws ProductNotFoundException
61
     */
62
    public function load(Request $request, SalesChannelContext $context): ProductPage
63
    {
64
        $productId = $request->attributes->get('productId');
65
        if (!$productId) {
66
            throw new MissingRequestParameterException('productId', '/productId');
67
        }
68
69
        $criteria = (new Criteria())
70
            ->addAssociation('manufacturer.media')
71
            ->addAssociation('options.group')
72
            ->addAssociation('properties.group')
73
            ->addAssociation('mainCategories.category')
74
            ->addAssociation('media');
75
76
        $this->eventDispatcher->dispatch(new ProductPageCriteriaEvent($productId, $criteria, $context));
77
78
        $result = $this->productDetailRoute->load($productId, $request, $context, $criteria);
79
        $product = $result->getProduct();
80
81
        if ($product->getMedia()) {
82
            $product->getMedia()->sort(function (ProductMediaEntity $a, ProductMediaEntity $b) {
83
                return $a->getPosition() <=> $b->getPosition();
84
            });
85
        }
86
87
        if ($product->getMedia() && $product->getCover()) {
88
            $product->setMedia(new ProductMediaCollection(array_merge(
89
                [$product->getCover()->getId() => $product->getCover()],
90
                $product->getMedia()->getElements()
91
            )));
92
        }
93
94
        if ($category = $product->getSeoCategory()) {
95
            $request->request->set('navigationId', $category->getId());
96
        }
97
98
        $page = $this->genericLoader->load($request, $context);
99
        /** @var ProductPage $page */
100
        $page = ProductPage::createFrom($page);
101
102
        $page->setProduct($product);
103
        $page->setConfiguratorSettings($result->getConfigurator() ?? new PropertyGroupCollection());
104
        $page->setNavigationId($product->getId());
105
106
        if (!Feature::isActive('v6.6.0.0')) {
107
            $this->loadDefaultAdditions($product, $page, $request, $context);
0 ignored issues
show
Deprecated Code introduced by
The function Shopware\Storefront\Page...:loadDefaultAdditions() has been deprecated. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

107
            /** @scrutinizer ignore-deprecated */ $this->loadDefaultAdditions($product, $page, $request, $context);
Loading history...
108
        } elseif ($cmsPage = $product->getCmsPage()) {
109
            $page->setCmsPage($cmsPage);
110
        }
111
112
        $this->loadOptions($page);
113
        $this->loadMetaData($page);
114
115
        $this->eventDispatcher->dispatch(
116
            new ProductPageLoadedEvent($page, $context, $request)
117
        );
118
119
        return $page;
120
    }
121
122
    private function loadOptions(ProductPage $page): void
123
    {
124
        $options = new PropertyGroupOptionCollection();
125
126
        if (($optionIds = $page->getProduct()->getOptionIds()) === null) {
127
            $page->setSelectedOptions($options);
128
129
            return;
130
        }
131
132
        foreach ($page->getConfiguratorSettings() as $group) {
133
            $groupOptions = $group->getOptions();
134
            if ($groupOptions === null) {
135
                continue;
136
            }
137
            foreach ($optionIds as $optionId) {
138
                $groupOption = $groupOptions->get($optionId);
139
                if ($groupOption !== null) {
140
                    $options->add($groupOption);
141
                }
142
            }
143
        }
144
145
        $page->setSelectedOptions($options);
146
    }
147
148
    private function loadMetaData(ProductPage $page): void
149
    {
150
        $metaInformation = $page->getMetaInformation();
151
152
        if (!$metaInformation) {
0 ignored issues
show
introduced by
$metaInformation is of type Shopware\Storefront\Page\MetaInformation, thus it always evaluated to true.
Loading history...
153
            return;
154
        }
155
156
        $metaDescription = $page->getProduct()->getTranslation('metaDescription')
157
            ?? $page->getProduct()->getTranslation('description');
158
        $metaInformation->setMetaDescription((string) $metaDescription);
159
160
        $metaInformation->setMetaKeywords((string) $page->getProduct()->getTranslation('keywords'));
161
162
        if ((string) $page->getProduct()->getTranslation('metaTitle') !== '') {
163
            $metaInformation->setMetaTitle((string) $page->getProduct()->getTranslation('metaTitle'));
164
165
            return;
166
        }
167
168
        $metaTitleParts = [$page->getProduct()->getTranslation('name')];
169
170
        foreach ($page->getSelectedOptions() as $option) {
171
            $metaTitleParts[] = $option->getTranslation('name');
172
        }
173
174
        $metaTitleParts[] = $page->getProduct()->getProductNumber();
175
176
        $metaInformation->setMetaTitle(implode(' | ', $metaTitleParts));
177
    }
178
179
    /**
180
     * @@deprecated tag:v6.6.0 - will be removed because cms page id will always be set
181
     */
182
    private function loadDefaultAdditions(SalesChannelProductEntity $product, ProductPage $page, Request $request, SalesChannelContext $context): void
183
    {
184
        if ($cmsPage = $product->getCmsPage()) {
185
            $page->setCmsPage($cmsPage);
186
187
            return;
188
        }
189
190
        $request->request->set('parentId', $product->getParentId());
191
        $reviews = $this->productReviewLoader->load($request, $context);
192
        $reviews->setParentId($product->getParentId() ?? $product->getId());
193
194
        $page->setReviews($reviews);
195
196
        $crossSellings = $this->crossSellingRoute->load($product->getId(), new Request(), $context, new Criteria());
197
198
        $page->setCrossSellings($crossSellings->getResult());
199
    }
200
}
201