<?php
// Copyright (c) Pickware GmbH. All rights reserved.
// This file is part of software that is released under a proprietary license.
// You must not copy, modify, distribute, make publicly available, or execute
// its contents or parts thereof without express permission by the copyright
// holder, unless otherwise permitted by law.

// Require composer dependecies if necessary
if (file_exists(__DIR__ . '/vendor/autoload.php')) {
    require_once(__DIR__ . '/vendor/autoload.php');
}

if (!class_exists('ViisonCommon_Plugin_BootstrapV14')) {
    require_once 'ViisonCommon/PluginBootstrapV14.php';
}

require_once('Util.php');

use Doctrine\ORM\Tools\SchemaTool;
use Shopware\Plugins\ViisonCommon\Classes\Exceptions\InstallationException;
use Shopware\Plugins\ViisonCommon\Classes\Installation\AttributeColumn\AttributeColumnDescription;
use Shopware\Plugins\ViisonCommon\Classes\Installation\AttributeColumn\AttributeColumnInstaller;
use Shopware\Plugins\ViisonCommon\Classes\Installation\AttributeColumn\AttributeColumnUninstaller;
use Shopware\Plugins\ViisonCommon\Classes\Installation\Schema\SchemaCreator;
use Shopware\Plugins\ViisonCommon\Classes\Installation\SQLHelper;
use Shopware\Plugins\ViisonCommon\Classes\Util\Util as ViisonCommonUtil;
use Shopware\Plugins\ViisonCommon\Components\Plugins\SwagImportExportProfileService;
use Shopware\Plugins\ViisonSetArticles\Classes;
use Shopware\Plugins\ViisonSetArticles\Components\PluginConfigService;
use Shopware\Plugins\ViisonSetArticles\Subscribers;
use Shopware\Plugins\ViisonSetArticles\Subscribers\PluginIntegration\SwagImportExportIntegrationSubscriber;

/*
 * "Declare" some methods that are not required in our bootstrap, but whose existence is checked during Shopware's
 * code review:
 *
 * public function getVersion() {}
 */

/**
 * Bootstrap for ArticleSet
 */
class Shopware_Plugins_Core_ViisonSetArticles_Bootstrap extends ViisonCommon_Plugin_BootstrapV14
{
    /**
     * @inheritdoc
     */
    protected $codeVersion = '1.12.5.55';

    /**
     * @inheritdoc
     */
    protected $minRequiredShopwareVersion = '5.5.0';

