@@ -61,28 +61,30 @@ static void dom_xpath_proxy_factory(xmlNodePtr node, zval *child, dom_object *in
6161 php_dom_create_object (node , child , intern );
6262}
6363
64- static void dom_xpath_ext_function_php (xmlXPathParserContextPtr ctxt , int nargs , php_dom_xpath_nodeset_evaluation_mode evaluation_mode ) /* {{{ */
64+ static dom_xpath_object * dom_xpath_ext_fetch_intern (xmlXPathParserContextPtr ctxt )
6565{
66- bool error = false;
67- dom_xpath_object * intern ;
68-
69- if (! zend_is_executing ()) {
66+ if (!zend_is_executing ()) {
7067 xmlGenericError (xmlGenericErrorContext ,
7168 "xmlExtFunctionTest: Function called from outside of PHP\n" );
72- error = true;
7369 } else {
74- intern = (dom_xpath_object * ) ctxt -> context -> userData ;
70+ dom_xpath_object * intern = (dom_xpath_object * ) ctxt -> context -> userData ;
7571 if (intern == NULL ) {
7672 xmlGenericError (xmlGenericErrorContext ,
7773 "xmlExtFunctionTest: failed to get the internal object\n" );
78- error = true ;
74+ return NULL ;
7975 }
76+ return intern ;
8077 }
78+ return NULL ;
79+ }
8180
82- if (error ) {
81+ static void dom_xpath_ext_function_php (xmlXPathParserContextPtr ctxt , int nargs , php_dom_xpath_nodeset_evaluation_mode evaluation_mode ) /* {{{ */
82+ {
83+ dom_xpath_object * intern = dom_xpath_ext_fetch_intern (ctxt );
84+ if (!intern ) {
8385 php_dom_xpath_callbacks_clean_argument_stack (ctxt , nargs );
8486 } else {
85- php_dom_xpath_callbacks_call (& intern -> xpath_callbacks , ctxt , nargs , evaluation_mode , & intern -> dom , dom_xpath_proxy_factory );
87+ php_dom_xpath_callbacks_call_php_ns (& intern -> xpath_callbacks , ctxt , nargs , evaluation_mode , & intern -> dom , dom_xpath_proxy_factory );
8688 }
8789}
8890/* }}} */
@@ -99,6 +101,16 @@ static void dom_xpath_ext_function_object_php(xmlXPathParserContextPtr ctxt, int
99101}
100102/* }}} */
101103
104+ static void dom_xpath_ext_function_trampoline (xmlXPathParserContextPtr ctxt , int nargs )
105+ {
106+ dom_xpath_object * intern = dom_xpath_ext_fetch_intern (ctxt );
107+ if (!intern ) {
108+ php_dom_xpath_callbacks_clean_argument_stack (ctxt , nargs );
109+ } else {
110+ php_dom_xpath_callbacks_call_custom_ns (& intern -> xpath_callbacks , ctxt , nargs , PHP_DOM_XPATH_EVALUATE_NODESET_TO_NODESET , & intern -> dom , dom_xpath_proxy_factory );
111+ }
112+ }
113+
102114/* {{{ */
103115PHP_METHOD (DOMXPath , __construct )
104116{
@@ -378,18 +390,60 @@ PHP_METHOD(DOMXPath, registerPhpFunctions)
378390{
379391 dom_xpath_object * intern = Z_XPATHOBJ_P (ZEND_THIS );
380392
381- zend_string * name = NULL ;
393+ zend_string * callable_name = NULL ;
382394 HashTable * callable_ht = NULL ;
383395
384396 ZEND_PARSE_PARAMETERS_START (0 , 1 )
385397 Z_PARAM_OPTIONAL
386- Z_PARAM_ARRAY_HT_OR_STR_OR_NULL (callable_ht , name )
398+ Z_PARAM_ARRAY_HT_OR_STR_OR_NULL (callable_ht , callable_name )
387399 ZEND_PARSE_PARAMETERS_END ();
388400
389- php_dom_xpath_callbacks_update_method_handler (& intern -> xpath_callbacks , NULL , name , callable_ht );
401+ php_dom_xpath_callbacks_update_method_handler (
402+ & intern -> xpath_callbacks ,
403+ intern -> dom .ptr ,
404+ NULL ,
405+ callable_name ,
406+ callable_ht ,
407+ PHP_DOM_XPATH_CALLBACK_NAME_VALIDATE_NULLS ,
408+ NULL
409+ );
390410}
391411/* }}} end dom_xpath_register_php_functions */
392412
413+ static void dom_xpath_register_func_in_ctx (xmlXPathContextPtr ctxt , const zend_string * ns , const zend_string * name )
414+ {
415+ xmlXPathRegisterFuncNS (ctxt , (const xmlChar * ) ZSTR_VAL (name ), (const xmlChar * ) ZSTR_VAL (ns ), dom_xpath_ext_function_trampoline );
416+ }
417+
418+ PHP_METHOD (DOMXPath , registerPhpFunctionsNS )
419+ {
420+ dom_xpath_object * intern = Z_XPATHOBJ_P (ZEND_THIS );
421+
422+ zend_string * namespace ;
423+ zend_string * callable_name ;
424+ HashTable * callable_ht ;
425+
426+ ZEND_PARSE_PARAMETERS_START (2 , 2 )
427+ Z_PARAM_PATH_STR (namespace )
428+ Z_PARAM_ARRAY_HT_OR_STR (callable_ht , callable_name )
429+ ZEND_PARSE_PARAMETERS_END ();
430+
431+ if (zend_string_equals_literal (namespace , "http://php.net/xpath" )) { // TODO: this is different for XSL!!!
432+ zend_argument_value_error (1 , "must not be \"http://php.net/xpath\" because it is reserved for PHP" );
433+ RETURN_THROWS ();
434+ }
435+
436+ php_dom_xpath_callbacks_update_method_handler (
437+ & intern -> xpath_callbacks ,
438+ intern -> dom .ptr ,
439+ namespace ,
440+ callable_name ,
441+ callable_ht ,
442+ PHP_DOM_XPATH_CALLBACK_NAME_VALIDATE_NCNAME ,
443+ dom_xpath_register_func_in_ctx
444+ );
445+ }
446+
393447#endif /* LIBXML_XPATH_ENABLED */
394448
395449#endif
0 commit comments