Merging r695 from the 2.1.x branch to the trunk
[isso.git] / Loader.php
1 <?php
2 /*=====================================================================*\
3 || ###################################################################
4 || # Blue Static ISSO Framework [#]issoversion[#]
5 || # Copyright ©2002-[#]year[#] Blue Static
6 || #
7 || # This program is free software; you can redistribute it and/or modify
8 || # it under the terms of the GNU General Public License as published by
9 || # the Free Software Foundation; version [#]gpl[#] of the License.
10 || #
11 || # This program is distributed in the hope that it will be useful, but
12 || # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 || # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 || # more details.
15 || #
16 || # You should have received a copy of the GNU General Public License along
17 || # with this program; if not, write to the Free Software Foundation, Inc.,
18 || # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
19 || ###################################################################
20 \*=====================================================================*/
21
22 /**
23 * System loader (Loader.php)
24 *
25 * @package ISSO
26 */
27
28 // we need PHP5 to run
29 if (!function_exists('stripos'))
30 {
31 trigger_error('You need PHP version 5.0.0 or newer to run ISSO', E_USER_ERROR);
32 exit;
33 }
34
35 // get rid of register_globals
36 if ((bool)ini_get('register_globals') === true)
37 {
38 $superglobals = array('_GET', '_COOKIE', '_FILES', '_POST', '_SERVER', '_ENV');
39 foreach ($superglobals AS $global)
40 {
41 if (is_array(${$global}))
42 {
43 foreach (${$global} AS $_key => $_val)
44 {
45 if (isset(${$_key}))
46 {
47 unset(${$_key});
48 }
49 }
50 }
51 }
52 }
53
54 /**
55 * System Loader
56 *
57 * This class contains static methods that are used to create new registers and
58 * load modules.
59 *
60 * @author Blue Static
61 * @copyright Copyright ©2002 - [#]year[#], Blue Static
62 * @version $Revision$
63 * @package ISSO
64 *
65 */
66 class BSLoader
67 {
68 /**
69 * Singleton instance
70 * @var object
71 */
72 private static $instance;
73
74 /**
75 * Array of all the registers
76 * @var array
77 */
78 private $registers = array();
79
80 /**
81 * The main register
82 * @var object
83 */
84 private $main;
85
86 // ###################################################################
87 /**
88 * Constructor
89 */
90 private function __construct() {}
91
92 // ###################################################################
93 /**
94 * Returns the shared instance of the BSLoader singleton class.
95 *
96 * @return object The BSLoader shared instance
97 */
98 private static function SharedInstance()
99 {
100 if (!self::$instance)
101 {
102 self::$instance = new BSLoader;
103 set_error_handler(array(self::$instance, 'errorHandler'));
104 }
105 return self::$instance;
106 }
107
108 // ###################################################################
109 /**
110 * Creates a new BSRegister instance and returns it.
111 *
112 * @return object New register
113 */
114 public static function NewRegister()
115 {
116 require_once('ISSO/Register.php');
117
118 self::SharedInstance()->registers[] = $return = new BSRegister();
119
120 return $return;
121 }
122
123 // ###################################################################
124 /**
125 * Returns the array of all the registers
126 *
127 * @return array The array of all the registers
128 */
129 public static function GetAllRegisters()
130 {
131 return self::SharedInstance()->registers;
132 }
133
134 // ###################################################################
135 /**
136 * Sets the main register
137 *
138 * @param object New main register
139 */
140 public static function SetRegister($register)
141 {
142 if (get_class($register) != 'BSRegister')
143 {
144 trigger_error('BSLoader::SetRegister() was not passed a BSRegister object');
145 return;
146 }
147
148 self::SharedInstance()->main = $register;
149 }
150
151 // ###################################################################
152 /**
153 * Gets the main register if no argument is passed, or an arbitrary
154 * one if the index of a register is passed.
155 *
156 * @param integer Register index
157 *
158 * @return object Specified register
159 */
160 public static function &GetRegister($index = null)
161 {
162 if (is_null($index))
163 {
164 if (!isset(self::SharedInstance()->main))
165 {
166 trigger_error('Cannot fetch the main register because it has not been set with BSLoader::SetRegister()');
167 return;
168 }
169 return self::SharedInstance()->main;
170 }
171 else
172 {
173 if (!isset(self::SharedInstance()->registers["$index"]))
174 {
175 trigger_error('Invalid register index passed to BSLoader::GetRegister()');
176 return;
177 }
178 return self::SharedInstance()->registers["$index"];
179 }
180 }
181
182 // ###################################################################
183 /**
184 * Determines if there's a main register set. If not, returns FALSE.
185 *
186 * @return bool Is there a main register set?
187 */
188 public static function HasRegister()
189 {
190 return (isset(self::SharedInstance()->main) AND self::SharedInstance()->main instanceof BSRegister);
191 }
192
193 // ###################################################################
194 /**
195 * Loads the specified module.
196 *
197 * @param string Module name
198 *
199 * @return object Instantiated module
200 */
201 public static function LoadModule($name)
202 {
203 @include_once("ISSO/$name.php");
204
205 $class = "BS$name";
206
207 if (!class_exists($class))
208 {
209 trigger_error('Specifed module does not conform to the ISSO specification, or the class is missing');
210 return;
211 }
212
213 return new $class;
214 }
215
216 // ###################################################################
217 /**
218 * Prints an ISSO message
219 *
220 * @param string The title of the message
221 * @param string The content of the message
222 * @param integer Type of message to be printed
223 * @param bool Return the output?
224 * @param bool Show the debug stack?
225 * @param integer Message width
226 *
227 * @return mixed Output or null
228 */
229 public static function Message($title, $message, $type, $return = false, $stack = true, $width = 500)
230 {
231 switch ($type)
232 {
233 // Message
234 case 1:
235 $prefix = 'Message';
236 $color = '#669900';
237 $font = '#000000';
238 break;
239
240 // Warning
241 case 2:
242 $prefix = 'Warning';
243 $color = '#003399';
244 $font = '#FFFFFF';
245 break;
246
247 case 3:
248 $prefix = 'Error';
249 $color = '#990000';
250 $font = '#EFEFEF';
251 break;
252 }
253
254 echo "\n<br />\n<table cellpadding=\"4\" cellspacing=\"1\" border=\"0\" width=\"$width\" style=\"background-color: $color; color: black; font-family: Verdana, sans-serif; font-size: 12px;\">";
255 echo "\n<tr style=\"color: $font; text-align: left\">\n\t<td><strong>$prefix: $title</strong></td>\n</tr>";
256 echo "\n<tr style=\"background-color: #FFFFFF; text-align: left\">\n\t<td>$message</td>\n</tr>";
257 if ($stack AND self::HasRegister() AND self::GetRegister()->getDebug())
258 {
259 echo "\n<tr style=\"background-color: #FFFFFF; text-align: left\">\n\t<td><strong>Debug Stack:</strong> <pre>";
260 debug_print_backtrace();
261 echo "</pre></td>\n</tr>";
262 }
263 echo "\n</table>\n<br />\n";
264 }
265
266 // ###################################################################
267 /**
268 * Custom error handler for ISSO; only handle E_WARNING, E_NOTICE,
269 * E_USER_ERROR, E_USER_WARNING, E_USER_NOTICE
270 *
271 * @param integer Error number
272 * @param string Error message string
273 * @param string File that contains the error
274 * @param string The line number of the error
275 * @param string The active symbol table at which point the error occurred
276 */
277 private function errorHandler($errno, $errstr, $errfile, $errline, $errcontext)
278 {
279 $level = ini_get('error_reporting');
280
281 switch ($errno)
282 {
283 // So we don't need to specify the error type in trigger_error(), all E_USER_NOTICEs
284 // are fatal and automatically kill the script
285 case E_USER_NOTICE:
286 $title = 'Fatal';
287 $mode = 3;
288 break;
289
290 // A non-fatal but important warning
291 case E_WARNING:
292 $title = 'Warning';
293 $mode = 2;
294 if (!($level & E_WARNING))
295 {
296 return;
297 }
298 break;
299
300 // A non-fatal notice that should all but be ignored unless in dev environments
301 case E_NOTICE:
302 case E_STRICT:
303 $title = 'Notice';
304 $mode = 1;
305 if (!($level & E_NOTICE))
306 {
307 return;
308 }
309 break;
310
311 case E_USER_WARNING:
312 case E_USER_NOTICE:
313 default:
314 trigger_error('The only error types supported are E_USER_NOTICE (fatal), E_WARNING, and E_NOTICE');
315 break;
316 }
317
318 $errstr .= " in <strong>$errfile</strong> on line <strong>$errline</strong>";
319
320 $errstr = str_replace(array(getcwd(), dirname(getcwd())), '', $errstr);
321
322 self::Message($title, $errstr, $mode);
323
324 if ($errno == E_USER_NOTICE)
325 {
326 exit;
327 }
328 }
329
330 // ###################################################################
331 /**
332 * Creates a table that explains the error reporting levels and their
333 * state
334 */
335 public static function ExplainErrorReporting()
336 {
337 $levels = array(
338 'E_ERROR' => E_ERROR,
339 'E_WARNING' => E_WARNING,
340 'E_PARSE' => E_PARSE,
341 'E_NOTICE' => E_NOTICE,
342 'E_CORE_ERROR' => E_CORE_ERROR,
343 'E_CORE_WARNING' => E_CORE_WARNING,
344 'E_COMPILE_ERROR' => E_COMPILE_ERROR,
345 'E_COMPILE_WARNING' => E_COMPILE_WARNING,
346 'E_USER_ERROR' => E_USER_ERROR,
347 'E_USER_WARNING' => E_USER_WARNING,
348 'E_USER_NOTICE' => E_USER_NOTICE,
349 'E_ALL' => E_ALL,
350 'E_STRICT' => E_STRICT
351 );
352
353 $table = '<table cellspacing="0" cellpadding="2" border="0">';
354
355 foreach ($levels AS $name => $value)
356 {
357 $table .= '
358 <tr>
359 <td>' . $name . '</td>
360 <td>' . (ini_get('error_reporting') & $value) . '</td>
361 </tr>';
362 }
363
364 $table .= '
365 </table>';
366
367 self::Message('Error Reporting', $table, 1);
368 }
369 }
370
371 /*=====================================================================*\
372 || ###################################################################
373 || # $HeadURL$
374 || # $Id$
375 || ###################################################################
376 \*=====================================================================*/
377 ?>