<?php

/**
 * Goweb_Controller_Action_Admin
 *
 * @version    5.0.0
 * @category   Goweb
 * @package    Goweb_Controller_Action
 * @subpackage Error
 * @author     I&D <dev@goweb.pt>, Pedro Pinto <ppinto@goweb.pt>
 * @copyright  2009 (c) Goweb (http://www.goweb.pt)
 */

/**
 * Goweb_Controller_Action
 */
Goweb::loadClass('Goweb_Controller_Action');
class Goweb_Controller_Action_Error extends Goweb_Controller_Action {
    /**
     * errorAction() is the action that will be called by the "ErrorHandler"
     * plugin.  When an error/exception has been encountered
     * in a ZF MVC application (assuming the ErrorHandler has not been disabled
     * in your bootstrap) - the Errorhandler will set the next dispatchable
     * action to come here.  This is the "default" module, "error" controller,
     * specifically, the "error" action.  These options are configurable.
     *
     * @see http://framework.zend.com/manual/en/zend.controller.plugins.html
     *
     * @return void
     */
    public function errorAction()
    {
        $this->_config = new Goweb_Config(Goweb_Config_Ini::load(ROOT_PATH.'/config.ini', 'production'), true);
        // Grab the error object from the request
        $errors = $this->_getParam('error_handler');
        // $errors will be an object set as a parameter of the request object,
        // type is a property
        $errno = $errors->exception->getCode();
        $errstr = $errors->exception->getMessage();
        $flag = true;
        switch ($errno) {
            case E_USER_ERROR:
            case E_COMPILE_ERROR:
            case E_CORE_ERROR:
            case E_ERROR:
                $msg  = "<b>FATAL</b> [$errno] $errstr<br />\n";
                $errorType = 'E_ERROR';
                break;
            case E_USER_WARNING:
            case E_COMPILE_WARNING:
            case E_CORE_WARNING:
            case E_WARNING:
                $flag = false;
                $msg = "<b>WARNING</b> [$errno] $errstr<br />\n";
                $errorType = 'E_WARNING';
                break;
            case E_PARSE:
                $msg = "<b>PARSE ERROR</b> [$errno] $errstr<br />\n";
                $errorType = 'E_PARSE';
                break;
            case E_NOTICE:
            case E_USER_NOTICE:
                //$flag = false;
                $msg = "<b>NOTICE</b> [$errno] $errstr<br />\n";
                $errorType = 'E_NOTICE';
                break;
            default:
                $msg = "Unknown error type: [$errno] $errstr<br />\n";
                /**
                 * @todo corrigir erro, não é UNKOWN é UNKNOWN
                 */
                $errorType = 'UNKOWN';
                break;
        }

        $this->sendMailError($errorType, self::fileExcerpt($errors->exception));

        $this->view->setViewsPath(VIEWS_PATH);
        $this->view->output = $this->displayEcraError($errorType,self::fileExcerpt($errors->exception));
        $this->view->titulo = "Auto-ErrorReport";
    	$this->_helper->viewRenderer->setRender('vazia');
    }

    /**
     * Funcao de tratamento de excepcoes
     *
     * @param  Exception  $exception
     */
    public function exception($exception) {
        $this->sendMailError('EXCEPTION', self::fileExcerpt($exception, 20));
        $this->displayEcraError("EXCEPTION",self::fileExcerpt($exception, 10));
    }

    /**
     * Funcao envia email suporte suporte_sm5@goweb.pt
     *
     * @param  String  $errorType
     * @param  String  $message
     */
    public function sendMailError($errorType, $message){
        $header = '<div style="background-color:#FFFFFF; font-family:Verdana, Arial, Helvetica, sans-serif; color:#999999; border:1px solid #FF0000; font-size:9px; display:block; width:98%; margin:2px; padding:3px;">
		   Site: <strong>' . $_SERVER['HTTP_HOST'] . '</strong> <br>
		   Url: <strong>' . $_SERVER['REQUEST_URI'] . '</strong> <br>
		   Data: <strong>' . date("Y-m-d H:m:s", time()) . '</strong> <br>
		   Endere&ccedil;o: <strong>' . $_SERVER['REMOTE_ADDR'] . '</strong> <br>';
        if (array_key_exists('HTTP_REFERER',$_SERVER)) $header.='Refer&ecirc;ncia: <strong>' . $_SERVER['HTTP_REFERER'] . '</strong> <br>';
        $header.='</div><br />';
        if((isset($this->_config->send_mail_error->$errorType) && $this->_config->send_mail_error->$errorType) || (!isset($this->_config->send_mail_error->$errorType))){
            Goweb::loadClass('Goweb_Mail');
            $mail = new Goweb_Mail();
            $mail->setSupportMail();

            $mail->setSubject(html_entity_decode("SM5 - BUG " . $errorType, ENT_NOQUOTES, CHARSET));

            $mail->setBodyHtml($header . $message);

            try {
                $mail->send();
            } catch (Exception $e) {
                // nao faz nada
            }
        }
    }

