Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 66 additions & 54 deletions features/profile-hook.feature
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
Feature: Profile a specific hook

@require-wp-4.0
Scenario: Profile all hooks when a specific hook isn't specified
Given a WP install

Expand All @@ -20,21 +19,6 @@ Feature: Profile a specific hook
| callback | cache_hits | cache_misses |
| sanitize_comment_cookies() | 0 | 0 |

@less-than-php-7 @require-wp-4.0
Scenario: Profile an intermediate stage hook
Given a WP install

When I run `wp profile hook wp_head:before --fields=callback,cache_hits,cache_misses`
Then STDOUT should be a table containing rows:
| callback | cache_hits | cache_misses |
| parse_blocks() | 0 | 0 |
| _get_wptexturize_split_regex() | 0 | 0 |
And STDOUT should not contain:
"""
WP_CLI\Profile\Profiler->wp_tick_profile_begin()
"""

@require-wp-4.0
Scenario: Profile a hook before the template is loaded
Given a WP install

Expand All @@ -43,7 +27,6 @@ Feature: Profile a specific hook
| callback |
And STDERR should be empty

@require-wp-4.0
Scenario: Profile a hook without any callbacks
Given a WP install

Expand All @@ -65,7 +48,7 @@ Feature: Profile a specific hook
<meta name="generator"
"""

@require-wp-4.0 @less-than-wp-6.9
@less-than-wp-6.9
Scenario: Profile the shutdown hook
Given a WP install
And a wp-content/mu-plugins/shutdown.php file:
Expand Down Expand Up @@ -107,7 +90,6 @@ Feature: Profile a specific hook
| total (3) | 0 | 1 |
And STDERR should be empty

@require-wp-4.0
Scenario: Indicate where a callback is defined with profiling a hook
Given a WP install
And a wp-content/mu-plugins/custom-action.php file:
Expand All @@ -127,63 +109,93 @@ Feature: Profile a specific hook
| total (1) | | 0 | 1 |
And STDERR should be empty

Scenario: Hooks should only be called once
Scenario: Search for callbacks by name pattern on a specific hook
Given a WP install
And a wp-content/mu-plugins/action-test.php file:
And a wp-content/mu-plugins/search-test.php file:
"""
<?php
add_action( 'init', function(){
static $i;
if ( ! isset( $i ) ) {
$i = 0;
}
$i++;
WP_CLI::warning( 'Called ' . $i );
});
function wp_cli_search_hook_one() {}
function wp_cli_search_hook_two() {}
function unrelated_callback() {}
add_action( 'init', 'wp_cli_search_hook_one' );
add_action( 'init', 'wp_cli_search_hook_two' );
add_action( 'init', 'unrelated_callback' );
"""

When I try `wp profile hook init`
Then STDERR should be:
When I run `wp profile hook init --fields=callback --search=wp_cli_search_hook`
Then STDOUT should contain:
"""
Warning: Called 1
wp_cli_search_hook_one()
"""
And STDOUT should contain:
"""
wp_cli_search_hook_two()
"""
And STDOUT should not contain:
"""
unrelated_callback()
"""
And STDERR should be empty

@less-than-php-7 @require-wp-4.0
Scenario: Profile the mu_plugins:before hook
Scenario: Search for callbacks by name pattern across all hooks
Given a WP install
And a wp-content/mu-plugins/awesome-file.php file:
And a wp-content/mu-plugins/search-all-test.php file:
"""
<?php
function awesome_func() {
// does nothing
}
awesome_func();
function wp_cli_search_all_hook() {}
add_action( 'init', 'wp_cli_search_all_hook' );
"""

When I run `wp profile hook muplugins_loaded:before --fields=callback`
When I run `wp profile hook --all --fields=callback --search=wp_cli_search_all_hook`
Then STDOUT should contain:
"""
wp-content/mu-plugins/awesome-file.php
wp_cli_search_all_hook()
"""
And STDERR should be empty

@less-than-php-7 @require-wp-4.0
Scenario: Profile the :after hooks
Scenario: Profile an intermediate stage hook
Given a WP install

When I run `wp profile hook wp_loaded:after`
Then STDOUT should contain:
"""
do_action()
"""
When I run `wp profile hook muplugins_loaded --fields=hook`
Then STDOUT should be a table containing rows:
| hook |
| muplugins_loaded |
And STDERR should be empty

When I run `wp profile hook wp:after`
Then STDOUT should contain:
Scenario: Profile the muplugins_loaded:before hook
Given a WP install

When I run `wp profile hook muplugins_loaded:before --fields=hook`
Then STDOUT should be a table containing rows:
| hook |
| muplugins_loaded:before |
And STDERR should be empty

Scenario: Profile the muplugins_loaded:after hook
Given a WP install

When I run `wp profile hook muplugins_loaded:after --fields=hook`
Then STDOUT should be a table containing rows:
| hook |
| muplugins_loaded:after |
And STDERR should be empty
Scenario: Hooks should only be called once
Given a WP install
And a wp-content/mu-plugins/action-test.php file:
"""
do_action_ref_array()
<?php
add_action( 'init', function(){
static $i;
if ( ! isset( $i ) ) {
$i = 0;
}
$i++;
WP_CLI::warning( 'Called ' . $i );
});
"""

When I run `wp profile hook wp_footer:after`
Then STDOUT should contain:
When I try `wp profile hook init`
Then STDERR should be:
"""
do_action()
Warning: Called 1
"""
2 changes: 1 addition & 1 deletion features/profile.feature
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Feature: Basic profile usage
"""
usage: wp profile eval <php-code> [--hook[=<hook>]] [--fields=<fields>] [--format=<format>] [--order=<order>] [--orderby=<fields>]
or: wp profile eval-file <file> [--hook[=<hook>]] [--fields=<fields>] [--format=<format>] [--order=<order>] [--orderby=<fields>]
or: wp profile hook [<hook>] [--all] [--spotlight] [--url=<url>] [--fields=<fields>] [--format=<format>] [--order=<order>] [--orderby=<fields>]
or: wp profile hook [<hook>] [--all] [--spotlight] [--url=<url>] [--fields=<fields>] [--format=<format>] [--order=<order>] [--orderby=<fields>] [--search=<pattern>]
or: wp profile stage [<stage>] [--all] [--spotlight] [--url=<url>] [--fields=<fields>] [--format=<format>] [--order=<order>] [--orderby=<fields>]

