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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.6 - (hide annotations)
Tue Mar 11 02:14:18 2003 UTC (21 years, 5 months ago) by joko
Branch: MAIN
Changes since 1.5: +6 -1 lines
+ fixed metadata for phpDocumentor

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

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