#49567 [Opn]: DOM/XSL: Suggestion: registerObjectMethods()

2009-09-25 Thread chregu
 ID:   49567
 Updated by:   chr...@php.net
 Reported By:  mjs at beebo dot org
 Status:   Open
 Bug Type: Feature/Change Request
 Operating System: OS X
 PHP Version:  5.3.0
 New Comment:

Thanks for your work. Here's the right place for the patches, but you 
could also send it to me or to php-internals, so that it won't get 
forgotten :)

chregu


Previous Comments:


[2009-09-23 09:10:33] mjs at beebo dot org

Thanks for your reply.

Yes, you can register exactly one object.  If you call 
registerPHPFunctions() twice, the functions/methods registered will be

those of the second object.

If there's a function of the same name, it won't get called--
essentially if you have php:function('foo') in your XSL, foo() is 
either considered as a function in global scope (if you registered an 
array of strings, or nothing at all), or a method name in the "scope" 
of the registered object (if you registered an object).

This is not the most flexible approach but I think it's a simple and 
straightforward enhancement that requires no extra syntax on either 
the PHP or XSL side.  Also, anything more advanced is beyond my 
extension-writing capabilities!

I've made a few changes to the patch, and am working on a few more 
little things that don't affect the syntax.  Is here the right place 
to post it when I'm done?



[2009-09-22 13:30:58] chr...@php.net

Thanks for your work. I didn't test it out, but looking at the code 2 
questions pop up:

You can register exactly one object?
and
What happens, if there's a function with that name? eg. 'add' in your 
test?

Not sure, if I'm happy how it is right now, but it certainly goes into

the right direction.



[2009-09-22 07:14:34] mjs at beebo dot org

Had a look at how the xsl extension works, and had a shot at 
implementing this myself--the patch is below.  

Instead of adding a new function I enhanced registerPHPFunctions() so 
that it can take an object.  It works like this: if an object is 
provided (say $foo), then  in the XSL results in a call to $foo->quux(44).

i.e. in PHP:

$foo = new Foo();

$processor->registerPHPFunctions($foo);

In XSL:



Two of the tests in ext/xsl failed, but they fail without this patch 
also.

The patch is:

Index: ext/xsl/tests/xsltprocessor_registerPHPFunctions-method.phpt
===
--- ext/xsl/tests/xsltprocessor_registerPHPFunctions-method.phpt
(revision 0)
+++ ext/xsl/tests/xsltprocessor_registerPHPFunctions-method.phpt
(revision 0)
@@ -0,0 +1,38 @@
+--TEST--
+Checks XSLTProcessor::registerPHPFunctions($obj) where the 
"functions"
+exposed in the XSL file are methods of $obj.
+--SKIPIF--
+
+--FILE--
+loadXML("");
+$xsl = new DOMDocument();
+$xsl->load(dirname(__FILE__) . "/phpmethod.xsl");
+
+$proc = new XSLTProcessor();
+$proc->importStylesheet($xsl);
+
+$foo = new Foo();
+
+$proc->registerPHPFunctions($foo);
+
+echo $proc->transformToXml($xml);
+--EXPECTF--
+
+--CREDITS--
+Michael Stillwell 
\ No newline at end of file
Index: ext/xsl/tests/phpmethod.xsl
===
--- ext/xsl/tests/phpmethod.xsl (revision 0)
+++ ext/xsl/tests/phpmethod.xsl (revision 0)
@@ -0,0 +1,15 @@
+http://www.w3.org/1999/XSL/Transform";
+  xmlns:php="http://php.net/xsl";
+  exclude-result-prefixes="php">
+  
+
+  
+  
+  
+  
+  
+  
+  
+
\ No newline at end of file
Index: ext/xsl/php_xsl.h
===
--- ext/xsl/php_xsl.h   (revision 288545)
+++ ext/xsl/php_xsl.h   (working copy)
@@ -55,6 +55,7 @@
HashTable *node_list;
php_libxml_node_object *doc;
char *profiling;
+   zval *object_ptr;
 } xsl_object;
 
 void php_xsl_set_object(zval *wrapper, void *obj TSRMLS_DC);