See 'wp help profile <command>' for more information on a specific command.
Expand Down
26 changes: 26 additions & 0 deletions src/Command.php
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,9 @@ public function stage( $args, $assoc_args ) {
* [--orderby=<fields>]
* : Set orderby which field.
*
* [--search=<pattern>]
* : Filter callbacks to those matching the given search pattern (case-insensitive).
*
* ## EXAMPLES
*
* # Profile a hook.
Expand Down Expand Up @@ -291,6 +294,13 @@ public function hook( $args, $assoc_args ) {
if ( Utils\get_flag_value( $assoc_args, 'spotlight' ) ) {
$loggers = self::shine_spotlight( $loggers, $metrics );
}
$search = Utils\get_flag_value( $assoc_args, 'search', false );
if ( false !== $search && '' !== $search ) {
if ( ! $focus ) {
WP_CLI::error( '--search requires --all or a specific hook.' );
}
$loggers = self::filter_by_callback( $loggers, $search );
}
$formatter->display_items( $loggers, true, $order, $orderby );
}

Expand Down Expand Up @@ -534,4 +544,20 @@ private static function shine_spotlight( $loggers, $metrics ) {

return $loggers;
}

/**
* Filter loggers to only those whose callback name matches a pattern.
*
* @param array $loggers
* @param string $pattern
* @return array
*/
private static function filter_by_callback( $loggers, $pattern ) {
return array_filter(
$loggers,
function ( $logger ) use ( $pattern ) {
return isset( $logger->callback ) && false !== stripos( $logger->callback, $pattern );
}
);
}
}
Loading