<?php
/*
 #########################################################################
 #                       xt:Commerce Shopsoftware
 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 #
 # Copyright 2021 xt:Commerce GmbH All Rights Reserved.
 # This file may not be redistributed in whole or significant part.
 # Content of this file is Protected By International Copyright Laws.
 #
 # ~~~~~~ xt:Commerce Shopsoftware IS NOT FREE SOFTWARE ~~~~~~~
 #
 # https://www.xt-commerce.com
 #
 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 #
 # @copyright xt:Commerce GmbH, www.xt-commerce.com
 #
 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 #
 # xt:Commerce GmbH, Maximilianstrasse 9, 6020 Innsbruck
 #
 # office@xt-commerce.com
 #
 #########################################################################
 */

set_time_limit ( 600 );
include_once _SRV_WEBROOT.'xtWizard/config.php';

include_once _SRV_WEBROOT._SRV_WEB_FRAMEWORK.'classes/class.plugin.php';
include_once _SRV_WEBROOT._SRV_WEB_FRAMEWORK.'classes/class.FileHandler.php';
include_once _SRV_WEBROOT._SRV_WEB_FRAMEWORK.'classes/class.ImageTypes.php';


class Update66xTo67x extends ExecutableScript {

    /**
     * (non-PHPdoc)
     * @see IExecutableScript::getWizardType()
     */
    public function getWizardType() {
        return Wizard::WIZARD_TYPE_UPDATE;
    }
    
    /**
     * Needed only for update scripts. Needed to determine if the script can be applied
     * to the current shop version
    */
    
    public function getAppliableShopVersion() {
        return '6.6.0';
    }


    public function getTargetShopVersion() {
        return '6.7.0';
    }
    public function getSkippableShopVersion(){
        return '6.7.0';
    }
    
    /**
     * Get pages
     * @return string
     */
    protected function getPagesXml() {
        return file_get_contents(dirname(__FILE__) . DS . 'pages.xml');
    }
    
    /**
     * Index action - testing quesries
     * @param WizardPage $page
     */
    public function displayStartPage(WizardPage $page) {
        $this->InitialSQL($page);
    }


    /**
     * Complete action
     * @param WizardPage $page
     */
    public function displayFinishPage(WizardPage $page)
    {
		$url = Wizard::getInstance()->buildUrl(array(
			Wizard::PARAM_SCRIPT => 'StartPageScript',
            Wizard::PARAM_PAGE => 'update',
        ));
        // Redirect to update page
        Wizard::getInstance()->redirect($url);
    }
    
    public function displayFinishInstructionsPage(WizardPage $page)
    {
        $page
            ->setTemplate('templates/info_page.html')
            ->assignTemplateVar('message', TEXT_FINISH_INSTRUCTIONS_63.
                '<br /><p class="alert alert-info">'.TEXT_COPY_VERSION_INFO.'</p>'.
                '<p class="alert">'.TEXT_INFO_PLACE_LICENSE.'</p>')
            ->assignTemplateVar('title', 'INFO')
            ->assignTemplateVar('next', true);
    }
    

    protected static function _getFileContent_66_67($filename) {
        $handle = fopen($filename, 'rb');
        $content = fread($handle, filesize($filename));
        fclose($handle);
        return $content;
    }

    public function _installSQL( $idb, $filename, $prefix='', $language_code='',$store_id='', $additionalSqlLines = false) {
        $query = '';
        // open sql
        $filename = dirname(__FILE__) . DS .$filename;
        $sql_content = $this->_getFileContent_66_67($filename);
        if($additionalSqlLines)
        {
            $sql_content .= PHP_EOL.$additionalSqlLines.PHP_EOL.' ';
        }
        $sql_content .= PHP_EOL.' ';

        // replace windows linefeeds
        $sql_content = str_replace("\r\n","\n",$sql_content);
        $queries = array();
        $chars = strlen($sql_content);
        for ($i = 0; $i < $chars; $i++) {
            // check if char is ; and next \n
            if ($sql_content[$i]==';' && $sql_content[$i+1]=="\n") {
                $query .= $sql_content[$i];
                $queries[] = $query;
                $query = '';
                $i++;
            } else {
                if ($sql_content[$i]=='-' && $sql_content[$i+1]=='-') {
                    // skip to next \n
                    for ($ii=$i;$ii<$chars;$ii++) {

                        if ($sql_content[$ii]=="\n") {
                            break;
                        } else {
                            $i++;
                        }

                    }
                } else {
                    if (!isset($query)) $query='';
                    $query.=$sql_content[$i];
                }
            }
        }

        foreach ($queries as $key => $val) {
            $query = trim($val);
            $query = str_replace('##_',$prefix,$query);
            if ($store_id!='') $query = str_replace('**_REPLACE_STORE_ID_**',$store_id,$query);

            // ok, now search vor OTHER INSERT INTO statements, and break them up
            if (substr($query,0,6)=='INSERT') {
                $check_qry = substr($query,7);

                if (strstr($check_qry,'INSERT')) {
                    $qry = explode('INSERT',$check_qry);
                    foreach ($qry as $k => $v) {
                        $queries[]='INSERT '.$v;
                    }
                    unset ($queries[$key]);
                } else {
                    $queries[$key]=$query;
                }
            } else {
                $queries[$key]=$query;
            }
        }
        return $queries;

    }


