5 * The Simplicity Error module provides advanced error handling.
7 * @author John Le Drew <jp@antz29.com>
8 * @copyright Copyright (c) 2009, John Le Drew
9 * @license http://www.opensource.org/licenses/mit-license.php MIT License
10 * @version 2.0.0-alpha
14 class smp_ErrorModule
extends smp_Module
17 private $_handled = false;
22 protected function init()
24 $this->setDefault('enabled',true);
25 $this->setDefault('chain',array('Basic'));
27 $this->createExtensionPoint('smp_ErrorHandler');
28 $this->registerPluginPrefix('smp_');
34 public function exec($args=array())
38 if ($this->getConfig('enabled')) {
39 ini_set('display_errors',0);
40 register_shutdown_function(array($this,'shutdown'));
41 set_error_handler(array($this,'error'));
42 set_exception_handler(array($this,'exception'));
49 public function error($errno,$errstr,$errfile,$errline)
51 restore_error_handler();
52 $this->_handled
= true;
53 $this->handle(new smp_Exception($errstr,$errline,$errno,$errfile));
59 public function shutdown()
61 restore_error_handler();
62 restore_exception_handler();
64 if ($this->_handled
) return false;
66 $e = error_get_last();
69 $e = new smp_FatalException('Fatal error: '.$e['message'],$e['line'],$e['type'],$e['file'],$GLOBALS,array());
77 public function exception(Exception
$e)
79 restore_error_handler();
80 restore_exception_handler();
82 $this->_handled
= true;
84 if (!($e instanceof smp_Exception
)) {
85 $e = new smp_Exception($e->getMessage(),$e->getLine(),$e->getCode(),$e->getFile());
91 public function getErrorReport($ref)
95 $cnf = $this->getConfig('logging');
96 $realpath = realpath($cnf['path']);
98 if (!$realpath) return false;
102 $dsn = "sqlite:{$realpath}errorlog.sq3";
104 $p = new PDO($dsn,null,null,array(PDO
::ATTR_ERRMODE
=> PDO
::ERRMODE_EXCEPTION
));
105 $p->sqliteCreateFunction('crc32', 'crc32', 1);
108 $qry = "create table if not exists error_log ( id integer primary key, timestamp default CURRENT_TIMESTAMP, message, trace, context, request, response )";
112 $qry = "select crc32(id || timestamp) as ref1,? as ref2,* from error_log";
113 $stm = $p->prepare($qry);
114 $stm->execute(array($ref));
115 var_dump($stm->fetchAll(PDO::FETCH_ASSOC));die();
118 $qry = "select * from error_log where crc32(id || timestamp) like ?";
119 $stm = $p->prepare($qry);
120 $stm->execute(array($ref));
121 $error = $stm->fetch(PDO
::FETCH_ASSOC
);
124 catch (Exception
$e) {
132 private function logException(smp_Exception
$e)
134 $msg = $e->getMessage() . ' on line ' . $e->getLine() . ' in file ' . $e->getFile();
136 $session = Simplicity
::getInstance()->getModule('Session');
138 if ($last = $session->get('last_exception')) {
139 if ($last['error']['message'] == $msg) return $last['ref'];
142 $cnf = $this->getConfig('logging');
144 $realpath = realpath($cnf['path']);
146 if (!$realpath) return false;
150 $dsn = "sqlite:{$realpath}errorlog.sq3";
151 $p = new PDO($dsn,null,null,array(PDO
::ATTR_ERRMODE
=> PDO
::ERRMODE_EXCEPTION
));
154 $qry = "create table if not exists error_log ( id integer primary key, timestamp default CURRENT_TIMESTAMP, message, trace, context, request, response )";
157 $qry = "insert into error_log (message,trace,context,request,response) values (?,?,?,?,?)";
158 $stm = $p->prepare($qry);
160 $trace = $e->getTraceAsString();
161 $context = print_r($e->getContext(),true);
163 $request = print_r(array(
164 'method' => smp_Request
::getInstance()->getMethod(),
165 'uri' => smp_Request
::getInstance()->getUri(),
166 'request_data' => smp_Request
::getInstance()->getData(),
167 'headers' => smp_Request
::getInstance()->getHeaders()
170 $response = print_r(array(
171 'status' => smp_Response
::getInstance()->getStatus(),
172 'encoding' => smp_Response
::getInstance()->getContentEncoding(),
173 'headers' => smp_Response
::getInstance()->getHeaders(),
174 'content' => smp_Response
::getInstance()->getContent()
177 $stm->execute(array($msg,$trace,$context,$request,$response));
179 catch (Exception
$e) {
183 $id = $p->lastInsertId();
184 $error = $p->query("select * from error_log where id = {$id}")->fetch(PDO
::FETCH_ASSOC
);
186 $ref = crc32($id.$error['timestamp']);
188 $session->set('last_exception',array('ref'=>$ref,'error' => $error));
190 $file = date('Ymdhis',strtotime($error['timestamp'])).'_'.$ref;
191 $file = $realpath."{$file}.log";
193 file_put_contents($file,print_r($error,true));
198 private function handle(smp_Exception
$e)
200 $chain = $this->getConfig('chain');
202 while ($module = array_shift($chain)) {
203 $cls = $this->getModuleClass($module);
204 $mod = new $cls($this,$e,$module);
206 $e = $mod->getException();
209 $this->getSimplicity()->clearCurrentChain();