@@ -126,17 +126,29 @@ function hooks_parse_files( array $files, string $root, array $ignore_hooks ) :
126
126
$ file_hooks = array_merge ( $ file_hooks , export_hooks ( $ file ->uses ['hooks ' ], $ path ) );
127
127
}
128
128
129
+ if ( ! empty ( $ file ->uses ['functions ' ] ) ) {
130
+ $ file_hooks = array_merge ( $ file_hooks , export_scheduled_hooks ( $ file ->uses ['functions ' ], $ path ) );
131
+ }
132
+
129
133
foreach ( $ file ->getFunctions () as $ function ) {
130
134
if ( ! empty ( $ function ->uses ) && ! empty ( $ function ->uses ['hooks ' ] ) ) {
131
135
$ file_hooks = array_merge ( $ file_hooks , export_hooks ( $ function ->uses ['hooks ' ], $ path ) );
132
136
}
137
+
138
+ if ( ! empty ( $ function ->uses ) && ! empty ( $ function ->uses ['functions ' ] ) ) {
139
+ $ file_hooks = array_merge ( $ file_hooks , export_scheduled_hooks ( $ function ->uses ['functions ' ], $ path ) );
140
+ }
133
141
}
134
142
135
143
foreach ( $ file ->getClasses () as $ class ) {
136
144
foreach ( $ class ->getMethods () as $ method ) {
137
145
if ( ! empty ( $ method ->uses ) && ! empty ( $ method ->uses ['hooks ' ] ) ) {
138
146
$ file_hooks = array_merge ( $ file_hooks , export_hooks ( $ method ->uses ['hooks ' ], $ path ) );
139
147
}
148
+
149
+ if ( ! empty ( $ method ->uses ) && ! empty ( $ method ->uses ['functions ' ] ) ) {
150
+ $ file_hooks = array_merge ( $ file_hooks , export_scheduled_hooks ( $ method ->uses ['functions ' ], $ path ) );
151
+ }
140
152
}
141
153
}
142
154
@@ -167,6 +179,74 @@ function hooks_parse_files( array $files, string $root, array $ignore_hooks ) :
167
179
return $ output ;
168
180
}
169
181
182
+ /**
183
+ * @param \WP_Parser\Function_Call_Reflector[] $nodes Array of hook references.
184
+ * @param string $path The file path.
185
+ * @return array<int,array<string,mixed>>
186
+ */
187
+ function export_scheduled_hooks ( array $ nodes , string $ path ) : array {
188
+ $ out = array ();
189
+
190
+ $ event_functions = [
191
+ 'wp_schedule_event ' ,
192
+ // WooCommerce action scheduler
193
+ 'as_schedule_recurring_action ' ,
194
+ 'as_schedule_cron_action ' ,
195
+ ];
196
+
197
+ $ single_event_functions = [
198
+ 'wp_schedule_single_event ' ,
199
+ // WooCommerce action scheduler
200
+ 'as_schedule_single_action ' ,
201
+ 'as_enqueue_async_action ' ,
202
+ ];
203
+
204
+ foreach ( $ nodes as $ wp_node ) {
205
+ if ( !$ wp_node instanceof \WP_Parser \Function_Call_Reflector ) {
206
+ continue ;
207
+ }
208
+
209
+ $ origNode = $ wp_node ->getNode ();
210
+
211
+ // same code used in psalm-plugin-wordpress
212
+ if ( $ origNode instanceof \PhpParser \Node \Expr \FuncCall && $ origNode ->name instanceof \PhpParser \Node \Name ) {
213
+ if ( in_array ( (string ) $ origNode ->name , $ event_functions , true ) ) {
214
+ $ hook_type = 'cron-action ' ;
215
+ // the 3rd arg (index key 2) is the hook name
216
+ $ hook_index = 2 ;
217
+ } elseif ( in_array ( (string ) $ origNode ->name , $ single_event_functions , true ) ) {
218
+ $ hook_type = 'cron-action ' ;
219
+ $ hook_index = 1 ;
220
+
221
+ if ( (string ) $ origNode ->name === 'as_enqueue_async_action ' ) {
222
+ $ hook_index = 0 ;
223
+ }
224
+ } else {
225
+ continue ;
226
+ }
227
+
228
+ if ( ! $ origNode ->args [ $ hook_index ]->value instanceof \PhpParser \Node \Scalar \String_ ) {
229
+ continue ;
230
+ }
231
+
232
+ $ out [] = array (
233
+ 'name ' => $ origNode ->args [ $ hook_index ]->value ->value ,
234
+ 'file ' => $ path ,
235
+ 'type ' => 'action ' ,
236
+ 'doc ' => array (
237
+ 'description ' =>'' ,
238
+ 'long_description ' => '' ,
239
+ 'tags ' => array (),
240
+ 'long_description_html ' => '' ,
241
+ ),
242
+ 'args ' => 0 ,
243
+ );
244
+ }
245
+ }
246
+
247
+ return $ out ;
248
+ }
249
+
170
250
/**
171
251
* @param \WP_Parser\Hook_Reflector[] $hooks Array of hook references.
172
252
* @param string $path The file path.
0 commit comments