<?php

/**
 * This Software is the property of Data Development and is protected
 * by copyright law - it is NOT Freeware.
 *
 * Any unauthorized use of this software without a valid license
 * is a violation of the license agreement and will be prosecuted by
 * civil and criminal law.
 *
 * http://www.shopmodule.com
 *
 * @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
 * @author    D3 Data Development - Daniel Seifert <support@shopmodule.com>
 * @link      http://www.oxidmodule.com
 */

namespace D3\Extsearch\setup;

use D3\Extsearch\Application\Model\d3_extsearch_synset;
use D3\ModCfg\Application\Model\Exception\d3_cfg_mod_exception;
use D3\ModCfg\Application\Model\Exception\d3ParameterNotFoundException;
use D3\ModCfg\Application\Model\Exception\d3ShopCompatibilityAdapterException;
use D3\ModCfg\Application\Model\Install\d3install_updatebase;
use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\Driver\PDOException;
use OxidEsales\Eshop\Core\Exception\ConnectionException;
use OxidEsales\Eshop\Core\Exception\DatabaseConnectionException;
use OxidEsales\Eshop\Core\Exception\DatabaseErrorException;
use OxidEsales\Eshop\Core\Exception\StandardException;
use OxidEsales\Eshop\Core\Registry;
use OxidEsales\Eshop\Application\Model\Shop;
use ReflectionException;

/**
 * Class d3_extsearch_update
 */
class d3_extsearch_update extends d3install_updatebase
{
    public $sModKey = 'd3_extsearch';
    public $sModName = 'erweiterte Suche';
    public $sModVersion = '6.3.1.0';
    public $sModRevision = '6310';
    public $sBaseConf = '8tPv2==M28zTmFlQzVOWDdtSDNOeCtRUkJXWjBFUUV6UUdsSkpvamo2eTNxTDlzRVhONHdrUHNhU1drU
3dKV0R5aWNOMEVPbGZMOGswRklrRDl6S096TERLOXhyWmtVcUlNUEs2cUE0R1U4VkpiME5HTktITTk0V
zc1ZS9wdzljemhWMVdHRzJEWG9WUTkrc2dFcTRGYW5CbnJ0Tk56dHVuVTFCRm5YM3FQcW1FMi9lZkZmc
mNLV0ZuanVkVkRDYlZiRXpDRDl5MGtpRUpGVklWeGFkbmNNL2N2ZEF1Um5PblBnVnRkaXR1b244VGowZ
HRoZzNEYmxUZW9zbkw1amIzSmdxbWNNMWlrRFptR0NiSzZKSk8vNWt2Y2RjOXZtN3RTcVFGajduMWJwT
2NBQWNHZVJINGwxNW9vL3h2d1M0SWNmVTJ2QUxRNXlmNXVsYmZYdHhqRGI5QWF3PT0=';
    public $sRequirements = '';
    public $sBaseValue = ' ';

    public $sMinModCfgVersion = '5.1.0.0';

    protected $_aUpdateMethods = array(
        array('check' => 'checkModCfgItemExist',
              'do'    => 'updateModCfgItemExist'),
        array('check' => 'checkRenameFields',
              'do'    => 'fixRenameFields'),
        array('check' => 'checkIndexRefreshMsg',
              'do'    => 'fixIndexRefreshMsg'),
        array('check' => 'checkAttribute2ObjectTableExist',
              'do'    => 'addAttribute2ObjectTable'),
        array('check' => 'checkStatisticTablesExist',
              'do'    => 'addStatisticTables'),
        array('check' => 'checkSynsetTablesExist',
              'do'    => 'addSynsetTables'),
        array('check' => 'checkFields',
              'do'    => 'fixFields'),
        array('check' => 'checkIndizes',
              'do'    => 'fixIndizes'),
        array('check' => 'checkUnsetSynsetTypes',
              'do'    => 'setInitialSynsetTypes'),
        array('check' => 'checkContentNoArtItemExist',
              'do'    => 'updateContentNoArtItemExist'),
        array('check' => 'hasUnregisteredFiles',
              'do'    => 'showUnregisteredFiles'),
        array('check' => 'checkModCfgSameRevision',
              'do'    => 'updateModCfgSameRevision'),
    );

