· 6 years ago · Nov 24, 2019, 01:52 PM
1<?php
2
3namespace Pulpo\Generator;
4
5use ElasticExport\Helper\ElasticExportCoreHelper;
6use ElasticExport\Helper\ElasticExportItemHelper;
7use ElasticExport\Helper\ElasticExportPropertyHelper;
8use ElasticExport\Helper\ElasticExportStockHelper;
9use Plenty\Modules\DataExchange\Contracts\PluginGenerator;
10use Plenty\Modules\Helper\Models\KeyValue;
11use Plenty\Modules\Helper\Services\ArrayHelper;
12use Plenty\Modules\Item\Search\Contracts\VariationElasticSearchScrollRepositoryContract;
13use Plenty\Modules\Item\Variation\Contracts\VariationRepositoryContract;
14use Plenty\Modules\StockManagement\Stock\Contracts\StockRepositoryContract;
15use Plenty\Plugin\Log\Loggable;
16use Plenty\Repositories\Models\PaginatedResult;
17use Pulpo\Controllers\LicenseController;
18use Pulpo\Helpers\PriceHelper;
19use Pulpo\Repositories\SupplierRepository;
20
21//use Pulpo\Helper\Loggable;
22
23/**
24 * Class Pulpo
25 * @package Pulpo\Generator
26 */
27class Pulpo extends PluginGenerator
28{
29 use Loggable;
30
31 /**
32 * @var ArrayHelper
33 */
34 private $arrayHelper;
35 /**
36 * @var PriceHelper
37 */
38 private $priceHelper;
39 /**
40 * @var array
41 */
42 private $imageCache = [];
43 /**
44 * @var
45 */
46 private $shippingCostCache;
47 /**
48 * @var
49 */
50 private $elasticExportHelper;
51 /**
52 * @var
53 */
54 private $elasticExportStockHelper;
55 /**
56 * @var
57 */
58 private $elasticExportItemHelper;
59 /**
60 * @var
61 */
62 private $elasticExportPropertyHelperInterface;
63 /**
64 * @var LicenseController
65 */
66 private $licenseController;
67
68 /**
69 * Pulpo constructor.
70 * @param ArrayHelper $arrayHelper
71 * @param PriceHelper $priceHelper
72 * @param LicenseController $licenseController
73 */
74 public function __construct(
75 ArrayHelper $arrayHelper,
76 PriceHelper $priceHelper,
77 LicenseController $licenseController
78 )
79 {
80 $this->arrayHelper = $arrayHelper;
81 $this->priceHelper = $priceHelper;
82 $this->licenseController = $licenseController;
83 }
84
85 /**
86 * @param VariationElasticSearchScrollRepositoryContract $elasticSearch
87 * @param array $formatSettings
88 * @param array $filter
89 */
90 protected function generatePluginContent($elasticSearch, array $formatSettings = [], array $filter = [])
91 {
92 $this->elasticExportStockHelper = pluginApp(ElasticExportStockHelper::class);
93 $this->elasticExportHelper = pluginApp(ElasticExportCoreHelper::class);
94 $this->elasticExportItemHelper = pluginApp(ElasticExportItemHelper::class, [1 => true]);
95 $this->elasticExportPropertyHelperInterface = pluginApp(ElasticExportPropertyHelper::class);
96
97 $settings = $this->arrayHelper->buildMapFromObjectList($formatSettings, 'key', 'value');
98
99 $JSON = [];
100
101 if ($elasticSearch instanceof VariationElasticSearchScrollRepositoryContract) {
102 // Initiate the counter for the variations limit
103 $limitReached = false;
104 $limit = 0;
105 do {
106 if ($limitReached === true) {
107 break;
108 }
109 // Get the data from Elastic Search
110 $resultList = $elasticSearch->execute();
111 if (count($resultList['error']) > 0) {
112 $this->getLogger(__METHOD__)->error('Pulpo::logs.occurredElasticSearchErrors', [
113 'Error message' => $resultList['error'],
114 ]);
115 break;
116 }
117 if (is_array($resultList['documents']) && count($resultList['documents']) > 0) {
118 $previousItemId = null;
119 foreach ($resultList['documents'] as $variation) {
120 // Stop and set the flag if limit is reached
121 if ($limit == $filter['limit']) {
122 $limitReached = true;
123 break;
124 }
125 // If filtered by stock is set and stock is negative, then skip the variation
126 if ($this->elasticExportStockHelper->isFilteredByStock($variation, $filter) === true) {
127 continue;
128 }
129
130 // Skip non-main variations that do not have attributes
131 $attributes = $this->getAttributeNameValueCombination($variation, $settings);
132
133 try {
134 // Set the caches if we have the first variation or when we have the first variation of an item
135 if ($previousItemId === null || $previousItemId != $variation['data']['item']['id']) {
136 $previousItemId = $variation['data']['item']['id'];
137 unset($this->shippingCostCache);
138 // Build the caches arrays
139 $this->buildCaches($variation, $settings);
140 }
141 // Build the new row for printing in the CSV file
142 $this->buildRow($variation, $settings, $attributes, $JSON);
143 } catch (\Throwable $throwable) {
144 $this->getLogger(__METHOD__)->error('Pulpo::logs.fillRowError', [
145 'Error message ' => $throwable->getMessage(),
146 'Error line' => $throwable->getLine(),
147 'VariationId' => $variation['id'],
148 ]);
149 }
150 // New line was added
151 $limit++;
152 }
153 }
154 } while ($elasticSearch->hasNext());
155 }
156 $this->addContent(json_encode($JSON));
157 }
158
159 /**
160 * @param array $item
161 * @param KeyValue $settings
162 * @param $attributes
163 * @param array $JSON
164 * @return void
165 */
166 private function buildRow($item, KeyValue $settings, $attributes, &$JSON)
167 {
168 $priceList = $this->priceHelper->getPriceList($item, $settings);
169
170 if (isset($priceList['price']) && $priceList['price'] > 0) {
171 $price = number_format((float)$priceList['price'], 2, '.', '');
172 } else {
173 $price = '';
174 }
175 $variationRepo = pluginApp(VariationRepositoryContract::class);
176 $contactRepo = pluginApp(SupplierRepository::class);
177 $variation = $variationRepo->findById($item['id']);
178 $this->getLogger(__METHOD__)->error('ITEM', [
179 'item' => $item,
180 'settings' => $settings,
181 '$attributes' =>$attributes,
182 'price' =>$price,
183 'priceList' =>$priceList,
184 'variation' =>$variation,
185 'suppliers' =>$variation->variationSuppliers
186 ]);
187 $unitName = $this->elasticExportHelper->getUnitName($item["data"]["unit"]["id"]);
188 $basePriceComponentList = $this->getBasePriceComponentList($item);
189 $name = $this->elasticExportHelper->getMutatedName($item, $settings);
190 $volume = ($item["data"]["variation"]["lengthMM"] * $item["data"]["variation"]["widthMM"] * $item["data"]["variation"]["heightMM"])/1000;
191 $third_party = $contactRepo->getWhere([
192 "identifier_number" => $variation->variationSuppliers[0]->supplierId,
193 "third_type" => "S" // S for 'Supplier'
194 ])[0];
195
196 $data = [
197 'supplier_product_id' => $item["id"],
198 'name'=>substr($name, 0, 255),
199 'description'=>$this->elasticExportHelper->getMutatedDescription($item, $settings, 5000),
200 'management_type' => 'none',
201 'sale_number'=>$item["data"]["unit"]["content"],
202 'minimum_purchase_unit'=>$item["data"]["variation"]["minimumOrderQuantity"],
203 'purchase_measure_units'=>$unitName["unitNameLong"],
204 'units_per_purchase_package'=>$item["data"]["variation"]["packingUnits"],
205 'sales_measure_units'=>$unitName["unitNameLong"],
206 'minimum_sales_unit'=>$item["data"]["variation"]["minimumOrderQuantity"],
207 'units_per_sales_package'=>$item["data"]["variation"]["packingUnits"],
208 'active'=>$item["data"]["variation"]["isActive"],
209 'sku'=>$item["id"],
210 'attributes'=>"",
211 'cost_price'=>$price,
212 'weight'=>$item["data"]["variation"]["weightG"]/1000,
213 'volume'=>$volume,
214 'height'=>$item["data"]["variation"]["heightMM"]/1000,
215 'width'=>$item["data"]["variation"]["widthMM"]/1000,
216 'length'=>$item["data"]["variation"]["lengthMM"]/1000,
217 'third_party_id'=> $third_party->id,
218 'barcodes' => [$this->elasticExportHelper->getBarcodeByType($item, $settings->get('barcode'))]
219 ];
220
221 array_push($JSON, $data);
222 }
223
224 /**
225 * @param $item
226 * @param $settings
227 * @param $position
228 * @return string
229 */
230 private function getImageByPosition($item, $settings, $position): string
231 {
232 $itemId = $item['data']['item']['id'];
233 if (!isset($this->imageCache[$itemId])) {
234 $this->imageCache = [];
235 if (is_array($item['data']['images']['all']) && count($item['data']['images']['all']) > 0) {
236 $count = 0;
237 $images = [];
238 $energyLabel = '';
239 foreach ($item['data']['images']['all'] as $image) {
240 if (!array_key_exists($image['position'], $images)
241 && $settings->get('energyLabel') != ''
242 && $image['position'] == $settings->get('energyLabel')) {
243 $energyLabel = $image;
244 } elseif (!array_key_exists($image['position'], $images)) {
245 $images[$image['position']] = $image;
246 } else {
247 $count++;
248 $images[$image['position'] . '_' . $count] = $image;
249 }
250 }
251 // sort by key
252 ksort($images);
253 $this->imageCache[$itemId] = array_values($images);
254 $this->imageCache[$itemId]['energyLabel'] = $energyLabel;
255 }
256 }
257 if (isset($this->imageCache[$itemId][$position])) {
258 return (string)$this->elasticExportHelper->getImageUrlBySize($this->imageCache[$itemId][$position]);
259 }
260 return '';
261 }
262
263 /**
264 * Returns the unit, if there is any unit configured, which is allowed
265 * for the Rakuten.de API.
266 *
267 * @param array $item
268 * @return string
269 */
270 private function getUnit($item): string
271 {
272 switch ((int)$item['data']['unit']['id']) {
273 case '32':
274 return 'ml'; // Milliliter
275 case '5':
276 return 'l'; // Liter
277 case '3':
278 return 'g'; // Gramm
279 case '2':
280 return 'kg'; // Kilogramm
281 case '51':
282 return 'cm'; // Zentimeter
283 case '31':
284 return 'm'; // Meter
285 case '38':
286 return 'm²'; // Quadratmeter
287 default:
288 return '';
289 }
290 }
291
292 /**
293 * Get necessary components to enable Rakuten to calculate a base price for the variation
294 * @param array $item
295 * @return array
296 */
297 private function getBasePriceComponentList($item): array
298 {
299 $unit = $this->getUnit($item);
300 $content = (float)$item['data']['unit']['content'];
301 $convertBasePriceContentTag = $this->elasticExportHelper->getConvertContentTag($content, 3);
302 if ($convertBasePriceContentTag == true && strlen($unit)) {
303 $content = $this->elasticExportHelper->getConvertedBasePriceContent($content, $unit);
304 $unit = $this->elasticExportHelper->getConvertedBasePriceUnit($unit);
305 }
306 return array(
307 'content' => $content,
308 'unit' => $unit,
309 );
310 }
311
312 /**
313 * Get the shipping cost.
314 *
315 * @param $variation
316 * @return string
317 */
318 private function getShippingCost($variation): string
319 {
320 $shippingCost = null;
321 if (isset($this->shippingCostCache) && array_key_exists($variation['data']['item']['id'], $this->shippingCostCache)) {
322 $shippingCost = $this->shippingCostCache[$variation['data']['item']['id']];
323 }
324 if (!is_null($shippingCost) && $shippingCost > 0) {
325 return number_format((float)$shippingCost, 2, '.', '');
326 }
327 return '';
328 }
329
330 /**
331 * Build the cache arrays for the item variation.
332 *
333 * @param $variation
334 * @param $settings
335 */
336 private function buildCaches($variation, $settings)
337 {
338 if (!is_null($variation) && !is_null($variation['data']['item']['id'])) {
339 $shippingCost = $this->elasticExportHelper->getShippingCost($variation['data']['item']['id'], $settings);
340 $this->shippingCostCache[$variation['data']['item']['id']] = (float)$shippingCost;
341 }
342 }
343
344 /**
345 * Get attribute and name value combination for a variation.
346 *
347 * @param $variation
348 * @param KeyValue $settings
349 * @return string
350 */
351 private function getAttributeNameValueCombination($variation, KeyValue $settings): string
352 {
353 $attributes = '';
354 $attributeName = $this->elasticExportHelper->getAttributeName($variation, $settings, ',');
355 $attributeValue = $this->elasticExportHelper->getAttributeValueSetShortFrontendName($variation, $settings, ',');
356 if (strlen($attributeName) && strlen($attributeValue)) {
357 $attributes = $this->elasticExportHelper->getAttributeNameAndValueCombination($attributeName, $attributeValue);
358 }
359 return $attributes;
360 }
361}