Index: ext/xsl/xsltprocessor.c
===
--- ext/xsl/xsltprocessor.c (revision 288545)
+++ ext/xsl/xsltprocessor.c (working copy)
@@ -308,11 +308,11 @@

fci.function_name = &handler;
fci.symbol_table = NULL;
-   fci.object_ptr = NULL;
fci.retval_ptr_ptr = &retval;
fci.no_separation = 0;
+   fci.object_ptr = intern->object_ptr ? intern->object_ptr : 
NULL;
/*fci.function_handler_cache = &function_ptr;*/
-   if (!zend_make_callable(&handler, &callable TSRMLS_CC)) {
+   if ((intern->registerPhpFunctions != 3) && 
!zend_make_callable(&handler, &callable TSRMLS_CC)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to 
call handler %s()", callable);

} else if ( intern->registerPhpFunctions == 2 && 
zend_hash_exists(intern->registered_phpfunctions, callable, 
strlen(ca

#49567 [Opn]: DOM/XSL: Suggestion: registerObjectMethods()

2009-09-23 Thread mjs at beebo dot org
 ID:   49567
 User updated by:  mjs at beebo dot org
 Reported By:  mjs at beebo dot org
 Status:   Open
 Bug Type: Feature/Change Request
 Operating System: OS X
 PHP Version:  5.3.0
 New Comment:

Thanks for your reply.

Yes, you can register exactly one object.  If you call 
registerPHPFunctions() twice, the functions/methods registered will be

those of the second object.

If there's a function of the same name, it won't get called--
essentially if you have php:function('foo') in your XSL, foo() is 
either considered as a function in global scope (if you registered an 
array of strings, or nothing at all), or a method name in the "scope" 
of the registered object (if you registered an object).

This is not the most flexible approach but I think it's a simple and 
straightforward enhancement that requires no extra syntax on either 
the PHP or XSL side.  Also, anything more advanced is beyond my 
extension-writing capabilities!

I've made a few changes to the patch, and am working on a few more 
little things that don't affect the syntax.  Is here the right place 
to post it when I'm done?


Previous Comments:


[2009-09-22 13:30:58] chr...@php.net

Thanks for your work. I didn't test it out, but looking at the code 2 
questions pop up:

You can register exactly one object?
and
What happens, if there's a function with that name? eg. 'add' in your 
test?

Not sure, if I'm happy how it is right now, but it certainly goes into

the right direction.



[2009-09-22 07:14:34] mjs at beebo dot org

Had a look at how the xsl extension works, and had a shot at 
implementing this myself--the patch is below.  

Instead of adding a new function I enhanced registerPHPFunctions() so 
that it can take an object.  It works like this: if an object is 
provided (say $foo), then  in the XSL results in a call to $foo->quux(44).

i.e. in PHP:

$foo = new Foo();

$processor->registerPHPFunctions($foo);

In XSL:



Two of the tests in ext/xsl failed, but they fail without this patch 
also.

The patch is:

Index: ext/xsl/tests/xsltprocessor_registerPHPFunctions-method.phpt
===
--- ext/xsl/tests/xsltprocessor_registerPHPFunctions-method.phpt
(revision 0)
+++ ext/xsl/tests/xsltprocessor_registerPHPFunctions-method.phpt
(revision 0)
@@ -0,0 +1,38 @@
+--TEST--
+Checks XSLTProcessor::registerPHPFunctions($obj) where the 
"functions"
+exposed in the XSL file are methods of $obj.
+--SKIPIF--
+
+--FILE--
+loadXML("");
+$xsl = new DOMDocument();
+$xsl->load(dirname(__FILE__) . "/phpmethod.xsl");
+
+$proc = new XSLTProcessor();
+$proc->importStylesheet($xsl);
+
+$foo = new Foo();
+
+$proc->registerPHPFunctions($foo);
+
+echo $proc->transformToXml($xml);
+--EXPECTF--
+
+--CREDITS--
+Michael Stillwell 
\ No newline at end of file
Index: ext/xsl/tests/phpmethod.xsl
===
--- ext/xsl/tests/phpmethod.xsl (revision 0)
+++ ext/xsl/tests/phpmethod.xsl (revision 0)
@@ -0,0 +1,15 @@
+http://www.w3.org/1999/XSL/Transform";
+  xmlns:php="http://php.net/xsl";
+  exclude-result-prefixes="php">
+  
+
+  
+  
+  
+  
+  
+  
+  
+
\ No newline at end of file
Index: ext/xsl/php_xsl.h
===
--- ext/xsl/php_xsl.h   (revision 288545)
+++ ext/xsl/php_xsl.h   (working copy)
@@ -55,6 +55,7 @@
HashTable *node_list;
php_libxml_node_object *doc;
char *profiling;
+   zval *object_ptr;
 } xsl_object;
 
 void php_xsl_set_object(zval *wrapper, void *obj TSRMLS_DC);
Index: ext/xsl/xsltprocessor.c
===
--- ext/xsl/xsltprocessor.c (revision 288545)
+++ ext/xsl/xsltprocessor.c (working copy)
@@ -308,11 +308,11 @@

fci.function_name = &handler;
fci.symbol_table = NULL;
-   fci.object_ptr = NULL;
fci.retval_ptr_ptr = &retval;
fci.no_separation = 0;
+   fci.object_ptr = intern->object_ptr ? intern->object_ptr : 
NULL;
/*fci.function_handler_cache = &function_ptr;*/
-   if (!zend_make_callable(&handler, &callable TSRMLS_CC)) {
+   if ((intern->registerPhpFunctions != 3) && 
!zend_make_callable(&handler, &callable TSRMLS_CC)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to 
call handler %s()", callable);

} else if ( intern->registerPhpFunctions == 2 && 
zend_hash_exists(intern->registered_phpfunctions, callable, 
strlen(callable) + 1) == 0) { 
@@ -320,6 +320,9 @@
/* Push an empty string, so that we at least have an 
xslt result... */
valuePush(ctxt, xmlXPathNewString(""));
} else {
+   if (intern->object_ptr) {
+   fci.

#49567 [Opn]: DOM/XSL: Suggestion: registerObjectMethods()

2009-09-22 Thread chregu
 ID:   49567
 Updated by:   chr...@php.net
 Reported By:  mjs at beebo dot org
 Status:   Open
 Bug Type: Feature/Change Request
 Operating System: OS X
 PHP Version:  5.3.0
 New Comment:

Thanks for your work. I didn't test it out, but looking at the code 2 
questions pop up:

You can register exactly one object?
and
What happens, if there's a function with that name? eg. 'add' in your 
test?

Not sure, if I'm happy how it is right now, but it certainly goes into

the right direction.


Previous Comments:


[2009-09-22 07:14:34] mjs at beebo dot org

Had a look at how the xsl extension works, and had a shot at 
implementing this myself--the patch is below.  

Instead of adding a new function I enhanced registerPHPFunctions() so 
that it can take an object.  It works like this: if an object is 
provided (say $foo), then  in the XSL results in a call to $foo->quux(44).

i.e. in PHP:

$foo = new Foo();

$processor->registerPHPFunctions($foo);

In XSL:



Two of the tests in ext/xsl failed, but they fail without this patch 
also.

The patch is:

Index: ext/xsl/tests/xsltprocessor_registerPHPFunctions-method.phpt
===
--- ext/xsl/tests/xsltprocessor_registerPHPFunctions-method.phpt
(revision 0)
+++ ext/xsl/tests/xsltprocessor_registerPHPFunctions-method.phpt
(revision 0)
@@ -0,0 +1,38 @@
+--TEST--
+Checks XSLTProcessor::registerPHPFunctions($obj) where the 
"functions"
+exposed in the XSL file are methods of $obj.
+--SKIPIF--
+
+--FILE--
+loadXML("");
+$xsl = new DOMDocument();
+$xsl->load(dirname(__FILE__) . "/phpmethod.xsl");
+
+$proc = new XSLTProcessor();
+$proc->importStylesheet($xsl);
+
+$foo = new Foo();
+
+$proc->registerPHPFunctions($foo);
+
+echo $proc->transformToXml($xml);
+--EXPECTF--
+
+--CREDITS--
+Michael Stillwell 
\ No newline at end of file
Index: ext/xsl/tests/phpmethod.xsl
===
--- ext/xsl/tests/phpmethod.xsl (revision 0)
+++ ext/xsl/tests/phpmethod.xsl (revision 0)
@@ -0,0 +1,15 @@
+http://www.w3.org/1999/XSL/Transform";
+  xmlns:php="http://php.net/xsl";
+  exclude-result-prefixes="php">
+  
+
+  
+  
+  
+  
+  
+  
+  
+
\ No newline at end of file
Index: ext/xsl/php_xsl.h
===
--- ext/xsl/php_xsl.h   (revision 288545)
+++ ext/xsl/php_xsl.h   (working copy)
@@ -55,6 +55,7 @@
HashTable *node_list;
php_libxml_node_object *doc;
char *profiling;
+   zval *object_ptr;
 } xsl_object;
 
 void php_xsl_set_object(zval *wrapper, void *obj TSRMLS_DC);
Index: ext/xsl/xsltprocessor.c
===
--- ext/xsl/xsltprocessor.c (revision 288545)
+++ ext/xsl/xsltprocessor.c (working copy)
@@ -308,11 +308,11 @@

fci.function_name = &handler;
fci.symbol_table = NULL;
-   fci.object_ptr = NULL;
fci.retval_ptr_ptr = &retval;
fci.no_separation = 0;
+   fci.object_ptr = intern->object_ptr ? intern->object_ptr : 
NULL;
/*fci.function_handler_cache = &function_ptr;*/
-   if (!zend_make_callable(&handler, &callable TSRMLS_CC)) {
+   if ((intern->registerPhpFunctions != 3) && 
!zend_make_callable(&handler, &callable TSRMLS_CC)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to 
call handler %s()", callable);

} else if ( intern->registerPhpFunctions == 2 && 
zend_hash_exists(intern->registered_phpfunctions, callable, 
strlen(callable) + 1) == 0) { 
@@ -320,6 +320,9 @@
/* Push an empty string, so that we at least have an 
xslt result... */
valuePush(ctxt, xmlXPathNewString(""));
} else {
+   if (intern->object_ptr) {
+   fci.object_ptr = intern->object_ptr;
+   }
result = zend_call_function(&fci, NULL TSRMLS_CC);
if (result == FAILURE) {
if (Z_TYPE(handler) == IS_STRING) {
@@ -794,6 +797,7 @@
zval *id;
xsl_object *intern;
zval *array_value, **entry, *new_string;
+   zval *obj_ptr;
int  name_len = 0;
char *name;
 
@@ -823,6 +827,12 @@
zend_hash_update(intern->registered_phpfunctions, 
name, name_len + 1, &new_string, sizeof(zval*), NULL);
intern->registerPhpFunctions = 2;

+   } else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, 
ZEND_NUM_ARGS() TSRMLS_CC, "o", &obj_ptr) == SUCCESS) {
+   intern = (xsl_object *)zend_object_store_get_object(id 
TSRMLS_CC);
+   zend_hash_clean(intern->registered_phpfunctions);
+   intern->object_ptr = obj_ptr;
+   Z_ADDREF_P(obj_ptr);
+   intern->registerPhpFunctions = 3;

#49567 [Opn]: DOM/XSL: Suggestion: registerObjectMethods()

2009-09-22 Thread mjs at beebo dot org
 ID:   49567
 User updated by:  mjs at beebo dot org
 Reported By:  mjs at beebo dot org
 Status:   Open
 Bug Type: Feature/Change Request
 Operating System: OS X
 PHP Version:  5.3.0
 New Comment:

Had a look at how the xsl extension works, and had a shot at 
implementing this myself--the patch is below.  

Instead of adding a new function I enhanced registerPHPFunctions() so 
that it can take an object.  It works like this: if an object is 
provided (say $foo), then  in the XSL results in a call to $foo->quux(44).

i.e. in PHP:

$foo = new Foo();

$processor->registerPHPFunctions($foo);

In XSL:



Two of the tests in ext/xsl failed, but they fail without this patch 
also.

The patch is:

Index: ext/xsl/tests/xsltprocessor_registerPHPFunctions-method.phpt
===
--- ext/xsl/tests/xsltprocessor_registerPHPFunctions-method.phpt
(revision 0)
+++ ext/xsl/tests/xsltprocessor_registerPHPFunctions-method.phpt
(revision 0)
@@ -0,0 +1,38 @@
+--TEST--
+Checks XSLTProcessor::registerPHPFunctions($obj) where the 
"functions"
+exposed in the XSL file are methods of $obj.
+--SKIPIF--
+
+--FILE--
+loadXML("");
+$xsl = new DOMDocument();
+$xsl->load(dirname(__FILE__) . "/phpmethod.xsl");
+
+$proc = new XSLTProcessor();
+$proc->importStylesheet($xsl);
+
+$foo = new Foo();
+
+$proc->registerPHPFunctions($foo);
+
+echo $proc->transformToXml($xml);
+--EXPECTF--
+
+--CREDITS--
+Michael Stillwell 
\ No newline at end of file
Index: ext/xsl/tests/phpmethod.xsl
===
--- ext/xsl/tests/phpmethod.xsl (revision 0)
+++ ext/xsl/tests/phpmethod.xsl (revision 0)
@@ -0,0 +1,15 @@
+http://www.w3.org/1999/XSL/Transform";
+  xmlns:php="http://php.net/xsl";
+  exclude-result-prefixes="php">
+  
+
+  
+  
+  
+  
+  
+  
+  
+
\ No newline at end of file
Index: ext/xsl/php_xsl.h
===
--- ext/xsl/php_xsl.h   (revision 288545)
+++ ext/xsl/php_xsl.h   (working copy)
@@ -55,6 +55,7 @@
HashTable *node_list;
php_libxml_node_object *doc;
char *profiling;
+   zval *object_ptr;
 } xsl_object;
 
 void php_xsl_set_object(zval *wrapper, void *obj TSRMLS_DC);
Index: ext/xsl/xsltprocessor.c
===
--- ext/xsl/xsltprocessor.c (revision 288545)
+++ ext/xsl/xsltprocessor.c (working copy)
@@ -308,11 +308,11 @@

fci.function_name = &handler;
fci.symbol_table = NULL;
-   fci.object_ptr = NULL;
fci.retval_ptr_ptr = &retval;
fci.no_separation = 0;
+   fci.object_ptr = intern->object_ptr ? intern->object_ptr : 
NULL;
/*fci.function_handler_cache = &function_ptr;*/
-   if (!zend_make_callable(&handler, &callable TSRMLS_CC)) {
+   if ((intern->registerPhpFunctions != 3) && 
!zend_make_callable(&handler, &callable TSRMLS_CC)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to 
call handler %s()", callable);

} else if ( intern->registerPhpFunctions == 2 && 
zend_hash_exists(intern->registered_phpfunctions, callable, 
strlen(callable) + 1) == 0) { 
@@ -320,6 +320,9 @@
/* Push an empty string, so that we at least have an 
xslt result... */
valuePush(ctxt, xmlXPathNewString(""));
} else {
+   if (intern->object_ptr) {
+   fci.object_ptr = intern->object_ptr;
+   }
result = zend_call_function(&fci, NULL TSRMLS_CC);
if (result == FAILURE) {
if (Z_TYPE(handler) == IS_STRING) {
@@ -794,6 +797,7 @@
zval *id;
xsl_object *intern;
zval *array_value, **entry, *new_string;
+   zval *obj_ptr;
int  name_len = 0;
char *name;
 
@@ -823,6 +827,12 @@
zend_hash_update(intern->registered_phpfunctions, 
name, name_len + 1, &new_string, sizeof(zval*), NULL);
intern->registerPhpFunctions = 2;

+   } else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, 
ZEND_NUM_ARGS() TSRMLS_CC, "o", &obj_ptr) == SUCCESS) {
+   intern = (xsl_object *)zend_object_store_get_object(id 
TSRMLS_CC);
+   zend_hash_clean(intern->registered_phpfunctions);
+   intern->object_ptr = obj_ptr;
+   Z_ADDREF_P(obj_ptr);
+   intern->registerPhpFunctions = 3;
} else {
intern = (xsl_object *)zend_object_store_get_object(id 
TSRMLS_CC);
intern->registerPhpFunctions = 1;
Index: ext/xsl/php_xsl.c
===
--- ext/xsl/php_xsl.c   (revision 288545)
+++ ext/xsl/php_xsl.c   (working copy)
@@ -84,6 +84,10 @@
zend_hash_destroy(intern->registered_phpfunctions);
FREE_HASHTABLE(intern->regi