OSDN Git Service

Merge branch 'release/2.6.0beta2'
[ethna/ethna.git] / class / Error.php
1 <?php
2 // vim: foldmethod=marker
3 /**
4  *  Error.php
5  *
6  *  @author     Masaki Fujimoto <fujimoto@php.net>
7  *  @license    http://www.opensource.org/licenses/bsd-license.php The BSD License
8  *  @package    Ethna
9  *  @version    $Id$
10  */
11
12 // {{{ ethna_error_handler
13 /**
14  *  エラーコールバック関数
15  *
16  *  @param  int     $errno      エラーレベル
17  *  @param  string  $errstr     エラーメッセージ
18  *  @param  string  $errfile    エラー発生箇所のファイル名
19  *  @param  string  $errline    エラー発生箇所の行番号
20  */
21 function ethna_error_handler($errno, $errstr, $errfile, $errline)
22 {
23     if ($errno === E_STRICT || $errno === E_DEPRECATED
24     || ($errno & error_reporting()) === 0) {
25         return;
26     }
27
28     list($level, $name) = Ethna_Logger::errorLevelToLogLevel($errno);
29     switch ($errno) {
30     case E_ERROR:
31     case E_CORE_ERROR:
32     case E_COMPILE_ERROR:
33     case E_USER_ERROR:
34         $php_errno = 'Fatal error'; break;
35     case E_WARNING:
36     case E_CORE_WARNING:
37     case E_COMPILE_WARNING:
38     case E_USER_WARNING:
39         $php_errno = 'Warning'; break;
40     case E_PARSE:
41         $php_errno = 'Parse error'; break;
42     case E_NOTICE:
43     case E_USER_NOTICE:
44     case E_STRICT:
45     case E_DEPRECATED:
46         $php_errno = 'Notice'; break;
47     default:
48         $php_errno = 'Unknown error'; break;
49     }
50     $php_errstr = sprintf('PHP %s: %s in %s on line %d',
51                           $php_errno, $errstr, $errfile, $errline);
52
53     // error_log()
54     if (ini_get('log_errors')) {
55         $locale = setlocale(LC_TIME, 0);
56         setlocale(LC_TIME, 'C');
57         error_log($php_errstr, 0);
58         setlocale(LC_TIME, $locale);
59     }
60
61     // $logger->log()
62     $c = Ethna_Controller::getInstance();
63     if ($c !== null) {
64         $logger = $c->getLogger();
65         $logger->log($level, sprintf("[PHP] %s: %s in %s on line %d",
66                                      $name, $errstr, $errfile, $errline));
67     }
68
69     // printf()
70     if (ini_get('display_errors')) {
71         $is_debug = true;
72         $has_echo = false;
73         if ($c !== null) {
74             $config = $c->getConfig();
75             $is_debug = $config->get('debug');
76             $facility = $logger->getLogFacility();
77             $has_echo = is_array($facility)
78                         ? in_array('echo', $facility) : $facility === 'echo';
79         }
80         if ($is_debug == true && $has_echo === false) {
81             return true;
82         }
83     }
84 }
85 set_error_handler('ethna_error_handler');
86 // }}}
87
88 // {{{ ethna_exception_handler
89     //  TODO: Implement ethna_exception_handler function.
90 // }}}
91
92 // {{{ Ethna_Error
93 /**
94  *  エラークラス
95  *
96  *  @author     Masaki Fujimoto <fujimoto@php.net>
97  *  @access     public
98  *  @package    Ethna
99  */
100 class Ethna_Error
101 {
102     /**#@+
103      *  @access private
104      */
105
106     /** @var    object  Ethna_I18N  i18nオブジェクト */
107     var $i18n;
108
109     /** @var    object  Ethna_Logger    loggerオブジェクト */
110     var $logger;
111
112     /** @var    string  エラーメッセージ */
113     var $message;
114
115     /** @var    integer エラーコード */
116     var $code;
117
118     /** @var    integer エラーモード */
119     var $mode;
120     
121     /** @var    array   エラーモード依存のオプション */
122     var $options;
123
124     /** @var    string  ユーザー定義もしくはデバッグ関連の追加情報を記した文字列。 */
125     var $userinfo;
126
127     /**#@-*/
128
129     /**
130      *  Ethna_Errorクラスのコンストラクタ
131      *  $userinfo は第5引数に設定すること。 
132      *
133      *  @access public
134      *  @param  string  $message            エラーメッセージ
135      *  @param  int     $code               エラーコード
136      *  @param  int     $mode               エラーモード(Ethna_Errorはコールバックを
137      *                                      常に使用するので実質無視される)
138      *  @param  array   $options            エラーモード依存のオプション
139      *  @param  array   $userinfo           エラー追加情報($options より後の全ての引数)
140      *  @see http://pear.php.net/manual/ja/core.pear.pear-error.pear-error.php
141      */
142     public function __construct($message = null, $code = null, $mode = null, $options = null)
143     {
144         $controller = Ethna_Controller::getInstance();
145         if ($controller !== null) {
146             $this->i18n = $controller->getI18N();
147         }
148
149         // $options 以降の引数 -> $userinfo
150         if (func_num_args() > 4) {
151             $userinfo = array_slice(func_get_args(), 4);
152             if (count($userinfo) == 1) {
153                 if (is_array($userinfo[0])) {
154                     $this->userinfo = $userinfo[0];
155                 } else if (is_null($userinfo[0])) {
156                     $this->userinfo = array();
157                 }
158             } else {
159                 $this->userinfo = $userinfo[0];
160             }
161         } else {
162             $this->userinfo = array();
163         }
164
165         // メッセージ補正処理 ($message)
166         if (is_null($message)) {
167             // $codeからメッセージを取得する
168             $message = $controller->getErrorMessage($code);
169             if (is_null($message)) {
170                 $message = 'unknown error';
171             }
172         }
173         $this->message = $message;
174
175         //  その他メンバ変数設定
176         $this->code = $code;
177         $this->mode = $mode;
178         $this->options = $options; 
179         $this->level = ($this->options === NULL) ? E_USER_NOTICE : $options;
180
181         //  Ethnaフレームワークのエラーハンドラ(callback)
182         Ethna::handleError($this);
183     }
184
185     /**
186      * エラーオブジェクトに関連付けられたエラーコードを返します。
187      *
188      * @return integer - エラー番号
189      */
190     public function getCode()
191     {
192         return $this->code;
193     }
194
195     /**
196      *  levelへのアクセサ(R)
197      *
198      *  @access public
199      *  @return int     エラーレベル
200      */
201     public function getLevel()
202     {
203         return $this->level;
204     }
205
206     /**
207      *  messageへのアクセサ(R)
208      *
209      *  以下の処理を行う
210      *  - エラーメッセージのi18n処理
211      *  - $userinfoとして渡されたデータによるvsprintf()処理
212      *
213      *  @access public
214      *  @return string  エラーメッセージ
215      */
216     public function getMessage()
217     {
218         $tmp_message = $this->i18n ? $this->i18n->get($this->message) : $this->message;
219         $tmp_userinfo = to_array($this->userinfo);
220         $tmp_message_arg_list = array();
221         for ($i = 0; $i < count($tmp_userinfo); $i++) {
222             $tmp_message_arg_list[] = $this->i18n ? $this->i18n->get($tmp_userinfo[$i]) : $tmp_userinfo[$i];
223         }
224         return vsprintf($tmp_message, $tmp_message_arg_list);
225     }
226
227     /**
228      *  エラー追加情報へのアクセサ(R)
229      *
230      *  エラー追加情報配列の個々のエントリへのアクセスをサポート
231      *
232      *  @access public
233      *  @param  int     $n      エラー追加情報のインデックス(省略可)
234      *  @return mixed   message引数
235      */
236     public function getUserInfo($n = null)
237     {
238         if (is_null($n)) {
239             return $this->userinfo;
240         }
241
242         if (isset($this->userinfo[$n])) {
243             return $this->userinfo[$n];
244         } else {
245             return null;
246         }
247     }
248
249     /**
250      *  エラー追加情報へのアクセサ(W)
251      *
252      *  @access public
253      *  @param  string  $info   追加するエラー情報
254      */
255     public function addUserInfo($info)
256     {
257         $this->userinfo[] = $info;
258     }
259 }
260 // }}}
261