    /**
     * Funcao mostra para o ecra se está em ambiente de desenvolvimento
     *
     *  @param String $message
     */
    public function displayEcraError($errorType, $message) {
         
        if($this->_config->debug){
            return $message;
        }
        else {
            $texto = '<br /><hr style="height:1px; color:#AAAAAA; "><br />
			<p>' . translate('Ocorreu um erro. O conte&uacute;do, ou parte dos conte&uacute;dos desta p&aacute;gina n&atilde;o podem ser apresentados. Por favor tente mais tarde.') . '<p />
<p>' . translate('Pedimos desculpa pelo inc&oacute;modo.') . '</p>
<p>' . translate('Este problema foi reportado automaticamente ao suporte t&eacute;cnico atrav&eacute;s do sistema de Auto-ErrorReport, e ser&aacute; resolvido o mais brevemente poss&iacute;vel.') . '</p>
<p>' . translate('Em caso de d&uacute;vidas, por favor contacte-nos atrav&eacute;s do email: ') . '<a href="mailto:info@goweb.pt">info@goweb.pt</a>.</p><hr style="height:1px; color:#AAAAAA; ">';
            return $texto;
        }
    }

    /**
     * Retorna o excerto do codigo onde ocorreu a excepcao/erro
     *
     * @param  Exception  $exception
     * @param  int        $linesToShow  O numero de linhas*2 a serem mostradas
     * @param  string                   Extracto do codigo onde ocorreu a excepcao
     */
    public static function fileExcerpt($exception, $linesToShow = 5) {
        $files = array();
        $lines = array();
        if ($exception instanceof Exception) {
            $files[] = $exception->getFile();
            $lines[] = $exception->getLine();
            $trace   = $exception->getTrace();
            for ($i=0; $i<count($trace); $i++) {
                if (isset($trace[$i]['file']) && isset($trace[$i]['file'])) {
                    $files[]    = $trace[$i]['file'];
                    $lines[]    = $trace[$i]['line'];
                }
            }
            $message = $exception->getMessage();
        } elseif (is_array($exception)) {
            $files    = array($exception['file']);
            $lines    = array($exception['line']);
            $message = $exception['message'];
        } else {
            return null;
        }

        $output = '';
        if (!headers_sent()) {
            header('Content-Type:text/html; charset=' . CHARSET);
        }

        if (is_array($files) && count($files) > 0){
            $output .= '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">' . "\n";
            $output  = "<html>\n";
            $output .= "<head>\n";
            $output .= '<meta http-equiv="Content-Type" content="text/html; charset=' . CHARSET . '">' . "\n";
            $output .= "</head>\n";
            $output .= "<body>\n";
            for ($fileCount=0; $fileCount<count($files); $fileCount++) {
                if (!isset($files[$fileCount]) || !isset($lines[$fileCount])) continue;
                $file = $files[$fileCount];
                $line = $lines[$fileCount];
                if (is_readable($file))  {
                    $content = preg_split('#<br />#', highlight_file($file, true));
                    $start = ($line - $linesToShow) > 0 ? $line - $linesToShow : 0;
                    $end = ($line + $linesToShow) < sizeof($content) ? $line + $linesToShow : sizeof($content);
                    $output .= '<ul style="font-family:monospace; font-size:11px; list-style:none; background-color:#EEEEEE; margin:0; padding:5px; border:1px solid #999999;">' . "\n";
                    $output .= '<li style="background-color:#666666; color:#FFFFFF; padding:3px; padding-left:5px;">FICHEIRO: ' . $file . '</li>';
                    $output .= '<li style="background-color:#666666; color:#FFFFFF; padding:3px; padding-left:5px;">LINHA: &nbsp;&nbsp;&nbsp;' . $line . '</li>';
                    if ($fileCount == 0) $output .= '<li style="background-color:#666666; color:#FFFFFF; padding:3px; margin-bottom:5px; padding-left:5px; border-bottom:3px solid #999999;">MENSAGEM: ' . $message . '</li>';
                    for($i = $start; $i < $end; $i++) {
                        $output .= '<li' . ($i+1 == $line ? ' style="background-color:#FFFFFF; padding-left:0;"' : '') . '>&nbsp;<span style="color:#666666;">' . ($i + 1) . '.</span> ' . $content[$i].'</li>';
                    }
                    $output .= "</ul>\n";
                    $output .= "<br />\n";
                }
            }
            $output .= "</body>\n";
            $output .= "</html>\n";
        }
        return $output;
    }
}