    public $aFields = array(
        'D3_PHONETIC'        => array(
            'sTableName'  => 'oxartextends',
            'sFieldName'  => 'D3_PHONETIC',
            'sType'       => 'LONGTEXT',
            'blNull'      => false,
            'sDefault'    => false,
            'sComment'    => 'modExtSearch',
            'sExtra'      => '',
            'blMultilang' => true,
        ),
        'D3_SEARCHINDEXDATE' => array(
            'sTableName'  => 'oxarticles',
            'sFieldName'  => 'D3_SEARCHINDEXDATE',
            'sType'       => 'DATETIME',
            'blNull'      => true,
            'sDefault'    => null,
            'sComment'    => 'modExtSearch',
            'sExtra'      => '',
            'blMultilang' => true,
        ),
        'D3PUSH'             => array(
            'sTableName'  => 'oxarticles',
            'sFieldName'  => 'D3PUSH',
            'sType'       => 'TINYINT(1)',
            'blNull'      => false,
            'sDefault'    => '1',
            'sComment'    => 'search sort criteria',
            'sExtra'      => '',
            'blMultilang' => false,
        ),
        'D3ISSEARCHABLE'     => array(
            'sTableName'  => 'oxcontents',
            'sFieldName'  => 'D3ISSEARCHABLE',
            'sType'       => 'TINYINT(1)',
            'blNull'      => false,
            'sDefault'    => '0',
            'sComment'    => 'modExtSearch',
            'sExtra'      => '',
            'blMultilang' => false,
        ),
        'D3NOTUSE4FILTER'    => array(
            'sTableName'  => 'oxattribute',
            'sFieldName'  => 'D3NOTUSE4FILTER',
            'sType'       => 'TINYINT(1)',
            'blNull'      => false,
            'sDefault'    => '0',
            'sComment'    => 'attrib use in extsearch',
            'sExtra'      => '',
            'blMultilang' => false,
        ),
        'D3USECORRESPONDINGVALUES'    => array(
            'sTableName'  => 'oxattribute',
            'sFieldName'  => 'D3USECORRESPONDINGVALUES',
            'sType'       => 'TINYINT(1)',
            'blNull'      => false,
            'sDefault'    => '0',
            'sComment'    => 'use synonyms in extsearch',
            'sExtra'      => '',
            'blMultilang' => false,
        ),
        'D3NOTUSE4FILTERCAT'    => array(
            'sTableName'  => 'oxcategories',
            'sFieldName'  => 'D3NOTUSE4FILTER',
            'sType'       => 'TINYINT(1)',
            'blNull'      => false,
            'sDefault'    => '0',
            'sComment'    => 'category use in extsearch',
            'sExtra'      => '',
            'blMultilang' => false,
        ),
    );

    public $aIndizes = array();

    public $aRenameFields = array(
        'D3_PHONETIC'        => array(
           'sTableName'  => 'oxarticles',
           'mOldFieldNames' => array('d3_phonetic'), // is case sensitive
           'sFieldName'  => 'D3_PHONETIC',
           'blMultilang' => true,
        ),
        'D3_SEARCHINDEXDATE'        => array(
           'sTableName'  => 'oxarticles',
           'mOldFieldNames' => array('d3_searchIndexDate'), // is case sensitive
           'sFieldName'  => 'D3_SEARCHINDEXDATE',
           'blMultilang' => true,
        ),
        'D3PUSH'        => array(
           'sTableName'  => 'oxarticles',
           'mOldFieldNames' => array('d3push'), // is case sensitive
           'sFieldName'  => 'D3PUSH',
           'blMultilang' => false,
        ),
        'D3NOTUSE4FILTER'        => array(
           'sTableName'  => 'oxattribute',
           'mOldFieldNames' => array('d3notuse4filter'), // is case sensitive
           'sFieldName'  => 'D3NOTUSE4FILTER',
           'blMultilang' => false,
        ),
    );