    /**
     * @param WizardPage $page
     * @throws WizardException
     */
    public function doUpdate(WizardPage $page)
    {
        global $store_handler, $language, $xtPlugin;

        $install_prefix = DB_PREFIX.'_';

        /** @var ADOConnection $idb */
        $idb = Wizard::getInstance()->getDatabaseObject();

        $sql_version = $idb->GetOne("SELECT VERSION() AS Version");
        if(version_compare($sql_version, '5.6') == -1)
        {
            die('Systemanforderung  mysql 5.6 minimum nicht erfüllt. <a href="https://xtcommerce.atlassian.net/wiki/spaces/MANUAL/pages/917573/Systemanforderungen" target="_blank">Handbuch</a>');
        }


        $update_sql = 'update.sql';
        $res = $this->_installSQL(Wizard::getInstance()->getDatabaseObject(), $update_sql, $install_prefix,'', '');

        foreach ($res as $key => $val) {
            $this->addControllerCommand(ControllerCommand::factory()
                ->setAction(function(ControllerCommand $command) use ($val, $idb) {
                    try{
                        $idb->Execute($val);
                    }catch (Exception $e){
                        /*'1060 - Duplicate column name','1062 - Duplicate entry', '1050- table alredy exists','1091 -  Can't DROP '%s'; check that column/key exists'*/
                        $allowed_error_codes = array(1062,1061,1060,1050,1091, 1054, 1091);
                        if (in_array($e->getCode(),$allowed_error_codes)) {
                            $command->setErrorMessage("<br/><span class='msg-skipped'>".TEXT_QUERY_SKIPPED."  " . $e->getMessage() . "</span>");
                        }else{
                            $command->setErrorMessage("<span class='msg-error'>".constant('TEXT_QUERY_FAILED')." " . $e->getMessage() . ' | '.$e->getCode()."</span><br/>");
                            return false;
                        }
                    }

                    return true;
                })
                ->setDescription(TEXT_EXECUTING_QUERY.' '.$val)
                ->setAbortOnError(true)
            );
        }

        // fehlende keys in config_x prüfen und hinzufügen bzw aktualisieren

        // 6.6.x 6.7.x _SYSTEM_TEMPLATE   zieht aus config nach config_x
        $this->addControllerCommand(ControllerCommand::factory()
            ->setAction(function(ControllerCommand $command) use ($idb, $store_handler) {

                $new_key = '_SYSTEM_TEMPLATE';

                $plg = new plugin();

                $system_tpl = $idb->GetOne("SELECT config_value FROM ".TABLE_CONFIGURATION." WHERE config_key = '_SYSTEM_TEMPLATE'");

                WizardLogger::getInstance()->log('DB _config_x create  _SYSTEM_TEMPLATE');

                $stores = $store_handler->getStores();
                foreach ($stores as $store)
                {
                    $table = DB_PREFIX.'_config_'.$store['id'];
                    try
                    {
                        $exists = $idb->GetOne("SELECT 1 FROM ".$table." WHERE config_key = '_SYSTEM_TEMPLATE'");
                        if(!$exists)
                        {
                            $store_tpl = $idb->GetOne("SELECT config_value FROM ".$table." WHERE config_key = '_STORE_DEFAULT_TEMPLATE'");

                            $insert_tpl = $system_tpl;
                            if(empty($insert_tpl))
                                $insert_tpl = $store_tpl;

                            WizardLogger::getInstance()->log($table.' # '.$system_tpl. ' # '.$store_tpl. ' # '.$insert_tpl);

                            $idb->Execute("INSERT INTO `".$table."` (`config_key`, `config_value`, `group_id`, `sort_order`, `type`, `url`) VALUES (?,?, 18, 20, 'dropdown', 'templateSets');", [$new_key, $insert_tpl]);

                            if(in_array($store_tpl, ['ew_adventury', 'ew_evelations', 'xt_responsive']))
                            {
                                // das sind idR eigenständige tpls und können daher als haupt-tpl gesetzt werden
                                $idb->Execute("UPDATE `".$table."` SET `config_value` = ? WHERE `config_key` = '_SYSTEM_TEMPLATE' ;",          [$store_tpl]);
                                $idb->Execute("UPDATE `".$table."` SET `config_value` = ? WHERE `config_key` = '_STORE_DEFAULT_TEMPLATE' ;",    ['']);
                            }
                            else if($system_tpl == $store_tpl)
                            {
                                $idb->Execute("UPDATE `".$table."` SET `config_value` = '' WHERE `config_key` = '_STORE_DEFAULT_TEMPLATE' ;");
                            }
                        }
                    }
                    catch (Exception $e){
                        $command->setErrorMessage("<span class='msg-error'>".constant('TEXT_QUERY_FAILED')." " . $e->getMessage() . "</span><br/>");
                    }
                }

                return true;
            })
            ->setDescription(constant('TEXT_UPDATING') . " DB _config_x create  _SYSTEM_TEMPLATE<br/>")
            ->setAbortOnError(true)
        );

        // jetzt erst den alten _SYSTEM_TEMPLATE aus xt_config löschen
        // Verknüpfung im Menü entfernen
        $post_update_sql = 'post_update.sql';
        $res2 = $this->_installSQL(Wizard::getInstance()->getDatabaseObject(), $post_update_sql, $install_prefix,'', '');

        foreach ($res2 as $key => $val) {
            $this->addControllerCommand(ControllerCommand::factory()
                ->setAction(function(ControllerCommand $command) use ($val, $idb) {
                    try{
                        $idb->Execute($val);
                    }catch (Exception $e){
                        /*'1060 - Duplicate column name','1062 - Duplicate entry', '1050- table alredy exists','1091 -  Can't DROP '%s'; check that column/key exists'*/
                        $allowed_error_codes = array(1062,1061,1060,1050,1091, 1054, 1091);
                        if (in_array($e->getCode(),$allowed_error_codes)) {
                            $command->setErrorMessage("<br/><span class='msg-skipped'>".TEXT_QUERY_SKIPPED."  " . $e->getMessage() . "</span>");
                        }else{
                            $command->setErrorMessage("<span class='msg-error'>".constant('TEXT_QUERY_FAILED')." " . $e->getMessage() . ' | '.$e->getCode()."</span><br/>");
                            return false;
                        }
                    }

                    return true;
                })
                ->setDescription(TEXT_EXECUTING_QUERY.' '.$val)
                ->setAbortOnError(true)
            );
        }

        // 6.6.x 6.7.x _USE_CAPTCHA_AT_REGISTRATION
        $this->addControllerCommand(ControllerCommand::factory()
            ->setAction(function(ControllerCommand $command) use ($idb, $store_handler) {

                $stores = $store_handler->getStores();
                foreach ($stores as $store)
                {
                    $table = DB_PREFIX.'_config_'.$store['id'];
                    try
                    {
                        $exists = $idb->GetOne("SELECT 1 FROM ".$table." WHERE config_key = '_USE_CAPTCHA_AT_REGISTRATION'");
                        if(!$exists)
                        {
                            $idb->Execute("INSERT INTO `".$table."` (`config_key`, `config_value`, `group_id`, `sort_order`, `type`) VALUES ('_USE_CAPTCHA_AT_REGISTRATION',0, 1, 83, 'status');");
                        }
                    }
                    catch (Exception $e){
                        $command->setErrorMessage("<span class='msg-error'>".constant('TEXT_QUERY_FAILED')." " . $e->getMessage() . "</span><br/>");
                    }
                }

                return true;
            })
            ->setDescription(constant('TEXT_UPDATING') . " DB _config_x create  _USE_CAPTCHA_AT_REGISTRATION<br/>")
            ->setAbortOnError(true)
        );

        // 6.6.x 6.7.x _STORE_PRODUCT_LIST_RESULTS  Anzahl der Downloads pros seite imm kundenkonto
        $this->addControllerCommand(ControllerCommand::factory()
            ->setAction(function(ControllerCommand $command) use ($idb, $store_handler) {

                $stores = $store_handler->getStores();
                foreach ($stores as $store)
                {
                    $table = DB_PREFIX.'_config_'.$store['id'];
                    try
                    {
                        $exists = $idb->GetOne("SELECT 1 FROM ".$table." WHERE config_key = '_STORE_PRODUCT_LIST_RESULTS'");
                        if(!$exists)
                        {
                            $idb->Execute("INSERT INTO `".$table."` (`config_key`, `config_value`, `group_id`, `sort_order`, `type`) VALUES ('_STORE_PRODUCT_LIST_RESULTS', '20', 8, 2, NULL);");
                        }
                    }
                    catch (Exception $e){
                        $command->setErrorMessage("<span class='msg-error'>".constant('TEXT_QUERY_FAILED')." " . $e->getMessage() . "</span><br/>");
                    }
                }

                return true;
            })
            ->setDescription(constant('TEXT_UPDATING') . " DB _config_x create  _STORE_PRODUCT_LIST_RESULTS<br/>")
            ->setAbortOnError(true)
        );

        // 6.6.x 6.7.x _STORE_ACCOUNT_ALLOW_EMAIL_CHANGE  Änderung Passwort erlauben
        $this->addControllerCommand(ControllerCommand::factory()
            ->setAction(function(ControllerCommand $command) use ($idb, $store_handler) {

                $stores = $store_handler->getStores();
                foreach ($stores as $store)
                {
                    $table = DB_PREFIX.'_config_'.$store['id'];
                    try
                    {
                        $exists = $idb->GetOne("SELECT 1 FROM ".$table." WHERE config_key = '_STORE_ACCOUNT_ALLOW_EMAIL_CHANGE'");
                        if(!$exists)
                        {
                            $idb->Execute("INSERT INTO `".$table."` (`config_key`, `config_value`, `group_id`, `sort_order`, `type`) VALUES ('_STORE_ACCOUNT_ALLOW_EMAIL_CHANGE', 0, 5, 130, 'status');");
                        }
                    }
                    catch (Exception $e){
                        $command->setErrorMessage("<span class='msg-error'>".constant('TEXT_QUERY_FAILED')." " . $e->getMessage() . "</span><br/>");
                    }
                }

                return true;
            })
            ->setDescription(constant('TEXT_UPDATING') . " DB _config_x create  _STORE_ACCOUNT_ALLOW_EMAIL_CHANGE<br/>")
            ->setAbortOnError(true)
        );

        // 6.6.x 6.7.x _STORE_PASSWORD_MIN_LENGTH  Passwort Mindestlänge
        $this->addControllerCommand(ControllerCommand::factory()
            ->setAction(function(ControllerCommand $command) use ($idb, $store_handler) {

                $stores = $store_handler->getStores();
                foreach ($stores as $store)
                {
                    $table = DB_PREFIX.'_config_'.$store['id'];
                    try
                    {
                        $idb->Execute("UPDATE `".$table."`  SET `config_value` = 8 WHERE `config_key` = '_STORE_PASSWORD_MIN_LENGTH' AND `config_value` < 8;");
                        $idb->Execute("UPDATE `".$table."`  SET `type` = 'hidden' WHERE `config_key` = '_STORE_PASSWORD_MIN_LENGTH';");

                    }
                    catch (Exception $e){
                        $command->setErrorMessage("<span class='msg-error'>".constant('TEXT_QUERY_FAILED')." " . $e->getMessage() . "</span><br/>");
                    }
                }

                return true;
            })
            ->setDescription(constant('TEXT_UPDATING') . " DB _config_x update  _STORE_PASSWORD_MIN_LENGTH hidden, Passwort Mindestlänge 8<br/>")
            ->setAbortOnError(true)
        );

        // 6.6.x 6.7.x _STORE_ALLOW_PARTLY_RESCISSION  Teilwiderspruch erlauben
        $this->addControllerCommand(ControllerCommand::factory()
            ->setAction(function(ControllerCommand $command) use ($idb, $store_handler) {

                $stores = $store_handler->getStores();
                foreach ($stores as $store)
                {
                    $table = DB_PREFIX.'_config_'.$store['id'];
                    try
                    {
                        $exists = $idb->GetOne("SELECT 1 FROM ".$table." WHERE config_key = '_STORE_ALLOW_PARTLY_RESCISSION'");
                        if(!$exists)
                        {
                            $idb->Execute("INSERT INTO `".$table."` (`config_key`, `config_value`, `group_id`, `sort_order`, `type`) VALUES ('_STORE_ALLOW_PARTLY_RESCISSION', 0, 1, 200, 'status');");
                        }
                    }
                    catch (Exception $e){
                        $command->setErrorMessage("<span class='msg-error'>".constant('TEXT_QUERY_FAILED')." " . $e->getMessage() . "</span><br/>");
                    }
                }

                return true;
            })
            ->setDescription(constant('TEXT_UPDATING') . " DB _config_x create  _STORE_ALLOW_PARTLY_RESCISSION<br/>")
            ->setAbortOnError(true)
        );

        // 6.6.x 6.7.x OAUTH
        $this->addControllerCommand(ControllerCommand::factory()
            ->setAction(function(ControllerCommand $command) use ($idb, $store_handler) {

                $stores = $store_handler->getStores();
                foreach ($stores as $store)
                {
                    $table = DB_PREFIX.'_config_'.$store['id'];
                    $keys = [
                        '_STORE_SMTP_OAUTH_REFRESHTOKEN',
                        '_STORE_SMTP_OAUTH_CLIENT_ID',
                        '_STORE_SMTP_OAUTH_TENANT_ID',
                        '_STORE_SMTP_OAUTH_CLIENT_SECRET'
                    ];
                    foreach ($keys as $key) {
                        try {
                            $exists = $idb->GetOne("SELECT 1 FROM " . $table . " WHERE config_key = ?", [$key]);
                            if (!$exists) {
                                $idb->Execute("INSERT INTO `" . $table . "` (`config_key`, `config_value`, `group_id`, `sort_order`, `type`, `url`) VALUES (?, '', 999, 0, NULL, NULL);", [$key]);
                            }
                        } catch (Exception $e) {
                            $command->setErrorMessage("<span class='msg-error'>" . constant('TEXT_QUERY_FAILED') . " " . $e->getMessage() . "</span><br/>");
                        }
                        try {
                            $idb->Execute("UPDATE `" . $table . "` SET `url` = 'smtp_auth' WHERE `config_key` = '_STORE_SMTP_AUTH';");
                        } catch (Exception $e) {
                            $command->setErrorMessage("<span class='msg-error'>" . constant('TEXT_QUERY_FAILED') . " " . $e->getMessage() . "</span><br/>");
                        }
                    }
                }

                return true;
            })
            ->setDescription(constant('TEXT_UPDATING') . " DB _config_x create email Auth settings<br/>")
            ->setAbortOnError(true)
        );

        // 6.6.x 6.7.x Einstellungen > Konfiguration > Email
        // verschieben nach
        // Shop-Einstellungen > Email
        // also aus xt_config nach xt_config_X
        $this->addControllerCommand(ControllerCommand::factory()
            ->setAction(function(ControllerCommand $command) use ($idb, $store_handler) {

                $keys = [
                    '_SYSTEM_MAIL_TYPE'     => '_STORE_MAIL_TYPE'
                ];

                $stores = $store_handler->getStores();
                foreach ($stores as $store)
                {
                    $table = DB_PREFIX.'_config_'.$store['id'];

                    $sortOrder = -20;
                    foreach ($keys as $sysKey => $storeKey) {
                        try {
                            $exists = $idb->GetOne("SELECT 1 FROM " . $table . " WHERE config_key = ?", [$storeKey]);
                            if (!$exists) {
                                $sysValues = $idb->GetArray("SELECT * FROM " . TABLE_CONFIGURATION . " WHERE config_key = ? LIMIT 1", [$sysKey]);
                                $sysValues = $sysValues[0];
                                $idb->Execute("INSERT INTO `" . $table . "` (`config_key`, `config_value`, `group_id`, `sort_order`, `type`, `url`) VALUES (?, ?, 12, ?, ?, ?);", [$storeKey, $sysValues['config_value'], $sortOrder, $sysValues['type'],$sysValues['url']]);
                            }
                        } catch (Exception $e) {
                            $command->setErrorMessage("<span class='msg-error'>" . constant('TEXT_QUERY_FAILED') . " " . $e->getMessage() . "</span><br/>");
                            return false;
                        }
                        $sortOrder = $sortOrder + 3;
                    }
                }
                try {
                    foreach ($keys as $sysKey => $storeKey)
                    {
                        $idb->Execute("DELETE FROM " . TABLE_CONFIGURATION . " WHERE config_key = ?", [$sysKey]);
                    }
                    $idb->Execute("DELETE FROM " . TABLE_CONFIGURATION_GROUP . " WHERE group_title = 'TEXT_CONF_MAIL'");
                }catch (Exception $e) {
                    $command->setErrorMessage("<span class='msg-error'>" . constant('TEXT_QUERY_FAILED') . " " . $e->getMessage() . "</span><br/>");
                }

                return true;
            })
            ->setDescription(constant('TEXT_UPDATING') . " DB _config_x move mail system settings to store email settings<br/>")
            ->setAbortOnError(true)
        );

        // 6.6.x 6.7.x Email tpls Widerruf
        $this->addControllerCommand(ControllerCommand::factory()
            ->setAction(function(ControllerCommand $command) use ($idb, $store_handler, $xtPlugin, $language) {

                try {

                    require_once(_SRV_WEBROOT.'xtWizard/lib/class.mail_installer_wizard.php');
                    $mi = new mail_installer_wizard();

                    foreach($language->_getLanguageList() as $lang)
                    {
                        $lang_dir = _SRV_WEBROOT.'xtWizard/scripts/update-6.6.x-6.7.x/languages/'.$lang["code"];
                        if(!is_dir($lang_dir))
                            $lang_dir = _SRV_WEBROOT.'xtWizard/scripts/update-6.6.x-6.7.x/languages/en';

                        $mail_dir = $lang_dir.'/mails';

                        $mi->_installMailTemplates($mail_dir, $lang["code"], $idb, DB_PREFIX.'_');
                    }

                } catch (Exception $e) {
                    WizardLogger::getInstance()->log($e->getMessage()."\n".$e->getTraceAsString());
                    $command->setErrorMessage("<span class='msg-error'>" . constant('TEXT_ERROR_EMAIL_TPL_INSTALL') . " (rescission) " . $e->getMessage() . "</span><br/>");
                    return false;
                }

                return true;
            })
            ->setDescription(constant('TEXT_UPDATING') . " DB install rescission emails<br/>")
            ->setAbortOnError(true)
        );

        // 6.6.x 6.7.x Email tpls Widerruf
        $this->addControllerCommand(ControllerCommand::factory()
            ->setAction(function(ControllerCommand $command) use ($idb, $store_handler, $xtPlugin, $language) {

                try {

                    require_once(_SRV_WEBROOT.'xtWizard/lib/class.mail_installer_wizard.php');
                    $mi = new mail_installer_wizard();

                    $mi->copyMailSettings('new_password', 'rescission_request', $idb, DB_PREFIX.'_' );
                    $mi->copyMailSettings('new_password', 'rescission_request_order', $idb, DB_PREFIX.'_' );
                    $mi->copyMailSettings('new_password', 'rescission_mail_admin', $idb, DB_PREFIX.'_' );

                } catch (Exception $e) {
                    WizardLogger::getInstance()->log($e->getMessage()."\n".$e->getTraceAsString());
                    $command->setErrorMessage("<span class='msg-error'>" . constant('TEXT_ERROR_EMAIL_TPL_INSTALL') . " (rescission) " . $e->getMessage() . "</span><br/>");
                    return false;
                }

                return true;
            })
            ->setDescription(constant('TEXT_UPDATING') . " DB setting up rescission emails from/reply<br/>")
            ->setAbortOnError(true)
        );


        // 6.6.x 6.7.x content Widerruf
        $this->addControllerCommand(ControllerCommand::factory()
            ->setAction(function(ControllerCommand $command) use ($idb, $store_handler) {

                try {
                    $exists = $idb->GetOne("SELECT content_id FROM " . TABLE_CONTENT . " WHERE content_form = ?", ['rescission.php']);
                    if(!$exists)
                        _installRescissionContent();
                    else {
                        $command->setErrorMessage("<span class='msg-skipped'>Hinweis: Content <i><b>Widerruf</b></i> existiert bereits. Content ID-".$exists." mit Formular <i>rescission.php</i> in der Datenbank gefunden.<br />Punkt wird übersprungen. </span><br/>");
                    }
                } catch (Exception $e) {
                    $command->setErrorMessage("<span class='msg-error'>" . constant('TEXT_ERROR_CONTENT_INSTALL') . " (rescission) " . $e->getMessage() . "</span><br/>");
                    return false;
                }
                return true;
            })
            ->setDescription(constant('TEXT_UPDATING') . " DB install rescission content<br/>")
            ->setAbortOnError(true)
        );

        // 6.6.x 6.7.x connector entfernen
        $this->addControllerCommand(ControllerCommand::factory()
            ->setAction(function(ControllerCommand $command) use ($idb, $store_handler) {

                try {
                    _removeConnector();
                } catch (Exception $e) {
                    $command->setErrorMessage("<span class='msg-error'>" . constant('TEXT_ERROR_CONTENT_INSTALL') . " (rescission) " . $e->getMessage() . "</span><br/>");
                    return false;
                }
                return true;
            })
            ->setDescription(constant('TEXT_UPDATING') . " remove connector<br/>")
            ->setAbortOnError(false)
        );

        ## finishing
        $this->addControllerCommand(ControllerCommand::factory()
            ->setAction(function(ControllerCommand $command) use ($idb, $store_handler) {

                return true;
            })
            ->setDescription(constant('TEXT_UPDATING') . " finishing<br/>")
            ->setAbortOnError(false)
        );

        $page->assignTemplateVar('processing',constant('TEXT_UPDATING'),true);
        $this->execAsyncAction($page);
    }

}

