PluginProbe
Code Profiler – WordPress Performance Profiling and Debugging Made Easy / 1.9.6
Code Profiler – WordPress Performance Profiling and Debugging Made Easy v1.9.6
1.9.6 1.9.5 1.9.4 1.9.3 trunk 1.4 1.4.1 1.4.2 1.4.3 1.4.4 1.5 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 1.6 1.6.1 1.6.10 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 All 41 releases
← All changes | lib/class-cli.php +157 -73 1.4.11.9.6 View file →
@@ -6,13 +6,13 @@
6 6 | | | / _ \ / _` |/ _ \ | |_) | '__/ _ \| |_| | |/ _ \ '__| |
7 7 | | |__| (_) | (_| | __/ | __/| | | (_) | _| | | __/ | |
8 8 | \____\___/ \__,_|\___| |_| |_| \___/|_| |_|_|\___|_| |
9 9 | |
10 - | (c) Jerome Bruandet ~ https://code-profiler.com/ |
10 + | (c) Jerome Bruandet ~ https://nintechnet.com/codeprofiler/ |
11 11 +=====================================================================+
12 12 */
13 13
14 -if (! defined( 'ABSPATH' ) ) { die( 'Forbidden' ); }
14 +if (! defined('ABSPATH') ) { die('Forbidden'); }
15 15
16 16 // =====================================================================
17 17
18 18 class CodeProfiler_CLI extends WP_CLI_Command {
@@ -17,12 +17,13 @@
17 17
18 18 class CodeProfiler_CLI extends WP_CLI_Command {
19 19
20 20 private $file;
21 + private $out = 'view';
21 22 private $cmd_view = 'wp code-profiler view';
22 23 private $cmd_run = 'wp code-profiler run';
23 24
24 - /*
25 + /**
25 26 * Run the profiler.
26 27 *
27 28 */
28 29 public function run( $args, $assoc_args ) {
@@ -28,20 +29,33 @@
28 29 public function run( $args, $assoc_args ) {
29 30
30 31 $this->is_enabled();
31 32
32 - $_POST['cp_nonce'] = wp_create_nonce( 'start_profiler_nonce' );
33 - $_POST['post'] = home_url( '/' );
34 - $_POST['where'] = 'frontend';
35 - // Detect if we're authenticated or not
36 - if ( is_user_logged_in() === true ) {
37 - $_POST['user'] = 'authenticated';
33 + $_POST['cp_nonce'] = wp_create_nonce('start_profiler_nonce');
34 +
35 + $_POST['post'] = home_url( '/' );
36 + // Mark the connection as 'HTTPS' if needed.
37 + if ( strtolower( parse_url( $_POST['post'], PHP_URL_SCHEME ) ) == 'https') {
38 + $_SERVER['HTTPS'] = 'on';
39 + }
40 +
41 + if (! empty( $assoc_args['wpcron'] ) ) {
42 + $_POST['x_end'] = 'wpcron';
43 + $_POST['post'] = $assoc_args['wpcron'];
44 +
38 45 } else {
39 - $_POST['user'] = 'unauthenticated';
46 + $_POST['x_end'] = 'frontend';
47 + // Detect if we're authenticated or not
48 + if ( is_user_logged_in() === true ) {
49 + $_POST['x_auth'] = 'authenticated';
50 + } else {
51 + $_POST['x_auth'] = 'unauthenticated';
52 + }
40 53 }
41 - $_POST['profile'] = 'WP-CLI_' . time();
42 - $_POST['ua'] = 'FireFox';
43 54
55 + $_POST['profile'] = 'WP-CLI_' . time();
56 + $_POST['user_agent'] = 'Firefox';
57 +
44 58 if (! empty( $assoc_args['dest'] ) ) {
45 59 $message = sprintf(
46 60 __('The "%s" option is only available in the pro version of Code Profiler.', 'code-profiler'),
47 61 '--dest'
@@ -49,11 +63,15 @@
49 63 WP_CLI::error( $message );
50 64 exit;
51 65 }
52 66
67 + if (! empty( $assoc_args['out'] ) && in_array( $assoc_args['out'], ['json', 'csv'] ) ) {
68 + $this->out = $assoc_args['out'];
69 + }
70 +
53 71 // HTTP basic authentication
54 72 if (! empty( $assoc_args['u'] ) ) {
55 - _e('Enter your HTTP basic authentication password:', 'code-profiler' );
73 + _e('Enter your HTTP basic authentication password:', 'code-profiler');
56 74 echo ' ';
57 75 echo "\033[30;40m";
58 76 $password = trim( stream_get_line( STDIN, 255, PHP_EOL) );
59 77 echo "\033[0m";
@@ -59,20 +77,22 @@
59 77 echo "\033[0m";
60 78 $_POST['Authorization'] = 'Basic '. base64_encode( "{$assoc_args['u']}:{$password}" );
61 79 }
62 80
63 - WP_CLI::log( sprintf(
64 - __('Starting Code Profiler v%s (profile: %s)', 'code-profiler' ),
65 - CODE_PROFILER_VERSION, $_POST['profile'] ) . "\n"
66 - );
81 + if ( $this->out == 'view') {
82 + WP_CLI::log( sprintf(
83 + __('Starting Code Profiler v%s (profile: %s)', 'code-profiler'),
84 + CODE_PROFILER_VERSION, $_POST['profile'] ) . "\n"
85 + );
67 86
68 - $progress = \WP_CLI\Utils\make_progress_bar( '', 3 );
69 - $progress->tick();
87 + $progress = \WP_CLI\Utils\make_progress_bar( '', 3 );
88 + $progress->tick();
89 + }
70 90
71 91 // Run the profiler
72 - $response = json_decode( codeprofiler_start_profiler(), true );
92 + $response = json_decode( CodeProfiler_helpers::codeprofiler_start_profiler(), true );
73 93 if ( $response === false ) {
74 - $message = __('Unknown error returned by AJAX', 'code-profiler' );
94 + $message = __('Unknown error returned by AJAX', 'code-profiler');
75 95 WP_CLI::error( $message );
76 96 exit;
77 97 }
78 98 if ( $response['status'] == 'error' ) {
@@ -79,15 +99,17 @@
79 99 WP_CLI::error( $response['message'] );
80 100 exit;
81 101 }
82 102
83 - $progress->tick();
103 + if ( $this->out == 'view') {
104 + $progress->tick();
105 + }
84 106
85 107 // All good, run the parser
86 108 $_POST['microtime'] = $response['microtime'];
87 - $response = json_decode( codeprofiler_prepare_report(), true );
109 + $response = json_decode( CodeProfiler_helpers::codeprofiler_prepare_report(), true );
88 110 if ( $response === false ) {
89 - $message = __('Unknown error returned by AJAX', 'code-profiler' );
111 + $message = __('Unknown error returned by AJAX', 'code-profiler');
90 112 WP_CLI::error( $message );
91 113 exit;
92 114 }
93 115 if ( $response['status'] == 'error' ) {
@@ -94,31 +116,37 @@
94 116 WP_CLI::error( $response['message'] );
95 117 exit;
96 118 }
97 119
98 - $progress->tick();
99 - $progress->finish();
120 + if ( $this->out == 'view') {
121 + $progress->tick();
122 + $progress->finish();
123 + }
100 124
101 125 // Run the parser and show the results
102 - $this->view( $response['cp_profile'] );
126 + $this->view( $args, $assoc_args, $response['cp_profile'] );
103 127
104 128 exit;
105 129 }
106 130
107 131
108 - /*
132 + /**
109 133 * Display last created profile.
110 134 *
111 135 */
112 - public function view( $profile = '' ) {
136 + public function view( $args = [], $assoc_args = [], $profile = '') {
113 137
114 138 $this->is_enabled();
115 139
140 + if (! empty( $assoc_args['out'] ) && in_array( $assoc_args['out'], ['json', 'csv'] ) ) {
141 + $this->out = $assoc_args['out'];
142 + }
143 +
116 144 // The profile was just created (`wp code-profiler run`)...
117 145 if (! empty( $profile ) ) {
118 146 $this->file = code_profiler_get_profile_path( $profile );
119 147 if ( $this->file === false ) {
120 - $message = __('Cannot find the profile file', 'code-profiler' );
148 + $message = __('Cannot find the profile file', 'code-profiler');
121 149 WP_CLI::error( $message );
122 150 exit;
123 151 }
124 152 $this->file .= '.slugs.profile';
@@ -127,9 +155,9 @@
127 155 } else {
128 156 $this->file = $this->find_last_profile();
129 157 if ( $this->file === false ) {
130 158 $message = sprintf(
131 - __('No profile found. Run the profiler at least once to create a profile: %s', 'code-profiler' ),
159 + __('No profile found. Run the profiler at least once to create a profile: %s', 'code-profiler'),
132 160 $this->cmd_run
133 161 );
134 162 WP_CLI::error( $message );
135 163 exit;
@@ -141,19 +169,37 @@
141 169 '`'. CODE_PROFILER_UPLOAD_DIR .'/\d{10}\.\d+\.(.+?)\.slugs\.profile$`',
142 170 $this->file,
143 171 $match
144 172 );
145 - $message = sprintf( __('Viewing: %s', 'code-profiler'), $match[1] );
146 - $date = date('Y/m/d \@ H:i:s', filemtime( $this->file ) );
147 - echo WP_CLI::colorize("\n%Y$message ~ $date%n\n\n");
148 173
149 - // Display stats
150 - $summary_file = str_replace( '.slugs.profile', '', $this->file );
151 - echo code_profiler_getsummarystats( $summary_file, 'text' );
174 + $cp_slug = __('Slug', 'code-profiler');
175 + $cp_time = __('Execution time', 'code-profiler');
176 + $cp_name = __('Name', 'code-profiler');
177 + $cp_type = __('Type', 'code-profiler');
152 178
179 + if ( $this->out == 'view' ) {
180 + $buffer = '';
181 + $message = sprintf( __('Viewing: %s', 'code-profiler'), $match[1] );
182 + $date = date('Y/m/d \@ H:i:s', filemtime( $this->file ) );
183 + echo WP_CLI::colorize("\n%Y$message ~ $date%n\n\n");
184 + // Display stats
185 + $summary_file = str_replace('.slugs.profile', '', $this->file );
186 + echo code_profiler_getsummarystats( $summary_file, 'text');
187 + /**
188 + * CSV output.
189 + */
190 + } elseif ( $this->out == 'csv' ) {
191 + $buffer = "$cp_slug,\"$cp_time\",$cp_name,$cp_type\n";
192 + /**
193 + * JSON-encoded output.
194 + */
195 + } else {
196 + $buffer = [];
197 + }
198 +
153 199 $slugs = $this->read_profile();
154 200
155 - $cp_options = get_option( 'code-profiler' );
201 + $cp_options = get_option('code-profiler');
156 202
157 203 // Get the total time and the slowest item
158 204 $total_time = 0;
159 205 foreach( $slugs as $k => $v ) {
@@ -163,44 +209,72 @@
163 209 $coeff = number_format( $slugs[0][1] / $total_time * 100 );
164 210
165 211 foreach( $slugs as $k => $v ) {
166 212
167 - // Display name, time and %
168 - if ( $cp_options['display_name'] == 'slug' ) {
169 - $name = $v[0];
213 + if ( $this->out == 'csv') {
214 + $buffer .= "{$v[0]},{$v[1]},{$v[2]},{$v[3]}\n";
215 +
216 + } elseif( $this->out == 'json') {
217 + $buffer[] = [
218 + $cp_slug = $v[0],
219 + $cp_time = $v[1],
220 + $cp_name = $v[2],
221 + $cp_type = $v[3]
222 + ];
223 +
170 224 } else {
171 - $name = $v[2];
172 - }
173 - $time = number_format( $v[1], 3 );
174 - $percent = number_format( $v[1] / $total_time * 100 );
175 - $chars = number_format( $percent * 80 / $coeff );
176 - // We use `echo` instead of `WP_CLI::log` because the layout could
177 - // be all messed-up when some caching plugins such as LiteSpeed Cache
178 - // are activated.
179 - echo " $name | {$time}s | {$percent}%\n";
180 - if (! $percent ) {
181 - echo " \u{258C}\n\n";
182 - } else {
183 - $bar = '';
184 - for ( $i = 0; $i < $chars; $i++ ) {
185 - $bar .= ' ';
225 + // Display name, time and %
226 + if ( isset( $cp_options['display_name'] ) && $cp_options['display_name'] == 'slug' ) {
227 + $name = $v[0];
228 + } else {
229 + $name = $v[2];
186 230 }
187 - echo WP_CLI::colorize(" %8$bar%n\n\n");
231 + // Inform if it's the theme or a mu-plugin
232 + if ( $v[3] == 'theme') {
233 + $name .= ' (theme)';
234 + } elseif ( $v[3] == 'mu-plugin') {
235 + $name .= ' (mu-plugin)';
236 + }
237 +
238 + $time = number_format( $v[1], 3 );
239 + $percent = number_format( $v[1] / $total_time * 100 );
240 + $chars = number_format( $percent * 80 / $coeff );
241 + // We use `echo` instead of `WP_CLI::log` because the layout could
242 + // be all messed-up when some caching plugins such as LiteSpeed Cache
243 + // are activated.
244 + echo " $name | {$time}s | {$percent}%\n";
245 + if (! $percent ) {
246 + echo " \u{258C}\n\n";
247 + } else {
248 + $bar = '';
249 + for ( $i = 0; $i < $chars; $i++ ) {
250 + $bar .= ' ';
251 + }
252 + echo WP_CLI::colorize(" %8$bar%n\n\n");
253 + }
188 254 }
189 255 }
256 + if ( $this->out == 'csv') {
257 + echo $buffer;
258 +
259 + } elseif ( $this->out == 'json' ) {
260 + echo json_encode( $buffer );
261 + }
262 +
190 263 exit;
191 264 }
192 265
193 - /*
266 +
267 + /**
194 268 * Retrieve the full path/name to the last created profile
195 269 *
196 270 */
197 271 private function find_last_profile() {
198 272
199 - $profiles = glob( CODE_PROFILER_UPLOAD_DIR .'/*.slugs.profile' );
273 + $profiles = code_profiler_glob( CODE_PROFILER_UPLOAD_DIR, '\.slugs\.profile$', true );
200 274
201 275 array_multisort(
202 - array_map( 'filectime', $profiles ),
276 + array_map('filectime', $profiles ),
203 277 SORT_NUMERIC,
204 278 SORT_DESC,
205 279 $profiles
206 280 );
@@ -212,15 +286,15 @@
212 286 return false;
213 287 }
214 288
215 289
216 - /*
290 + /**
217 291 * Parse and return the profile's data
218 292 *
219 293 */
220 294 private function read_profile() {
221 295
222 - $profile = str_replace( '.slugs.profile', '', $this->file );
296 + $profile = str_replace('.slugs.profile', '', $this->file );
223 297
224 298 $res = code_profiler_get_profile_data( $profile );
225 299 if ( isset( $res['error'] ) ) {
226 300 WP_CLI::error( $res['error'] );
@@ -234,15 +308,16 @@
234 308
235 309 return $res;
236 310 }
237 311
238 - /*
312 +
313 + /**
239 314 * Verify wether WP CLI integration is enabled or not
240 315 *
241 316 */
242 317 private function is_enabled() {
243 318
244 - $cp_options = get_option( 'code-profiler' );
319 + $cp_options = get_option('code-profiler');
245 320 if ( empty( $cp_options['enable_wpcli'] ) ) {
246 321 $message = __('WP-CLI integration is disabled. To enable it, log in to your admin dashboard and go to the Code Profiler settings page.', 'code-profiler');
247 322 WP_CLI::error( $message );
248 323 exit;
@@ -248,9 +323,10 @@
248 323 exit;
249 324 }
250 325 }
251 326
252 - /*
327 +
328 + /**
253 329 * Display help screen and quit.
254 330 *
255 331 */
256 332 public function help() {
@@ -256,24 +332,32 @@
256 332 public function help() {
257 333
258 334 $this->is_enabled();
259 335
260 - WP_CLI::log( "\nCode Profiler v". CODE_PROFILER_VERSION .
261 - " (c)". date('Y') ." Jerome Bruandet & NinTechNet Limited ~ https://code-profiler.com/\n\n".
336 + WP_CLI::log("\nCode Profiler v". CODE_PROFILER_VERSION .
337 + " (c)". date('Y') ." Jerome Bruandet & NinTechNet Limited ~ https://nintechnet.com/codeprofiler/\n\n".
262 338 " {$this->cmd_view} ". __('View last created profile', 'code-profiler') ."\n".
263 - " {$this->cmd_run} ". __('Run the profiler on the frontend', 'code-profiler') ."\n\n".
339 + " {$this->cmd_run} ". __('Run the profiler in the frontend', 'code-profiler') ."\n\n".
264 340 __('GLOBAL PARAMETERS', 'code-profiler') ."\n\n".
265 341 " --dest=<URL to profile> **". __('Pro version only', 'code-profiler') ."**\n".
266 - " ". __('Path to the WordPress page or post to profile. If missing, profile the frontend.', 'code-profiler-pro') ."\n\n".
267 - " --user=<id|login|email>\n".
342 + " ". __('Path to the WordPress page or post to profile. If missing, profile the frontend.', 'code-profiler') ."\n\n".
343 + " --wpcron=<cron event> (optional)\n".
344 + " ". __('WordPress cron event to profile.', 'code-profiler') ."\n\n".
345 + " --user=<id|login|email> (optional)\n".
268 346 " ". __('Run the profiler as the corresponding WordPress user. If missing, run as an unauthenticated user.', 'code-profiler') ."\n\n".
269 - " --u=<username>\n".
270 - " ". __('HTTP Basic authentication username. You will be prompted to enter your password.', 'code-profiler') ."\n\n" );
347 + " --u=<username> (optional)\n".
348 + " ". __('HTTP Basic authentication username. You will be prompted to enter your password.', 'code-profiler') ."\n\n".
349 + " --out=<json|csv> (optional)\n".
350 + " ". __('Return the results in JSON-encoded or CSV format.', 'code-profiler') ."\n\n" );
271 351 exit;
272 352 }
273 353
274 354 }
275 355
276 -WP_CLI::add_command( 'code-profiler', 'CodeProfiler_CLI', ['shortdesc' => __('Profile your blog with Code Profiler.', 'code-profiler') ] );
356 +WP_CLI::add_command(
357 + 'code-profiler',
358 + 'CodeProfiler_CLI',
359 + ['shortdesc' => 'Profile your blog with Code Profiler.']
360 +);
277 361
278 362 // =====================================================================
279 363 // EOF