    public $aSemanticTables = array();
    public $aStatisticTables = array();

    public $aOldModuleFiles = array(
        'd3/d3_extsearch/models/d3_extsearch_update.php',
    );

    protected $_aRefreshMetaModuleIds = array('d3_extsearch');

    /**
     * constructor
     */
    public function __construct()
    {
        require('d3_extsearch_semanticstructure.php');
        require('d3_extsearch_statisticlog.php');
        require('d3_extsearch_attribute2object.php');

        parent::__construct();
    }

    /**
     * @return bool
     */
    public function checkIndexRefreshMsg()
    {
        if (Registry::getSession()->getVariable('checkIndexRefreshMsg')) {
            return true;
        }

        return false;
    }

    /**
     * @return bool
     */
    public function fixIndexRefreshMsg()
    {
        $blRet = true;

        if (Registry::getSession()->getVariable('checkIndexRefreshMsg')) {
            Registry::getSession()->setVariable('checkIndexRefreshMsg', false);
            $this->_confirmMessage('D3_EXTSEARCH_UPDATE_GENPHONETIC');
        }

        return $blRet;
    }

    /**
     * @return bool
     * @throws DBALException
     * @throws DatabaseConnectionException
     */
    public function checkContentNoArtItemExist()
    {
        $blRet = false;
        foreach ($this->getShopList() as $oShop) {
            /** @var $oShop Shop */
            $aWhere = array(
                'oxloadid' => 'd3extsearch_noarticlefound',
                'oxshopid' => $oShop->getId(),
            );

            $blRet = $this->_checkTableItemNotExist('oxcontents', $aWhere);

            if ($blRet) {
                return $blRet;
            }
        }

        return $blRet;
    }

    /**
     * @return bool
     * @throws DBALException
     * @throws DatabaseConnectionException
     * @throws ConnectionException
     * @throws DatabaseErrorException
     */
    public function updateContentNoArtItemExist()
    {
        $blRet = false;

        foreach ($this->getShopList() as $oShop) {
            /** @var $oShop Shop */
            $aWhere = array(
                'oxloadid' => 'd3extsearch_noarticlefound',
                'oxshopid' => $oShop->getId(),
            );

            if ($this->_checkTableItemNotExist('oxcontents', $aWhere)) {
                $aWhere = array();
                $aInsertFields = array(
                    array (
                        'fieldname'     => 'OXID',
                        'content'       => "md5('d3extsearch_noarticlefound " . $oShop->getId() . "')",
                        'force_update'  => true,
                        'use_quote'     => false,
                    ),
                    array (
                        'fieldname'     => 'OXLOADID',
                        'content'       => "d3extsearch_noarticlefound",
                        'force_update'  => true,
                        'use_quote'     => true,
                    ),
                    array (
                        'fieldname'     => 'OXSHOPID',
                        'content'       => $oShop->getId(),
                        'force_update'  => true,
                        'use_quote'     => true,
                    ),
                    array (
                        'fieldname'     => 'OXSNIPPET',
                        'content'       => "1",
                        'force_update'  => true,
                        'use_quote'     => true,
                    ),
                    array (
                        'fieldname'     => 'OXTYPE',
                        'content'       => "0",
                        'force_update'  => true,
                        'use_quote'     => true,
                    ),
                    array (
                        'fieldname'     => 'OXACTIVE',
                        'content'       => "1",
                        'force_update'  => false,
                        'use_quote'     => true,
                        'use_multilang' => true,
                    ),
                    array (
                        'fieldname'     => 'OXPOSITION',
                        'content'       => "",
                        'force_update'  => true,
                        'use_quote'     => true,
                    ),
                    array (
                        'fieldname'     => $this->_getLangAbbrFieldName('oxcontents', 'OXTITLE', 'de'),
                        'content'       => "Leider wurden keine Artikel gefunden",
                        'force_update'  => false,
                        'use_quote'     => true,
                        'use_multilang' => true,
                    ),
                    array (
                        'fieldname'     => 'OXCONTENT',
                        'content'       => "<p>Versuchen Sie es mit einem anderen Suchbegriff, einer anderen ".
                            "Schreibweise oder anderen Filtern bitte noch einmal. </p><p>Erhalten Sie dennoch keine ".
                            "Ergebnisse, kontaktieren Sie uns bitte ".
                            "<a href=\"[{oxgetseourl ident=\$oViewConf->getSelfLink()|cat:\"cl=contact\"}]\">hier</a>.".
                            "</p><br />",
                        'force_update'  => false,
                        'use_quote'     => true,
                        'use_multilang' => true,
                    ),
                    array (
                        'fieldname'     => $this->_getLangAbbrFieldName('oxcontents', 'OXTITLE', 'en'),
                        'content'       => "Sorry, no items were found.",
                        'force_update'  => false,
                        'use_quote'     => true,
                    ),
                    array (
                        'fieldname'     => 'OXCATID',
                        'content'       => "kgo83a794223bfd23cbb091d0a34019d",
                        'force_update'  => true,
                        'use_quote'     => true,
                    ),
                    array (
                        'fieldname'     => 'OXFOLDER',
                        'content'       => "CMSFOLDER_USERINFO",
                        'force_update'  => true,
                        'use_quote'     => true,
                    ),
                );

                $this->setInitialExecMethod(__METHOD__);
                $blRet  = $this->_updateTableItem2('oxcontents', $aInsertFields, $aWhere);

                if ($this->getStepByStepMode()) {
                    break;
                }
            }
        }

        return $blRet;
    }

