Completed
Pull Request — master (#352)
by Stefan
03:45
created

Update::updateConnectAttribute()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 19
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 19
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 10
nc 3
nop 0
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\Bootstrap;
9
10
use Shopware\CustomModels\Connect\Attribute;
11
use Shopware\Components\Model\ModelManager;
12
use Enlight_Components_Db_Adapter_Pdo_Mysql as Pdo;
13
use Shopware\Models\Attribute\Configuration;
14
use Shopware\Models\Order\Status;
15
use ShopwarePlugins\Connect\Components\ProductQuery\BaseProductQuery;
16
use ShopwarePlugins\Connect\Components\Utils\ConnectOrderUtil;
17
18
/**
19
 * Updates existing versions of the plugin
20
 *
21
 * Class Update
22
 * @package ShopwarePlugins\Connect\Bootstrap
23
 */
24
class Update
25
{
26
    /**
27
     * @var \Shopware_Plugins_Backend_SwagConnect_Bootstrap
28
     */
29
    protected $bootstrap;
30
31
    /**
32
     * @var Pdo
33
     */
34
    protected $db;
35
36
    /**
37
     * @var ModelManager
38
     */
39
    protected $modelManager;
40
41
    /**
42
     * @var string
43
     */
44
    protected $version;
45
46
    /**
47
     * Setup constructor.
48
     * @param \Shopware_Plugins_Backend_SwagConnect_Bootstrap $bootstrap
49
     * @param ModelManager $modelManager
50
     * @param Pdo $db
51
     * @param $version
52
     */
53 View Code Duplication
    public function __construct(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
54
        \Shopware_Plugins_Backend_SwagConnect_Bootstrap $bootstrap,
55
        ModelManager $modelManager,
56
        Pdo $db,
57
        $version
58
    ) {
59
        $this->bootstrap = $bootstrap;
60
        $this->modelManager = $modelManager;
61
        $this->db = $db;
62
        $this->version = $version;
63
    }
64
65
    public function run()
66
    {
67
        // Force an SDK re-verify
68
        $this->reVerifySDK();
69
70
        $this->createExportedFlag();
71
        $this->removeRedirectMenu();
72
        $this->updateConnectAttribute();
73
        $this->addConnectDescriptionElement();
74
        $this->updateProductDescriptionSetting();
75
        $this->createUpdateAdditionalDescriptionColumn();
76
        $this->createDynamicStreamTable();
77
        $this->addOrderStatus();
78
        $this->fixExportDescriptionSettings();
79
        $this->fixMarketplaceUrl();
80
        $this->addIndexToChangeTable();
81
        $this->removeDuplicatedMenuItems();
82
        $this->addConnectItemsIndex();
83
84
        return true;
85
    }
86
87
    /**
88
     * Forces the SDK to re-verify the API key
89
     */
90
    public function reVerifySDK()
91
    {
92
        $this->db->query('
93
            UPDATE sw_connect_shop_config
94
            SET s_config = ?
95
            WHERE s_shop = "_last_update_"
96
            LIMIT 1; ',
97
            [time() - 8 * 60 * 60 * 24]
98
        );
99
    }
100
101
    private function createExportedFlag()
102
    {
103
        if (version_compare($this->version, '1.0.1', '<=')) {
104
            $this->db->query('
105
                ALTER TABLE `s_plugin_connect_items`
106
                ADD COLUMN `exported` TINYINT(1) DEFAULT 0
107
            ');
108
109
            $this->db->query('
110
                UPDATE `s_plugin_connect_items`
111
                SET `exported` = 1
112
                WHERE (`export_status` = ? OR `export_status` = ? OR `export_status` = ?) AND `shop_id` IS NULL',
113
                [Attribute::STATUS_INSERT, Attribute::STATUS_UPDATE, Attribute::STATUS_SYNCED]
114
            );
115
        }
116
    }
117
118
    private function removeRedirectMenu()
119
    {
120
        if (version_compare($this->version, '1.0.4', '<=')) {
121
            $connectItem = $this->bootstrap->Menu()->findOneBy(['label' => 'Open Connect', 'action' => '']);
122
            if ($connectItem) {
123
                $this->modelManager->remove($connectItem);
124
                $this->modelManager->flush();
125
            }
126
        }
127
    }
128
129
    private function updateConnectAttribute()
130
    {
131
        if (version_compare($this->version, '1.0.6', '<=')) {
132
            $result = $this->db->query("SELECT value FROM s_plugin_connect_config WHERE name = 'connectAttribute'");
133
            $row = $result->fetch();
134
            $attr = 19;
135
            if ($row) {
136
                $attr = $row['value'];
137
            }
138
139
            $this->db->query('
140
                    UPDATE `s_articles_attributes` 
141
                    SET `connect_reference` = `attr' . $attr . '` 
142
                    WHERE connect_reference IS NULL;
143
                ');
144
145
            $this->db->query("DELETE FROM s_plugin_connect_config WHERE name = 'connectAttribute'");
146
        }
147
    }
148
149
    private function addConnectDescriptionElement()
150
    {
151
        if (version_compare($this->version, '1.0.9', '<=')) {
152
            $tableName = $this->modelManager->getClassMetadata('Shopware\Models\Attribute\Article')->getTableName();
153
            $columnName = 'connect_product_description';
154
155
            $repo = $this->modelManager->getRepository('Shopware\Models\Attribute\Configuration');
156
            $element = $repo->findOneBy([
157
                'tableName' => $tableName,
158
                'columnName' => $columnName,
159
            ]);
160
161
            if (!$element) {
162
                $element = new Configuration();
163
                $element->setTableName($tableName);
164
                $element->setColumnName($columnName);
165
            }
166
167
            $element->setColumnType('html');
168
            $element->setTranslatable(true);
169
            $element->setLabel('Connect Beschreibung');
170
            $element->setDisplayInBackend(true);
171
172
            $this->modelManager->persist($element);
173
            $this->modelManager->flush();
174
        }
175
    }
176
177
    private function updateProductDescriptionSetting()
178
    {
179
        if (version_compare($this->version, '1.0.9', '<=')) {
180
            //migrates to the new export settings
181
            $result = $this->db->query("SELECT `value` FROM s_plugin_connect_config WHERE name = 'alternateDescriptionField'");
182
            $row = $result->fetch();
183
184
            if ($row) {
185
                $mapper = [
186
                    'a.description' => BaseProductQuery::SHORT_DESCRIPTION_FIELD,
187
                    'a.descriptionLong' => BaseProductQuery::LONG_DESCRIPTION_FIELD,
188
                    'attribute.connectProductDescription' => BaseProductQuery::CONNECT_DESCRIPTION_FIELD,
189
                ];
190
191
                if ($name = $mapper[$row['value']]) {
192
                    $result = $this->db->query("SELECT `id` FROM s_plugin_connect_config WHERE name = '$name'");
193
                    $row = $result->fetch();
194
195
                    $id = null;
196
                    if (isset($row['id'])) {
197
                        $id = $row['id'];
198
                    }
199
200
                    $this->db->query(
201
                        "REPLACE INTO `s_plugin_connect_config`
202
                        (`id`, `name`, `value`, `shopId`, `groupName`)
203
                        VALUES
204
                        (?, ?, 1, null, 'export')",
205
                        [$id, $name]
206
                    );
207
                }
208
            }
209
210
            $this->db->query("
211
                ALTER TABLE `s_plugin_connect_items`
212
                ADD `update_additional_description` VARCHAR(255) NULL DEFAULT 'inherit' AFTER `update_short_description`;
213
            ");
214
        }
215
    }
216
217
    private function createUpdateAdditionalDescriptionColumn()
218
    {
219
        // for some reason update_additional_description column is missing in 1.0.11
220
        if (version_compare($this->version, '1.0.11', '<=')) {
221
            try {
222
                $this->db->query("
223
                        ALTER TABLE `s_plugin_connect_items`
224
                        ADD `update_additional_description` VARCHAR(255) NULL DEFAULT 'inherit' AFTER `update_short_description`;
225
                    ");
226
            } catch (\Exception $e) {
227
                // ignore it if the column already exists
228
            }
229
        }
230
    }
231
232
    private function createDynamicStreamTable()
233
    {
234
        if (version_compare($this->version, '1.0.12', '<=')) {
235
            $query = "CREATE TABLE IF NOT EXISTS `s_plugin_connect_streams_relation` (
236
                `stream_id` int(11) unsigned NOT NULL,
237
                `article_id` int(11) unsigned NOT NULL,
238
                `deleted` int(1) NOT NULL DEFAULT '0',
239
                UNIQUE KEY `stream_id` (`stream_id`,`article_id`),
240
                CONSTRAINT s_plugin_connect_streams_selection_fk_stream_id FOREIGN KEY (stream_id) REFERENCES s_product_streams (id) ON DELETE CASCADE,
241
                CONSTRAINT s_plugin_connect_streams_selection_fk_article_id FOREIGN KEY (article_id) REFERENCES s_articles (id) ON DELETE CASCADE
242
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;";
243
244
            $this->db->exec($query);
245
        }
246
    }
247
248
    private function addOrderStatus()
249
    {
250
        if (version_compare($this->version, '1.0.12', '<=')) {
251
            $query = $this->modelManager->getRepository('Shopware\Models\Order\Status')->createQueryBuilder('s');
252
            $query->select('MAX(s.id)');
253
            $result = $query->getQuery()->getOneOrNullResult();
254
255
            if (count($result) > 0) {
256
                $currentId = (int) reset($result);
257
            } else {
258
                $currentId = 0;
259
            }
260
261
            $name = ConnectOrderUtil::ORDER_STATUS_ERROR;
262
            $group = Status::GROUP_STATE;
263
264
            $isExists = $this->db->query('
265
                SELECT `id` FROM `s_core_states`
266
                WHERE `name` = ? AND `group` = ?
267
                ', [$name, $group]
268
            )->fetch();
269
270
            if ($isExists) {
271
                return;
272
            }
273
274
            ++$currentId;
275
            $this->db->query('
276
                INSERT INTO `s_core_states`
277
                (`id`, `name`, `description`, `position`, `group`, `mail`)
278
                VALUES (?, ?, ?, ?, ?, ?)
279
                ', [$currentId, $name, 'SC error', $currentId, $group, 0]
280
            );
281
        }
282
    }
283
284
    /**
285
     * Replace longDescriptionField and shortDescription values,
286
     * because of wrong snippets in previous versions.
287
     *
288
     * ExtJs view show longDescription label, but the value was stored as shortDescription
289
     */
290
    private function fixExportDescriptionSettings()
291
    {
292
        if (version_compare($this->version, '1.0.12', '<=')) {
293
            $rows = $this->db->fetchPairs(
294
                'SELECT `name`, `value` FROM s_plugin_connect_config WHERE name = ? OR name = ?',
295
                ['longDescriptionField', 'shortDescriptionField']
296
            );
297
298
            if (!array_key_exists('longDescriptionField', $rows) || !array_key_exists('shortDescriptionField', $rows)) {
299
                return;
300
            }
301
302
            if (($rows['longDescriptionField'] == 1 && $rows['shortDescriptionField'] == 1)
303
                || ($rows['longDescriptionField'] == 0 && $rows['shortDescriptionField'] == 0)) {
304
                return;
305
            }
306
307
            $newValues = [
308
                'longDescriptionField' => $rows['shortDescriptionField'],
309
                'shortDescriptionField' => $rows['longDescriptionField'],
310
            ];
311
312
            $this->db->query('
313
                UPDATE `s_plugin_connect_config`
314
                SET `value` = ?
315
                WHERE `name` = ?',
316
                [$newValues['longDescriptionField'], 'longDescriptionField']
317
            );
318
319
            $this->db->query('
320
                UPDATE `s_plugin_connect_config`
321
                SET `value` = ?
322
                WHERE `name` = ?',
323
                [$newValues['shortDescriptionField'], 'shortDescriptionField']
324
            );
325
        }
326
    }
327
328
    private function fixMarketplaceUrl()
329
    {
330
        if (version_compare($this->version, '1.0.12', '<=')) {
331
            $repo = $this->modelManager->getRepository('Shopware\Models\Config\Form');
332
            /** @var \Shopware\Models\Config\Form $form */
333
            $form = $repo->findOneBy([
334
                'name' => 'SwagConnect',
335
            ]);
336
337
            if (!$form) {
338
                return;
339
            }
340
341
            /** @var \Shopware\Models\Config\Element $element */
342
            foreach ($form->getElements() as $element) {
343
                if ($element->getName() != 'connectDebugHost') {
344
                    continue;
345
                }
346
347 View Code Duplication
                if (strlen($element->getValue()) > 0 && strpos($element->getValue(), 'sn.') === false) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
348
                    $element->setValue('sn.' . $element->getValue());
349
                    $this->modelManager->persist($element);
350
                }
351
352
                $values = $element->getValues();
353
                if (count($values) > 0) {
354
                    /** @var \Shopware\Models\Config\Value $element */
355
                    $value = $values[0];
356 View Code Duplication
                    if (strlen($value->getValue()) > 0 && strpos($value->getValue(), 'sn.') === false) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
357
                        $value->setValue('sn.' . $value->getValue());
358
                        $this->modelManager->persist($value);
359
                    }
360
                }
361
362
                $this->modelManager->flush();
363
            }
364
        }
365
    }
366
367
    private function addIndexToChangeTable()
368
    {
369
        if (version_compare($this->version, '1.0.16', '<=')) {
370
            $this->db->query('
371
              ALTER TABLE `sw_connect_change`
372
              ADD INDEX `c_operation` (`c_operation`)
373
             ');
374
        }
375
    }
376
377
    /**
378
     * In some cases Connect main menu was duplicated
379
     * when shop is connected to SEM project. All not needed menu items must be removed.
380
     */
381
    private function removeDuplicatedMenuItems()
382
    {
383
        if (version_compare($this->version, '1.0.16', '<=')) {
384
            $mainMenuItems = $this->bootstrap->Menu()->findBy([
385
                'class' => Menu::CONNECT_CLASS,
386
                'parent' => null,
387
            ], ['id' => 'ASC']);
388
389
            foreach (array_slice($mainMenuItems, 1) as $menuItem) {
390
                foreach ($menuItem->getChildren() as $children) {
391
                    $this->modelManager->remove($children);
392
                }
393
394
                $this->modelManager->remove($menuItem);
395
            }
396
            $this->modelManager->flush();
397
        }
398
    }
399
400
    /**
401
     * Create an index by source_id and shop_id.
402
     * It's most used combination to search for products in this table
403
     */
404
    private function addConnectItemsIndex()
405
    {
406
        if (version_compare($this->version, '1.1.1', '<=')) {
407
            try {
408
                $this->db->query('ALTER TABLE s_plugin_connect_items ADD INDEX source_id (source_id, shop_id)');
409
            } catch (\Exception $e) {
410
                // ignore it if exists
411
            }
412
        }
413
    }
414
}
415