global $language;
if($language)
{
    $langFile = dirname(__FILE__) . DIRECTORY_SEPARATOR . "wizard_{$language->content_language}.yml";
    if (file_exists($langFile))
    {

        $contents = file_get_contents($langFile);
        $languageParts = explode("\n", $contents);

        foreach ($languageParts as $part)
        {
            $delimiterPos = strpos($part, "=", 0);

            if ($delimiterPos === false)
            {
                continue;
            }
            $systemParts = substr($part, 0, $delimiterPos);
            $value = substr($part, $delimiterPos + 1);

            list($plugin, $type, $key) = explode(".", $systemParts);
            if (!defined($key))
            {
                $value = str_replace(array("\r", "\n"), '', $value);
                define($key, $value);
            }
        }
    }
}
Wizard::getInstance()->registerScript(new Update66xTo67x());

function _removeConnector()
{
    if(file_exists(_SRV_WEBROOT.'connector.php')) unlink(_SRV_WEBROOT.'connector.php');

    $dir = _SRV_WEBROOT._SRV_WEB_CORE.'connector/';

    if(is_dir($dir)) {
        $it = new RecursiveDirectoryIterator($dir, FilesystemIterator::SKIP_DOTS);
        $files = new RecursiveIteratorIterator($it,
            RecursiveIteratorIterator::CHILD_FIRST);
        foreach ($files as $file) {
            if ($file->isDir()) {
                rmdir($file->getPathname());
            } else {
                unlink($file->getPathname());
            }
        }
        rmdir($dir);
    }
}