    /**
     * @return bool true, if table is missing
     * @throws DBALException
     * @throws DatabaseConnectionException
     * @throws DatabaseErrorException
     */
    public function checkStatisticTablesExist()
    {
        foreach ($this->aStatisticTables as $aStatisticTable) {
            if (($blRet = $this->_checkTableNotExist($aStatisticTable['sName']))) {
                return $blRet;
            };
        }

        return false;
    }

    /**
     * @return bool
     * @throws ConnectionException
     * @throws DBALException
     * @throws DatabaseConnectionException
     * @throws DatabaseErrorException
     */
    public function addStatisticTables()
    {
        $this->setInitialExecMethod(__METHOD__);

        $blDoRet = false;
        foreach ($this->aStatisticTables as $aStatisticTable) {
            if ($this->_checkTableNotExist($aStatisticTable['sName'])) {
                if ($this->hasExecute()) {
                    $iCount = $this->getUpdateStepCount();
                    Registry::getSession()->setVariable('iD3UpdatebaseCount', $iCount + 1);
                }

                $blDoRet = $this->_addTable2(
                    $aStatisticTable['sName'],
                    $this->aFields,
                    $this->aIndizes,
                    $aStatisticTable['sComment'],
                    $aStatisticTable['sType']
                );

                if ($this->getUpdateBreak() || false == $blDoRet) {
                    return $blDoRet;
                }
            }
        }

        return $blDoRet;
    }

    /**
     * @return bool true, if table is missing
     * @return bool
     * @throws DBALException
     * @throws DatabaseConnectionException
     * @throws DatabaseErrorException
     */
    public function checkAttribute2ObjectTableExist()
    {
        return $this->_checkTableNotExist('d3extsearch_attribute2object');
    }

    /**
     * @return bool
     * @return bool
     * @throws ConnectionException
     * @throws DBALException
     * @throws DatabaseConnectionException
     * @throws DatabaseErrorException
     */
    public function addAttribute2ObjectTable()
    {
        $this->setInitialExecMethod(__METHOD__);

        $blDoRet = false;
        if ($this->checkAttribute2ObjectTableExist()) {
            if ($this->hasExecute()) {
                $iCount = $this->getUpdateStepCount();
                Registry::getSession()->setVariable('iD3UpdatebaseCount', $iCount + 1);
            }

            $blDoRet = $this->_addTable2(
                'd3extsearch_attribute2object',
                $this->aFields,
                $this->aIndizes,
                'Shows many-to-many relationship between attributes and objects (table determined by oxtype)',
                'InnoDb'
            );
        }

        return $blDoRet;
    }

