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 +156 -79 1.4.41.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,51 +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 - // Inform if it's the theme or a mu-plugin
174 - if ( $v[3] == 'theme' ) {
175 - $name .= ' (theme)';
176 - } elseif ( $v[3] == 'mu-plugin' ) {
177 - $name .= ' (mu-plugin)';
178 - }
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];
230 + }
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 + }
179 237
180 - $time = number_format( $v[1], 3 );
181 - $percent = number_format( $v[1] / $total_time * 100 );
182 - $chars = number_format( $percent * 80 / $coeff );
183 - // We use `echo` instead of `WP_CLI::log` because the layout could
184 - // be all messed-up when some caching plugins such as LiteSpeed Cache
185 - // are activated.
186 - echo " $name | {$time}s | {$percent}%\n";
187 - if (! $percent ) {
188 - echo " \u{258C}\n\n";
189 - } else {
190 - $bar = '';
191 - for ( $i = 0; $i < $chars; $i++ ) {
192 - $bar .= ' ';
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");
193 253 }
194 - echo WP_CLI::colorize(" %8$bar%n\n\n");
195 254 }
196 255 }
256 + if ( $this->out == 'csv') {
257 + echo $buffer;
258 +
259 + } elseif ( $this->out == 'json' ) {
260 + echo json_encode( $buffer );
261 + }
262 +
197 263 exit;
198 264 }
199 265
200 - /*
266 +
267 + /**
201 268 * Retrieve the full path/name to the last created profile
202 269 *
203 270 */
204 271 private function find_last_profile() {
205 272
206 - $profiles = glob( CODE_PROFILER_UPLOAD_DIR .'/*.slugs.profile' );
273 + $profiles = code_profiler_glob( CODE_PROFILER_UPLOAD_DIR, '\.slugs\.profile$', true );
207 274
208 275 array_multisort(
209 - array_map( 'filectime', $profiles ),
276 + array_map('filectime', $profiles ),
210 277 SORT_NUMERIC,
211 278 SORT_DESC,
212 279 $profiles
213 280 );
@@ -219,15 +286,15 @@
219 286 return false;
220 287 }
221 288
222 289
223 - /*
290 + /**
224 291 * Parse and return the profile's data
225 292 *
226 293 */
227 294 private function read_profile() {
228 295
229 - $profile = str_replace( '.slugs.profile', '', $this->file );
296 + $profile = str_replace('.slugs.profile', '', $this->file );
230 297
231 298 $res = code_profiler_get_profile_data( $profile );
232 299 if ( isset( $res['error'] ) ) {
233 300 WP_CLI::error( $res['error'] );
@@ -241,15 +308,16 @@
241 308
242 309 return $res;
243 310 }
244 311
245 - /*
312 +
313 + /**
246 314 * Verify wether WP CLI integration is enabled or not
247 315 *
248 316 */
249 317 private function is_enabled() {
250 318
251 - $cp_options = get_option( 'code-profiler' );
319 + $cp_options = get_option('code-profiler');
252 320 if ( empty( $cp_options['enable_wpcli'] ) ) {
253 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');
254 322 WP_CLI::error( $message );
255 323 exit;
@@ -255,9 +323,10 @@
255 323 exit;
256 324 }
257 325 }
258 326
259 - /*
327 +
328 + /**
260 329 * Display help screen and quit.
261 330 *
262 331 */
263 332 public function help() {
@@ -263,24 +332,32 @@
263 332 public function help() {
264 333
265 334 $this->is_enabled();
266 335
267 - WP_CLI::log( "\nCode Profiler v". CODE_PROFILER_VERSION .
268 - " (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".
269 338 " {$this->cmd_view} ". __('View last created profile', 'code-profiler') ."\n".
270 - " {$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".
271 340 __('GLOBAL PARAMETERS', 'code-profiler') ."\n\n".
272 341 " --dest=<URL to profile> **". __('Pro version only', 'code-profiler') ."**\n".
273 - " ". __('Path to the WordPress page or post to profile. If missing, profile the frontend.', 'code-profiler-pro') ."\n\n".
274 - " --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".
275 346 " ". __('Run the profiler as the corresponding WordPress user. If missing, run as an unauthenticated user.', 'code-profiler') ."\n\n".
276 - " --u=<username>\n".
277 - " ". __('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" );
278 351 exit;
279 352 }
280 353
281 354 }
282 355
283 -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 +);
284 361
285 362 // =====================================================================
286 363 // EOF