@@ -37,14 +37,14 @@ typedef struct {
37
37
bool result ;
38
38
} dom_query_selector_matches_ctx ;
39
39
40
- lxb_status_t php_dom_query_selector_find_single_callback (const xmlNode * node , lxb_css_selector_specificity_t spec , void * ctx )
40
+ lxb_status_t dom_query_selector_find_single_callback (const xmlNode * node , lxb_css_selector_specificity_t spec , void * ctx )
41
41
{
42
42
xmlNodePtr * result = (xmlNodePtr * ) ctx ;
43
43
* result = (xmlNodePtr ) node ;
44
44
return LXB_STATUS_STOP ;
45
45
}
46
46
47
- lxb_status_t php_dom_query_selector_find_array_callback (const xmlNode * node , lxb_css_selector_specificity_t spec , void * ctx )
47
+ lxb_status_t dom_query_selector_find_array_callback (const xmlNode * node , lxb_css_selector_specificity_t spec , void * ctx )
48
48
{
49
49
dom_query_selector_all_ctx * qsa_ctx = (dom_query_selector_all_ctx * ) ctx ;
50
50
zval object ;
@@ -53,7 +53,7 @@ lxb_status_t php_dom_query_selector_find_array_callback(const xmlNode *node, lxb
53
53
return LXB_STATUS_OK ;
54
54
}
55
55
56
- lxb_status_t php_dom_query_selector_find_matches_callback (const xmlNode * node , lxb_css_selector_specificity_t spec , void * ctx )
56
+ lxb_status_t dom_query_selector_find_matches_callback (const xmlNode * node , lxb_css_selector_specificity_t spec , void * ctx )
57
57
{
58
58
dom_query_selector_matches_ctx * matches_ctx = (dom_query_selector_matches_ctx * ) ctx ;
59
59
if (node == matches_ctx -> reference ) {
@@ -63,7 +63,7 @@ lxb_status_t php_dom_query_selector_find_matches_callback(const xmlNode *node, l
63
63
return LXB_STATUS_OK ;
64
64
}
65
65
66
- static lxb_css_selector_list_t * php_dom_parse_selector (
66
+ static lxb_css_selector_list_t * dom_parse_selector (
67
67
lxb_css_parser_t * parser ,
68
68
lxb_selectors_t * selectors ,
69
69
const zend_string * selectors_str ,
@@ -98,7 +98,7 @@ static lxb_css_selector_list_t *php_dom_parse_selector(
98
98
return list ;
99
99
}
100
100
101
- static lxb_status_t php_dom_check_css_execution_status (lxb_status_t status )
101
+ static lxb_status_t dom_check_css_execution_status (lxb_status_t status )
102
102
{
103
103
if (UNEXPECTED (status != LXB_STATUS_OK && status != LXB_STATUS_STOP )) {
104
104
zend_argument_value_error (1 , "contains an unsupported selector" );
@@ -107,17 +107,17 @@ static lxb_status_t php_dom_check_css_execution_status(lxb_status_t status)
107
107
return LXB_STATUS_OK ;
108
108
}
109
109
110
- static void php_dom_selector_cleanup (lxb_css_parser_t * parser , lxb_selectors_t * selectors , lxb_css_selector_list_t * list )
110
+ static void dom_selector_cleanup (lxb_css_parser_t * parser , lxb_selectors_t * selectors , lxb_css_selector_list_t * list )
111
111
{
112
112
lxb_css_selector_list_destroy_memory (list );
113
113
lxb_selectors_destroy (selectors );
114
114
(void ) lxb_css_parser_destroy (parser , false);
115
115
}
116
116
117
- static lxb_status_t php_dom_query_selector_common (
117
+ static lxb_status_t dom_query_selector_common (
118
118
zval * return_value ,
119
119
const xmlNode * root ,
120
- zend_string * selectors_str ,
120
+ const zend_string * selectors_str ,
121
121
lxb_selectors_cb_f cb ,
122
122
void * ctx ,
123
123
lxb_selectors_opt_t options
@@ -128,56 +128,86 @@ static lxb_status_t php_dom_query_selector_common(
128
128
lxb_css_parser_t parser ;
129
129
lxb_selectors_t selectors ;
130
130
131
- lxb_css_selector_list_t * list = php_dom_parse_selector (& parser , & selectors , selectors_str , options );
131
+ lxb_css_selector_list_t * list = dom_parse_selector (& parser , & selectors , selectors_str , options );
132
132
if (UNEXPECTED (list == NULL )) {
133
133
status = LXB_STATUS_ERROR ;
134
134
} else {
135
135
status = lxb_selectors_find (& selectors , root , list , cb , ctx );
136
- status = php_dom_check_css_execution_status (status );
136
+ status = dom_check_css_execution_status (status );
137
137
}
138
138
139
- php_dom_selector_cleanup (& parser , & selectors , list );
139
+ dom_selector_cleanup (& parser , & selectors , list );
140
140
141
141
return status ;
142
142
}
143
143
144
- static lxb_status_t php_dom_query_matches (
145
- zval * return_value ,
144
+ static lxb_status_t dom_query_matches (
146
145
const xmlNode * root ,
147
- zend_string * selectors_str ,
148
- lxb_selectors_cb_f cb ,
149
- void * ctx ,
150
- lxb_selectors_opt_t options
146
+ const zend_string * selectors_str ,
147
+ void * ctx
151
148
)
152
149
{
153
150
lxb_status_t status ;
154
151
155
152
lxb_css_parser_t parser ;
156
153
lxb_selectors_t selectors ;
157
154
158
- lxb_css_selector_list_t * list = php_dom_parse_selector (& parser , & selectors , selectors_str , options );
155
+ lxb_css_selector_list_t * list = dom_parse_selector (& parser , & selectors , selectors_str , LXB_SELECTORS_OPT_MATCH_FIRST );
159
156
if (UNEXPECTED (list == NULL )) {
160
157
status = LXB_STATUS_ERROR ;
161
158
} else {
162
- status = lxb_selectors_match_node (& selectors , root , list , cb , ctx );
163
- status = php_dom_check_css_execution_status (status );
159
+ status = lxb_selectors_match_node (& selectors , root , list , dom_query_selector_find_matches_callback , ctx );
160
+ status = dom_check_css_execution_status (status );
164
161
}
165
162
166
- php_dom_selector_cleanup (& parser , & selectors , list );
163
+ dom_selector_cleanup (& parser , & selectors , list );
167
164
168
165
return status ;
169
166
}
170
167
168
+ static const xmlNode * dom_query_closest (
169
+ const xmlNode * root ,
170
+ const zend_string * selectors_str
171
+ )
172
+ {
173
+ const xmlNode * ret = NULL ;
174
+
175
+ lxb_css_parser_t parser ;
176
+ lxb_selectors_t selectors ;
177
+
178
+ lxb_css_selector_list_t * list = dom_parse_selector (& parser , & selectors , selectors_str , LXB_SELECTORS_OPT_MATCH_FIRST );
179
+ if (EXPECTED (list != NULL )) {
180
+ const xmlNode * current = root ;
181
+ while (current != NULL ) {
182
+ dom_query_selector_matches_ctx ctx = { current , false };
183
+ lxb_status_t status = lxb_selectors_match_node (& selectors , current , list , dom_query_selector_find_matches_callback , & ctx );
184
+ status = dom_check_css_execution_status (status );
185
+ if (UNEXPECTED (status != LXB_STATUS_OK )) {
186
+ break ;
187
+ }
188
+ if (ctx .result ) {
189
+ ret = current ;
190
+ break ;
191
+ }
192
+ current = current -> parent ;
193
+ }
194
+ }
195
+
196
+ dom_selector_cleanup (& parser , & selectors , list );
197
+
198
+ return ret ;
199
+ }
200
+
171
201
/* https://dom.spec.whatwg.org/#dom-parentnode-queryselector */
172
- void dom_parent_node_query_selector (xmlNodePtr thisp , dom_object * intern , zval * return_value , zend_string * selectors_str )
202
+ void dom_parent_node_query_selector (xmlNodePtr thisp , dom_object * intern , zval * return_value , const zend_string * selectors_str )
173
203
{
174
204
xmlNodePtr result = NULL ;
175
205
176
- if (php_dom_query_selector_common (
206
+ if (dom_query_selector_common (
177
207
return_value ,
178
208
thisp ,
179
209
selectors_str ,
180
- php_dom_query_selector_find_single_callback ,
210
+ dom_query_selector_find_single_callback ,
181
211
& result ,
182
212
LXB_SELECTORS_OPT_MATCH_FIRST
183
213
) != LXB_STATUS_OK || result == NULL ) {
@@ -188,16 +218,16 @@ void dom_parent_node_query_selector(xmlNodePtr thisp, dom_object *intern, zval *
188
218
}
189
219
190
220
/* https://dom.spec.whatwg.org/#dom-parentnode-queryselectorall */
191
- void dom_parent_node_query_selector_all (xmlNodePtr thisp , dom_object * intern , zval * return_value , zend_string * selectors_str )
221
+ void dom_parent_node_query_selector_all (xmlNodePtr thisp , dom_object * intern , zval * return_value , const zend_string * selectors_str )
192
222
{
193
223
HashTable * list = zend_new_array (0 );
194
224
dom_query_selector_all_ctx ctx = { list , intern };
195
225
196
- if (php_dom_query_selector_common (
226
+ if (dom_query_selector_common (
197
227
return_value ,
198
228
thisp ,
199
229
selectors_str ,
200
- php_dom_query_selector_find_array_callback ,
230
+ dom_query_selector_find_array_callback ,
201
231
& ctx ,
202
232
LXB_SELECTORS_OPT_DEFAULT
203
233
) != LXB_STATUS_OK ) {
@@ -213,17 +243,14 @@ void dom_parent_node_query_selector_all(xmlNodePtr thisp, dom_object *intern, zv
213
243
}
214
244
215
245
/* https://dom.spec.whatwg.org/#dom-element-matches */
216
- void dom_element_matches (xmlNodePtr thisp , dom_object * intern , zval * return_value , zend_string * selectors_str )
246
+ void dom_element_matches (xmlNodePtr thisp , zval * return_value , const zend_string * selectors_str )
217
247
{
218
248
dom_query_selector_matches_ctx ctx = { thisp , false };
219
249
220
- if (php_dom_query_matches (
221
- return_value ,
250
+ if (dom_query_matches (
222
251
thisp ,
223
252
selectors_str ,
224
- php_dom_query_selector_find_matches_callback ,
225
- & ctx ,
226
- LXB_SELECTORS_OPT_MATCH_FIRST
253
+ & ctx
227
254
) != LXB_STATUS_OK ) {
228
255
RETURN_THROWS ();
229
256
} else {
@@ -232,32 +259,12 @@ void dom_element_matches(xmlNodePtr thisp, dom_object *intern, zval *return_valu
232
259
}
233
260
234
261
/* https://dom.spec.whatwg.org/#dom-element-closest */
235
- void dom_element_closest (xmlNodePtr thisp , dom_object * intern , zval * return_value , zend_string * selectors_str )
262
+ void dom_element_closest (xmlNodePtr thisp , dom_object * intern , zval * return_value , const zend_string * selectors_str )
236
263
{
237
- lxb_css_parser_t parser ;
238
- lxb_selectors_t selectors ;
239
-
240
- lxb_css_selector_list_t * list = php_dom_parse_selector (& parser , & selectors , selectors_str , LXB_SELECTORS_OPT_MATCH_FIRST );
241
- if (UNEXPECTED (list == NULL )) {
242
- RETURN_THROWS ();
243
- } else {
244
- xmlNodePtr current = thisp ;
245
- while (current != NULL ) {
246
- dom_query_selector_matches_ctx ctx = { current , false };
247
- lxb_status_t status = lxb_selectors_match_node (& selectors , current , list , php_dom_query_selector_find_matches_callback , & ctx );
248
- status = php_dom_check_css_execution_status (status );
249
- if (UNEXPECTED (status != LXB_STATUS_OK )) {
250
- break ;
251
- }
252
- if (ctx .result ) {
253
- DOM_RET_OBJ (current , intern );
254
- break ;
255
- }
256
- current = current -> parent ;
257
- }
264
+ const xmlNode * result = dom_query_closest (thisp , selectors_str );
265
+ if (EXPECTED (result != NULL )) {
266
+ DOM_RET_OBJ ((xmlNodePtr ) result , intern );
258
267
}
259
-
260
- php_dom_selector_cleanup (& parser , & selectors , list );
261
268
}
262
269
263
270
#endif
0 commit comments