PluginProbe
Code Profiler – WordPress Performance Profiling and Debugging Made Easy / 1.5
Code Profiler – WordPress Performance Profiling and Debugging Made Easy v1.5
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 1.6.8 All 40 releases
code-profiler / lib / class-cli.php

class-cli.php in Code Profiler – WordPress Performance Profiling and Debugging Made Easy 1.5, at lib/class-cli.php

287 lines 8.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /*
3 +=====================================================================+
4 | ____ _ ____ __ _ _ |
5 | / ___|___ __| | ___ | _ \ _ __ ___ / _(_) | ___ _ __ |
6 | | | / _ \ / _` |/ _ \ | |_) | '__/ _ \| |_| | |/ _ \ '__| |
7 | | |__| (_) | (_| | __/ | __/| | | (_) | _| | | __/ | |
8 | \____\___/ \__,_|\___| |_| |_| \___/|_| |_|_|\___|_| |
9 | |
10 | (c) Jerome Bruandet ~ https://code-profiler.com/ |
11 +=====================================================================+
12 */
13
14 if (! defined( 'ABSPATH' ) ) { die( 'Forbidden' ); }
15
16 // =====================================================================
17
18 class CodeProfiler_CLI extends WP_CLI_Command {
19
20 private $file;
21 private $cmd_view = 'wp code-profiler view';
22 private $cmd_run = 'wp code-profiler run';
23
24 /*
25 * Run the profiler.
26 *
27 */
28 public function run( $args, $assoc_args ) {
29
30 $this->is_enabled();
31
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';
38 } else {
39 $_POST['user'] = 'unauthenticated';
40 }
41 $_POST['profile'] = 'WP-CLI_' . time();
42 $_POST['ua'] = 'Firefox';
43
44 if (! empty( $assoc_args['dest'] ) ) {
45 $message = sprintf(
46 __('The "%s" option is only available in the pro version of Code Profiler.', 'code-profiler'),
47 '--dest'
48 );
49 WP_CLI::error( $message );
50 exit;
51 }
52
53 // HTTP basic authentication
54 if (! empty( $assoc_args['u'] ) ) {
55 _e('Enter your HTTP basic authentication password:', 'code-profiler' );
56 echo ' ';
57 echo "\033[30;40m";
58 $password = trim( stream_get_line( STDIN, 255, PHP_EOL) );
59 echo "\033[0m";
60 $_POST['Authorization'] = 'Basic '. base64_encode( "{$assoc_args['u']}:{$password}" );
61 }
62
63 WP_CLI::log( sprintf(
64 __('Starting Code Profiler v%s (profile: %s)', 'code-profiler' ),
65 CODE_PROFILER_VERSION, $_POST['profile'] ) . "\n"
66 );
67
68 $progress = \WP_CLI\Utils\make_progress_bar( '', 3 );
69 $progress->tick();
70
71 // Run the profiler
72 $response = json_decode( codeprofiler_start_profiler(), true );
73 if ( $response === false ) {
74 $message = __('Unknown error returned by AJAX', 'code-profiler' );
75 WP_CLI::error( $message );
76 exit;
77 }
78 if ( $response['status'] == 'error' ) {
79 WP_CLI::error( $response['message'] );
80 exit;
81 }
82
83 $progress->tick();
84
85 // All good, run the parser
86 $_POST['microtime'] = $response['microtime'];
87 $response = json_decode( codeprofiler_prepare_report(), true );
88 if ( $response === false ) {
89 $message = __('Unknown error returned by AJAX', 'code-profiler' );
90 WP_CLI::error( $message );
91 exit;
92 }
93 if ( $response['status'] == 'error' ) {
94 WP_CLI::error( $response['message'] );
95 exit;
96 }
97
98 $progress->tick();
99 $progress->finish();
100
101 // Run the parser and show the results
102 $this->view( $response['cp_profile'] );
103
104 exit;
105 }
106
107
108 /*
109 * Display last created profile.
110 *
111 */
112 public function view( $profile = '' ) {
113
114 $this->is_enabled();
115
116 // The profile was just created (`wp code-profiler run`)...
117 if (! empty( $profile ) ) {
118 $this->file = code_profiler_get_profile_path( $profile );
119 if ( $this->file === false ) {
120 $message = __('Cannot find the profile file', 'code-profiler' );
121 WP_CLI::error( $message );
122 exit;
123 }
124 $this->file .= '.slugs.profile';
125
126 // ... or we show last created one (`wp code-profiler view`)
127 } else {
128 $this->file = $this->find_last_profile();
129 if ( $this->file === false ) {
130 $message = sprintf(
131 __('No profile found. Run the profiler at least once to create a profile: %s', 'code-profiler' ),
132 $this->cmd_run
133 );
134 WP_CLI::error( $message );
135 exit;
136 }
137 }
138
139 // Fetch and display the profile's name only
140 preg_match(
141 '`'. CODE_PROFILER_UPLOAD_DIR .'/\d{10}\.\d+\.(.+?)\.slugs\.profile$`',
142 $this->file,
143 $match
144 );
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
149 // Display stats
150 $summary_file = str_replace( '.slugs.profile', '', $this->file );
151 echo code_profiler_getsummarystats( $summary_file, 'text' );
152
153 $slugs = $this->read_profile();
154
155 $cp_options = get_option( 'code-profiler' );
156
157 // Get the total time and the slowest item
158 $total_time = 0;
159 foreach( $slugs as $k => $v ) {
160 $total_time += $v[1];
161 }
162
163 $coeff = number_format( $slugs[0][1] / $total_time * 100 );
164
165 foreach( $slugs as $k => $v ) {
166
167 // Display name, time and %
168 if ( $cp_options['display_name'] == 'slug' ) {
169 $name = $v[0];
170 } 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 }
179
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 .= ' ';
193 }
194 echo WP_CLI::colorize(" %8$bar%n\n\n");
195 }
196 }
197 exit;
198 }
199
200 /*
201 * Retrieve the full path/name to the last created profile
202 *
203 */
204 private function find_last_profile() {
205
206 $profiles = glob( CODE_PROFILER_UPLOAD_DIR .'/*.slugs.profile' );
207
208 array_multisort(
209 array_map( 'filectime', $profiles ),
210 SORT_NUMERIC,
211 SORT_DESC,
212 $profiles
213 );
214
215 if (! empty( $profiles[0] ) ) {
216 return $profiles[0];
217 }
218
219 return false;
220 }
221
222
223 /*
224 * Parse and return the profile's data
225 *
226 */
227 private function read_profile() {
228
229 $profile = str_replace( '.slugs.profile', '', $this->file );
230
231 $res = code_profiler_get_profile_data( $profile );
232 if ( isset( $res['error'] ) ) {
233 WP_CLI::error( $res['error'] );
234 exit;
235 }
236
237 // Sort data (slowest plugin/theme first)
238 usort( $res, function( $a, $b ) {
239 return $b[1] <=> $a[1];
240 } );
241
242 return $res;
243 }
244
245 /*
246 * Verify wether WP CLI integration is enabled or not
247 *
248 */
249 private function is_enabled() {
250
251 $cp_options = get_option( 'code-profiler' );
252 if ( empty( $cp_options['enable_wpcli'] ) ) {
253 $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 WP_CLI::error( $message );
255 exit;
256 }
257 }
258
259 /*
260 * Display help screen and quit.
261 *
262 */
263 public function help() {
264
265 $this->is_enabled();
266
267 WP_CLI::log( "\nCode Profiler v". CODE_PROFILER_VERSION .
268 " (c)". date('Y') ." Jerome Bruandet & NinTechNet Limited ~ https://code-profiler.com/\n\n".
269 " {$this->cmd_view} ". __('View last created profile', 'code-profiler') ."\n".
270 " {$this->cmd_run} ". __('Run the profiler on the frontend', 'code-profiler') ."\n\n".
271 __('GLOBAL PARAMETERS', 'code-profiler') ."\n\n".
272 " --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".
275 " ". __('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" );
278 exit;
279 }
280
281 }
282
283 WP_CLI::add_command( 'code-profiler', 'CodeProfiler_CLI', ['shortdesc' => __('Profile your blog with Code Profiler.', 'code-profiler') ] );
284
285 // =====================================================================
286 // EOF
287