|
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\Subscribers; |
|
9
|
|
|
|
|
10
|
|
|
use Enlight\Event\SubscriberInterface; |
|
11
|
|
|
use Shopware\Connect\SDK; |
|
12
|
|
|
use Shopware\CustomModels\Connect\Attribute; |
|
13
|
|
|
use Shopware\Models\ProductStream\ProductStream; |
|
14
|
|
|
use ShopwarePlugins\Connect\Components\Config; |
|
15
|
|
|
use ShopwarePlugins\Connect\Components\ErrorHandler; |
|
16
|
|
|
use ShopwarePlugins\Connect\Components\Helper; |
|
17
|
|
|
use ShopwarePlugins\Connect\Components\ImageImport; |
|
18
|
|
|
use ShopwarePlugins\Connect\Components\Logger; |
|
19
|
|
|
use ShopwarePlugins\Connect\Components\ConnectExport; |
|
20
|
|
|
use ShopwarePlugins\Connect\Components\ProductStream\ProductSearch; |
|
21
|
|
|
use ShopwarePlugins\Connect\Components\ProductStream\ProductStreamsAssignments; |
|
22
|
|
|
use ShopwarePlugins\Connect\Components\ProductStream\ProductStreamService; |
|
23
|
|
|
use Shopware\Components\DependencyInjection\Container; |
|
24
|
|
|
|
|
25
|
|
|
/** |
|
26
|
|
|
* Cronjob callback |
|
27
|
|
|
* |
|
28
|
|
|
* Class CronJob |
|
29
|
|
|
* @package ShopwarePlugins\Connect\Subscribers |
|
30
|
|
|
*/ |
|
31
|
|
|
class CronJob implements SubscriberInterface |
|
32
|
|
|
{ |
|
33
|
|
|
/** |
|
34
|
|
|
* @var \ShopwarePlugins\Connect\Components\Config |
|
35
|
|
|
*/ |
|
36
|
|
|
private $configComponent; |
|
37
|
|
|
|
|
38
|
|
|
/** |
|
39
|
|
|
* @var SDK |
|
40
|
|
|
*/ |
|
41
|
|
|
protected $sdk; |
|
42
|
|
|
|
|
43
|
|
|
/** |
|
44
|
|
|
* @var ProductStreamService |
|
45
|
|
|
*/ |
|
46
|
|
|
protected $streamService; |
|
47
|
|
|
|
|
48
|
|
|
/** |
|
49
|
|
|
* @var ConnectExport |
|
50
|
|
|
*/ |
|
51
|
|
|
protected $connectExport; |
|
52
|
|
|
|
|
53
|
|
|
/** |
|
54
|
|
|
* @var Helper |
|
55
|
|
|
*/ |
|
56
|
|
|
private $helper; |
|
57
|
|
|
|
|
58
|
|
|
/** |
|
59
|
|
|
* @var ProductSearch |
|
60
|
|
|
*/ |
|
61
|
|
|
private $productSearch; |
|
62
|
|
|
|
|
63
|
|
|
/** |
|
64
|
|
|
* @var Container |
|
65
|
|
|
*/ |
|
66
|
|
|
private $container; |
|
67
|
|
|
|
|
68
|
|
|
/** |
|
69
|
|
|
* @var ProductStreamService |
|
70
|
|
|
*/ |
|
71
|
|
|
private $productStreamService; |
|
72
|
|
|
|
|
73
|
|
|
/** |
|
74
|
|
|
* @param SDK $sdk |
|
75
|
|
|
* @param ConnectExport $connectExport |
|
76
|
|
|
* @param Config $configComponent |
|
77
|
|
|
* @param Helper $helper |
|
78
|
|
|
* @param Container $container |
|
79
|
|
|
* @param ProductStreamService $productStreamService |
|
80
|
|
|
*/ |
|
81
|
|
View Code Duplication |
public function __construct( |
|
|
|
|
|
|
82
|
|
|
SDK $sdk, |
|
83
|
|
|
ConnectExport $connectExport, |
|
84
|
|
|
Config $configComponent, |
|
85
|
|
|
Helper $helper, |
|
86
|
|
|
Container $container, |
|
87
|
|
|
ProductStreamService $productStreamService |
|
88
|
|
|
) { |
|
89
|
|
|
$this->connectExport = $connectExport; |
|
90
|
|
|
$this->sdk = $sdk; |
|
91
|
|
|
$this->configComponent = $configComponent; |
|
92
|
|
|
$this->helper = $helper; |
|
93
|
|
|
$this->container = $container; |
|
94
|
|
|
$this->productStreamService = $productStreamService; |
|
95
|
|
|
} |
|
96
|
|
|
|
|
97
|
|
|
/** |
|
98
|
|
|
* {@inheritdoc} |
|
99
|
|
|
*/ |
|
100
|
|
|
public static function getSubscribedEvents() |
|
101
|
|
|
{ |
|
102
|
|
|
return [ |
|
103
|
|
|
'Shopware_CronJob_ShopwareConnectImportImages' => 'importImages', |
|
104
|
|
|
'Shopware_CronJob_ShopwareConnectUpdateProducts' => 'updateProducts', |
|
105
|
|
|
'Shopware_CronJob_ConnectExportDynamicStreams' => 'exportDynamicStreams', |
|
106
|
|
|
]; |
|
107
|
|
|
} |
|
108
|
|
|
|
|
109
|
|
|
/** |
|
110
|
|
|
* @return ImageImport |
|
111
|
|
|
*/ |
|
112
|
|
View Code Duplication |
public function getImageImport() |
|
|
|
|
|
|
113
|
|
|
{ |
|
114
|
|
|
// do not use thumbnail_manager as a dependency!!! |
|
115
|
|
|
// MediaService::__construct uses Shop entity |
|
116
|
|
|
// this also could break the session in backend when it's used in subscriber |
|
117
|
|
|
return new ImageImport( |
|
118
|
|
|
Shopware()->Models(), |
|
119
|
|
|
$this->helper, |
|
120
|
|
|
$this->container->get('thumbnail_manager'), |
|
121
|
|
|
new Logger(Shopware()->Db()) |
|
122
|
|
|
); |
|
123
|
|
|
} |
|
124
|
|
|
|
|
125
|
|
|
/** |
|
126
|
|
|
* Import images of new products |
|
127
|
|
|
* |
|
128
|
|
|
* @param \Shopware_Components_Cron_CronJob $job |
|
129
|
|
|
* @return bool |
|
130
|
|
|
*/ |
|
131
|
|
|
public function importImages(\Shopware_Components_Cron_CronJob $job) |
|
132
|
|
|
{ |
|
133
|
|
|
$limit = $this->configComponent->getConfig('articleImagesLimitImport', 10); |
|
|
|
|
|
|
134
|
|
|
$this->getImageImport()->import($limit); |
|
135
|
|
|
|
|
136
|
|
|
return true; |
|
137
|
|
|
} |
|
138
|
|
|
|
|
139
|
|
|
/** |
|
140
|
|
|
* Collect all own products and send them |
|
141
|
|
|
* to Connect system. |
|
142
|
|
|
* |
|
143
|
|
|
* Used to update products with many variants. |
|
144
|
|
|
* |
|
145
|
|
|
* @param \Shopware_Components_Cron_CronJob $job |
|
146
|
|
|
* @return bool |
|
147
|
|
|
*/ |
|
148
|
|
|
public function updateProducts(\Shopware_Components_Cron_CronJob $job) |
|
149
|
|
|
{ |
|
150
|
|
|
$sourceIds = Shopware()->Db()->fetchCol( |
|
151
|
|
|
'SELECT source_id FROM s_plugin_connect_items WHERE shop_id IS NULL AND cron_update = 1 AND exported = 1 LIMIT 100' |
|
152
|
|
|
); |
|
153
|
|
|
|
|
154
|
|
|
if (empty($sourceIds)) { |
|
155
|
|
|
return true; |
|
156
|
|
|
} |
|
157
|
|
|
|
|
158
|
|
|
$this->connectExport->processChanged($sourceIds); |
|
159
|
|
|
|
|
160
|
|
|
$quotedSourceIds = Shopware()->Db()->quote($sourceIds); |
|
161
|
|
|
Shopware()->Db()->query( |
|
162
|
|
|
"UPDATE s_plugin_connect_items |
|
163
|
|
|
SET cron_update = false |
|
164
|
|
|
WHERE source_id IN ($quotedSourceIds)" |
|
165
|
|
|
)->execute(); |
|
166
|
|
|
|
|
167
|
|
|
return true; |
|
168
|
|
|
} |
|
169
|
|
|
|
|
170
|
|
|
/** |
|
171
|
|
|
* @param \Shopware_Components_Cron_CronJob $job |
|
172
|
|
|
*/ |
|
173
|
|
|
public function exportDynamicStreams(\Shopware_Components_Cron_CronJob $job) |
|
174
|
|
|
{ |
|
175
|
|
|
$streams = $this->productStreamService->getAllExportedStreams(ProductStreamService::DYNAMIC_STREAM); |
|
176
|
|
|
$streamsAssignments = new ProductStreamsAssignments(); |
|
177
|
|
|
|
|
178
|
|
|
/** @var ProductStream $stream */ |
|
179
|
|
|
foreach ($streams as $stream) { |
|
180
|
|
|
$streamId = $stream->getId(); |
|
181
|
|
|
$productSearchResult = $this->getProductSearch()->getProductFromConditionStream($stream); |
|
182
|
|
|
$orderNumbers = array_keys($productSearchResult->getProducts()); |
|
183
|
|
|
|
|
184
|
|
|
//no products found |
|
185
|
|
|
if (!$orderNumbers) { |
|
|
|
|
|
|
186
|
|
|
//removes all products from this stream |
|
187
|
|
|
$this->productStreamService->markProductsToBeRemovedFromStream($streamId); |
|
188
|
|
|
} else { |
|
189
|
|
|
$articleIds = $this->helper->getArticleIdsByNumber($orderNumbers); |
|
190
|
|
|
|
|
191
|
|
|
$this->productStreamService->markProductsToBeRemovedFromStream($streamId); |
|
192
|
|
|
$this->productStreamService->createStreamRelation($streamId, $articleIds); |
|
193
|
|
|
} |
|
194
|
|
|
|
|
195
|
|
|
try { |
|
196
|
|
|
$streamsAssignments->merge($this->productStreamService->prepareStreamsAssignments($streamId)); |
|
197
|
|
|
} catch (\RuntimeException $e) { |
|
198
|
|
|
$this->productStreamService->changeStatus($streamId, ProductStreamService::STATUS_ERROR, $e->getMessage()); |
|
199
|
|
|
continue; |
|
200
|
|
|
} |
|
201
|
|
|
} |
|
202
|
|
|
if (count($streamsAssignments->assignments) === 0) { |
|
203
|
|
|
return; |
|
204
|
|
|
} |
|
205
|
|
|
|
|
206
|
|
|
//article ids must be taken from streamsAssignments |
|
207
|
|
|
$exportArticleIds = $streamsAssignments->getArticleIds(); |
|
208
|
|
|
|
|
209
|
|
|
$removeArticleIds = $streamsAssignments->getArticleIdsWithoutStreams(); |
|
210
|
|
|
|
|
211
|
|
|
if (!empty($removeArticleIds)) { |
|
212
|
|
|
$this->removeArticlesFromStream($removeArticleIds); |
|
213
|
|
|
|
|
214
|
|
|
//filter the $exportArticleIds |
|
215
|
|
|
$exportArticleIds = array_diff($exportArticleIds, $removeArticleIds); |
|
216
|
|
|
} |
|
217
|
|
|
|
|
218
|
|
|
$sourceIds = $this->helper->getArticleSourceIds($exportArticleIds); |
|
219
|
|
|
|
|
220
|
|
|
$errorMessages = $this->connectExport->export($sourceIds, $streamsAssignments); |
|
221
|
|
|
|
|
222
|
|
|
if ($errorMessages) { |
|
|
|
|
|
|
223
|
|
|
$errorMessagesText = ''; |
|
224
|
|
|
$displayedErrorTypes = [ |
|
225
|
|
|
ErrorHandler::TYPE_DEFAULT_ERROR, |
|
226
|
|
|
ErrorHandler::TYPE_PRICE_ERROR |
|
227
|
|
|
]; |
|
228
|
|
|
|
|
229
|
|
|
foreach ($displayedErrorTypes as $displayedErrorType) { |
|
230
|
|
|
$errorMessagesText .= implode('\n', $errorMessages[$displayedErrorType]); |
|
231
|
|
|
} |
|
232
|
|
|
|
|
233
|
|
|
foreach ($streams as $stream) { |
|
234
|
|
|
$this->productStreamService->changeStatus($stream->getId(), ProductStreamService::STATUS_ERROR, $errorMessagesText); |
|
235
|
|
|
} |
|
236
|
|
|
} |
|
237
|
|
|
|
|
238
|
|
|
foreach ($streams as $stream) { |
|
239
|
|
|
$this->productStreamService->changeStatus($stream->getId(), ProductStreamService::STATUS_EXPORT); |
|
240
|
|
|
} |
|
241
|
|
|
} |
|
242
|
|
|
|
|
243
|
|
|
/** |
|
244
|
|
|
* If article is not taking part of any shopware stream it will be removed |
|
245
|
|
|
* @param array $articleIds |
|
246
|
|
|
*/ |
|
247
|
|
|
private function removeArticlesFromStream(array $articleIds) |
|
248
|
|
|
{ |
|
249
|
|
|
$sourceIds = $this->helper->getArticleSourceIds($articleIds); |
|
250
|
|
|
$items = $this->connectExport->fetchConnectItems($sourceIds, false); |
|
251
|
|
|
|
|
252
|
|
|
foreach ($items as $item) { |
|
253
|
|
|
$this->sdk->recordDelete($item['sourceId']); |
|
254
|
|
|
} |
|
255
|
|
|
|
|
256
|
|
|
$this->productStreamService->removeMarkedStreamRelations(); |
|
257
|
|
|
$this->connectExport->updateConnectItemsStatus($sourceIds, Attribute::STATUS_DELETE); |
|
258
|
|
|
} |
|
259
|
|
|
|
|
260
|
|
|
/** |
|
261
|
|
|
* @return ProductSearch |
|
262
|
|
|
*/ |
|
263
|
|
|
private function getProductSearch() |
|
264
|
|
|
{ |
|
265
|
|
|
if (!$this->productSearch) { |
|
266
|
|
|
// HACK |
|
267
|
|
|
// do not use as a dependency!!! |
|
268
|
|
|
// this class uses Shopware product search which depends on shop context |
|
269
|
|
|
// so if it's used as dependency of subscriber, plugin returns error on deactivate |
|
270
|
|
|
// see CON-4922 |
|
271
|
|
|
$this->productSearch = $this->container->get('swagconnect.product_search'); |
|
272
|
|
|
} |
|
273
|
|
|
|
|
274
|
|
|
return $this->productSearch; |
|
275
|
|
|
} |
|
276
|
|
|
} |
|
277
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.