<?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
 */

class d3_oxshopcontrol_modcfg_extension extends d3_oxshopcontrol_modcfg_extension_parent
{
    private $_blD3Productive = null;
    /** @var d3_cfg_mod */
    private $_oClrTmpSet = null;
    private $_sClrTmpSetId = 'd3modcfg_lib';
    private $_sLogSetId = 'd3modcfg_lib';
    private $_blDevMode = null;
    
    /**
     * @param null $sClass
     * @param null $sFunction
     * @param null $aParams
     * @param null $aViewsChain
     */
    public function start ($sClass = null, $sFunction = null, $aParams = null, $aViewsChain = null)
    {
        startProfile(__METHOD__);

        if (class_exists('d3log') && d3log::isCallable()) {
            /** @var $oD3Log d3log */
            $oD3Log = oxNew('d3log');
            $oD3Log->setModId('ErrorReporting');
            if (class_exists('d3_cfg_mod') && d3_cfg_mod::isCallable()) {
                $oD3Log->setLogType($oD3Log->getLogSet()->getFieldData('oxismodulelog'));
            }
            $oD3Log->registerErrorHandler();
        }
        
        // d3_cfg_mod
        if (class_exists('d3utils')) {
            oxRegistry::get('d3utils')->d3AddCoreViewTables();
        }
        
        // d3clrtmp
        if ($this->_d3CheckDevMode()) {
            /** @var $oClrTmp d3clrtmp */
            $oClrTmp = oxNew('d3clrtmp');
            $oClrTmp->setHideErrorMsg();
            $oClrTmp->clearAllCache();
        }

        stopProfile(__METHOD__);

        parent::start($sClass, $sFunction, $aParams, $aViewsChain);

        $this->_d3GetProfiling();
    }

    /**
     * check, if developer mode has to be enabled
     *
     * @return bool
     */
    protected function _d3CheckDevMode()
    {
        if ($this->_blDevMode === null) {
            $this->_blDevMode = false;

            if ($this->_blD3Productive === null) {
                $this->_blD3Productive = oxRegistry::getConfig()->isProductiveMode();
            }

            if ($this->_blD3Productive === false && class_exists('d3_cfg_mod')) {
                $this->_oClrTmpSet = d3_cfg_mod::get($this->_sClrTmpSetId);

                if (is_object($this->_oClrTmpSet) &&
                    $this->_oClrTmpSet->getValue('blClrTmp_notmpuse') == '1'
                ) {
                    $this->_blDevMode = true;
                }
            }
        }

        return $this->_blDevMode;
    }

    /**
     * @return bool
     */
    private function _d3GetProfiling()
    {
        if (!class_exists('d3_cfg_mod')) {
            return true;
        }

        if (d3_cfg_mod::isCallable() && d3_cfg_mod::isAvailable($this->_sLogSetId)) {
            /** @var d3_cfg_mod $oLogModCfg */
            $oLogModCfg = d3_cfg_mod::get($this->_sLogSetId);
            if (isAdmin() && $oLogModCfg->getValue('blLog_enableAdminProfiling')) {
                /** @var d3log $oLog */
                $oLog = $oLogModCfg->d3getLog();
                if ($oLog) {
                    $oLog->d3GetProfiling();
                }
            }
        }

        return true;
    }

    /**
     * @param string $sClass
     * @param string $sFunction
     * @param null   $aParams
     * @param null   $aViewsChain
     *
     * @return null|void
     */
    protected function _process($sClass, $sFunction, $aParams = null, $aViewsChain = null)
    {
        if (class_exists('d3_cfg_mod') &&
            d3_cfg_mod::isCallable() && (
                d3_cfg_mod::get($this->_sLogSetId)->getValue('blLog_showAllExceptions') ||
                d3_cfg_mod::get($this->_sLogSetId)->getValue('blLog_enableExceptionReporting')
            )
        ) {
            try {
                parent::_process($sClass, $sFunction, $aParams, $aViewsChain);
            } catch (Exception $oEx) {
                if (d3_cfg_mod::get($this->_sLogSetId)->getValue('blLog_showAllExceptions')) {
                    echo $oEx->getMessage();
                    echo "<pre>";
                    print_r($oEx);
                    echo "</pre>";
                }

                $this->_d3WriteExc2Log($oEx);
            }
        } else {
            parent::_process($sClass, $sFunction, $aParams, $aViewsChain);
        }
    }

    /**
     * @return bool
     */
    protected function _d3CanWriteExc2Log()
    {
        if (d3_cfg_mod::isCallable() &&
            d3_cfg_mod::isAvailable($this->_sLogSetId) &&
            class_exists('d3log') &&
            d3log::isCallable() &&
            d3_cfg_mod::get($this->_sLogSetId)->getValue('blLog_enableExceptionReporting')
        ) {
            return true;
        }

        return false;
    }

    /**
     * @param $oException
     */
    protected function _d3WriteExc2Log($oException)
    {
        if ($this->_d3CanWriteExc2Log()) {
            $class = '';
            $fnc = '';
            $line = 0;
            extract($this->getExceptionThrownClass($oException));

            /** @var d3_cfg_mod $oLogModCfg */
            $oLogModCfg = d3_cfg_mod::get($this->_sLogSetId);
            $oD3Log = $oLogModCfg->d3getLog();
            $oD3Log->setModId('ExceptionReporting');
            $oD3Log->log(
                d3log::EMERGENCY,
                $class,
                $fnc,
                $line,
                get_class($oException),
                substr(print_r($oException, true), 0, 65532) . '...'
            );
        }
    }

    /**
     * @param Exception $oException
     * @return array
     */
    public function getExceptionThrownClass($oException)
    {
        $aTrace = $oException->getTrace();

        if (count($aTrace)) {
            foreach ($oException->getTrace() as $aItem) {
                if ($aItem['class']) {
                    return array(
                        'class' => $aItem['class'],
                        'line'  => $aItem['line'] ? $aItem['line'] : 0,
                        'fnc'   => $aItem['function'] ? $aItem['function'] : 'no function defined',
                    );
                }
            }
            foreach ($oException->getTrace() as $aItem) {
                if ($aItem['file']) {
                    $sFile = 'file: '.end(array_values(explode('/', $aItem['file'])));
                    return array(
                        'class' => $sFile,
                        'line'  => $aItem['line'] ? $aItem['line'] : 0,
                        'fnc'   => $aItem['function'] ? $aItem['function'] : 'no function defined',
                    );
                }
            }
        }

        return array(
            'class' => 'no class name or file defined',
            'line'  => 0,
            'fnc'   => 'no function defined'
        );
    }

    /**
     * @param oxConnectionException $oEx
     */
    protected function _handleDbConnectionException($oEx)
    {
        $this->_d3WriteExc2Log($oEx);

        parent::_handleDbConnectionException($oEx);
    }

    /**
     * @param oxException $oEx
     */
    protected function _handleSystemException($oEx)
    {
        $this->_d3WriteExc2Log($oEx);

        parent::_handleSystemException($oEx);
    }

    /**
     * @param oxException $oEx
     */
    protected function _handleCookieException($oEx)
    {
        $this->_d3WriteExc2Log($oEx);

        parent::_handleCookieException($oEx);
    }

    /**
     * @param oxException $oEx
     */
    protected function _handleAccessRightsException($oEx)
    {
        $this->_d3WriteExc2Log($oEx);

        parent::_handleAccessRightsException($oEx);
    }

    /**
     * @param oxException $oEx
     */
    protected function _handleBaseException($oEx)
    {
        $this->_d3WriteExc2Log($oEx);

        parent::_handleBaseException($oEx);
    }
}
