PluginProbe
Code Profiler – WordPress Performance Profiling and Debugging Made Easy / 1.4.3
Code Profiler – WordPress Performance Profiling and Debugging Made Easy v1.4.3
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.4.3, at lib/class-cli.php

280 lines 7.8 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 $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 .= ' ';
186 }
187 echo WP_CLI::colorize(" %8$bar%n\n\n");
188 }
189 }
190 exit;
191 }
192
193 /*
194 * Retrieve the full path/name to the last created profile
195 *
196 */
197 private function find_last_profile() {
198
199 $profiles = glob( CODE_PROFILER_UPLOAD_DIR .'/*.slugs.profile' );
200
201 array_multisort(
202 array_map( 'filectime', $profiles ),
203 SORT_NUMERIC,
204 SORT_DESC,
205 $profiles
206 );
207
208 if (! empty( $profiles[0] ) ) {
209 return $profiles[0];
210 }
211
212 return false;
213 }
214
215
216 /*
217 * Parse and return the profile's data
218 *
219 */
220 private function read_profile() {
221
222 $profile = str_replace( '.slugs.profile', '', $this->file );
223
224 $res = code_profiler_get_profile_data( $profile );
225 if ( isset( $res['error'] ) ) {
226 WP_CLI::error( $res['error'] );
227 exit;
228 }
229
230 // Sort data (slowest plugin/theme first)
231 usort( $res, function( $a, $b ) {
232 return $b[1] <=> $a[1];
233 } );
234
235 return $res;
236 }
237
238 /*
239 * Verify wether WP CLI integration is enabled or not
240 *
241 */
242 private function is_enabled() {
243
244 $cp_options = get_option( 'code-profiler' );
245 if ( empty( $cp_options['enable_wpcli'] ) ) {
246 $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 WP_CLI::error( $message );
248 exit;
249 }
250 }
251
252 /*
253 * Display help screen and quit.
254 *
255 */
256 public function help() {
257
258 $this->is_enabled();
259
260 WP_CLI::log( "\nCode Profiler v". CODE_PROFILER_VERSION .
261 " (c)". date('Y') ." Jerome Bruandet & NinTechNet Limited ~ https://code-profiler.com/\n\n".
262 " {$this->cmd_view} ". __('View last created profile', 'code-profiler') ."\n".
263 " {$this->cmd_run} ". __('Run the profiler on the frontend', 'code-profiler') ."\n\n".
264 __('GLOBAL PARAMETERS', 'code-profiler') ."\n\n".
265 " --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".
268 " ". __('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" );
271 exit;
272 }
273
274 }
275
276 WP_CLI::add_command( 'code-profiler', 'CodeProfiler_CLI', ['shortdesc' => __('Profile your blog with Code Profiler.', 'code-profiler') ] );
277
278 // =====================================================================
279 // EOF
280