Completed
Pull Request — master (#393)
by Jonas
03:21
created

Lifecycle   C

Complexity

Total Complexity 66

Size/Duplication

Total Lines 456
Duplicated Lines 14.47 %

Coupling/Cohesion

Components 1
Dependencies 7

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 66
loc 456
rs 5.7474
wmc 66
lcom 1
cbo 7

19 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 14 14 1
A getSubscribedEvents() 0 14 1
B onPreUpdate() 0 38 6
A onUpdateOrder() 0 16 3
A onDeleteArticle() 0 5 1
A onPreDeleteCategory() 0 5 1
A onPostDeleteCategory() 0 4 1
A onDeleteDetail() 0 13 3
A onUpdateArticle() 0 6 1
C handleChange() 0 57 14
C onPersistDetail() 0 39 7
A onDeleteShop() 0 15 3
B generateChangesForDetail() 21 21 5
B generateChangesForArticle() 20 20 5
A isAutoUpdateEnabled() 0 4 2
A updateOrderStatus() 0 16 4
A updatePaymentStatus() 0 12 2
A generateChangeForPaymentStatus() 0 8 2
A hasPriceType() 11 11 4

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like Lifecycle often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Lifecycle, and based on these observations, apply Extract Interface, too.

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\Connect\Struct\PaymentStatus;
13
use Shopware\Components\Model\ModelManager;
14
use Shopware\CustomModels\Connect\Attribute;
15
use ShopwarePlugins\Connect\Components\Config;
16
use ShopwarePlugins\Connect\Components\Helper;
17
use ShopwarePlugins\Connect\Components\Utils;
18
use ShopwarePlugins\Connect\Components\ConnectExport;
19
use Shopware\Models\Order\Order;
20
21
/**
22
 * Handles article lifecycle events in order to automatically update/delete products to/from connect
23
 *
24
 * Class Lifecycle
25
 * @package ShopwarePlugins\Connect\Subscribers
26
 */
27
class Lifecycle implements SubscriberInterface
28
{
29
    /**
30
     * @var \Shopware\Components\Model\ModelManager
31
     */
32
    private $manager;
33
34
    /**
35
     * @var Helper
36
     */
37
    private $helper;
38
    /**
39
     * @var SDK
40
     */
41
    private $sdk;
42
43
    /**
44
     * @var Config
45
     */
46
    private $config;
47
48
    /**
49
     * @var ConnectExport
50
     */
51
    private $connectExport;
52
53
    /**
54
     * @var int
55
     */
56
    private $autoUpdateProducts;
57
58
    /**
59
     * Lifecycle constructor.
60
     *
61
     * @param ModelManager $modelManager
62
     * @param Helper $helper
63
     * @param SDK $sdk
64
     * @param Config $config
65
     * @param ConnectExport $connectExport
66
     */
67 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...
68
        ModelManager $modelManager,
69
        Helper $helper,
70
        SDK $sdk,
71
        Config $config,
72
        ConnectExport $connectExport
73
    ) {
74
        $this->manager = $modelManager;
75
        $this->helper = $helper;
76
        $this->sdk = $sdk;
77
        $this->config = $config;
78
        $this->connectExport = $connectExport;
79
        $this->autoUpdateProducts = $this->config->getConfig('autoUpdateProducts', 1);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $this->autoUpdateProducts is correct as $this->config->getConfig('autoUpdateProducts', 1) (which targets ShopwarePlugins\Connect\...nts\Config::getConfig()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
80
    }
81
82
    /**
83
     * {@inheritdoc}
84
     */
85
    public static function getSubscribedEvents()
86
    {
87
        return [
88
            'Shopware\Models\Article\Article::preUpdate' => 'onPreUpdate',
89
            'Shopware\Models\Article\Article::postPersist' => 'onUpdateArticle',
90
            'Shopware\Models\Article\Detail::postPersist' => 'onPersistDetail',
91
            'Shopware\Models\Article\Article::preRemove' => 'onDeleteArticle',
92
            'Shopware\Models\Article\Detail::preRemove' => 'onDeleteDetail',
93
            'Shopware\Models\Order\Order::postUpdate' => 'onUpdateOrder',
94
            'Shopware\Models\Shop\Shop::preRemove' => 'onDeleteShop',
95
            'Shopware\Models\Category\Category::preRemove' => 'onPreDeleteCategory',
96
            'Shopware\Models\Category\Category::postRemove' => 'onPostDeleteCategory'
97
        ];
98
    }
99
100
    public function onPreUpdate(\Enlight_Event_EventArgs $eventArgs)
101
    {
102
        /** @var \Shopware\Models\Article\Article $entity */
103
        $entity = $eventArgs->get('entity');
104
        $db = Shopware()->Db();
105
106
        // Check if entity is a connect product
107
        $attribute = $this->helper->getConnectAttributeByModel($entity);
108
        if (!$attribute) {
109
            return;
110
        }
111
112
        // if article is not exported to Connect
113
        // don't need to generate changes
114
        if (!$this->helper->isProductExported($attribute) || !empty($attribute->getShopId())) {
115
            return;
116
        }
117
118
        if (!$this->hasPriceType()) {
119
            return;
120
        }
121
122
        $changeSet = $eventArgs->get('entityManager')->getUnitOfWork()->getEntityChangeSet($entity);
123
124
        // If product propertyGroup is changed we need to store the old one,
125
        // because product property value are still not changed and
126
        // this will generate wrong Connect changes
127
        if ($changeSet['propertyGroup']) {
128
            $filterGroupId = $db->fetchOne(
129
                'SELECT filtergroupID FROM s_articles WHERE id = ?', [$entity->getId()]
130
            );
131
132
            $db->executeUpdate(
133
                'UPDATE `s_articles_attributes` SET `connect_property_group` = ? WHERE `articledetailsID` = ?',
134
                [$filterGroupId, $entity->getMainDetail()->getId()]
135
            );
136
        }
137
    }
138
139
    /**
140
     * @param \Enlight_Event_EventArgs $eventArgs
141
     */
142
    public function onUpdateOrder(\Enlight_Event_EventArgs $eventArgs)
143
    {
144
        /** @var \Shopware\Models\Order\Order $order */
145
        $order = $eventArgs->get('entity');
146
147
        // Compute the changeset and return, if orderStatus did not change
148
        $changeSet = $eventArgs->get('entityManager')->getUnitOfWork()->getEntityChangeSet($order);
149
150
        if (isset($changeSet['paymentStatus'])) {
151
            $this->updatePaymentStatus($order);
152
        }
153
154
        if (isset($changeSet['orderStatus'])) {
155
            $this->updateOrderStatus($order);
156
        }
157
    }
158
159
    /**
160
     * Callback function to delete an product from connect
161
     * after it is going to be deleted locally
162
     *
163
     * @param \Enlight_Event_EventArgs $eventArgs
164
     */
165
    public function onDeleteArticle(\Enlight_Event_EventArgs $eventArgs)
166
    {
167
        $entity = $eventArgs->get('entity');
168
        $this->connectExport->setDeleteStatusForVariants($entity);
169
    }
170
171
    /**
172
     * Callback function to delete an product from connect
173
     * after it is going to be deleted locally
174
     *
175
     * @param \Enlight_Event_EventArgs $eventArgs
176
     */
177
    public function onPreDeleteCategory(\Enlight_Event_EventArgs $eventArgs)
178
    {
179
        $category = $eventArgs->get('entity');
180
        $this->connectExport->markProductsInToBeDeletedCategories($category);
181
    }
182
183
    /**
184
     * Callback function to delete an product from connect
185
     * after it is going to be deleted locally
186
     *
187
     * @param \Enlight_Event_EventArgs $eventArgs
188
     */
189
    public function onPostDeleteCategory(\Enlight_Event_EventArgs $eventArgs)
190
    {
191
        $this->connectExport->handleMarkedProducts();
192
    }
193
194
    /**
195
     * Callback function to delete product detail from connect
196
     * after it is going to be deleted locally
197
     *
198
     * @param \Enlight_Event_EventArgs $eventArgs
199
     */
200
    public function onDeleteDetail(\Enlight_Event_EventArgs $eventArgs)
201
    {
202
        /** @var \Shopware\Models\Article\Detail $entity */
203
        $entity = $eventArgs->get('entity');
204
        if ($entity->getKind() !== 1) {
205
            $attribute = $this->helper->getConnectAttributeByModel($entity);
206
            if (!$this->helper->isProductExported($attribute)) {
207
                return;
208
            }
209
            $this->sdk->recordDelete($attribute->getSourceId());
210
            $this->connectExport->updateConnectItemsStatus([$attribute->getSourceId()], Attribute::STATUS_DELETE);
211
        }
212
    }
213
214
    /**
215
     * Callback method to update changed connect products
216
     *
217
     * @param \Enlight_Event_EventArgs $eventArgs
218
     */
219
    public function onUpdateArticle(\Enlight_Event_EventArgs $eventArgs)
220
    {
221
        $entity = $eventArgs->get('entity');
222
223
        $this->handleChange($entity);
224
    }
225
226
    /**
227
     * Generate changes for Article or Detail if necessary
228
     *
229
     * @param \Shopware\Models\Article\Article | \Shopware\Models\Article\Detail $entity
230
     */
231
    public function handleChange($entity)
232
    {
233
        if (!$entity instanceof \Shopware\Models\Article\Article
0 ignored issues
show
Bug introduced by
The class Shopware\Models\Article\Article does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
234
            && !$entity instanceof \Shopware\Models\Article\Detail
0 ignored issues
show
Bug introduced by
The class Shopware\Models\Article\Detail does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
235
        ) {
236
            return;
237
        }
238
239
        $id = $entity->getId();
240
        $className = get_class($entity);
241
        $model = $this->manager->getRepository($className)->find($id);
242
        // Check if we have a valid model
243
        if (!$model) {
244
            return;
245
        }
246
247
        // Check if entity is a connect product
248
        $attribute = $this->helper->getConnectAttributeByModel($model);
249
        if (!$attribute) {
250
            return;
251
        }
252
253
        // if article is not exported to Connect
254
        // or at least one article detail from same article is not exported
255
        // don't need to generate changes
256
        if (!$this->helper->isProductExported($attribute) || !empty($attribute->getShopId())) {
257
            if (!$this->helper->hasExportedVariants($attribute)) {
258
                return;
259
            }
260
        }
261
262
        if (!$this->hasPriceType()) {
263
            return;
264
        }
265
266
        $forceExport = false;
267
        if ($entity instanceof \Shopware\Models\Article\Detail) {
0 ignored issues
show
Bug introduced by
The class Shopware\Models\Article\Detail does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
268
            $changeSet = $this->manager->getUnitOfWork()->getEntityChangeSet($entity);
269
            // if detail number has been changed
270
            // sc plugin must generate & sync the change immediately
271
            if (array_key_exists('number', $changeSet)) {
272
                $forceExport = true;
273
            }
274
        }
275
276
        // Mark the product for connect update
277
        try {
278
            if ($model instanceof \Shopware\Models\Article\Detail) {
0 ignored issues
show
Bug introduced by
The class Shopware\Models\Article\Detail does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
279
                $this->generateChangesForDetail($model, $forceExport);
280
            } elseif ($model instanceof \Shopware\Models\Article\Article) {
0 ignored issues
show
Bug introduced by
The class Shopware\Models\Article\Article does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
281
                $this->generateChangesForArticle($model, $forceExport);
282
            }
283
        } catch (\Exception $e) {
284
            // If the update fails due to missing requirements
285
            // (e.g. category assignment), continue without error
286
        }
287
    }
288
289
    /**
290
     * Callback method to insert new article details in Connect system
291
     * Used when article is exported and after that variants are generated
292
     *
293
     * @param \Enlight_Event_EventArgs $eventArgs
294
     */
295
    public function onPersistDetail(\Enlight_Event_EventArgs $eventArgs)
296
    {
297
        /** @var \Shopware\Models\Article\Detail $detail */
298
        $detail = $eventArgs->get('entity');
299
300
        /** @var \Shopware\Models\Article\Article $article */
301
        $article = $detail->getArticle();
302
        $articleAttribute = $this->helper->getConnectAttributeByModel($article);
303
        if (!$articleAttribute) {
304
            return;
305
        }
306
307
        // if article is not exported to Connect
308
        // don't need to generate changes
309
        if (!$this->helper->isProductExported($articleAttribute) || !empty($articleAttribute->getShopId())) {
310
            return;
311
        }
312
313
        if (!$this->hasPriceType()) {
314
            return;
315
        }
316
317
        // Mark the article detail for connect export
318
        try {
319
            $this->helper->getOrCreateConnectAttributeByModel($detail);
320
            $forceExport = false;
321
            $changeSet = $eventArgs->get('entityManager')->getUnitOfWork()->getEntityChangeSet($detail);
322
            // if detail number has been changed
323
            // sc plugin must generate & sync the change immediately
324
            if (array_key_exists('number', $changeSet)) {
325
                $forceExport = true;
326
            }
327
328
            $this->generateChangesForDetail($detail, $forceExport);
329
        } catch (\Exception $e) {
330
            // If the update fails due to missing requirements
331
            // (e.g. category assignment), continue without error
332
        }
333
    }
334
335
    /**
336
     * Callback function to shop from export languages
337
     *
338
     * @param \Enlight_Event_EventArgs $eventArgs
339
     */
340
    public function onDeleteShop(\Enlight_Event_EventArgs $eventArgs)
341
    {
342
        /** @var \Shopware\Models\Shop\Shop $shop */
343
        $shop = $eventArgs->get('entity');
344
        $shopId = $shop->getId();
345
        $exportLanguages = $this->config->getConfig('exportLanguages');
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $exportLanguages is correct as $this->config->getConfig('exportLanguages') (which targets ShopwarePlugins\Connect\...nts\Config::getConfig()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
346
        $exportLanguages = $exportLanguages ?: [];
347
348
        if (!in_array($shopId, $exportLanguages)) {
349
            return;
350
        }
351
352
        $exportLanguages = array_splice($exportLanguages, array_search($shopId, $exportLanguages), 1);
353
        $this->config->setConfig('exportLanguages', $exportLanguages, null, 'export');
354
    }
355
356
    /**
357
     * @param \Shopware\Models\Article\Detail $detail
358
     * @param bool $force
359
     */
360 View Code Duplication
    private function generateChangesForDetail(\Shopware\Models\Article\Detail $detail, $force = false)
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...
361
    {
362
        $attribute = $this->helper->getConnectAttributeByModel($detail);
363
        if (!$detail->getActive() && $this->config->getConfig('excludeInactiveProducts')) {
364
            $this->connectExport->syncDeleteDetail($detail);
365
366
            return;
367
        }
368
369
        if ($this->isAutoUpdateEnabled($force)) {
370
            $this->connectExport->export(
371
                [$attribute->getSourceId()], null
372
            );
373
        } elseif ($this->autoUpdateProducts == Config::UPDATE_CRON_JOB) {
374
            $this->manager->getConnection()->update(
375
                's_plugin_connect_items',
376
                ['cron_update' => 1],
377
                ['article_detail_id' => $detail->getId()]
378
            );
379
        }
380
    }
381
382
    /**
383
     * @param \Shopware\Models\Article\Article $article
384
     * @param bool $force
385
     */
386 View Code Duplication
    private function generateChangesForArticle(\Shopware\Models\Article\Article $article, $force = false)
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...
387
    {
388
        if (!$article->getActive() && $this->config->getConfig('excludeInactiveProducts')) {
389
            $this->connectExport->setDeleteStatusForVariants($article);
390
391
            return;
392
        }
393
394
        if ($this->isAutoUpdateEnabled($force)) {
395
            $sourceIds = $this->helper->getSourceIdsFromArticleId($article->getId());
396
397
            $this->connectExport->export($sourceIds, null);
398
        } elseif ($this->autoUpdateProducts == Config::UPDATE_CRON_JOB) {
399
            $this->manager->getConnection()->update(
400
                's_plugin_connect_items',
401
                ['cron_update' => 1],
402
                ['article_id' => $article->getId()]
403
            );
404
        }
405
    }
406
407
    /**
408
     * @param bool $force
409
     * @return bool
410
     */
411
    private function isAutoUpdateEnabled($force)
412
    {
413
        return $this->autoUpdateProducts == Config::UPDATE_AUTO || $force === true;
414
    }
415
416
    /**
417
     * Sends the new order status when supplier change it
418
     *
419
     * @param Order $order
420
     */
421
    private function updateOrderStatus(Order $order)
422
    {
423
        $attribute = $order->getAttribute();
424
        if (!$attribute || !$attribute->getConnectShopId()) {
425
            return;
426
        }
427
428
        $orderStatusMapper = new Utils\OrderStatusMapper();
429
        $orderStatus = $orderStatusMapper->getOrderStatusStructFromOrder($order);
430
431
        try {
432
            $this->sdk->updateOrderStatus($orderStatus);
433
        } catch (\Exception $e) {
434
            // if sn is not available, proceed without exception
435
        }
436
    }
437
438
    /**
439
     * Sends the new payment status when merchant change it
440
     *
441
     * @param Order $order
442
     */
443
    private function updatePaymentStatus(Order $order)
444
    {
445
        $orderUtil = new Utils\ConnectOrderUtil();
446
        if (!$orderUtil->hasLocalOrderConnectProducts($order->getId())) {
447
            return;
448
        }
449
450
        $paymentStatusMapper = new Utils\OrderPaymentStatusMapper();
451
        $paymentStatus = $paymentStatusMapper->getPaymentStatus($order);
452
453
        $this->generateChangeForPaymentStatus($paymentStatus);
454
    }
455
456
    /**
457
     * @param PaymentStatus $paymentStatus
458
     */
459
    private function generateChangeForPaymentStatus(PaymentStatus $paymentStatus)
460
    {
461
        try {
462
            $this->sdk->updatePaymentStatus($paymentStatus);
463
        } catch (\Exception $e) {
464
            // if sn is not available, proceed without exception
465
        }
466
    }
467
468
    /**
469
     * @return bool
470
     */
471 View Code Duplication
    private function hasPriceType()
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...
472
    {
473
        if ($this->sdk->getPriceType() === SDK::PRICE_TYPE_PURCHASE
474
            || $this->sdk->getPriceType() === SDK::PRICE_TYPE_RETAIL
475
            || $this->sdk->getPriceType() === SDK::PRICE_TYPE_BOTH
476
        ) {
477
            return true;
478
        }
479
480
        return false;
481
    }
482
}
483