Completed
Push — master ( a95920...0228a1 )
by Jonas
14s
created

BaseProductQuery::attributeGroup()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 13
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 10
nc 1
nop 1
1
<?php
2
/**
3
 * (c) shopware AG <[email protected]>
4
 * For the full copyright and license information, please view the LICENSE
5
 * file that was distributed with this source code.
6
 */
7
8
namespace ShopwarePlugins\Connect\Components\ProductQuery;
9
10
use Shopware\Connect\Struct\Product;
11
use Shopware\Components\Model\ModelManager;
12
use Doctrine\ORM\Query\Expr\Join;
13
14
abstract class BaseProductQuery
15
{
16
    const IMAGE_PATH = '/media/image/';
17
    const LONG_DESCRIPTION_FIELD = 'longDescriptionField';
18
    const SHORT_DESCRIPTION_FIELD = 'shortDescriptionField';
19
    const CONNECT_DESCRIPTION_FIELD = 'connectDescriptionField';
20
21
    protected $manager;
22
23
    private $mediaService;
24
25
    public function __construct(ModelManager $manager, $mediaService = null)
26
    {
27
        $this->manager = $manager;
28
        $this->mediaService = $mediaService;
29
    }
30
31
    protected $attributeMapping = [
32
        'weight' => Product::ATTRIBUTE_WEIGHT,
33
        'unit' => Product::ATTRIBUTE_UNIT,
34
        'referenceUnit' => Product::ATTRIBUTE_REFERENCE_QUANTITY,
35
        'purchaseUnit' => Product::ATTRIBUTE_QUANTITY,
36
        'packageUnit' => Product::ATTRIBUTE_PACKAGEUNIT,
37
        'basicUnit' => Product::ATTRIBUTE_BASICUNIT,
38
        'manufacturerNumber' => Product::ATTRIBUTE_MANUFACTURERNUMBER
39
    ];
40
41
    /**
42
     * @return \Doctrine\ORM\QueryBuilder
43
     */
44
    abstract public function getProductQuery();
45
46
    /**
47
     * @param $rows
48
     * @return array
49
     */
50
    abstract public function getConnectProducts($rows);
51
52
    /**
53
     * Returns array of Product structs by given sourceIds
54
     *
55
     * @param array $sourceIds
56
     * @param int|null $shopId
57
     * @return array
58
     */
59
    public function get(array $sourceIds, $shopId = null)
60
    {
61
        $implodedIds = "'" . implode("','", $sourceIds) . "'";
62
        $builder = $this->getProductQuery();
63
        $builder->andWhere("at.sourceId IN ($implodedIds)");
64
        if ($shopId > 0) {
65
            $builder->andWhere('at.shopId = :shopId')
66
                    ->setParameter('shopId', $shopId);
67
        }
68
69
        $query = $builder->getQuery();
70
71
        return $this->getConnectProducts($query->getArrayResult());
72
    }
73
74
    /**
75
     * @param int $articleId
76
     * @return array
77
     */
78
    protected function getProperties($articleId)
79
    {
80
        $columns = [
81
            'v.value',
82
            'v.position as valuePosition',
83
            'o.name as option',
84
            'o.filterable',
85
            'g.name as groupName',
86
            'g.position as groupPosition',
87
            'g.comparable',
88
            'g.sortMode',
89
        ];
90
91
        $builder = $this->manager->createQueryBuilder();
92
        $builder->select($columns)
93
            ->from('Shopware\Models\Property\Value', 'v')
94
            ->leftJoin('v.option', 'o')
95
            ->leftJoin('v.articles', 'a')
96
            ->leftJoin('a.propertyGroup', 'g')
97
            ->where('a.id = :articleId')
98
            ->setParameter('articleId', $articleId);
99
100
        return $builder->getQuery()->getArrayResult();
101
    }
102
103
    /**
104
     * @param $articleId
105
     * @throws \Doctrine\ORM\NonUniqueResultException
106
     * @return mixed
107
     */
108
    protected function attributeGroup($articleId)
109
    {
110
        $builder = $this->manager->createQueryBuilder();
111
112
        return $builder->select('g')
113
            ->from('Shopware\Models\Attribute\Article', 'attr')
114
            ->leftJoin('Shopware\Models\Article\Detail', 'd', Join::WITH, 'd.id = attr.articleDetailId')
115
            ->leftJoin('Shopware\Models\Property\Group', 'g', Join::WITH, 'g.id = attr.connectPropertyGroup')
116
            ->where('d.articleId = :articleId')
117
            ->andWhere('d.kind = 1')
118
            ->setParameter(':articleId', $articleId)
119
            ->getQuery()->getOneOrNullResult();
120
    }
121
122
    /**
123
     * @param $id
124
     * @return string[]
125
     */
126
    protected function getImagesById($id)
127
    {
128
        $builder = $this->manager->createQueryBuilder();
129
        $builder->select(['i.path', 'i.extension', 'i.main', 'i.position'])
130
            ->from('Shopware\Models\Article\Image', 'i')
131
            ->where('i.articleId = :articleId')
132
            ->andWhere('i.parentId IS NULL')
133
            ->setParameter('articleId', $id)
134
            ->orderBy('i.main', 'ASC')
135
            ->addOrderBy('i.position', 'ASC');
136
137
        $query = $builder->getQuery();
138
        $query->setHydrationMode($query::HYDRATE_OBJECT);
139
140
        $images = $query->getArrayResult();
141
142
        $images = array_map(function ($image) {
143
            return $this->getImagePath($image['path'] . '.' . $image['extension']);
144
        }, $images);
145
146
147
        return $images;
148
    }
149
150
    /**
151
     * Returns URL for the shopware image directory
152
     *
153
     * @param string $image
154
     * @return string
155
     */
156
    protected function getImagePath($image)
157
    {
158
        if ($this->mediaService) {
159
            return $this->mediaService->getUrl(self::IMAGE_PATH . $image);
160
        }
161
162
        $request = Shopware()->Front()->Request();
163
164
        if (!$request) {
165
            return '';
166
        }
167
168
        $imagePath = $request->getScheme() . '://'
169
            . $request->getHttpHost() . $request->getBasePath() . self::IMAGE_PATH . $image;
170
171
        return $imagePath;
172
    }
173
174
    /**
175
     * Prepares some common fields for local and remote products
176
     *
177
     * @param $row
178
     * @return mixed
179
     */
180
    public function prepareCommonAttributes($row)
181
    {
182
        if (isset($row['deliveryDate'])) {
183
            /** @var \DateTime $time */
184
            $time = $row['deliveryDate'];
185
            $row['deliveryDate'] = $time->getTimestamp();
186
        }
187
188
        // Fix categories
189
        if (is_string($row['category']) && strlen($row['category']) > 0) {
190
            $row['categories'] = json_decode($row['category'], true) ?: [];
191
        }
192
        unset($row['category']);
193
194
        // The SDK expects the weight to be numeric. So if it is NULL, we unset it here
195
        if ($row['weight'] === null) {
196
            unset($row['weight']);
197
        }
198
199
        // Make sure that there is a unit
200
        if ($row['unit'] === null) {
201
            unset($row['unit']);
202
        }
203
204
        // Fix attributes
205
        $row['attributes'] = [];
206
        foreach ($this->getAttributeMapping() as $swField => $connectField) {
207
            if (!array_key_exists($swField, $row)) {
208
                continue;
209
            }
210
            $row['attributes'][$connectField] = $row[$swField];
211
            unset($row[$swField]);
212
        }
213
214
        // Fix dimensions
215
        $row = $this->prepareProductDimensions($row);
216
        // Fix availability
217
        $row['availability'] = (int) $row['availability'];
218
219
        $row = $this->prepareCrossSellingProducts($row);
220
221
        return $row;
222
    }
223
224
    /**
225
     * @param $row
226
     * @return mixed
227
     */
228
    public function prepareProductDimensions($row)
229
    {
230
        if (!empty($row['width']) && !empty($row['height']) && !empty($row['length'])) {
231
            $dimension = [
232
                $row['length'], $row['width'], $row['height']
233
            ];
234
            $row['attributes'][Product::ATTRIBUTE_DIMENSION] = implode('x', $dimension);
235
        }
236
        unset($row['width'], $row['height'], $row['length']);
237
238
        return $row;
239
    }
240
241
    public function getAttributeMapping()
242
    {
243
        return $this->attributeMapping;
244
    }
245
246
    /**
247
     * adds the related and similar products
248
     * this is not possible in productQuery because we need to fetch all Ids of the inverse side in join table
249
     * @param array $row
250
     * @return array
251
     */
252
    private function prepareCrossSellingProducts(array $row)
253
    {
254
        // do this just for mainvariant because crossSelling can just be defined for Products not for Variants
255
        if (isset($row['detailKind']) && $row['detailKind'] == 1) {
256
            $relatedArticleIds = $this->manager->getConnection()->executeQuery(
257
                'SELECT relatedarticle FROM s_articles_relationships WHERE articleID = ?',
258
                [$row['localId']])->fetchAll(\PDO::FETCH_COLUMN);
259
260
            if ($relatedArticleIds) {
261
                $row['related'] = $relatedArticleIds;
262
            }
263
264
            $similarArticleIds = $this->manager->getConnection()->executeQuery(
265
                'SELECT relatedarticle FROM s_articles_similar WHERE articleID = ?',
266
                [$row['localId']])->fetchAll(\PDO::FETCH_COLUMN);
267
268
            if ($similarArticleIds) {
269
                $row['similar'] = $similarArticleIds;
270
            }
271
        }
272
273
        return $row;
274
    }
275
}
276