    /**
     * @inheritdoc
     */
    public function runUpdate($oldVersion)
    {
        $this->checkLicenseInternal();

        // Initialize helpers
        $entityManager = $this->get('models');
        $database = $this->get('db');
        $sqlHelper = new SQLHelper($database);
        $form = $this->Form();
        $schemaTool = new SchemaTool($entityManager);
        $schemaCreator = new SchemaCreator($entityManager->getConnection()->getSchemaManager(), $schemaTool);
        $attributeColumnInstaller = new AttributeColumnInstaller($entityManager, $sqlHelper);
        $attributeColumnUninstaller = new AttributeColumnUninstaller($entityManager, $sqlHelper);

        $oldInstallVersion = ViisonCommonUtil::convertBinaryVersionToInstallVersion($oldVersion);
        switch ($oldInstallVersion) {
            case 'install':
                $this->subscribeEvent(
                    'Enlight_Controller_Front_StartDispatch',
                    'onStartDispatch'
                );

                // Create custom model schema
                $schemaCreator->createSchemaUnlessTableExists([
                    $entityManager->getClassMetaData('Shopware\\CustomModels\\ViisonSetArticles\\SetArticle')
                ]);

                // Add attributes
                $attributeColumnInstaller->addAttributeColumnsIfNotExist([
                    new AttributeColumnDescription(
                        's_articles_attributes',
                        'viison_setarticle_active',
                        'tinyint(1)'
                    ),
                    new AttributeColumnDescription(
                        's_order_details_attributes',
                        'viison_setarticle_orderid',
                        'int(11)'
                    ),
                ]);
            case '1.0.0':
                // Remove the not null constraint from the 'viison_setarticle_active' article attribute field
                $sqlHelper->removeNotNullConstraint('s_articles_attributes', 'viison_setarticle_active');
            case '1.0.1':
                // Nothing to do, bugfix release
            case '1.0.2':
                // Nothing to do, bugfix release
            case '1.0.3':
                // Nothing to do, bugfix release
            case '1.0.4':
                // Nothing to do, bugfix release
            case '1.0.5':
                // Nothing to do, bugfix release
            case '1.0.6':
                // Nothing to do, bugfix release
            case '1.0.7':
                // Nothing to do, bugfix release
            case '1.0.8':
                // Nothing to do, bugfix release
            case '1.0.9':
                // Nothing to do, bugfix release
            case '1.0.10':
                // Nothing to do, bugfix release
            case '1.0.11':
                // Nothing to do, bugfix release
            case '1.0.12':
                // Nothing to do, bugfix release
            case '1.0.13':
                // Fix generated variants before version 1.0.9 (custom attribute viisonSetArticleActive fix):
                // Copy viison_setarticle_active flag from main variant (kind = 1) to all other variants
                $database->query(
                    'UPDATE s_articles_attributes AS att
                        INNER JOIN s_articles_attributes AS att_main
                        INNER JOIN s_articles_details AS ad
                        INNER JOIN s_articles_details AS ad_main
                        SET att.viison_setarticle_active = att_main.viison_setarticle_active
                        WHERE ad_main.id = att_main.articledetailsID
                        AND ad.id = att.articledetailsID
                        AND ad.articleID = ad_main.articleID
                        AND ad_main.kind = 1'
                );
            case '1.0.14':
                // Nothing to do, bugfix release
            case '1.0.15':
                // Nothing to do, bugfix release
            case '1.0.16':
                // Nothing to do, bugfix release
            case '1.0.17':
                // Nothing to do, bugfix release
            case '1.0.18':
                // Nothing to do, bugfix release
            case '1.0.19':
                // Nothing to do, bugfix release
            case '1.0.20':
                // Nothing to do, bugfix release
            case '1.0.21':
                // Nothing to do, bugfix release
            case '1.0.22':
                // Make display of sub articles in Documents configurable (default is 1)
                $form->setElement(
                    'select',
                    'viisonDocumentUnfolding',
                    [
                        'label' => 'Stücklisten-Artikel auf Dokumenten ausklappen',
                        'description' => 'Stücklisten-Artikel werden auf Dokumenten (Rechnung, Lieferschein, etc.) "aufgeklappt", sodass alle Sub-Artikel ebenfalls aufgelistet werden.',
                        'store' => [
                            [
                                1,
                                'Sub-Artikel anzeigen (ohne eigenen Preis)',
                            ],
                            [
                                0,
                                'Sub-Artikel verbergen',
                            ],
                        ],
                        'value' => 1,
                    ]
                );
            case '1.0.23':
                // Nothing to do, bugfix release
            case '1.0.24':
                // Nothing to do, bugfix release
            case '1.0.25':
                // Nothing to do, bugfix release
            case '1.0.26':
                // Nothing to do, bugfix release
            case '1.1.0':
                // Nothing to do, bugfix release
            case '1.1.1':
                // Nothing to do, bugfix release
            case '1.1.2':
                // Nothing to do, bugfix release
            case '1.1.3':
                // Nothing to do, bugfix release
            case '1.1.4':
                // Nothing to do, bugfix release
            case '1.1.5':
                // Nothing to do, bugfix release
            case '1.1.6':
                // Nothing to do, bugfix release
            case '1.1.7':
                // Nothing to do, bugfix release
            case '1.1.8':
                // Nothing to do, bugfix release
            case '1.1.9':
                // Nothing to do
            case '1.1.10':
                // Nothing to do
            case '1.1.11':
                // setarticle_active: add information to order position wether or not it's a SetArticle
                $attributeColumnInstaller->addAttributeColumnsIfNotExist([
                    new AttributeColumnDescription(
                        's_order_details_attributes',
                        'viison_setarticle_active',
                        'tinyint(1)',
                        0,
                        false
                    )
                ]);
            case '1.1.12':
                // Nothing to do
            case '1.1.13':
                // Fix attribute field constraint (make viison_setarticle_active nullable)
                $sqlHelper->removeNotNullConstraint('s_order_details_attributes', 'viison_setarticle_active');
            case '1.1.14':
                // Nothing to do
            case '1.1.15':
                // Nothing to do
            case '1.1.16':
                // Nothing to do
            case '1.1.17':
                // Nothing to do
            case '1.1.18':
                // Patch Magnalister plugin
                if (ViisonCommonUtil::isPluginInstalledAndActive('Backend', 'RedMagnalister')) {
                    $magnalisterPatcher = new Classes\MagnalisterPatcher($this->get('models'));
                    $patchResult = $magnalisterPatcher->doPatch();
                    $this->growlMessages[] = $patchResult['message'];
                }

                // Activate viison_not_relevant_for_stock_manager for each set article (detail) if PickwareERP is
                // installed
                if ($sqlHelper->doesColumnExist('s_articles_attributes', 'viison_not_relevant_for_stock_manager')) {
                    $database->query(
                        'UPDATE s_articles_attributes
                        SET viison_not_relevant_for_stock_manager = 1
                        WHERE viison_setarticle_active = 1'
                    );
                }
            case '1.1.19':
                // Nothing to do
            case '1.2.0':
                // Nothing to do
            case '1.2.1':
                // Nothing to do
            case '1.2.2':
                // Nothing to do
            case '1.2.3':
                // Nothing to do
            case '1.2.4':
                // Set weight to all set articles initially. Old weights are overwritten
                $database->query(
                    'UPDATE s_articles_details sad
                     SET weight = 0.001
                     WHERE sad.id IN (
                        SELECT articledetailsID
                        FROM s_articles_attributes
                        WHERE viison_setarticle_active = 1
                    )'
                );
            case '1.2.5':
                // Nothing to do
            case '1.2.6':
                // Nothing to do
            case '1.2.7':
                // Nothing to do
            case '1.2.8':
                // Nothing to do
            case '1.2.9':
                // Nothing to do
            case '1.2.10':
                // Nothing to do
            case '1.2.11':
                // Nothing to do
            case '1.2.12':
                // Nothing to do
            case '1.3.0':
                // Nothing to do
            case '1.3.1':
                // Nothing to do
            case '1.3.2':
                // Nothing to do
            case '1.3.3':
                // Nothing to do
            case '1.3.4':
                // Register this plugin (and its subscribers) when a CLI command is executed
                $this->subscribeEvent(
                    'Shopware_Console_Add_Command',
                    'onAddConsoleCommand'
                );
            case '1.3.5':
                // Nothing to do
            case '1.3.6':
                // Nothing to do
            case '1.3.7':
                // Remove set article rows that refer to deleted articles that no longer exist
                $database->query(
                    'DELETE FROM s_articles_viison_setarticles
                        WHERE articledetailid NOT IN (SELECT id FROM s_articles_details)
                        OR setid NOT IN (SELECT id FROM s_articles_details)'
                );

                // Then alter column type (make it unsigned), and add not null constraint to add the foreign key
                // constraint so set article connections are deleted if the respective article detail is deleted.
                $sqlHelper->alterColumnIfExists(
                    's_articles_viison_setarticles',
                    'articledetailid',
                    'articledetailid',
                    'int(11) unsigned NOT NULL DEFAULT 0'
                );
                $sqlHelper->addForeignKeyConstraint(
                    's_articles_viison_setarticles',
                    'articledetailid',
                    's_articles_details',
                    'id',
                    'CASCADE'
                );
                // Do the same for setid of set article connections
                $sqlHelper->alterColumnIfExists(
                    's_articles_viison_setarticles',
                    'setid',
                    'setid',
                    'int(11) unsigned NOT NULL DEFAULT 0'
                );
                $sqlHelper->addForeignKeyConstraint(
                    's_articles_viison_setarticles',
                    'setid',
                    's_articles_details',
                    'id',
                    'CASCADE'
                );
            case '1.3.8':
                // Nothing to do
            case '1.3.9':
                // Nothing to do
            case '1.3.10':
                // Nothing to do
            case '1.3.11':
                // Nothing to do
            case '1.3.12':
                // In version 1.1.12 a new attribute viison_setarticle_active was added to the order details
                // attributes model. Unfortunately the model re-generation was missing. This caused a lot of
                // support issues in the past. To catch up on this issue we regenerate the model here.
                $entityManager->generateAttributeModels([
                    's_order_details_attributes'
                ]);
            case '1.3.13':
                $attributeColumnUninstaller->removeAttributeColumnsIfExist([
                    new AttributeColumnDescription(
                        's_order_details_attributes',
                        'viison_setarticle_active'
                    ),
                ]);

                // Also update plugin Magnalister patch files
                if (ViisonCommonUtil::isPluginInstalledAndActive('Backend', 'RedMagnalister')) {
                    $magnalisterPatcher = new Classes\MagnalisterPatcher($this->get('models'));
                    $patchResult = $magnalisterPatcher->doPatch();
                    $this->growlMessages[] = $patchResult['message'];
                }
            case '1.3.14':
                // Nothing to do
            case '1.3.15':
                // Nothing to do
            case '1.3.16':
                // Nothing to do
            case '1.3.17':
                // Nothing to do
            case '1.3.18':
                // Nothing to do
            case '1.3.19':
                // Nothing to do
            case '1.3.20':
                // Nothing to do
            case '1.3.21':
                // Nothing to do
            case '1.3.22':
                // Nothing to do
            case '1.3.23':
                // Nothing to do
            case '1.3.24':
                // Nothing to do
            case '1.3.25':
                // Nothing to do
            case '1.3.26':
                // Clear maxpurchase of set articles
                $database->query('UPDATE s_articles_details sad
                    LEFT JOIN s_articles_attributes saa ON sad.id = saa.articledetailsID
                    SET sad.maxpurchase = NULL
                    WHERE saa.viison_setarticle_active = 1');
                // Clear laststock of set articles main articles
                $database->query('UPDATE s_articles sa
                    LEFT JOIN s_articles_details sad ON sa.id = sad.articleID
                    LEFT JOIN s_articles_attributes saa ON sad.id = saa.articledetailsID
                    SET sa.laststock = 0
                    WHERE saa.viison_setarticle_active = 1
                    AND sad.kind = 1');
                // Clear last stock of set article details in SW5.4+
                if (ViisonCommonUtil::assertMinimumShopwareVersion('5.4.0')) {
                    $database->query('UPDATE s_articles_details sad
                        LEFT JOIN s_articles_attributes saa ON sad.id = saa.articledetailsID
                        SET sad.laststock = 0
                        WHERE saa.viison_setarticle_active = 1');
                }
            case '1.3.27':
                // Nothing to do
            case '1.3.28':
                // Nothing to do
            case '1.3.29':
                // Nothing to do
            case '1.3.30':
                // Update magnalister patch files (we updates the sub-set-assignment after an order was imported)
                if (ViisonCommonUtil::isPluginInstalledAndActive('Backend', 'RedMagnalister')) {
                    $magnalisterPatcher = new Classes\MagnalisterPatcher($this->get('models'));
                    $patchResult = $magnalisterPatcher->doPatch();
                    $this->growlMessages[] = $patchResult['message'];
                }
            case '1.3.31':
                // Update magnalister patch files (we fixed a bug)
                if (ViisonCommonUtil::isPluginInstalledAndActive('Backend', 'RedMagnalister')) {
                    $magnalisterPatcher = new Classes\MagnalisterPatcher($this->get('models'));
                    $patchResult = $magnalisterPatcher->doPatch();
                    $this->growlMessages[] = $patchResult['message'];
                }
            case '1.3.32':
                // Nothing to do
            case '1.3.33':
                // Nothing to do
            case '1.3.34':
                // Update magnalister patch files (we fixed a bug by removing the article name html-encoding)
                if (ViisonCommonUtil::isPluginInstalledAndActive('Backend', 'RedMagnalister')) {
                    $magnalisterPatcher = new Classes\MagnalisterPatcher($this->get('models'));
                    $patchResult = $magnalisterPatcher->doPatch();
                    $this->growlMessages[] = $patchResult['message'];
                }
            case '1.3.35':
                // Nothing to do
            case '1.3.36':
                // Nothing to do
            case '1.3.37':
                // Nothing to do
            case '1.3.38':
                // Nothing to do
            case '1.3.39':
                // Nothing to do
            case '1.4.0':
                // Nothing to do
            case '1.4.1':
                // Nothing to do
            case '1.5.0':
                // Nothing to do
            case '1.6.0':
                // Nothing to do
            case '1.6.1':
                // Nothing to do
            case '1.6.2':
                // Nothing to do
            case '1.6.3':
                // Update existing config element option snippets and allow option for partial delivery notes via
                // Pickware WMS. Rename config field to reflect the new functionality.
                $entityManager->persist($form);
                $oldConfigElement = $form->getElement('viisonDocumentUnfolding');
                $newConfigElement = $form->getElement('displaySubArticlesOnDocuments');
                if ($oldConfigElement && !$newConfigElement) {
                    $configElementOptions = $oldConfigElement->getOptions();
                    $configElementOptions['store'] = [
                        0 => [
                            PluginConfigService::NEVER_SHOW_SUB_ARTICLES_ON_DOCUMENTS,
                            'Sub-Artikel immer ausblenden',
                        ],
                        1 => [
                            PluginConfigService::ALWAYS_SHOW_SUB_ARTICLES_ON_DOCUMENTS,
                            'Sub-Artikel immer anzeigen (ohne Preis)',
                        ],
                        2 => [
                            PluginConfigService::ONLY_SHOW_SUB_ARTICLES_ON_PARTIAL_DELIVERY_NOTES,
                            'Sub-Artikel nur auf Teillieferscheinen anzeigen',
                        ],
                    ];
                    $oldConfigElement->setOptions($configElementOptions);
                    $oldConfigElement->setName('displaySubArticlesOnDocuments');
                    $entityManager->flush($oldConfigElement);
                } elseif ($oldConfigElement && $newConfigElement) {
                    // When double-installing the plugin (flag as uninstalled in the db, install again) we need to check
                    // if the new config element name already exist. Do not change but remove the old config element in
                    // that case to ensure idempotency
                    $form->removeElement($oldConfigElement);
                    $entityManager->remove($oldConfigElement);
                    $entityManager->flush($form);
                }
            case '1.7.0':
                // Update SwagImportExport profiles if necessary
                if (ViisonCommonUtil::isPluginInstalledAndActive('', 'SwagImportExport')) {
                    /** @var SwagImportExportProfileService $profileLoader */
                    $profileLoader = $this->get('viison_common.swag_import_export_profile_service');
                    $profileLoader->updateExistingProfiles(
                        SwagImportExportIntegrationSubscriber::PROFILE_NAMES,
                        $this->Path() . 'Components/SwagImportExportIntegration/Profiles/'
                    );
                }
            case '1.8.0':
                // Nothing to do
            case '1.8.1':
                // Nothing to do
            case '1.8.2':
                // Nothing to do
            case '1.8.3':
                // Nothing to do
            case '1.8.4':
                // Nothing to do
            case '1.8.5':
                // Nothing to do
            case '1.8.6':
                // Nothing to do
            case '1.9.0':
                // Nothing to do
            case '1.9.1':
                // Nothing to do
            case '1.9.2':
                // Nothing to do
            case '1.9.3':
                // Nothing to do
            case '1.9.4':
                // Nothing to do
            case '1.9.5':
                // Nothing to do
            case '1.9.6':
                // Nothing to do
            case '1.10.0':
                // Nothing to do
            case '1.10.1':
                // Nothing to do
            case '1.10.2':
                // Nothing to do
            case '1.11.0':
                // Nothing to do
            case '1.11.1':
                // Nothing to do
            case '1.11.2':
                // Nothing to do
            case '1.11.3':
                // Nothing to do
            case '1.11.4':
                // Nothing to do
            case '1.11.5':
                // Nothing to do
            case '1.11.6':
                // Nothing to do
            case '1.11.7':
                // Nothing to do
            case '1.12.0':
                // Nothing to do
            case '1.12.1':
                // Nothing to do
            case '1.12.2':
                // Nothing to do
            case '1.12.3':
                // Nothing to do
            case '1.12.4':
                // Nothing to do
            case '1.12.5':
                // Next release

                // Do not remove this break
                break;
            default:
                throw InstallationException::updateFromVersionNotSupported(
                    $this,
                    $oldVersion,
                    $this->getVersion()
                );
        }

        // Execute after each update
        $this->removeObsoletePluginFiles();

        // Update the form translations
        $this->updateConfigFormTranslations();
    }

    /**
     * @inheritdoc
     */
    public function runUninstall($deleteData)
    {
        if (!$deleteData) {
            return;
        }

        // Initialize helpers
        $entityManager = $this->get('models');
        $sqlHelper = new SQLHelper($this->get('db'));
        $schemaTool = new SchemaTool($entityManager);
        $attributeColumnUninstaller = new AttributeColumnUninstaller($entityManager, $sqlHelper);

        // Remove custom model schema
        $schemaTool->dropSchema([
            $entityManager->getClassMetaData('Shopware\\CustomModels\\ViisonSetArticles\\SetArticle')
        ]);

        // Remove attributes
        $attributeColumnUninstaller->removeAttributeColumnsIfExist([
            new AttributeColumnDescription(
                's_articles_attributes',
                'viison_setarticle_active'
            ),
            new AttributeColumnDescription(
                's_order_details_attributes',
                'viison_setarticle_active'
            ),
            new AttributeColumnDescription(
                's_order_details_attributes',
                'viison_setarticle_orderid'
            ),
        ]);

        // Remove plugin patch files
        if (ViisonCommonUtil::isPluginInstalled('Backend', 'RedMagnalister')) {
            $magnalisterPatcher = new Classes\MagnalisterPatcher($this->get('models'));
            $magnalisterPatcher->undoPatch();
        }
    }

    /**
     * @inheritdoc
     */
    public function runActivation()
    {
        if (ViisonCommonUtil::isPluginInstalledAndActive('Backend', 'RedMagnalister')) {
            $magnalisterPatcher = new Classes\MagnalisterPatcher($this->get('models'));
            $magnalisterPatcher->doPatch();
        }
    }

    /**
     * @inheritdoc
     */
    public function runDeactivation()
    {
        // Do nothing
    }

    /**
     * Registers the plugin's namespaces and default models.
     */
    public function afterInit()
    {
        $this->loadDependencies();
        $this->loadPlugin();
    }

    /**
     * Could add CLI command, but is not needed.
     *
     * @param \Enlight_Event_EventArgs $args
     */
    public function onAddConsoleCommand(\Enlight_Event_EventArgs $args)
    {
        // Nothing to do here, since the dynamic subscribers were already registered in 'afterInit()'
    }

    /**
     * This callback function is triggered at the very beginning of the dispatch process and allows
     * us to register additional events on the fly.
     *
     * @param \Enlight_Event_EventArgs $args
     */
    public function onStartDispatch(\Enlight_Event_EventArgs $args)
    {
        // Nothing to do here, since the dynamic subscribers were already registered in 'afterInit()'
    }

    /**
     * Uses the dependency loader to load the namespaces and susbcribers of all required,
     * shared dependencies.
     */
    private function loadDependencies()
    {
        // Require all shared dependencies
        $loader = VIISON\ShopwarePluginDependencyLoader\Loader::getInstance();
        $loader->requireDependencies(
            $this->Path(),
            [
                'ViisonCommon'
            ]
        );
        Shopware\Plugins\ViisonCommon\Classes\PickwareAutoloadDependencyLoader::ensureDependenciesLoaded();

        // Add the subscribers of all dependencies
        $viisonCommonSubscriberRegistrator = new Shopware\Plugins\ViisonCommon\Classes\SubscriberRegistrator($this);
        $viisonCommonSubscriberRegistrator->registerSubscribers();

        // Load the Shopware polyfill
        require_once __DIR__ . '/ViisonCommon/Polyfill/Loader.php';
    }

    /**
     * First checks whether the plugin has a valid license, is installed and is active.
     * If all this is true, first the namespaces of this plugin are registered with the
     * class loader, before all subscribers are instanciated and added to the event manager.
     */
    private function loadPlugin()
    {
        if (!$this->checkLicenseInternal(false)) {
            return;
        }

        // Make sure this plugin is installed and active before registering the susbcribers
        if (!$this->isInstalledAndActive()) {
            return;
        }

        // Create all plugin subscribers
        $subscribers = [
            new Subscribers\Api\OrderSubscriber($this),
            new Subscribers\Backend\AnalyticsSubscriber($this),
            new Subscribers\Backend\ArticleSubscriber($this),
            new Subscribers\Backend\CommonSubscriber($this),
            new Subscribers\Backend\CoreOrderSubscriber($this),
            new Subscribers\Backend\ExportSubscriber($this),
            new Subscribers\Backend\NotificationSubscriber($this),
            new Subscribers\Backend\OrderSubscriber($this),
            new Subscribers\CompatibilityCheckSubscriber($this),
            new Subscribers\Components\DocumentSubscriber($this),
            new Subscribers\Components\TemplateMailComponentSubscriber($this),
            new Subscribers\ControllersSubscriber($this),
            new Subscribers\Core\ArticleSubscriber($this),
            new Subscribers\Extension\BackendSubscriber($this),
            new Subscribers\Frontend\AccountSubscriber($this),
            new Subscribers\Frontend\AdminSubscriber($this),
            new Subscribers\Frontend\ArticleSubscriber($this),
            new Subscribers\Frontend\BasketSubscriber($this),
            new Subscribers\Frontend\CheckoutSubscriber($this),
            new Subscribers\Frontend\FrontendArticleCartEnablerSubscriber($this),
            new Subscribers\Frontend\SearchSubscriber($this),
            new Subscribers\Frontend\StorytellingSubscriber($this),
            new Subscribers\Modules\MailSubscriber($this),
            new Subscribers\PluginIntegration\SwagImportExportIntegrationSubscriber($this),
            new Subscribers\PluginInstallationSubscriber($this),
            new Subscribers\ServiceDecorationSubscriber($this),
            new Subscribers\ServicesSubscriber($this),
            new Subscribers\SubApplicationRegistrationSubscriber($this),
            new Subscribers\ThemeSubscriber($this),
        ];

        // Make sure that the subscribers are only added once
        if (!$this->isSubscriberRegistered($subscribers[0])) {
            $eventManager = $this->get('events');
            foreach ($subscribers as $subscriber) {
                $eventManager->addSubscriber($subscriber);
            }
        }
    }

    // Removed license checking method
    // Removed license checking method
    // Removed license checking method
    // Removed license checking method
    // Removed license checking method
    // Removed license checking method

    /**
     * Checks whether this shop has a license to run this plugin.
     *
     * @param bool $throwException
     * @throws Exception
     * @return bool True, if the plugin is licensed. Otherwise false.
     */
    public function checkLicenseInternal($throwException = true)
    {
        $ionCubeNotLoaded = !extension_loaded('ionCube Loader');
        $fileNotEncoded = function_exists('ioncube_file_is_encoded') && !ioncube_file_is_encoded();
        if ($ionCubeNotLoaded || $fileNotEncoded) {
            return true;
        }

        if (!Shopware()->Container()->has('license')) {
            if ($throwException) {
                throw new Exception('The license manager has to be installed and active');
            } else {
                return false;
            }
        }

        try {
            static $r;
            static $module = 'ViisonSetArticles';
            if (!isset($r)) {
                $s = base64_decode('JHfWbSisxP417nWbhO2ujyfcCB4=');
                $c = base64_decode('4EGj5rc0Q+s64O6K6S+l4F6W6+k=');
                $r = sha1(uniqid('', true), true);
                /** @var $l Shopware_Components_License */
                $l = $this->Application()->License();
                $i = $l->getLicense($module, $r);
                $t = $l->getCoreLicense();
                // phpcs:ignore Generic.PHP.ForbiddenFunctions -- using mb_strlen() here changes the semantics and breaks the license check for some customers
                $u = strlen($t) === 20 ? sha1($t . $s . $t, true) : 0;
                $r = $i === sha1($c . $u . $r, true);
            }
            if (!$r && $throwException) {
                throw new Exception('License check for module "' . $module . '" has failed.');
            }

            return $r;
        } catch (Exception $e) {
            if ($throwException) {
                throw new Exception('License check for module "' . $module . '" has failed.');
            } else {
                return false;
            }
        }
    }
}
