/[cvs]/nfo/php/libs/org.netfrag.glib/php_extensions.php
ViewVC logotype

Contents of /nfo/php/libs/org.netfrag.glib/php_extensions.php

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.5 - (show annotations)
Mon Mar 10 22:58:46 2003 UTC (21 years, 4 months ago) by joko
Branch: MAIN
Changes since 1.4: +9 -10 lines
+ fixed metadata for phpDocumentor

1 <?php
2
3 /**
4 * This file contains some core functions extending php.
5 *
6 * @author Andreas Motl <andreas.motl@ilo.de>
7 * @package org.netfrag.glib
8 * @name php
9 *
10 */
11
12 /**
13 * $Id: php_extensions.php,v 1.4 2003/03/05 23:16:46 joko Exp $
14 *
15 * $Log: php_extensions.php,v $
16 * Revision 1.4 2003/03/05 23:16:46 joko
17 * updated docu - phpDocumentor is very strict about its 'blocks'...
18 *
19 * Revision 1.3 2003/03/05 18:54:41 joko
20 * updated docu - phpDocumentor is very strict about its 'blocks'...
21 *
22 * Revision 1.2 2003/03/05 11:58:49 joko
23 * modified is_hash, mkInstance and others
24 *
25 * Revision 1.1 2003/03/03 21:08:21 joko
26 * refactored from flib/utils
27 *
28 *
29 */
30
31
32 /**
33 * --- shortcut functions
34 * Is there a mechanism in php to 'export' these methods
35 * to the global symbol table automagically?
36 * We wouldn't require declaring these shortcuts below and
37 * could also do some nice stuff at runtime.
38 * (maybe resembling CPAN's Exporter)
39 *
40 * Okay, 'eval' and 'create_function' are alternatives, but i'm
41 * still looking for something that would let us manipulate the
42 * symbol table.... (would also be a nice-to-have feature for
43 * mungling "other" symbol table entries, like variables
44 * and/or object references etc.)
45 *
46 * TODO: $php::EXPORT_OK = array('Dumper', 'session_register_safe', 'mkObject', 'is_hash', 'merge_to');
47 *
48 */
49 // this is (and will probably always be) required by the "Exporter"
50 function &Dumper() {
51 $args = func_get_args();
52 // shrink array to single item?
53 //if (sizeof($args) == 1) { $args = $args[0]; }
54 php::array_shrink($args);
55 return php::Dumper($args);
56 }
57
58 // these could be refactore using Exporter proposal below,
59 // which just does this code at runtime via eval
60 //function &session_register_safe() { return php::session_register_safe(func_get_args()); }
61 //function &is_hash() { return php::is_hash(func_get_args()); }
62 //function &loadModule() { return php::loadModule(func_get_args()); }
63 //function &mkObject() { return php::mkInstance(func_get_args()); }
64
65
66 //exit;
67
68 // yes!
69 php::export_symbols();
70
71
72
73 /**
74 * --- php extension functions living in the php:: namespace
75 *
76 * <pre>
77 * x php::Dumper
78 * x php::session_register_safe
79 * x php::array_init
80 * x php::is_hash
81 * x php::array_join_merge
82 * o php::merge
83 * o php::merge_to
84 * x php::loadModule
85 * x php::mkInstance
86 * </pre>
87 *
88 * @author Andreas Motl <andreas.motl@ilo.de>
89 * @copyright (c) 2003 - All Rights reserved.
90 * @license GNU LGPL (GNU Lesser General Public License)
91 *
92 * @link http://www.netfrag.org/~joko/
93 * @link http://www.gnu.org/licenses/lgpl.txt
94 *
95 * @package org.netfrag.glib
96 * @name php
97 *
98 * Todo:
99 * @todo (o) establish mkInstance here (move from DesignPattern::Object::mkObject)
100 * @todo (o) establish loadModule here (move from DesignPattern::Object::loadModule)
101 *
102 * Ideas:
103 * @todo (o) php::create_redirector_function('func', array( type => 'lamba|function|method', name => 'Abc::do_xyz') )
104 * @todo (o) php::create_redirector_method('class|obj_ref', 'method', $target)
105 * @todo (o) php::export_symbol(from, to) (maybe solves above two)
106 *
107 */
108 class php {
109
110
111 // Exporter proposal
112
113 // does (e.g.) Exporter::export_symbol('php', 'loadModule', array( php_function => 'loadModule' ));
114 // (or) Exporter::export_symbol('php', 'mkInstance', array( php_function => 'mkObject' ));
115 // -> just all from EXPORT_OK
116
117 function export_symbols() {
118
119 $symbols = func_get_args();
120 php::array_shrink($symbols);
121
122 global $PHP_EXTENSIONS_EXPORT;
123 //print Dumper($PHP_EXTENSIONS_EXPORT);
124 //exit;
125
126 if (is_array($PHP_EXTENSIONS_EXPORT)) {
127 //if (defined('EXPORT_OK')) {
128 //print EXPORT_OK . "<br/>";
129 //$symbols = split(' ', EXPORT_OK);
130 //foreach ($php->EXPORT_OK as $symbol) {
131 /*
132 foreach (EXPORT_OK as $symbol) {
133 print "exporting: $symbol<br/>";
134 Exporter::export_symbol('php', $symbol, array( php_function => $symbol ));
135 }
136 */
137
138 $symbols = php::array_join_merge($PHP_EXTENSIONS_EXPORT, $symbols);
139
140 php::loadModule('Exporter');
141 if (class_exists('Exporter')) {
142 Exporter::export_symbols('php', $symbols);
143 }
144
145 }
146
147 }
148
149 function Dumper() {
150 $arg_list = func_get_args();
151 $count = 1;
152
153 // build dump by catching output of php's 'print_r'
154 // using php's output buffering functions
155 ob_start();
156 foreach ($arg_list as $arg) {
157 print_r($arg);
158 if (is_string($arg)) {
159 print "\n";
160 }
161 $count++;
162 }
163 $var_dump = ob_get_contents();
164 ob_end_clean();
165
166 //print "mode: " . $this->Dumper_mode . "<br/>";
167 //if ($this->Dumper_mode == HTML) {
168 $var_dump = str_replace("\n", '<br/>', $var_dump);
169 $var_dump = str_replace(" ", '&nbsp;', $var_dump);
170 //}
171
172 //if (sizeof($args) == 1) { $var_dump .= '<br/>'; }
173
174 return $var_dump;
175 }
176
177 function session_register_safe($varname) {
178 if (!session_is_registered($varname)) {
179 session_register($varname);
180 return 1;
181 }
182 }
183
184 // -------------------------------------------------
185 // array initializer
186 // initializes passed variable (taken by reference) with an empty array
187 // does this only if it doesn't exist yet or initialization is explicitely requested ($clear = 1)
188 function array_init(&$var, $clear = 0) {
189 if (!is_array($var) || $clear) { $var = array(); }
190 }
191
192 // from: php.net - http://www.php.net/manual/en/function.array-merge-recursive.php
193 function is_hash( $var = null ) {
194 if( is_array( $var ) ) {
195 $keys = array_keys( $var );
196 $all_num = true;
197 for( $i=0; $i<count($keys); $i++ )
198 if( is_string($keys[$i] ) ) return true;
199 }
200 return false;
201 }
202
203 // from: php.net - http://www.php.net/manual/en/function.array-merge-recursive.php
204 function array_join_merge( $arr1, $arr2 ) {
205 if( is_array( $arr1 ) and is_array( $arr2 ) ) {
206 // the same -> merge
207 $new_array = array();
208
209 if( php::is_hash( $arr1 ) and php::is_hash( $arr2 ) ) {
210 // hashes -> merge based on keys
211 $keys = array_merge( array_keys( $arr1 ), array_keys( $arr2 ) );
212 foreach( $keys as $key ) {
213 $new_array[$key] = php::array_join_merge( $arr1[$key], $arr2[$key] );
214 }
215 } else {
216 // two real arrays -> merge
217 $new_array =
218 array_reverse(array_unique(array_reverse(array_merge($arr1,$arr2))));
219 }
220
221 return $new_array;
222 } else {
223 // not the same ... take new one if defined, else the old one stays
224 return $arr2 ? $arr2 : $arr1;
225 }
226 }
227
228
229 // TODO:
230 // o refactor to the php:: namespace?
231 // o PEAR::???
232 // x rename mkObject to mkInstance
233 // x rename loadModule? let it like is.... (suggestions? loadPackage?)
234 // o enhance loadModule: make it possible to load packages from anywhere?! #?)&%$
235
236 function namespace2filename($nsName) {
237 if ($filename = str_replace('::', '/', $nsName)) {
238 return $filename;
239 }
240 }
241
242 function loadModule($namespacedClassname, $options = null) {
243
244 if (DEBUG_PHP_EXTENSIONS == 1) {
245 print "php::loadModule: " . Dumper($namespacedClassname);
246 }
247 if (LOG_PHP_EXTENSIONS == 1) {
248 php::append_log( "php::loadModule( $namespacedClassname )" );
249 }
250
251 if ($filename = php::namespace2filename($namespacedClassname)) {
252
253 if (is_array($options)) {
254 $extension = $options[extension];
255 } elseif ($options) {
256 $extension = $options;
257 } else {
258 $extension = 'php';
259 }
260
261 $filename .= ".$extension";
262
263 // V1: just require
264 //require_once($filename);
265
266 // V2: check file for existance (didn't work!!! problem with path-style conversion regarding platform running on?)
267 /*
268 if (file_exists($filename)) {
269 require_once($filename);
270 } else {
271 //user_error("Could not load module '$namespacedClassname', file '$filename' does not exist.");
272 }
273 */
274
275 // V3: wrapped through eval (weird)
276 /*
277 $evalstring = "return include_once('$filename');";
278 $result = eval($evalstring);
279 if (!$result) {
280 user_error("DesignPattern::Object: Could not load module '$namespacedClassname', file '$filename' does not exist.");
281 return;
282 }
283 */
284
285 // V4: just include
286 //define ("WARNING", E_USER_NOTICE);
287 //error_reporting(E_USER_WARNING);
288 //error_reporting(E_ALL);
289 //error_reporting(E_CORE_ERROR);
290 //set_error_handler(array('php::error_handler_2'));
291
292 //set_error_handler('php_error_handler');
293 // TODO: do stack-backtracing here to determine function called two or three levels before!!!
294 //print "file: $filename<br/>";
295 if (!include_once($filename)) {
296 $msg = "php::loadModule error: Could not load module '$namespacedClassname', file '$filename' does not exist.";
297 user_error($msg);
298 php::append_log($msg, PEAR_LOG_ERR);
299 //trigger_error($msg);
300 //print "msg: $msg<br/>";
301 return;
302 }
303 //restore_error_handler();
304
305 //exit;
306
307 return 1;
308 }
309 }
310
311
312 function &mkComponent() {
313
314 // argument handling - perl style
315 $arg_list = &func_get_args();
316
317 // trace
318 //print "php::mkInstance: " . Dumper($arg_list);
319 //exit;
320
321 // patch arglist if all arguments are passed in as a single array
322 if (sizeof($arg_list) == 1 && is_array($arg_list[0])) {
323 $arg_list = &$arg_list[0];
324 }
325
326 //print "arg_list: $arg_list<br/>";
327 $namespacedClassname = array_shift($arg_list);
328
329 // debug
330 if (DEBUG_PHP_EXTENSIONS == 1) {
331 print "php::mkComponent: $namespacedClassname<br/>";
332 }
333 if (LOG_PHP_EXTENSIONS == 1) {
334 php::append_log( "php::mkComponent( $namespacedClassname )" );
335 }
336
337 $classname = $namespacedClassname;
338 $filename = $namespacedClassname;
339 $load_module_options = null;
340
341 if (strstr($namespacedClassname, '_')) {
342 //print "mkObject: unallowed character in namespaced classname: '_' ($namespacedClassname)<br/>";
343 //return;
344 }
345
346 if (strstr($namespacedClassname, '.')) {
347 //print "mkObject: unallowed character in namespaced classname: '_' ($namespacedClassname)<br/>";
348 //return;
349 $parts = split('\.', $namespacedClassname);
350 $filename = $parts[0];
351 $extension = $parts[sizeof($parts) - 1];
352 $load_module_options = array( extension => $extension );
353 }
354
355
356 // trace
357 //print "mkObject: $classname<br>";
358 //print "file: $filename<br>";
359
360 // build native class name from namespaced one
361 $classname = str_replace('::', '_', $classname);
362 $classname = str_replace('/', '_', $classname);
363
364 // load class-file
365 if (!class_exists($classname)) {
366 php::loadModule($filename, $load_module_options);
367 }
368
369 // instantiate object
370 $attributes = $arg_list;
371 // V0:
372 //$obj = new $classname($attributes);
373 // V1:
374 //$obj = new DesignPattern_Bridge($classname, $attributes);
375 // V2:
376 $obj = php::mkInstance($classname, $attributes);
377
378 // constructor autocall - if possible
379 // FIXME: take care for side-effects!!!
380 /*
381 if (method_exists($obj, 'constructor')) {
382 $obj->constructor();
383 }
384 */
385
386 // return instance
387 return $obj;
388
389 }
390
391 // from: http://www.php.net/manual/en/function.method-exists.php
392 function class_has_method($className, $methodName) {
393 $bool_exists = (in_array(strtolower($methodName), get_class_methods($className)));
394 return $bool_exists;
395 }
396
397 // down: array( item ) => item
398 function &array_shrink(&$array) {
399 // shrink array to single item? yes!
400 if (is_array($array) && !php::is_hash($array) && (sizeof($array) == 1)) { $array = $array[0]; }
401 return $array;
402 }
403
404 function append_log($message, $level = PEAR_LOG_DEBUG) {
405 static $Class_Logger_loaded;
406 static $Class_Logger_instance;
407 if (!$Class_Logger_loaded) {
408 $Class_Logger_loaded++;
409 //print "LOAD<br/>";
410 php::loadModule('Class::Logger');
411 }
412 if (class_exists('Class_Logger')) {
413 //$Class_Logger_instance = new Class_Logger();
414 $Class_Logger_instance = php::mkComponent('Class::Logger');
415 //print "YAI<br/>";
416 //Class_Logger::log($message);
417 $Class_Logger_instance->log($message, $level);
418 } else {
419 // FIXME! pre-logger log-messages (two or three):
420 // [PEAR_LOG_DEBUG] php::loadModule( Class::Logger )
421 // [PEAR_LOG_DEBUG] php::loadModule( DesignPattern::AbstractClass )
422 //print "[$level] $message" . "<br/>";
423 }
424 }
425
426 function &mkInstance($classname, $attributes = array()) {
427
428 $oo = is_object($this);
429
430 // autocall constructor?
431 if ($oo) {
432 //print Dumper($this);
433 //exit;
434 //print "this: $this<br/>";
435 //print "parent: $parent<br/>";
436 // V1:
437 //parent::constructor();
438 // V2:
439 //call_user_func('parent::constructor');
440 // V3:
441 //call_user_func(array($this, 'constructor'));
442 if (method_exists($this, 'constructor')) {
443 //print "YAI<br/>";
444 //call_user_func(array($this, 'constructor'));
445 }
446 }
447
448 if ($oo) {
449 //$this->log( get_class($this) . "->mkInstance( classname $classname )" );
450 //Class_Logger::log( get_class($this) . "->mkInstance( classname $classname )" );
451 } else {
452 //php::append_log( "php::mkInstance( classname $classname )" );
453 }
454
455 if (isset($attributes)) {
456 //print Dumper($attributes);
457
458 /*
459 // pass single argument 1:1
460 if (count($attributes) == 1) {
461 $attributes_merged = $attributes[0];
462
463
464
465 // pass hash 1:1
466 } elseif (is_hash($attributes)) {
467 $attributes_merged = $attributes;
468
469 } else {
470 $attributes_merged = $attributes;
471 }
472 */
473
474 $args_pass = array();
475 for ($i=0; $i<=count($attributes); $i++) {
476 array_push($args_pass, '&$attributes[' . $i . ']');
477 }
478
479 $arg_string = join(', ', $args_pass);
480
481 /*
482 // merge entries of numerical indexed arrays together into one hash
483 } else {
484 $attributes_merged = array();
485 foreach ($attributes as $entry) {
486 $attributes_merged = array_merge($attributes_merged, $entry);
487 }
488 }
489 */
490
491 if (!class_exists($classname)) {
492 user_error("Class '$classname' doesn't exist.");
493 return;
494 }
495
496 //print Dumper($attributes_merged);
497 //print Dumper($attributes);
498 //$instance = new $classname($attributes_merged);
499 //$instance = new $classname($attributes[0]);
500 $evalstr = 'return new $classname(' . $arg_string . ');';
501
502 //print "eval: $evalstr<br/>";
503
504 $instance = eval($evalstr);
505 //print $evalstr . "<br>";
506 } else {
507 $instance = new $classname;
508 }
509 //$this->log("ok");
510 return $instance;
511 }
512
513 // up: string -> array
514 function array_cast_safe(&$array_or_not) {
515 if (!is_array($array_or_not)) {
516 $array_or_not = array($array_or_not);
517 //print Dumper($array_or_not);
518 //exit;
519 }
520 }
521
522 // To return all ancestors class of an object
523 // from: http://www.php.net/manual/en/function.get-parent-class.php
524 function get_ancestors_class($classname) {
525 $father = get_parent_class($classname);
526 if ($father != "") {
527 $ancestors = php::get_ancestors_class($father);
528 $ancestors[] = $father;
529 }
530 return $ancestors;
531 }
532
533 // ------ override/expand php's 'include_path' setting ------
534 function add_libpath($paths) {
535
536 if (!is_array($paths)) {
537 $paths = array($paths);
538 }
539 array_push($paths, ini_get("include_path"));
540
541 // determine OS
542 $os = 'linux';
543 if (stristr($_SERVER["SERVER_SOFTWARE"], 'win32')) {
544 $os = 'windows';
545 }
546
547 $path_delimiter = ':';
548 // change path-delimiter for win32
549 if ($os == 'windows') { $path_delimiter = ';'; }
550 // build new 'include_path'-string
551 $path_new = join($path_delimiter, $paths);
552 ini_set("include_path", $path_new);
553 }
554
555 // from: http://www.php.net/manual/en/function.is-subclass-of.php
556 function is_subclass($child, $parent) {
557 if (is_string($child)) {
558 do {
559 $child = get_parent_class($child);
560 if (!$child) return false;
561 //} while ($child == $parent);
562 } while ($child != $parent);
563 return true;
564 } else {
565 return is_subclass_of($child, $parent);
566 }
567 }
568
569
570 }
571
572 //function error_handler($errno, $errstr, $errfile, $errline) {
573 function php_error_handler() {
574 //print "ERROR!<br/>";
575 $error_raw = func_get_args();
576
577 //print Dumper($error_raw);
578
579 $error = array(
580 'level' => $error_raw[0],
581 'message' => $error_raw[1],
582 'file' => $error_raw[2],
583 'line' => $error_raw[3],
584 'context' => &$error_raw[4],
585 'object_context' => &$error_raw[4][this],
586 );
587 $error[component] = $error[object_context]->_component_name;
588
589 //$output_order = array( 'message', 'component', 'file', 'line', 'level' );
590 $output_order = array( 'message', 'file', 'line' );
591
592 /*
593 $level = $error[0];
594 $context = &$error[4];
595 $cc = &$context['this'];
596 */
597
598
599 //print Dumper($context);
600 //print Dumper($cc);
601 //print Dumper($cc->_component_name);
602
603 // by level
604 //$do_trace = ($level <= 5);
605
606 //$c_name = $context['this']['_component_name'];
607
608 //print "c_error: $c_name<br/>";
609
610 // if component
611 //$do_trace = isset($context[this][_component_name]);
612 //$do_trace = isset($context->this[_component_name]);
613 //$do_trace = isset($cc->_component_name);
614 $do_trace = isset($error[component]);
615
616 //$do_trace = 1;
617
618 //print Dumper($context);
619
620 if ($do_trace) {
621
622 //print php::Dumper($error);
623 //exit;
624
625 //print "<hr/><b><font color=\"red\">ERROR:</font></b><br/>";
626 print "<b><font color=\"red\">ERROR:</font></b><br/> ";
627
628 foreach ($output_order as $key) {
629 print "<b>$key:</b> $error[$key]<br/>";
630 }
631
632 }
633
634 }
635
636
637 ?>

MailToCvsAdmin">MailToCvsAdmin
ViewVC Help
Powered by ViewVC 1.1.26 RSS 2.0 feed