function _installRescissionContent()
{
    global $db, $language, $store_handler;

    GLOBAL $ADODB_THROW_EXCEPTIONS;
    $ADODB_THROW_EXCEPTIONS = true;

    $supported_langs = array('de','en');

    $txt_dir = __DIR__.'/content/';

    $newContentId = $db->GetOne("SELECT MAX(content_id) FROM ".TABLE_CONTENT_ELEMENTS);
    if (!$newContentId) $newContentId = 0;
    $newContentId++;

    $plg = new Plugin();
    $store_id_col_exists_content = $plg->_FieldExists('content_store_id', TABLE_CONTENT_ELEMENTS);
    $store_id_col_exists_seo =     $plg->_FieldExists('store_id', TABLE_SEO_URL);

    foreach($store_handler->getStores() as $store)
    {
        foreach($language->_getLanguageList('admin') as $lang)
        {
            if( in_array(strtolower($lang['id']),$supported_langs))
            {
                $title = _getFileContent_66_67($txt_dir.strtolower($lang['id']).'/rescission_title.txt');
                $body = _getFileContent_66_67($txt_dir.strtolower($lang['id']).'/rescission_body.html');
                $url = _getFileContent_66_67($txt_dir.strtolower($lang['id']).'/rescission_url.txt');
            }
            else {
                $title = _getFileContent_66_67($txt_dir.'en/rescission_title.txt');
                $body = _getFileContent_66_67($txt_dir.'en/rescission_body.html');
                $url = _getFileContent_66_67($txt_dir.'en/rescission_url.txt');
            }
            if ($store_id_col_exists_content)
            {
                $sql = "INSERT IGNORE INTO ".TABLE_CONTENT_ELEMENTS." (content_id,language_code,content_title,content_heading,content_body,content_store_id) VALUES (?, ?, ?, ?, ?, ?)";
                $db->Execute($sql, array(
                    $newContentId,
                    $lang['id'],
                    $title,
                    $title,
                    $body,
                    $store['id']
                ));
            }
            else {
                $sql = "INSERT IGNORE INTO ".TABLE_CONTENT_ELEMENTS." (content_id,language_code,content_title,content_heading,content_body) VALUES (?, ?, ?, ?, ?)";
                $db->Execute($sql, array(
                    $newContentId,
                    $lang['id'],
                    $title,
                    $title,
                    $body
                ));
            }

            $url_text = $url;
            if(constant('_SYSTEM_SEO_URL_LANG_BASED') == 'true')
                $url_text = $lang['id'].'/'.$url;
            $url_md5 = md5($url_text);

            if($store_id_col_exists_seo)
            {
                $sql = "INSERT IGNORE INTO ".TABLE_SEO_URL." (`url_md5`,`url_text`,`language_code`,`link_type`,`link_id`,`meta_title`,`meta_description`,`meta_keywords`,`store_id`) 
                VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)";
                $db->Execute($sql, array(
                    $url_md5,
                    $url_text,
                    $lang['id'],
                    3,
                    $newContentId,
                    '',
                    '',
                    '',
                    $store['id']
                ));
            }
            else {
                $sql = "INSERT IGNORE INTO ".TABLE_SEO_URL." (`url_md5`,`url_text`,`language_code`,`link_type`,`link_id`,`meta_title`,`meta_description`,`meta_keywords`) 
                VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
                $db->Execute($sql, array(
                    $url_md5,
                    $url_text,
                    $lang['id'],
                    3,
                    $newContentId,
                    '',
                    '',
                    ''
                ));
            }
        }
    }

    // content
    $sql = "INSERT IGNORE INTO ".TABLE_CONTENT." (content_id,content_parent,content_status,content_hook,content_form,content_image,content_sort) VALUES (?, ?, ?, ?, ?, ?, ?)";
    $db->Execute($sql, array(
        $newContentId,
        0,
        1,
        0,
        'rescission.php',
        '',
        -999
    ));

    // content positions
    $content_positions = [
        'footer',
        'information',
        'ew_evelations_footer_info',
        'ew_adventury_footer_info',
    ];
    foreach($content_positions as $position)
    {
        $block_id = $db->GetOne("SELECT block_id FROM ".TABLE_CONTENT_BLOCK." WHERE block_tag = ?", array($position));
        if($block_id)
            $db->Execute("INSERT INTO ".TABLE_CONTENT_TO_BLOCK."(block_id, content_id) VALUES (?, ?);", [$block_id, $newContentId]);
    }

}