    /**
     * @return bool true, if table is missing
     * @throws DBALException
     * @throws DatabaseConnectionException
     * @throws DatabaseErrorException
     */
    public function checkSynsetTablesExist()
    {
        foreach ($this->aSemanticTables as $aSemanticTable) {
            if (($blRet = $this->_checkTableNotExist($aSemanticTable['sName']))) {
                return $blRet;
            };
        }

        return false;
    }

    /**
     * @return bool
     * @throws ConnectionException
     * @throws DBALException
     * @throws DatabaseConnectionException
     * @throws DatabaseErrorException
     */
    public function addSynsetTables()
    {
        $this->setInitialExecMethod(__METHOD__);

        $blDoRet = false;
        foreach ($this->aSemanticTables as $aSemanticTable) {
            if ($this->_checkTableNotExist($aSemanticTable['sName'])) {

                if ($this->hasExecute()) {
                    $iCount = $this->getUpdateStepCount();
                    Registry::getSession()->setVariable('iD3UpdatebaseCount', $iCount + 1);
                }

                $blDoRet = $this->_addTable2(
                    $aSemanticTable['sName'],
                    $this->aFields,
                    $this->aIndizes,
                    $aSemanticTable['sComment'],
                    $aSemanticTable['sType']
                );

                if ($this->getUpdateBreak() || false == $blDoRet) {
                    return $blDoRet;
                }
            }
        }

        return $blDoRet;
    }

    /**
     * @return bool // true, if there are unassigned synsets
     * @throws DatabaseConnectionException
     */
    public function checkUnsetSynsetTypes()
    {
        $iUnassigned = (int) $this->getDb()->getOne(
            "SELECT count(*) FROM `".oxNew(d3_extsearch_synset::class)->getCoreTableName()."` WHERE 1 IN (`USEFORTERMS`, `USEFORATTRIBUTES`)"
        );
        $iTotal = (int) $this->getDb()->getOne(
            "SELECT count(*) FROM `".oxNew(d3_extsearch_synset::class)->getCoreTableName()."` WHERE 1"
        );

        return !$iUnassigned && $iTotal;
    }

    /**
     * @return bool
     * @throws DatabaseConnectionException
     * @throws DatabaseErrorException
     */
    public function setInitialSynsetTypes()
    {
        if ($this->checkUnsetSynsetTypes()) {
            $sQuery = "UPDATE `" . oxNew(d3_extsearch_synset::class)->getCoreTableName() . "` SET USEFORTERMS = 1 WHERE 1;";

            if ($this->hasExecute()) {
                try {
                    $this->getDb()->execute($sQuery);
                } catch (PDOException $exception) {
                    if ($exception->errorInfo[1]) {
                        $this->setErrorMessage($exception->errorInfo[2]);
                    }
                }
            }

            $this->setUpdateBreak(false);

            if ($sQuery) {
                $this->setActionLog('SQL', $sQuery, __METHOD__);
            }
        }

        return true;
    }

    /**
     * @return bool
     * @throws DBALException
     * @throws DatabaseConnectionException
     * @throws DatabaseErrorException
     * @throws StandardException
     * @throws ReflectionException
     * @throws d3ParameterNotFoundException
     * @throws d3ShopCompatibilityAdapterException
     * @throws d3_cfg_mod_exception
     */
    public function hasUnregisteredFiles()
    {
        return $this->_hasUnregisteredFiles('d3_extsearch', array('blocks', 'd3FileRegister'));
    }

    /**
     * @return bool
     * @throws DBALException
     * @throws DatabaseConnectionException
     * @throws DatabaseErrorException
     * @throws StandardException
     * @throws ReflectionException
     * @throws d3ShopCompatibilityAdapterException
     * @throws d3_cfg_mod_exception
     */
    public function showUnregisteredFiles()
    {
        return $this->_showUnregisteredFiles('d3_extsearch', array('blocks', 'd3FileRegister'));
    }
}
