<?php if (!defined('HTTP_SERVER')) die('You can not access this file directly!');
/**
  @licence GPL 2005-2010  The osCSS developers - osCSS Open Source E-commerce
  @portion code Copyright (c) 2002 osCommerce
  @package osCSS-2 <www http://www.oscss.org>
  @version 2.1.0
  @date  10/06/10, 09:08
  @author oscim <mail aurelien@oscim.fr> <www http://www.oscim.fr>
*/

/**
  Gestionnaire d'execption
  @class osC_ErrorHandler

*/
class MyException extends Exception {
  public function __toString() {
    return " class '".get_class($this) ."' ".PHP_EOL.
	   " with message '".$this->getMessage()."'".PHP_EOL.
	   " in ".$this->getFile().":".$this->getLine()."".PHP_EOL.
	   "Stack trace:\n".$this->getTraceAsString();
  }
}

/**
  Gestionnaire d'exception
  @package oscss-2 <www http://www.oscss.org>
  @param string
*/
function exception_handler() {
   try {
        throw new MyException();
	throw new Exception();
    }
    catch (MyException $e) {
// print_r($e);
        echo("FATAL:: Caught MyException ('{$e->__toString()}')\n{$e}\n" );
    }
    catch (Exception $e) {
        echo $e->getMessage();
    }
}


/**
  Gestionnaire d'erreur
  @class osC_ErrorHandler

*/
class osC_ErrorHandler
  implements SplSubject, IteratorAggregate {

  private $_errno;
  private $_errstr;
  private $_errline;
  private $_errfile;
  private $_observers = array();
  protected static $_instance;

  protected function __construct() {
    $this->_observers = new SplObjectStorage();
    $this->timer_start = PAGE_PARSE_START_TIME;
  }

  public static function getInstance() {
      if(self::$_instance == null) {
	  self::$_instance = new self();
      }
      return self::$_instance;
  }

  public static function resetInstance() {
      self::$_instance = null;
      return self::getInstance();
  }



  public function factory($listener, array $args = array()) {
      $reflect = new ReflectionClass($listener);
      return $reflect->newInstanceArgs($args);
  }

  public static function start() {
      set_error_handler(array(self::getInstance(),'error'));
      return self::getInstance();
  }

  public static function stop() {
      restore_error_handler();
      return self::getInstance();
  }

  public function error($errno, $errstr, $errfile, $errline) {
      if(error_reporting() == 0)  return;

      $this->_errno   = $errno;
      $this->_errstr  = $errstr;
      $this->_errfile = $errfile;
      $this->_errline = $errline;
      $this->notify();
      return true;
  }

  public function getError($format=false) {
    return  (!$format)
	      ? $this->_errstr . ', ' . $this->_errfile . ', ' . $this->_errline
	      : array($this->_errstr , $this->_errfile , $this->_errline)
	    ;
  }

  public function attach(SplObserver $obs)  {
      $this->_observers->attach($obs);
      return $this;
  }

  public function detach(SplObserver $obs) {
      $this->_observers->detach($obs);
      return $this;
  }

  public function __call($funct, $args) {
      if (preg_match('#(att|det)ach(\w+)#', $funct, $matches)) {
	  $meth     = $matches[1].'ach';
	  $listener = strtolower($matches[2]);
	  return $this->$meth(self::factory($listener, $args));
      }
      throw new BadMethodCallException("methode $funct inexistante");
  }

  public function notify()  {
      foreach ($this->_observers AS $observer) {
	  try{
	      $observer->update($this); // délégation
	  }catch(Exception $e){
	      die($e->getMessage());
	  }
      }
  }


  public function getIterator() {
      return $this->_observers; // SplObjectStorage est itératif :)
  }
}

/**
  @class FileWriter
  Sortie en fichier
*/
class FileWriter implements SplObserver{
    private $_fp;
    private $maxSize ;

    public function __construct($filepath)
    {
	$this->maxSize= 5 * 1024 * 1024;
	  $intFileSize = @filesize($filepath);
	  if ( $intFileSize >= $this->maxSize) {
	    //On archive le fichier
	    $strFileContent = file_get_contents($filepath);
	    $strToFileGz = $filepath . '.' . date('Ymd_His') . '.gz';
	    $strFileContentGz = gzencode($strFileContent,9);
	    $objFileGz = @fopen($strToFileGz, 'w+');
	    fwrite($objFileGz,$strFileContentGz);
	    fclose($objFileGz);
	    //On suprime le fichier
	    unlink($filepath);
	  }
	    if (FALSE === $this->_fp = @fopen($filepath,'a+')) {
		throw new Exception('Impossible d\'ouvrir le fichier de log');
	    }

    }

    public function update(SplSubject $errorHandler)
    {
      @fputs($this->_fp,
	(function_exists('tep_strftime')
	  ?  tep_strftime(STORE_PARSE_DATE_TIME_FORMAT).' '
	  : '' ) .
        $errorHandler->getError() . PHP_EOL);
    }
}



/**
  @class BDDWriter
  Sortie en bd
*/
// class BDDWriter implements SplObserver
// {
//     private $_pdo;
//     private $_table;
//     private $_col;
//
//     public function __construct($host,$login,$pass,$dbname,$table,$col)
//     {
//         $this->_pdo = new PDO("mysql:host=$host;dbname=$dbname",$login,$pass);
//         $this->_pdo->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
//         $this->_col   = (string)$col;
//         $this->_table = (string)$table;
//     }
//
//     public function update(SplSubject $errorHandler)
// 	{
//         $this->_pdo->exec("INSERT INTO $this->_table (`$this->_col`) VALUES('{$errorHandler->getError()}')");
//     }
// }

/**
  @class MockWriter
  Sortie en ecran
*/
class MockWriter implements SplObserver
{
    private $_messages = array();

    public function update(SplSubject $errorHandler)
    {
        $this->_messages[] = $errorHandler->getError();
    }
    public function is_count() {
        return ((count($this->_messages)>0)?true:false);
    }
    public function show() {
        return print_r($this->_messages, true);
    }
}

/**
  @class MailWriter
  Sortie en mail
*/
class MailWriter implements SplObserver
{
    private $_to;
    const SUBJECT = 'erreur signalée';

    public function __construct($to)
    {
        $this->_to = (string)$to;
        if(preg_match('#[a-z0-9_-]*[@][a-z0-9]*[.][a-z]{2,4}#', $this->_to) === false) {
            throw new Exception('Adresse email non conforme');
        }
    }

    public function update(SplSubject $errorHandler)
    {
        @mail($this->_to,self::SUBJECT, $errorHandler->getError());
    }
}
?>