Skip to content

Commit 52a50c1

Browse files
authored
Merge pull request #84 from wp-cli/copilot/add-hook-flag-to-eval-shell
Add --hook flag to defer eval execution to WordPress lifecycle hooks
2 parents 4ccf1b4 + 33d7538 commit 52a50c1

File tree

3 files changed

+136
-4
lines changed

3 files changed

+136
-4
lines changed

features/eval.feature

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,3 +248,88 @@ Feature: Evaluating PHP code and files.
248248
"""
249249
eval()'d code
250250
"""
251+
252+
Scenario: Eval with --hook flag
253+
Given a WP install
254+
255+
When I run `wp eval 'echo "Hook: " . current_action();' --hook=init`
256+
Then STDOUT should contain:
257+
"""
258+
Hook: init
259+
"""
260+
261+
When I run `wp eval 'echo "Hook: " . current_action();' --hook=wp_loaded`
262+
Then STDOUT should contain:
263+
"""
264+
Hook: wp_loaded
265+
"""
266+
267+
Scenario: Eval-file with --hook flag
268+
Given a WP install
269+
And a hook-script.php file:
270+
"""
271+
<?php
272+
echo "Hook: " . current_action() . "\n";
273+
echo "Is admin: " . (is_admin() ? 'yes' : 'no') . "\n";
274+
"""
275+
276+
When I run `wp eval-file hook-script.php --hook=init`
277+
Then STDOUT should contain:
278+
"""
279+
Hook: init
280+
"""
281+
And STDOUT should contain:
282+
"""
283+
Is admin:
284+
"""
285+
286+
When I run `wp eval-file hook-script.php --hook=wp_loaded`
287+
Then STDOUT should contain:
288+
"""
289+
Hook: wp_loaded
290+
"""
291+
292+
Scenario: Eval with --hook and --skip-wordpress should error
293+
Given a WP install
294+
295+
When I try `wp eval 'echo "test";' --hook=init --skip-wordpress`
296+
Then STDERR should contain:
297+
"""
298+
Error: The --hook parameter cannot be used with --skip-wordpress.
299+
"""
300+
And the return code should be 1
301+
302+
Scenario: Eval-file with --hook and --skip-wordpress should error
303+
Given an empty directory
304+
And a script.php file:
305+
"""
306+
<?php
307+
echo "test";
308+
"""
309+
310+
When I try `wp eval-file script.php --hook=init --skip-wordpress`
311+
Then STDERR should contain:
312+
"""
313+
Error: The --hook parameter cannot be used with --skip-wordpress.
314+
"""
315+
And the return code should be 1
316+
317+
Scenario: Eval-file with --hook and positional arguments
318+
Given a WP install
319+
And a args-script.php file:
320+
"""
321+
<?php
322+
echo "Hook: " . current_action() . "\n";
323+
echo "Args: " . implode(' ', $args) . "\n";
324+
"""
325+
326+
When I run `wp eval-file args-script.php arg1 arg2 --hook=init`
327+
Then STDOUT should contain:
328+
"""
329+
Hook: init
330+
"""
331+
And STDOUT should contain:
332+
"""
333+
Args: arg1 arg2
334+
"""
335+

src/EvalFile_Command.php

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,19 @@ class EvalFile_Command extends WP_CLI_Command {
3131
* [--use-include]
3232
* : Process the provided file via include instead of evaluating its contents.
3333
*
34+
* [--hook=<hook>]
35+
* : Execute file after a specific WordPress hook has fired.
36+
*
3437
* @when before_wp_load
3538
*
3639
* ## EXAMPLES
3740
*
3841
* # Execute file my-code.php and pass value1 and value2 arguments.
3942
* # Access arguments in $args array ($args[0] = value1, $args[1] = value2).
4043
* $ wp eval-file my-code.php value1 value2
44+
*
45+
* # Execute file after the 'init' hook.
46+
* $ wp eval-file my-code.php --hook=init
4147
*/
4248
public function __invoke( $args, $assoc_args ) {
4349
$file = array_shift( $args );
@@ -52,11 +58,28 @@ public function __invoke( $args, $assoc_args ) {
5258
WP_CLI::error( '"-" and "--use-include" parameters cannot be used at the same time' );
5359
}
5460

55-
if ( null === Utils\get_flag_value( $assoc_args, 'skip-wordpress' ) ) {
61+
$execute_closure = function () use ( $file, $args, $use_include ) {
62+
self::execute_eval( $file, $args, $use_include );
63+
};
64+
65+
$hook = Utils\get_flag_value( $assoc_args, 'hook' );
66+
$skip_wordpress = Utils\get_flag_value( $assoc_args, 'skip-wordpress' );
67+
68+
if ( $hook && null !== $skip_wordpress ) {
69+
WP_CLI::error( 'The --hook parameter cannot be used with --skip-wordpress.' );
70+
}
71+
72+
if ( $hook ) {
73+
WP_CLI::add_wp_hook( $hook, $execute_closure );
74+
}
75+
76+
if ( null === $skip_wordpress ) {
5677
WP_CLI::get_runner()->load_wordpress();
5778
}
5879

59-
self::execute_eval( $file, $args, $use_include );
80+
if ( ! $hook ) {
81+
$execute_closure();
82+
}
6083
}
6184

6285
/**

src/Eval_Command.php

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ class Eval_Command extends WP_CLI_Command {
1818
* [--skip-wordpress]
1919
* : Execute code without loading WordPress.
2020
*
21+
* [--hook=<hook>]
22+
* : Execute code after a specific WordPress hook has fired.
23+
*
2124
* ## EXAMPLES
2225
*
2326
* # Display WordPress content directory.
@@ -28,14 +31,35 @@ class Eval_Command extends WP_CLI_Command {
2831
* $ wp eval 'echo rand();' --skip-wordpress
2932
* 479620423
3033
*
34+
* # Execute code after WordPress is fully loaded.
35+
* $ wp eval 'echo "Current user: " . wp_get_current_user()->user_login;' --hook=wp_loaded
36+
* Current user: admin
37+
*
3138
* @when before_wp_load
3239
*/
3340
public function __invoke( $args, $assoc_args ) {
3441

35-
if ( null === Utils\get_flag_value( $assoc_args, 'skip-wordpress' ) ) {
42+
$execute_closure = function () use ( $args ) {
43+
eval( $args[0] );
44+
};
45+
46+
$hook = Utils\get_flag_value( $assoc_args, 'hook' );
47+
$skip_wordpress = Utils\get_flag_value( $assoc_args, 'skip-wordpress' );
48+
49+
if ( $hook && null !== $skip_wordpress ) {
50+
WP_CLI::error( 'The --hook parameter cannot be used with --skip-wordpress.' );
51+
}
52+
53+
if ( $hook ) {
54+
WP_CLI::add_wp_hook( $hook, $execute_closure );
55+
}
56+
57+
if ( null === $skip_wordpress ) {
3658
WP_CLI::get_runner()->load_wordpress();
3759
}
3860

39-
eval( $args[0] );
61+
if ( ! $hook ) {
62+
$execute_closure();
63+
}
4064
}
4165
}

0 commit comments

Comments
 (0)