function _installMailTemplatesRescission_XXX($langs, $tpls, $mail_dir = __DIR__.'/mails/') {
    global $db, $language;

    foreach($tpls as $new_tpl => $copy_data_from_tpl)
    {
        // _SYSTEM_MAIL_TYPE wird heir schon nicht mehr existieren
        if(!defined('_SYSTEM_MAIL_TYPE'))
            define('_SYSTEM_MAIL_TYPE', 'foobar');
        $m = new xtMailer($copy_data_from_tpl, -1, -1, -1, -1);
        $m->prepareMail();

        $data = array(
            'tpl_type' => $new_tpl,
            'tpl_special' => '-1',

            'email_from'        => $m->tplData["email_from"],
            'email_from_name'   => $m->tplData["email_from_name"],
            'email_reply'       => $m->tplData["email_reply"],
            'email_reply_name'  => $m->tplData["email_reply_name"],
            'email_forward'     => $m->tplData["email_forward"]
        );
        $c = (int) $db->GetOne("SELECT count(tpl_id) FROM ".TABLE_MAIL_TEMPLATES." where `tpl_type` = '".$data['tpl_type']."'");
        if ($c>0)
        {
            continue;
        }
        $db->AutoExecute(TABLE_MAIL_TEMPLATES ,$data);
        $tplId = $db->GetOne("SELECT `tpl_id` FROM `".TABLE_MAIL_TEMPLATES."` WHERE `tpl_type`='".$data['tpl_type']."'");

        foreach($language->_getLanguageList('admin') as $lang)
        {
            $lang = $lang['code'];
            $fname = $new_tpl;
            $html = file_exists($mail_dir.$lang.'/'.$fname.'_html.html') ?  _getFileContent_66_67($mail_dir.$lang.'/'.$fname.'_html.html') : _getFileContent_66_67($mail_dir.'en'.'/'.$fname.'_html.html');
            $txt = file_exists($mail_dir.$lang.'/'.$fname.'_txt.txt') ?  _getFileContent_66_67($mail_dir.$lang.'/'.$fname.'_txt.txt') : _getFileContent_66_67($mail_dir.'en'.'/'.$fname.'_txt.txt');
            $subject = file_exists($mail_dir.$lang.'/'.$fname.'_subject.txt') ?  _getFileContent_66_67($mail_dir.$lang.'/'.$fname.'_subject.txt') : _getFileContent_66_67($mail_dir.'en'.'/'.$fname.'_subject.txt');

            $data = array(
                'tpl_id' => $tplId,
                'language_code' => $lang,
                'mail_body_html' => $html,
                'mail_body_txt' => $txt,
                'mail_subject' => $subject
            );
            try {
                $db->AutoExecute(TABLE_MAIL_TEMPLATES_CONTENT ,$data);
            } catch (exception $e) {
                throw $e;
            }
        }
    }
}

function _getFileContent_66_67($filename) {
    $handle = fopen($filename, 'rb');
    $content = fread($handle, filesize($filename));
    fclose($handle);
    return $content;
}

    