2121#include "php.h"
2222#if defined(HAVE_LIBXML ) && defined(HAVE_DOM )
2323#include "php_dom.h"
24+ #include "nodelist.h"
25+ #include "html_collection.h"
2426#include "namespace_compat.h"
2527
28+ typedef struct _dom_named_item {
29+ dom_object * context_intern ;
30+ xmlNodePtr node ;
31+ } dom_named_item ;
32+
2633/* https://dom.spec.whatwg.org/#dom-htmlcollection-nameditem-key */
27- PHP_METHOD ( DOM_HTMLCollection , namedItem )
34+ static dom_named_item dom_html_collection_named_item ( zend_string * key , zend_object * zobj )
2835{
29- zend_string * key ;
30- ZEND_PARSE_PARAMETERS_START (1 , 1 )
31- Z_PARAM_PATH_STR (key )
32- ZEND_PARSE_PARAMETERS_END ();
36+ dom_named_item ret = {NULL , NULL };
3337
3438 /* 1. If key is the empty string, return null. */
3539 if (ZSTR_LEN (key ) == 0 ) {
36- RETURN_NULL () ;
40+ return ret ;
3741 }
3842
39- dom_object * intern = Z_DOMOBJ_P ( ZEND_THIS );
43+ dom_object * intern = php_dom_obj_from_obj ( zobj );
4044 dom_nnodemap_object * objmap = intern -> ptr ;
4145
4246 /* 2. Return the first element in the collection for which at least one of the following is true: */
4347 xmlNodePtr basep = dom_object_get_node (objmap -> baseobj );
4448 if (basep != NULL ) {
4549 int cur = 0 ;
46- int next = cur ;
50+ int next = cur ; /* not +1, otherwise we skip the first candidate */
4751 xmlNodePtr candidate = basep -> children ;
4852 while (candidate != NULL ) {
4953 candidate = dom_get_elements_by_tag_name_ns_raw (basep , candidate , objmap -> ns , objmap -> local , objmap -> local_lower , & cur , next );
@@ -55,20 +59,85 @@ PHP_METHOD(DOM_HTMLCollection, namedItem)
5559
5660 /* it has an ID which is key; */
5761 if ((attr = xmlHasNsProp (candidate , BAD_CAST "id" , NULL )) != NULL && dom_compare_value (attr , BAD_CAST ZSTR_VAL (key ))) {
58- DOM_RET_OBJ (candidate , objmap -> baseobj );
59- return ;
62+ ret .context_intern = objmap -> baseobj ;
63+ ret .node = candidate ;
64+ return ret ;
6065 }
6166 /* it is in the HTML namespace and has a name attribute whose value is key; */
6267 else if (php_dom_ns_is_fast (candidate , php_dom_ns_is_html_magic_token )) {
6368 if ((attr = xmlHasNsProp (candidate , BAD_CAST "name" , NULL )) != NULL && dom_compare_value (attr , BAD_CAST ZSTR_VAL (key ))) {
64- DOM_RET_OBJ (candidate , objmap -> baseobj );
65- return ;
69+ ret .context_intern = objmap -> baseobj ;
70+ ret .node = candidate ;
71+ return ret ;
6672 }
6773 }
6874
6975 next = cur + 1 ;
7076 }
7177 }
78+
79+ return ret ;
80+ }
81+
82+ static void dom_html_collection_named_item_into_zval (zval * return_value , zend_string * key , zend_object * zobj )
83+ {
84+ dom_named_item named_item = dom_html_collection_named_item (key , zobj );
85+ if (named_item .node != NULL ) {
86+ DOM_RET_OBJ (named_item .node , named_item .context_intern );
87+ } else {
88+ RETURN_NULL ();
89+ }
90+ }
91+
92+ PHP_METHOD (DOM_HTMLCollection , namedItem )
93+ {
94+ zend_string * key ;
95+ ZEND_PARSE_PARAMETERS_START (1 , 1 )
96+ Z_PARAM_STR (key )
97+ ZEND_PARSE_PARAMETERS_END ();
98+ dom_html_collection_named_item_into_zval (return_value , key , Z_OBJ_P (ZEND_THIS ));
99+ }
100+
101+ zval * dom_html_collection_read_dimension (zend_object * object , zval * offset , int type , zval * rv )
102+ {
103+ if (UNEXPECTED (!offset )) {
104+ zend_throw_error (NULL , "Cannot append to %s" , ZSTR_VAL (object -> ce -> name ));
105+ return NULL ;
106+ }
107+
108+ dom_nodelist_dimension_index index = dom_modern_nodelist_get_index (offset );
109+ if (UNEXPECTED (index .type == DOM_NODELIST_DIM_ILLEGAL )) {
110+ zend_illegal_container_offset (object -> ce -> name , offset , type );
111+ return NULL ;
112+ }
113+
114+ if (index .type == DOM_NODELIST_DIM_STRING ) {
115+ dom_html_collection_named_item_into_zval (rv , index .str , object );
116+ } else {
117+ ZEND_ASSERT (index .type == DOM_NODELIST_DIM_LONG );
118+ php_dom_nodelist_get_item_into_zval (php_dom_obj_from_obj (object )-> ptr , index .lval , rv );
119+ }
120+
121+ return rv ;
122+ }
123+
124+ int dom_html_collection_has_dimension (zend_object * object , zval * member , int check_empty )
125+ {
126+ /* If it exists, it cannot be empty because nodes aren't empty. */
127+ ZEND_IGNORE_VALUE (check_empty );
128+
129+ dom_nodelist_dimension_index index = dom_modern_nodelist_get_index (member );
130+ if (UNEXPECTED (index .type == DOM_NODELIST_DIM_ILLEGAL )) {
131+ zend_illegal_container_offset (object -> ce -> name , member , BP_VAR_IS );
132+ return 0 ;
133+ }
134+
135+ if (index .type == DOM_NODELIST_DIM_STRING ) {
136+ return dom_html_collection_named_item (index .str , object ).node != NULL ;
137+ } else {
138+ ZEND_ASSERT (index .type == DOM_NODELIST_DIM_LONG );
139+ return index .lval >= 0 && index .lval < php_dom_get_nodelist_length (php_dom_obj_from_obj (object ));
140+ }
72141}
73142
74143#endif
0 commit comments