P3 (Plugin Performance Profiler) - Version 1.1.0

Version Description

Several usability enhancements and bugfixes.

Download this release

Release Info

Developer StarfieldTech
Plugin Icon wp plugin P3 (Plugin Performance Profiler)
Version 1.1.0
Comparing to
See all releases

Code changes from version 1.0.5 to 1.1.0

class.p3-profile-reader.php CHANGED
@@ -104,6 +104,12 @@ if ( !defined('P3_PATH') )
104
  */
105
  public $plugin_times = array();
106
 
 
 
 
 
 
 
107
  /**
108
  * Averaged values for the report
109
  * @var array
@@ -129,6 +135,12 @@ if ( !defined('P3_PATH') )
129
  * @var array
130
  */
131
  private $_data = array();
 
 
 
 
 
 
132
 
133
  /**
134
  * Constructor
@@ -161,6 +173,9 @@ if ( !defined('P3_PATH') )
161
  // Close the file
162
  fclose( $fp );
163
 
 
 
 
164
  // Parse the data
165
  $this->_parse();
166
  }
@@ -170,6 +185,12 @@ if ( !defined('P3_PATH') )
170
  * @return void
171
  */
172
  private function _parse() {
 
 
 
 
 
 
173
  foreach ( $this->_data as $o ) {
174
  // Set report meta-data
175
  if ( empty( $this->report_date ) ) {
@@ -205,7 +226,7 @@ if ( !defined('P3_PATH') )
205
  $tmp = $this->plugin_times;
206
  $this->plugin_times = array();
207
  foreach ( $tmp as $k => $v ) {
208
- $k = ucwords( str_replace( array( '-', '_' ), ' ', $k ) );
209
  $this->plugin_times[$k] = $v / $this->visits;
210
  }
211
 
@@ -215,6 +236,15 @@ if ( !defined('P3_PATH') )
215
 
216
  // Calculate the averages
217
  $this->_get_averages();
 
 
 
 
 
 
 
 
 
218
  }
219
 
220
  /**
@@ -261,7 +291,7 @@ if ( !defined('P3_PATH') )
261
  'breakdown' => array()
262
  );
263
  foreach ( $o->runtime->breakdown as $k => $v ) {
264
- $name = ucwords( str_replace( array( '-', '_' ), ' ', $k ) );
265
  if ( !array_key_exists( $name, $tmp['breakdown'] ) ) {
266
  $tmp['breakdown'][$name] = 0;
267
  }
@@ -271,4 +301,57 @@ if ( !defined('P3_PATH') )
271
  }
272
  return $ret;
273
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
274
  }
104
  */
105
  public $plugin_times = array();
106
 
107
+ /**
108
+ * Theme name, as determined from the file path
109
+ * @var string
110
+ */
111
+ public $theme_name = '';
112
+
113
  /**
114
  * Averaged values for the report
115
  * @var array
135
  * @var array
136
  */
137
  private $_data = array();
138
+
139
+ /**
140
+ * Scan name, correlates to a file name, with .json stripped off
141
+ * @var string
142
+ */
143
+ public $profile_name = '';
144
 
145
  /**
146
  * Constructor
173
  // Close the file
174
  fclose( $fp );
175
 
176
+ // Set the profile name
177
+ $this->profile_name = preg_replace( '/\.json$/', '', basename ( $file ) );
178
+
179
  // Parse the data
180
  $this->_parse();
181
  }
185
  * @return void
186
  */
187
  private function _parse() {
188
+
189
+ // Check for empty data
190
+ if ( empty( $this->_data ) ) {
191
+ throw new P3_Profile_No_Data_Exception('No visits in this profile. Check the IP address you\'re scanning from.');
192
+ }
193
+
194
  foreach ( $this->_data as $o ) {
195
  // Set report meta-data
196
  if ( empty( $this->report_date ) ) {
226
  $tmp = $this->plugin_times;
227
  $this->plugin_times = array();
228
  foreach ( $tmp as $k => $v ) {
229
+ $k = $this->_get_plugin_name( $k );
230
  $this->plugin_times[$k] = $v / $this->visits;
231
  }
232
 
236
 
237
  // Calculate the averages
238
  $this->_get_averages();
239
+
240
+ // Get theme name
241
+ if ( property_exists( $this->_data[0], 'theme_name') ) {
242
+ $this->theme_name = str_replace( realpath( WP_CONTENT_DIR . '/themes/' ), '', realpath( $this->_data[0]->theme_name ) );
243
+ $this->theme_name = preg_replace('|^[\\\/]+([^\\\/]+)[\\\/]+.*|', '$1', $this->theme_name);
244
+ $this->theme_name = $this->_get_theme_name( $this->theme_name );
245
+ } else {
246
+ $this->theme_name = 'unknown';
247
+ }
248
  }
249
 
250
  /**
291
  'breakdown' => array()
292
  );
293
  foreach ( $o->runtime->breakdown as $k => $v ) {
294
+ $name = $this->_get_plugin_name( $k );
295
  if ( !array_key_exists( $name, $tmp['breakdown'] ) ) {
296
  $tmp['breakdown'][$name] = 0;
297
  }
301
  }
302
  return $ret;
303
  }
304
+
305
+ /**
306
+ * Translate a plugin name
307
+ * Uses get_plugin_data if available.
308
+ * @param string $plugin Plugin name (possible paths will be guessed)
309
+ * @return string
310
+ */
311
+ private function _get_plugin_name( $plugin ) {
312
+ if ( function_exists( 'get_plugin_data' ) ) {
313
+ $plugin_info = array();
314
+ $possible_paths = array(
315
+ WP_PLUGIN_DIR . "/$plugin.php",
316
+ WP_PLUGIN_DIR . "/$plugin/$plugin.php",
317
+ WPMU_PLUGIN_DIR . "/$plugin.php"
318
+ );
319
+ foreach ( $possible_paths as $path ) {
320
+ if ( file_exists( $path ) ) {
321
+ $plugin_info = get_plugin_data( $path );
322
+ if ( !empty( $plugin_info ) && !empty( $plugin_info['Name'] ) ) {
323
+ return $plugin_info['Name'];
324
+ }
325
+ }
326
+ }
327
+ }
328
+ return $this->_format_name( $plugin );
329
+ }
330
+
331
+ /**
332
+ * Translate a theme name
333
+ * Uses get_theme_data if available.
334
+ * @param string $plugin Theme name (possible path will be guessed)
335
+ * @return string
336
+ */
337
+ private function _get_theme_name( $theme ) {
338
+ if ( function_exists( 'get_theme_data' ) ) {
339
+ $theme_info = get_theme_data( WP_CONTENT_DIR . '/themes/' . $theme . '/style.css' );
340
+ if ( !empty( $theme_info ) && !empty( $theme_info['Name'] ) ) {
341
+ return $theme_info['Name'];
342
+ }
343
+ }
344
+ return $this->_format_name( $theme );
345
+ }
346
+
347
+ /**
348
+ * Format plugin / theme name. This is only to be used if
349
+ * get_plugin_data() / get_theme_data() aren't available or if the
350
+ * original files are missing
351
+ * @param string $name
352
+ * @return string
353
+ */
354
+ private function _format_name( $name ) {
355
+ return ucwords( str_replace( array( '-', '_' ), ' ', $name ) );
356
+ }
357
  }
class.p3-profile-table.php CHANGED
@@ -59,7 +59,7 @@ class P3_Profile_Table extends WP_List_Table {
59
  $total_items = count( $data );
60
 
61
  // Carve out only the visible dataset
62
- $data = array_slice( $data, $current_page - 1 * $per_page, $per_page );
63
  $this->items = $data;
64
 
65
  // Set up the paginator
@@ -168,10 +168,11 @@ class P3_Profile_Table extends WP_List_Table {
168
  array(
169
  'p3_action' => 'view-scan',
170
  'name' => $key,
 
171
  )
172
  );
173
  return <<<EOD
174
- <a href="$url"><strong>$display</strong></a>
175
  <div class="row-actions-visible">
176
  <span class="view">
177
  <a href="$url" data-name="$key" title="View the results of this scan" class="view-results">View</a> |
59
  $total_items = count( $data );
60
 
61
  // Carve out only the visible dataset
62
+ $data = array_slice( $data, ( $current_page - 1 ) * $per_page, $per_page );
63
  $this->items = $data;
64
 
65
  // Set up the paginator
168
  array(
169
  'p3_action' => 'view-scan',
170
  'name' => $key,
171
+ 'current_scan' => null,
172
  )
173
  );
174
  return <<<EOD
175
+ <a href="$url" title="View the results of this scan"><strong>$display</strong></a>
176
  <div class="row-actions-visible">
177
  <span class="view">
178
  <a href="$url" data-name="$key" title="View the results of this scan" class="view-results">View</a> |
class.p3-profiler.php CHANGED
@@ -130,7 +130,7 @@ class P3_Profiler {
130
  }
131
  $found = false;
132
  foreach ( (array) $p3_json as $k => $v ) {
133
- if ( 0 === strpos( $_SERVER['REQUEST_URI'], $v->site_url ) && preg_match( '/' . preg_quote( $v->ip ) . '/', $this->get_ip() ) ) {
134
  $found = true;
135
  break;
136
  }
@@ -346,6 +346,10 @@ class P3_Profiler {
346
  // timing plugins over themes, and thems over the core.
347
  } elseif ( FALSE !== $is_a_theme ) {
348
  $this->_last_call_category = self::CATEGORY_THEME;
 
 
 
 
349
  // We must be in the core
350
  } else {
351
  $this->_last_call_category = self::CATEGORY_CORE;
130
  }
131
  $found = false;
132
  foreach ( (array) $p3_json as $k => $v ) {
133
+ if ( 0 === strpos( $_SERVER['REQUEST_URI'], $v->site_url ) && preg_match( '/' . $v->ip . '/', $this->get_ip() ) ) {
134
  $found = true;
135
  break;
136
  }
346
  // timing plugins over themes, and thems over the core.
347
  } elseif ( FALSE !== $is_a_theme ) {
348
  $this->_last_call_category = self::CATEGORY_THEME;
349
+ if ( !isset( $this->_profile['theme_name'] ) ) {
350
+ $this->_profile['theme_name'] = $file;
351
+ }
352
+
353
  // We must be in the core
354
  } else {
355
  $this->_last_call_category = self::CATEGORY_CORE;
css/p3.css CHANGED
@@ -7,6 +7,15 @@
7
  }
8
 
9
 
 
 
 
 
 
 
 
 
 
10
  /** The grey box behind the big buttons **/
11
  #p3-scan-form-wrapper {
12
  cursor: default;
@@ -17,6 +26,7 @@
17
  margin-top: 10px;
18
  }
19
 
 
20
  /** Big buttons **/
21
  .p3-big-button {
22
  margin: auto;
@@ -114,17 +124,17 @@ button.p3-cancel-button{
114
  /** Charts and graphs **/
115
  div.p3-plugin-graph {
116
  margin: 10px auto 20px auto;
117
- width: 620px;
118
  height: 320px;
119
  }
120
  div.p3-graph-holder {
121
- width: 500px;
122
  height: 300px;
123
  margin: auto;
124
  }
125
  div.p3-custom-legend {
126
  float: left;
127
- width: 120px;
128
  height: 280px;
129
  overflow: auto;
130
  }
@@ -281,7 +291,7 @@ div.p3-y-axis-label {
281
 
282
  position: relative;
283
  top: 135px;
284
- left: -20px;
285
 
286
  /* Safari */
287
  -webkit-transform: rotate(-90deg);
@@ -342,4 +352,4 @@ div.p3-question {
342
  div.p3-question h2.p3-help-question {
343
  margin-top: -15px;
344
  border-bottom: 1px solid #cccccc;
345
- }
7
  }
8
 
9
 
10
+ /** Scan label, far right of the nav buttons **/
11
+ #p3-scan-label {
12
+ float: right;
13
+ font-weight: bold;
14
+ margin-top: 7px;
15
+ margin-right: 12px;
16
+ }
17
+
18
+
19
  /** The grey box behind the big buttons **/
20
  #p3-scan-form-wrapper {
21
  cursor: default;
26
  margin-top: 10px;
27
  }
28
 
29
+
30
  /** Big buttons **/
31
  .p3-big-button {
32
  margin: auto;
124
  /** Charts and graphs **/
125
  div.p3-plugin-graph {
126
  margin: 10px auto 20px auto;
127
+ width: 750px;
128
  height: 320px;
129
  }
130
  div.p3-graph-holder {
131
+ width: 550px;
132
  height: 300px;
133
  margin: auto;
134
  }
135
  div.p3-custom-legend {
136
  float: left;
137
+ width: 200px;
138
  height: 280px;
139
  overflow: auto;
140
  }
291
 
292
  position: relative;
293
  top: 135px;
294
+ left: 10px;
295
 
296
  /* Safari */
297
  -webkit-transform: rotate(-90deg);
352
  div.p3-question h2.p3-help-question {
353
  margin-top: -15px;
354
  border-bottom: 1px solid #cccccc;
355
+ }
exceptions/.htaccess ADDED
@@ -0,0 +1 @@
 
1
+ Deny from all
exceptions/class.p3-profiler-no-data-exception.php ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( !defined('P3_PATH') )
4
+ die( 'Forbidden ');
5
+
6
+ /**
7
+ * Exception when no data is found
8
+ *
9
+ * @author GoDaddy.com
10
+ * @version 1.0
11
+ * @package P3_Profiler
12
+ */
13
+ class P3_Profile_No_Data_Exception extends Exception {}
exceptions/index.php ADDED
@@ -0,0 +1,2 @@
 
 
1
+ <?php header( 'Status: 404 Not found' ); ?>
2
+ Not found
p3-profiler.php CHANGED
@@ -4,7 +4,7 @@ Plugin Name: P3 (Plugin Performance Profiler)
4
  Plugin URI: http://support.godaddy.com/godaddy/wordpress-p3-plugin/
5
  Description: See which plugins are slowing down your site. Create a profile of your WordPress site's plugins' performance by measuring their impact on your site's load time.
6
  Author: GoDaddy.com
7
- Version: 1.0.5
8
  Author URI: http://www.godaddy.com/
9
  */
10
 
@@ -46,11 +46,15 @@ $p3_profiler_plugin = new P3_Profiler_Plugin();
46
  if ( is_admin() ) {
47
  // Show the 'Profiler' option under the 'Plugins' menu
48
  add_action( 'admin_menu', array( $p3_profiler_plugin, 'settings_menu' ) );
 
 
 
49
 
50
  // Ajax actions
51
  add_action( 'wp_ajax_p3_start_scan', array( $p3_profiler_plugin, 'ajax_start_scan' ) );
52
  add_action( 'wp_ajax_p3_stop_scan', array( $p3_profiler_plugin, 'ajax_stop_scan' ) );
53
  add_action( 'wp_ajax_p3_send_results', array( $p3_profiler_plugin, 'ajax_send_results' ) );
 
54
 
55
  // Show any notices
56
  add_action( 'admin_notices', array( $p3_profiler_plugin, 'show_notices' ) );
@@ -69,8 +73,8 @@ register_activation_hook( P3_PATH . DIRECTORY_SEPARATOR . 'p3-profiler.php', arr
69
  register_deactivation_hook( P3_PATH . DIRECTORY_SEPARATOR . 'p3-profiler.php', array( $p3_profiler_plugin, 'deactivate' ) );
70
  register_uninstall_hook( P3_PATH . DIRECTORY_SEPARATOR . 'p3-profiler.php', array( 'P3_Profiler_Plugin', 'uninstall' ) );
71
  if ( function_exists( 'is_multisite' ) && is_multisite() ) {
72
- add_action( 'wpmu_add_blog', array( $p3_profiler_plugin, 'sync_profiles_folder' ) );
73
- add_action( 'wpmu_delete_blog', array( $p3_profiler_plugin, 'sync_profiles_folder' ) );
74
  }
75
 
76
  /**
@@ -95,7 +99,7 @@ class P3_Profiler_Plugin {
95
  * @return void
96
  */
97
  public function remove_admin_bar() {
98
- if ( !is_admin() ) {
99
  remove_action( 'wp_footer', 'wp_admin_bar_render', 1000 );
100
  if ( true === force_ssl_admin() ) {
101
  add_filter( 'site_url', array( $this, '_fix_url' ) );
@@ -156,6 +160,9 @@ class P3_Profiler_Plugin {
156
  include_once P3_PATH . '/class.p3-profile-table-sorter.php';
157
  include_once P3_PATH . '/class.p3-profile-table.php';
158
  include_once P3_PATH . '/class.p3-profile-reader.php';
 
 
 
159
  }
160
 
161
  /**
@@ -346,7 +353,7 @@ class P3_Profiler_Plugin {
346
 
347
  // Add the entry ( multisite installs can run more than one concurrent profile )
348
  $json[] = array(
349
- 'ip' => $_POST['p3_ip'],
350
  'disable_opcode_cache' => ( 'true' == $_POST['p3_disable_opcode_cache'] ),
351
  'site_url' => $site_url,
352
  'name' => $filename,
@@ -418,6 +425,25 @@ class P3_Profiler_Plugin {
418
  }
419
  }
420
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
421
 
422
  /**************************************************************/
423
  /** EMAIL RESULTS **/
@@ -530,7 +556,7 @@ class P3_Profiler_Plugin {
530
  // Loop through the files, get the path and the last modified time
531
  $files = array();
532
  while ( false !== ( $file = readdir( $dir ) ) ) {
533
- if ( '.json' == substr( $file, -5 ) ) {
534
  $files[filemtime( P3_PROFILES_PATH . "/$file" )] = P3_PROFILES_PATH . "/$file";
535
  }
536
  }
@@ -550,9 +576,10 @@ class P3_Profiler_Plugin {
550
  * Add a notices
551
  * @uses transients
552
  * @param string $notice
 
553
  * @return void
554
  */
555
- public function add_notice( $notice ) {
556
 
557
  // Get any notices on the stack
558
  $notices = get_transient( 'p3_notices' );
@@ -561,7 +588,10 @@ class P3_Profiler_Plugin {
561
  }
562
 
563
  // Add the notice to the stack
564
- $notices[] = $notice;
 
 
 
565
 
566
  // Save the stack
567
  set_transient( 'p3_notices', $notices );
@@ -583,7 +613,7 @@ class P3_Profiler_Plugin {
583
  if ( !empty( $notices ) ) {
584
  $notices = array_unique( $notices );
585
  foreach ( $notices as $notice ) {
586
- echo '<div class="updated"><p>' . htmlentities( $notice ) . '</p></div>';
587
  }
588
  }
589
  set_transient( 'p3_notices', array() );
@@ -623,7 +653,7 @@ class P3_Profiler_Plugin {
623
  // .htaccess for mod_php
624
  if ( 'apache2handler' == $sapi ) {
625
  insert_with_markers(
626
- P3_PATH . '/../../../.htaccess',
627
  'p3-profiler',
628
  array( 'php_value auto_prepend_file "' . P3_PATH . DIRECTORY_SEPARATOR . 'start-profile.php"' )
629
  );
@@ -631,19 +661,16 @@ class P3_Profiler_Plugin {
631
 
632
  // Always try to create the mu-plugin loader in case either of the above methods fail
633
 
634
- // mu-plugins doesn't exist
635
- if ( !file_exists( P3_PATH . '/../../mu-plugins/' ) && is_writable( P3_PATH . '/../../' ) ) {
636
- $flag = wp_mkdir_p( P3_PATH . '/../../mu-plugins/' );
637
  }
638
- if ( file_exists( P3_PATH . '/../../mu-plugins/' ) && is_writable( P3_PATH . '/../../mu-plugins' ) ) {
639
  file_put_contents(
640
- P3_PATH . '/../../mu-plugins/p3-profiler.php',
641
  '<' . "?php // Start profiling\nrequire_once( realpath( dirname( __FILE__ ) ) . '/../plugins/p3-profiler/start-profile.php' ); ?" . '>'
642
  );
643
  }
644
-
645
- // Create the profiles folder
646
- $this->sync_profiles_folder();
647
  }
648
 
649
  /**
@@ -681,76 +708,27 @@ class P3_Profiler_Plugin {
681
 
682
  /**
683
  * Deactivation hook
684
- * Uninstall the profiler loader
685
  * @return void
686
  */
687
  public function deactivate() {
688
 
689
  // Remove any .htaccess modifications
690
- $file = P3_PATH . '/../../../.htaccess';
691
  if ( file_exists( $file ) && array() !== extract_from_markers( $file, 'p3-profiler' ) ) {
692
  insert_with_markers( $file, 'p3-profiler', array( '# removed during uninstall' ) );
693
  }
694
 
695
  // Remove mu-plugin
696
- if ( file_exists( P3_PATH . '/../../mu-plugins/p3-profiler.php' ) ) {
697
- if ( is_writable( P3_PATH . '/../../mu-plugins/p3-profiler.php' ) ) {
698
  // Some servers give write permission, but not delete permission. Empty the file out, first, then try to delete it.
699
- file_put_contents( P3_PATH . '/../../mu-plugins/p3-profiler.php', '' );
700
- unlink( P3_PATH . '/../../mu-plugins/p3-profiler.php' );
701
  }
702
  }
703
  }
704
 
705
- /**
706
- * Sync profiles folder
707
- * Call whenever a blog is added / removed
708
- * @return void
709
- */
710
- public function sync_profiles_folder() {
711
-
712
- // Base blog profiles folder
713
- $uploads_dir = wp_upload_dir();
714
- $folder = $uploads_dir['basedir'] . DIRECTORY_SEPARATOR . 'profiles';
715
- $this->_make_profiles_folder( $folder );
716
-
717
- // Only for multisite
718
- if ( !function_exists( 'is_multisite' ) || !is_multisite() ) {
719
- return;
720
- }
721
-
722
- // List profiles/<blog id> folders
723
- $folders = array();
724
- $dir = opendir( $folder );
725
- while ( ( $file = readdir( $dir ) ) !== false ) {
726
- if ( $file != '.' && $file != '..' && is_dir( "$folder/$file" ) && is_numeric( $file ) ) {
727
- $folders[] = $file;
728
- }
729
- }
730
- closedir( $dir );
731
-
732
- // List blogs
733
- $blogs = array();
734
- $blogs = get_blog_list( 0, 'all' );
735
- foreach ( $blogs as $blog ) {
736
- $blogs[] = $blog['blog_id'];
737
- }
738
-
739
- // Folders without a blog
740
- foreach ( array_diff( $folders, $blogs ) as $id ) {
741
- $this->_delete_profiles_folder( $folder . DIRECTORY_SEPARATOR . $id );
742
- }
743
-
744
- // Blogs without a folder
745
- foreach ( array_diff( $blogs, $folders ) as $id ) {
746
- switch_to_blog( $id );
747
- $uploads_dir = wp_upload_dir();
748
- $folder = $uploads_dir['basedir'] . DIRECTORY_SEPARATOR . 'profiles';
749
- $this->_make_profiles_folder( $folder );
750
- restore_current_blog();
751
- }
752
- }
753
-
754
  /**
755
  * Uninstall hook
756
  * Remove profile data
@@ -770,10 +748,22 @@ class P3_Profiler_Plugin {
770
  $uploads_dir = wp_upload_dir();
771
  $folder = $uploads_dir['basedir'] . DIRECTORY_SEPARATOR . 'profiles' . DIRECTORY_SEPARATOR;
772
  $me->_delete_profiles_folder( $folder );
 
 
 
 
 
 
773
  }
774
  restore_current_blog();
775
  } else {
776
  $me->_delete_profiles_folder( P3_PROFILES_PATH );
 
 
 
 
 
 
777
  }
778
  }
779
 
@@ -811,4 +801,50 @@ class P3_Profiler_Plugin {
811
  $size /= pow( 1024, $pow );
812
  return round( $size, 0 ) . ' ' . $units[$pow];
813
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
814
  }
4
  Plugin URI: http://support.godaddy.com/godaddy/wordpress-p3-plugin/
5
  Description: See which plugins are slowing down your site. Create a profile of your WordPress site's plugins' performance by measuring their impact on your site's load time.
6
  Author: GoDaddy.com
7
+ Version: 1.1.0
8
  Author URI: http://www.godaddy.com/
9
  */
10
 
46
  if ( is_admin() ) {
47
  // Show the 'Profiler' option under the 'Plugins' menu
48
  add_action( 'admin_menu', array( $p3_profiler_plugin, 'settings_menu' ) );
49
+
50
+ // Upgrade routine
51
+ add_action( 'admin_init', array( $p3_profiler_plugin, 'upgrade' ) );
52
 
53
  // Ajax actions
54
  add_action( 'wp_ajax_p3_start_scan', array( $p3_profiler_plugin, 'ajax_start_scan' ) );
55
  add_action( 'wp_ajax_p3_stop_scan', array( $p3_profiler_plugin, 'ajax_stop_scan' ) );
56
  add_action( 'wp_ajax_p3_send_results', array( $p3_profiler_plugin, 'ajax_send_results' ) );
57
+ add_action( 'wp_ajax_p3_save_settings', array( $p3_profiler_plugin, 'ajax_save_settings' ) );
58
 
59
  // Show any notices
60
  add_action( 'admin_notices', array( $p3_profiler_plugin, 'show_notices' ) );
73
  register_deactivation_hook( P3_PATH . DIRECTORY_SEPARATOR . 'p3-profiler.php', array( $p3_profiler_plugin, 'deactivate' ) );
74
  register_uninstall_hook( P3_PATH . DIRECTORY_SEPARATOR . 'p3-profiler.php', array( 'P3_Profiler_Plugin', 'uninstall' ) );
75
  if ( function_exists( 'is_multisite' ) && is_multisite() ) {
76
+ add_action( 'wpmu_add_blog', array( $p3_profiler_plugin, 'add_blog' ) );
77
+ add_action( 'wpmu_delete_blog', array( $p3_profiler_plugin, 'delete_blog' ) );
78
  }
79
 
80
  /**
99
  * @return void
100
  */
101
  public function remove_admin_bar() {
102
+ if ( !is_admin() && is_user_logged_in() ) {
103
  remove_action( 'wp_footer', 'wp_admin_bar_render', 1000 );
104
  if ( true === force_ssl_admin() ) {
105
  add_filter( 'site_url', array( $this, '_fix_url' ) );
160
  include_once P3_PATH . '/class.p3-profile-table-sorter.php';
161
  include_once P3_PATH . '/class.p3-profile-table.php';
162
  include_once P3_PATH . '/class.p3-profile-reader.php';
163
+
164
+ // Load exceptions
165
+ include_once P3_PATH . '/exceptions/class.p3-profiler-no-data-exception.php';
166
  }
167
 
168
  /**
353
 
354
  // Add the entry ( multisite installs can run more than one concurrent profile )
355
  $json[] = array(
356
+ 'ip' => stripslashes( $_POST['p3_ip'] ),
357
  'disable_opcode_cache' => ( 'true' == $_POST['p3_disable_opcode_cache'] ),
358
  'site_url' => $site_url,
359
  'name' => $filename,
425
  }
426
  }
427
 
428
+ /**
429
+ * Save advanced settings
430
+ * @return void
431
+ */
432
+ public function ajax_save_settings() {
433
+
434
+ // Check nonce
435
+ if ( !wp_verify_nonce( $_POST ['p3_nonce'], 'p3_save_settings' ) ) {
436
+ wp_die( 'Invalid nonce' );
437
+ }
438
+
439
+ // Save the new options
440
+ update_option( 'p3-profiler_disable_opcode_cache', 'true' == $_POST['p3_disable_opcode_cache'] );
441
+ update_option( 'p3-profiler_use_current_ip', 'true' == $_POST['p3_use_current_ip'] );
442
+ update_option( 'p3-profiler_ip_address', $_POST['p3_ip_address'] );
443
+
444
+ die( '1' );
445
+ }
446
+
447
 
448
  /**************************************************************/
449
  /** EMAIL RESULTS **/
556
  // Loop through the files, get the path and the last modified time
557
  $files = array();
558
  while ( false !== ( $file = readdir( $dir ) ) ) {
559
+ if ( '.json' == substr( $file, -5 ) && filesize( P3_PROFILES_PATH . '/' . $file ) > 0 ) {
560
  $files[filemtime( P3_PROFILES_PATH . "/$file" )] = P3_PROFILES_PATH . "/$file";
561
  }
562
  }
576
  * Add a notices
577
  * @uses transients
578
  * @param string $notice
579
+ * @param bool $error Default false. If true, this is a red error. If false, this is a yellow notice.
580
  * @return void
581
  */
582
+ public function add_notice( $notice, $error = false ) {
583
 
584
  // Get any notices on the stack
585
  $notices = get_transient( 'p3_notices' );
588
  }
589
 
590
  // Add the notice to the stack
591
+ $notices[] = array(
592
+ 'msg' => $notice,
593
+ 'error' => $error,
594
+ );
595
 
596
  // Save the stack
597
  set_transient( 'p3_notices', $notices );
613
  if ( !empty( $notices ) ) {
614
  $notices = array_unique( $notices );
615
  foreach ( $notices as $notice ) {
616
+ echo '<div class="' . ( ( $notice['error'] ) ? 'error' : 'updated' ) . '"><p>' . htmlentities( $notice['msg'] ) . '</p></div>';
617
  }
618
  }
619
  set_transient( 'p3_notices', array() );
653
  // .htaccess for mod_php
654
  if ( 'apache2handler' == $sapi ) {
655
  insert_with_markers(
656
+ ABSPATH . '/.htaccess',
657
  'p3-profiler',
658
  array( 'php_value auto_prepend_file "' . P3_PATH . DIRECTORY_SEPARATOR . 'start-profile.php"' )
659
  );
661
 
662
  // Always try to create the mu-plugin loader in case either of the above methods fail
663
 
664
+ // mu-plugins doesn't exist
665
+ if ( !file_exists( WPMU_PLUGIN_DIR ) && is_writable( WPMU_PLUGIN_DIR . '/../' ) ) {
666
+ $flag = wp_mkdir_p( WPMU_PLUGIN_DIR );
667
  }
668
+ if ( file_exists( WPMU_PLUGIN_DIR ) && is_writable( WPMU_PLUGIN_DIR ) ) {
669
  file_put_contents(
670
+ WPMU_PLUGIN_DIR . '/p3-profiler.php',
671
  '<' . "?php // Start profiling\nrequire_once( realpath( dirname( __FILE__ ) ) . '/../plugins/p3-profiler/start-profile.php' ); ?" . '>'
672
  );
673
  }
 
 
 
674
  }
675
 
676
  /**
708
 
709
  /**
710
  * Deactivation hook
711
+ * Remove the profiler loader
712
  * @return void
713
  */
714
  public function deactivate() {
715
 
716
  // Remove any .htaccess modifications
717
+ $file = ABSPATH . '/.htaccess';
718
  if ( file_exists( $file ) && array() !== extract_from_markers( $file, 'p3-profiler' ) ) {
719
  insert_with_markers( $file, 'p3-profiler', array( '# removed during uninstall' ) );
720
  }
721
 
722
  // Remove mu-plugin
723
+ if ( file_exists( WPMU_PLUGIN_DIR . '/p3-profiler.php' ) ) {
724
+ if ( is_writable( WPMU_PLUGIN_DIR . '/p3-profiler.php' ) ) {
725
  // Some servers give write permission, but not delete permission. Empty the file out, first, then try to delete it.
726
+ file_put_contents( WPMU_PLUGIN_DIR . '/p3-profiler.php', '' );
727
+ unlink( WPMU_PLUGIN_DIR . '/p3-profiler.php' );
728
  }
729
  }
730
  }
731
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
732
  /**
733
  * Uninstall hook
734
  * Remove profile data
748
  $uploads_dir = wp_upload_dir();
749
  $folder = $uploads_dir['basedir'] . DIRECTORY_SEPARATOR . 'profiles' . DIRECTORY_SEPARATOR;
750
  $me->_delete_profiles_folder( $folder );
751
+
752
+ // Remove any options
753
+ delete_option( 'p3-profiler_disable_opcode_cache' );
754
+ delete_option( 'p3-profiler_use_current_ip' );
755
+ delete_option( 'p3-profiler_ip_address' );
756
+ delete_option( 'p3-profiler_version' );
757
  }
758
  restore_current_blog();
759
  } else {
760
  $me->_delete_profiles_folder( P3_PROFILES_PATH );
761
+
762
+ // Remove any options
763
+ delete_option( 'p3-profiler_disable_opcode_cache' );
764
+ delete_option( 'p3-profiler_use_current_ip' );
765
+ delete_option( 'p3-profiler_ip_address' );
766
+ delete_option( 'p3-profiler_version' );
767
  }
768
  }
769
 
801
  $size /= pow( 1024, $pow );
802
  return round( $size, 0 ) . ' ' . $units[$pow];
803
  }
804
+
805
+ /**
806
+ * Actions to take when a multisite blog is added
807
+ * @return void
808
+ */
809
+ public function add_blog() {
810
+ // Reserved for future use
811
+ }
812
+
813
+ /**
814
+ * Actions to take when a multisite blog is removed
815
+ * @return void
816
+ */
817
+ public function delete_blog() {
818
+ $uploads_dir = wp_upload_dir();
819
+ $folder = $uploads_dir['basedir'] . DIRECTORY_SEPARATOR . 'profiles' . DIRECTORY_SEPARATOR;
820
+ $this->_delete_profiles_folder( $folder );
821
+ delete_option( 'p3-profiler_disable_opcode_cache' );
822
+ delete_option( 'p3-profiler_use_current_ip' );
823
+ delete_option( 'p3-profiler_ip_address' );
824
+ delete_option( 'p3-profiler_version' );
825
+ }
826
+
827
+ /**
828
+ * Upgrade
829
+ * Check options, perform any necessary data conversions
830
+ * @return void
831
+ */
832
+ public function upgrade() {
833
+
834
+ // Get the current version
835
+ $version = get_option( 'p3-profiler_version' );
836
+
837
+ // Upgrading from < 1.1.0
838
+ if ( empty( $version ) || version_compare( $version, '1.1.0') < 0 ) {
839
+ update_option( 'p3-profiler_disable_opcode_cache', true );
840
+ update_option( 'p3-profiler_use_current_ip', true );
841
+ update_option( 'p3-profiler_ip_address', '' );
842
+ update_option( 'p3-profiler_version', '1.1.0' );
843
+ }
844
+
845
+ // Ensure the profiles folder is there
846
+ $uploads_dir = wp_upload_dir();
847
+ $folder = $uploads_dir['basedir'] . DIRECTORY_SEPARATOR . 'profiles';
848
+ $this->_make_profiles_folder( $folder );
849
+ }
850
  }
readme.txt CHANGED
@@ -3,14 +3,14 @@ Contributors: Godaddy, StarfieldTech
3
  Tags: debug, debugging, developer, development, performance, plugin, profiler, speed
4
  Requires at least: 3.3
5
  Tested up to: 3.3
6
- Stable tag: 1.0.5
7
 
8
  See which plugins are slowing down your site. This plugin creates a performance report for your site.
9
 
10
  == Description ==
11
  This plugin creates a profile of your WordPress site's plugins' performance by measuring their impact on your site's load time.  Often times, WordPress sites load slowly because of poorly configured plugins or because there are so many of them. By using the P3 plugin, you can narrow down anything causing slowness on your site.
12
 
13
- Requires Firefox, Chrome, Opera, Safari, or IE9 or later.
14
 
15
  == Screenshots ==
16
 
@@ -42,6 +42,9 @@ Manual installation:
42
 
43
  == Upgrade Notice ==
44
 
 
 
 
45
  = 1.0.5 =
46
  This version addresses a path disclosure issue. Users are encouraged to upgrade.
47
 
@@ -51,11 +54,34 @@ This version addresses a path disclosure issue. Users are encouraged to upgrade
51
 
52
  Warning messages like this: `Warning: usort() [function.usort]: Array was modified by the user comparison function` are due to a known php bug. See [php bug #50688](https://bugs.php.net/bug.php?id=50688) for more information. This warning does not affect the functionality of your site and it is not visible to your users.
53
 
 
 
 
 
54
  == Changelog ==
55
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
  = 1.0.5 =
57
  * Security - Fixed a path disclosure vulnerability
58
  * Security - sanitized user input before it gets back to the browser
 
59
 
60
  = 1.0.4 =
61
  * Bugfix - uninstalling the plugin when it hasn't been activated can result in an error message
@@ -85,4 +111,4 @@ Warning messages like this: `Warning: usort() [function.usort]: Array was modifi
85
  * Activate / deactivate hooks to try different loader methods so the profiler runs as early as possible
86
  * Uninstall hooks to clean up profiles
87
  * Hooks add/delete blog to clean up profiles
88
- * Send profile summary via e-mail
3
  Tags: debug, debugging, developer, development, performance, plugin, profiler, speed
4
  Requires at least: 3.3
5
  Tested up to: 3.3
6
+ Stable tag: 1.1.0
7
 
8
  See which plugins are slowing down your site. This plugin creates a performance report for your site.
9
 
10
  == Description ==
11
  This plugin creates a profile of your WordPress site's plugins' performance by measuring their impact on your site's load time.  Often times, WordPress sites load slowly because of poorly configured plugins or because there are so many of them. By using the P3 plugin, you can narrow down anything causing slowness on your site.
12
 
13
+ This plugin uses the canvas element for drawing charts and requires requires Firefox, Chrome, Opera, Safari, or IE9 or later. Will not work in IE8 or lower.
14
 
15
  == Screenshots ==
16
 
42
 
43
  == Upgrade Notice ==
44
 
45
+ = 1.1.0 =
46
+ Several usability enhancements and bugfixes.
47
+
48
  = 1.0.5 =
49
  This version addresses a path disclosure issue. Users are encouraged to upgrade.
50
 
54
 
55
  Warning messages like this: `Warning: usort() [function.usort]: Array was modified by the user comparison function` are due to a known php bug. See [php bug #50688](https://bugs.php.net/bug.php?id=50688) for more information. This warning does not affect the functionality of your site and it is not visible to your users.
56
 
57
+ = In the e-mail report, why is my theme detected as "unknown?" =
58
+
59
+ Previous version of the plugin (before 1.1.0) did not have theme name detection support. If you performed a scan with a previous version, then upgraded to 1.1.0+ to view the scan, the theme name will show as "unknown."
60
+
61
  == Changelog ==
62
 
63
+ = 1.1.0 =
64
+ * Including plugin usage percentage / seconds in e-mail report
65
+ * Including theme name in e-mail report. Profiles created in older versions will show "unknown"
66
+ * Grammar / wording changes
67
+ * Remembering "disable opcode cache" in options table
68
+ * New option for "use my IP." If this is set, the current user's IP address will be used, if not, the stored IP pattern will be used
69
+ * IP patterns will be stored as an option
70
+ * Fixed: IP patterns were incorrectly escaped
71
+ * Now displaying profile name in the top right
72
+ * If the profile didn't record any visits (e.g. wrong IP pattern) then an error will be displayed
73
+ * Fixing pagination on the history page
74
+ * Made the legends on the charts a bit wider for sites with a lot of plugins and plugins with long names
75
+ * Added the ability to toggle series on/off in the "detailed timeline" chart
76
+ * Removed network wide activation code - each site will be "activated" when the admin logs in
77
+ * Removed "sync all profile folders whenever a blog is added/deleted" code. Profile folders will be added when admins log in, removed when blogs are removed
78
+ * When uninstalling, all profile folders and options will be removed
79
+ * Using get_plugin_data() to get plugin names. If the plugin doesn't exist anymore, or there's a problem getting the plugin name, the old formatting code is used
80
+
81
  = 1.0.5 =
82
  * Security - Fixed a path disclosure vulnerability
83
  * Security - sanitized user input before it gets back to the browser
84
+ * Thanks to Julio Potier from [Boiteaweb.fr](http://www.boiteaweb.fr/)
85
 
86
  = 1.0.4 =
87
  * Bugfix - uninstalling the plugin when it hasn't been activated can result in an error message
111
  * Activate / deactivate hooks to try different loader methods so the profiler runs as early as possible
112
  * Uninstall hooks to clean up profiles
113
  * Hooks add/delete blog to clean up profiles
114
+ * Send profile summary via e-mail
start-profile.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  // If profiling hasn't started, start it
4
  if ( !isset( $GLOBALS['p3_profiler'] ) && basename( __FILE__ ) != basename( $_SERVER['SCRIPT_FILENAME'] ) ) {
5
- declare( ticks = 1 ); // Capture ever user function call
6
  include_once realpath( dirname( __FILE__ ) ) . '/class.p3-profiler.php';
7
  $GLOBALS['p3_profiler'] = new P3_Profiler(); // Go
8
  }
2
 
3
  // If profiling hasn't started, start it
4
  if ( !isset( $GLOBALS['p3_profiler'] ) && basename( __FILE__ ) != basename( $_SERVER['SCRIPT_FILENAME'] ) ) {
5
+ declare( ticks = 1 ); // Capture every user function call
6
  include_once realpath( dirname( __FILE__ ) ) . '/class.p3-profiler.php';
7
  $GLOBALS['p3_profiler'] = new P3_Profiler(); // Go
8
  }
templates/callouts.php CHANGED
@@ -159,6 +159,17 @@ if ( !defined('P3_PATH') )
159
  }
160
  };
161
 
 
 
 
 
 
 
 
 
 
 
 
162
 
163
  // Onload functionality
164
  jQuery( document ).ready( function( $) {
@@ -175,7 +186,7 @@ if ( !defined('P3_PATH') )
175
  'resizable' : false,
176
  'modal' : true,
177
  'width' : 450,
178
- 'height' : 255,
179
  'title' : "Advanced Settings",
180
  'buttons' :
181
  [
@@ -183,7 +194,21 @@ if ( !defined('P3_PATH') )
183
  text: 'OK',
184
  'class' : 'button-secondary',
185
  click: function() {
186
- $( this ).dialog( "close" );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
187
  }
188
  },
189
  {
@@ -352,7 +377,7 @@ if ( !defined('P3_PATH') )
352
  if ( response.indexOf( '.json' ) < 0 ) {
353
  alert( "There was an error processing your request. Please reload the page and try again. [" + response + "]");
354
  } else {
355
- location.href = "<?php echo add_query_arg( array( 'p3_action' => 'view-scan' ) ); ?>&name=" + response;
356
  }
357
  })
358
  $( "#p3-scanner-dialog" ).dialog( "close" );
@@ -396,7 +421,7 @@ if ( !defined('P3_PATH') )
396
  jQuery( "#p3-progress-dialog" ).dialog( "close" );
397
 
398
  // View the scan
399
- location.href = "<?php echo add_query_arg( array( 'p3_action' => 'view-scan' ) ); ?>&name=" + $( this ).attr( "data-scan-name" );
400
  });
401
  $( "#p3-view-incomplete-results-submit" ).click( function() {
402
  $( "#p3-view-results-submit" ).trigger( "click" );
@@ -417,6 +442,10 @@ if ( !defined('P3_PATH') )
417
  }
418
  });
419
 
 
 
 
 
420
  // Callouts
421
  $( "div.p3-callout-inner-wrapper" )
422
  .corner( "round 8px" )
@@ -464,7 +493,7 @@ if ( !defined('P3_PATH') )
464
  <td class="p3-callout">
465
  <div class="p3-callout-outer-wrapper qtip-tip" title="Total number of active plugins, including must-use plugins, on your site.">
466
  <div class="p3-callout-inner-wrapper">
467
- <div class="p3-callout-caption">Total plugins:</div>
468
  <div class="p3-callout-data">
469
  <?php
470
  // Get the total number of plugins
@@ -487,7 +516,7 @@ if ( !defined('P3_PATH') )
487
  <div class="p3-callout-outer-wrapper qtip-tip" title="Total number of seconds dedicated to plugin code per visit on your site."
488
  <?php if ( !empty( $scan ) ) { ?>title="From <?php echo basename( $scan ); ?><?php } ?>">
489
  <div class="p3-callout-inner-wrapper">
490
- <div class="p3-callout-caption">Plugin load time</div>
491
  <div class="p3-callout-data">
492
  <?php if ( null === $profile ) { ?>
493
  <span class="p3-faded-grey">n/a</span>
@@ -505,7 +534,7 @@ if ( !defined('P3_PATH') )
505
  <div class="p3-callout-outer-wrapper qtip-tip" title="Percent of load time on your site dedicated to plugin code."
506
  <?php if ( !empty( $scan ) ) { ?>title="From <?php echo basename( $scan ); ?><?php } ?>">
507
  <div class="p3-callout-inner-wrapper">
508
- <div class="p3-callout-caption">Plugin impact</div>
509
  <div class="p3-callout-data">
510
  <?php if ( null === $profile ) { ?>
511
  <span class="p3-faded-grey">n/a</span>
@@ -531,7 +560,7 @@ if ( !defined('P3_PATH') )
531
  <?php echo round( $profile->averages['queries'] ); ?>
532
  <?php } ?>
533
  </div>
534
- <div class="p3-callout-caption">Per visit</div>
535
  </div>
536
  </div>
537
  </td>
@@ -542,15 +571,17 @@ if ( !defined('P3_PATH') )
542
  <!-- Dialog for IP settings -->
543
  <div id="p3-ip-dialog" class="p3-dialog">
544
  <div>
545
- IP address or pattern:<br />
546
- <input type="text" id="p3-advanced-ip" style="width:90%;" size="35"
547
- value="<?php echo $GLOBALS['p3_profiler']->get_ip(); ?>" title="Enter IP address or regular expression pattern" />
 
 
548
  <br />
549
  <em class="p3-em">Example: 1.2.3.4 or ( 1.2.3.4|4.5.6.7 )</em>
550
  </div>
551
  <br />
552
  <div>
553
- <input type="checkbox" id="p3-disable-opcode-cache" checked="checked" />
554
  <label for="p3-disable-opcode-cache">Attempt to disable opcode caches <em>( recommended )</em></label>
555
  <br />
556
  <em class="p3-em">This can increase accuracy in plugin detection, but decrease accuracy in timing</em>
159
  }
160
  };
161
 
162
+ // Sync save settings
163
+ function p3_sync_advanced_settings() {
164
+ if ( jQuery( "#p3-use-current-ip" ).prop( "checked" ) ) {
165
+ jQuery( "#p3-advanced-ip" ).val( "<?php echo esc_js( $GLOBALS['p3_profiler']->get_ip() ); ?>" );
166
+ jQuery( "#p3-advanced-ip" ).prop( "disabled", true );
167
+ } else {
168
+ <?php $ip = get_option( 'p3-profiler_ip_address' ); if ( empty( $ip ) ) { $ip = $GLOBALS['p3_profiler']->get_ip(); } ?>
169
+ jQuery( "#p3-advanced-ip" ).val( "<?php echo esc_js( $ip ); ?>" );
170
+ jQuery( "#p3-advanced-ip" ).prop( "disabled", false );
171
+ }
172
+ }
173
 
174
  // Onload functionality
175
  jQuery( document ).ready( function( $) {
186
  'resizable' : false,
187
  'modal' : true,
188
  'width' : 450,
189
+ 'height' : 305,
190
  'title' : "Advanced Settings",
191
  'buttons' :
192
  [
194
  text: 'OK',
195
  'class' : 'button-secondary',
196
  click: function() {
197
+
198
+ // Save settings
199
+ data = {
200
+ 'action' : 'p3_save_settings',
201
+ 'p3_disable_opcode_cache' : $( '#p3-disable-opcode-cache' ).prop( 'checked' ),
202
+ 'p3_use_current_ip' : $( '#p3-use-current-ip' ).prop( 'checked' ),
203
+ 'p3_ip_address' : $( '#p3-advanced-ip' ).val(),
204
+ 'p3_nonce' : '<?php echo wp_create_nonce( 'p3_save_settings' ); ?>'
205
+ }
206
+ $.post( ajaxurl, data, function( response ) {
207
+ if ( 1 != response ) {
208
+ alert( "There was an error saving your settings. Please reload the page and try again. [" + response + "]");
209
+ }
210
+ $( "#p3-ip-dialog" ).dialog( "close" );
211
+ });
212
  }
213
  },
214
  {
377
  if ( response.indexOf( '.json' ) < 0 ) {
378
  alert( "There was an error processing your request. Please reload the page and try again. [" + response + "]");
379
  } else {
380
+ location.href = "<?php echo add_query_arg( array( 'p3_action' => 'current-scan', 'current_scan' => 1 ) ); ?>&name=" + response;
381
  }
382
  })
383
  $( "#p3-scanner-dialog" ).dialog( "close" );
421
  jQuery( "#p3-progress-dialog" ).dialog( "close" );
422
 
423
  // View the scan
424
+ location.href = "<?php echo add_query_arg( array( 'p3_action' => 'view-scan', 'current_scan' => '1' ) ); ?>&name=" + $( this ).attr( "data-scan-name" );
425
  });
426
  $( "#p3-view-incomplete-results-submit" ).click( function() {
427
  $( "#p3-view-results-submit" ).trigger( "click" );
442
  }
443
  });
444
 
445
+ // Enable / disable the IP text based on the "use current ip" checkbox
446
+ $( "#p3-use-current-ip").live( "click", p3_sync_advanced_settings );
447
+ p3_sync_advanced_settings();
448
+
449
  // Callouts
450
  $( "div.p3-callout-inner-wrapper" )
451
  .corner( "round 8px" )
493
  <td class="p3-callout">
494
  <div class="p3-callout-outer-wrapper qtip-tip" title="Total number of active plugins, including must-use plugins, on your site.">
495
  <div class="p3-callout-inner-wrapper">
496
+ <div class="p3-callout-caption">Total Plugins:</div>
497
  <div class="p3-callout-data">
498
  <?php
499
  // Get the total number of plugins
516
  <div class="p3-callout-outer-wrapper qtip-tip" title="Total number of seconds dedicated to plugin code per visit on your site."
517
  <?php if ( !empty( $scan ) ) { ?>title="From <?php echo basename( $scan ); ?><?php } ?>">
518
  <div class="p3-callout-inner-wrapper">
519
+ <div class="p3-callout-caption">Plugin Load Time</div>
520
  <div class="p3-callout-data">
521
  <?php if ( null === $profile ) { ?>
522
  <span class="p3-faded-grey">n/a</span>
534
  <div class="p3-callout-outer-wrapper qtip-tip" title="Percent of load time on your site dedicated to plugin code."
535
  <?php if ( !empty( $scan ) ) { ?>title="From <?php echo basename( $scan ); ?><?php } ?>">
536
  <div class="p3-callout-inner-wrapper">
537
+ <div class="p3-callout-caption">Plugin Impact</div>
538
  <div class="p3-callout-data">
539
  <?php if ( null === $profile ) { ?>
540
  <span class="p3-faded-grey">n/a</span>
560
  <?php echo round( $profile->averages['queries'] ); ?>
561
  <?php } ?>
562
  </div>
563
+ <div class="p3-callout-caption">per visit</div>
564
  </div>
565
  </div>
566
  </td>
571
  <!-- Dialog for IP settings -->
572
  <div id="p3-ip-dialog" class="p3-dialog">
573
  <div>
574
+ IP address or pattern:<br /><br />
575
+ <input type="checkbox" id="p3-use-current-ip" <?php if ( true == get_option( 'p3-profiler_use_current_ip' ) ) : ?>checked="checked"<?php endif; ?> />
576
+ <label for="p3-use-current-ip">Use my IP address</label>
577
+ <br />
578
+ <input type="text" id="p3-advanced-ip" style="width:90%;" size="35" value="" title="Enter IP address or regular expression pattern" />
579
  <br />
580
  <em class="p3-em">Example: 1.2.3.4 or ( 1.2.3.4|4.5.6.7 )</em>
581
  </div>
582
  <br />
583
  <div>
584
+ <input type="checkbox" id="p3-disable-opcode-cache" <?php if ( true == get_option( 'p3-profiler_disable_opcode_cache' ) ) : ?>checked="checked"<?php endif; ?> />
585
  <label for="p3-disable-opcode-cache">Attempt to disable opcode caches <em>( recommended )</em></label>
586
  <br />
587
  <em class="p3-em">This can increase accuracy in plugin detection, but decrease accuracy in timing</em>
templates/help.php CHANGED
@@ -206,7 +206,7 @@ if ( !defined('P3_PATH') )
206
  If a plugin shows as fast-slow-fast-slow-fast-slow, it could be caused as the plugin loads its main code, then a follow-up piece
207
  of code, like a piece of generated JavaScript.
208
  <br /><br />
209
- If a plugin is consistently shows slowness, you might want to contact the plugin author or try deactivating the plugin temporarily
210
  to see if it makes a difference on your site.
211
  </blockquote>
212
  </div>
@@ -290,27 +290,16 @@ if ( !defined('P3_PATH') )
290
  </blockquote>
291
  </div>
292
 
293
- <div class="p3-question">
294
- <h2 class="p3-help-question">What if I get a warning about usort()?</h2>
295
- <blockquote>
296
- Warning messages like this:
297
- <code>Warning: usort() [function.usort]: Array was modified by the user comparison function</code> are due
298
- to a known php bug. See <a href="https://bugs.php.net/bug.php?id=50688" target="_blank">php bug #50688</a>
299
- for more information. This warning does not affect the functionality of your site and it is not visible
300
- to your users.
301
- </blockquote>
302
- </div>
303
-
304
  <div class="p3-question">
305
  <h2 class="p3-help-question">My plugins don't seem to cause site slowness. Why is my site still slow?</h2>
306
  <blockquote>
307
  Your site can be slow for a number of reasons. Your site could have a lot of traffic, other sites on
308
  your server could have a lot of traffic, you could be referencing content from other sites that are slow,
309
- your internet connection could be slow, your server could be out of RAM, your site could be very image
310
  heavy, your site could require a lot of HTTP requests, etc. In short, a lot of factors can cause slowness
311
  on your site
312
  <br /><br />
313
- Your next stop should be to <a href="http://tools.pingdom.com/" target="_blank">Pingdom Tools</a>,
314
  <a href="http://webpagetest.org/" target="_blank">Webpage Test</a>, <a href="http://developer.yahoo.com/yslow/"
315
  target="_blank">YSlow</a>, <a href="https://developers.google.com/pagespeed/" target="_blank">Google PageSpeed</a>,
316
  and your browser's development tools like <a href="http://getfirebug.com/" target="_blank">Firebug</a> for Firefox,
@@ -323,6 +312,28 @@ if ( !defined('P3_PATH') )
323
  </blockquote>
324
  </div>
325
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
326
  <div class="p3-question">
327
  <h2 class="p3-help-question" style="border-bottom-width: 0px !important;">Glossary</h2>
328
  <blockquote>
@@ -446,7 +457,7 @@ if ( !defined('P3_PATH') )
446
  <tr>
447
  <td class="term"><strong>MySQL Queries</strong>
448
  <div id="mysql-queries-definition" style="display: none;" class="definition">
449
- The number of queries sent to the database. This reported by the WordPress function
450
  <a href="http://codex.wordpress.org/Function_Reference/get_num_queries"
451
  target="_new">get_num_queries()</a>. Fewer is better.
452
  </div>
206
  If a plugin shows as fast-slow-fast-slow-fast-slow, it could be caused as the plugin loads its main code, then a follow-up piece
207
  of code, like a piece of generated JavaScript.
208
  <br /><br />
209
+ If a plugin consistently shows slowness, you might want to contact the plugin author or try deactivating the plugin temporarily
210
  to see if it makes a difference on your site.
211
  </blockquote>
212
  </div>
290
  </blockquote>
291
  </div>
292
 
 
 
 
 
 
 
 
 
 
 
 
293
  <div class="p3-question">
294
  <h2 class="p3-help-question">My plugins don't seem to cause site slowness. Why is my site still slow?</h2>
295
  <blockquote>
296
  Your site can be slow for a number of reasons. Your site could have a lot of traffic, other sites on
297
  your server could have a lot of traffic, you could be referencing content from other sites that are slow,
298
+ your Internet connection could be slow, your server could be out of RAM, your site could be very image
299
  heavy, your site could require a lot of HTTP requests, etc. In short, a lot of factors can cause slowness
300
  on your site
301
  <br /><br />
302
+ Your next stop should be to use <a href="http://tools.pingdom.com/" target="_blank">Pingdom Tools</a>,
303
  <a href="http://webpagetest.org/" target="_blank">Webpage Test</a>, <a href="http://developer.yahoo.com/yslow/"
304
  target="_blank">YSlow</a>, <a href="https://developers.google.com/pagespeed/" target="_blank">Google PageSpeed</a>,
305
  and your browser's development tools like <a href="http://getfirebug.com/" target="_blank">Firebug</a> for Firefox,
312
  </blockquote>
313
  </div>
314
 
315
+
316
+ <div class="p3-question">
317
+ <h2 class="p3-help-question">What if I get a warning about usort()?</h2>
318
+ <blockquote>
319
+ Warning messages like this:
320
+ <code>Warning: usort() [function.usort]: Array was modified by the user comparison function</code> are due
321
+ to a known php bug. See <a href="https://bugs.php.net/bug.php?id=50688" target="_blank">php bug #50688</a>
322
+ for more information. This warning does not affect the functionality of your site and it is not visible
323
+ to your users.
324
+ </blockquote>
325
+ </div>
326
+
327
+ <div class="p3-question">
328
+ <h2 class="p3-help-question">Does this plugin increase memory usage on my site?</h2>
329
+ <blockquote>
330
+ When you run a performance scan on your site, the memory requirements go up during the scan. Accordingly, P3 sets your
331
+ <a href="http://www.php.net/manual/en/ini.core.php#ini.memory-limit" target="_blank">memory limit</a> to 128
332
+ MB and <a href="http://php.net/set_time_limit" target="_blank">request timeout</a> to 90 seconds during a
333
+ performance scan. These changes are not permanent and are only in effect when a performance scan is actively running.
334
+ </blockquote>
335
+ </div>
336
+
337
  <div class="p3-question">
338
  <h2 class="p3-help-question" style="border-bottom-width: 0px !important;">Glossary</h2>
339
  <blockquote>
457
  <tr>
458
  <td class="term"><strong>MySQL Queries</strong>
459
  <div id="mysql-queries-definition" style="display: none;" class="definition">
460
+ The number of queries sent to the database. This is reported by the WordPress function
461
  <a href="http://codex.wordpress.org/Function_Reference/get_num_queries"
462
  target="_new">get_num_queries()</a>. Fewer is better.
463
  </div>
templates/template.php CHANGED
@@ -5,8 +5,8 @@ $p3_action = '';
5
  if ( !empty( $_REQUEST['p3_action'] ) ) {
6
  $p3_action = $_REQUEST['p3_action'];
7
  }
8
- $scan = $this->get_latest_profile();
9
  if ( empty( $p3_action ) || 'current-scan' == $p3_action ) {
 
10
  $p3_action = 'current-scan';
11
  } elseif ( 'view-scan' == $p3_action && !empty( $_REQUEST['name'] ) ) {
12
  $scan = sanitize_file_name( basename( $_REQUEST['name'] ) );
@@ -18,24 +18,41 @@ if ( empty( $p3_action ) || 'current-scan' == $p3_action ) {
18
  $button_current_checked = '';
19
  $button_history_checked = '';
20
  $button_help_checked = '';
21
- if ( 'current-scan' == $p3_action ) {
22
  $button_current_checked = 'checked="checked"';
23
  } elseif ( 'help' == $p3_action || 'fix-flag-file' == $p3_action ) {
24
  $button_help_checked = 'checked="checked"';
25
  } else {
26
  $button_history_checked = 'checked="checked"';
27
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
  ?>
29
  <script type="text/javascript">
30
  jQuery( document ).ready( function( $) {
31
  $( "#button-current-scan" ).click( function() {
32
- location.href = "<?php echo add_query_arg( array( 'p3_action' => 'current-scan' ) ); ?>";
33
  });
34
  $( "#button-history-scans" ).click( function() {
35
- location.href = "<?php echo add_query_arg( array( 'p3_action' => 'list-scans' ) ); ?>";
36
  });
37
  $( "#button-help" ).click( function() {
38
- location.href = "<?php echo add_query_arg( array( 'p3_action' => 'help' ) ); ?>";
39
  })
40
  $( ".p3-button" ).button();
41
  $( "#p3-navbar" ).buttonset();
@@ -75,25 +92,16 @@ if ( 'current-scan' == $p3_action ) {
75
  <input type="radio" name="p3-nav" id="button-history-scans" <?php echo $button_history_checked; ?> />
76
  <label for="button-history-scans">History</label>
77
  <input type="radio" name="p3-nav" id="button-help" <?php echo $button_help_checked; ?> /><label for="button-help">Help</label>
 
 
 
 
 
 
78
  </div>
79
 
80
  <!-- Start / stop button and callouts -->
81
- <?php
82
-
83
- // If there's a scan, create a viewer object
84
- if ( !empty( $scan ) ) {
85
- try {
86
- $profile = new P3_Profile_Reader( $scan );
87
- } catch ( Exception $e ) {
88
- wp_die( '<div id="message" class="error"><p>Error reading scan</p></div>' );
89
- }
90
- } else {
91
- $profile = null;
92
- }
93
-
94
- // Show the callouts bar
95
- require_once P3_PATH . '/templates/callouts.php';
96
- ?>
97
 
98
  <!-- View scan or show a list of scans -->
99
  <?php if ( ( 'current-scan' == $p3_action && !empty( $scan ) ) || 'view-scan' == $p3_action ) { ?>
5
  if ( !empty( $_REQUEST['p3_action'] ) ) {
6
  $p3_action = $_REQUEST['p3_action'];
7
  }
 
8
  if ( empty( $p3_action ) || 'current-scan' == $p3_action ) {
9
+ $scan = $this->get_latest_profile();
10
  $p3_action = 'current-scan';
11
  } elseif ( 'view-scan' == $p3_action && !empty( $_REQUEST['name'] ) ) {
12
  $scan = sanitize_file_name( basename( $_REQUEST['name'] ) );
18
  $button_current_checked = '';
19
  $button_history_checked = '';
20
  $button_help_checked = '';
21
+ if ( 'current-scan' == $p3_action || !empty( $_REQUEST['current_scan'] ) ) {
22
  $button_current_checked = 'checked="checked"';
23
  } elseif ( 'help' == $p3_action || 'fix-flag-file' == $p3_action ) {
24
  $button_help_checked = 'checked="checked"';
25
  } else {
26
  $button_history_checked = 'checked="checked"';
27
  }
28
+
29
+ // If there's a scan, create a viewer object
30
+ if ( !empty( $scan ) ) {
31
+ try {
32
+ $profile = new P3_Profile_Reader( $scan );
33
+ } catch ( P3_Profile_No_Data_Exception $e ) {
34
+ echo '<div class="error"><p>' . $e->getMessage() . '</p></div>';
35
+ $scan = null;
36
+ $profile = null;
37
+ $p3_action = 'list-scans';
38
+ } catch ( Exception $e ) {
39
+ wp_die( '<div id="message" class="error"><p>Error reading scan</p></div>' );
40
+ }
41
+ } else {
42
+ $profile = null;
43
+ }
44
+
45
  ?>
46
  <script type="text/javascript">
47
  jQuery( document ).ready( function( $) {
48
  $( "#button-current-scan" ).click( function() {
49
+ location.href = "<?php echo add_query_arg( array( 'p3_action' => 'current-scan', 'name' => null, 'current_scan' => null ) ); ?>";
50
  });
51
  $( "#button-history-scans" ).click( function() {
52
+ location.href = "<?php echo add_query_arg( array( 'p3_action' => 'list-scans', 'name' => null, 'current_scan' => null ) ); ?>";
53
  });
54
  $( "#button-help" ).click( function() {
55
+ location.href = "<?php echo add_query_arg( array( 'p3_action' => 'help', 'name' => null, 'current_scan' => null ) ); ?>";
56
  })
57
  $( ".p3-button" ).button();
58
  $( "#p3-navbar" ).buttonset();
92
  <input type="radio" name="p3-nav" id="button-history-scans" <?php echo $button_history_checked; ?> />
93
  <label for="button-history-scans">History</label>
94
  <input type="radio" name="p3-nav" id="button-help" <?php echo $button_help_checked; ?> /><label for="button-help">Help</label>
95
+
96
+ <div id="p3-scan-label">
97
+ <?php if ( !empty( $profile ) ) : ?>
98
+ Scan name: <?php echo $profile->profile_name; ?>
99
+ <?php endif; ?>
100
+ </div>
101
  </div>
102
 
103
  <!-- Start / stop button and callouts -->
104
+ <?php require_once P3_PATH . '/templates/callouts.php'; ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
105
 
106
  <!-- View scan or show a list of scans -->
107
  <?php if ( ( 'current-scan' == $p3_action && !empty( $scan ) ) || 'view-scan' == $p3_action ) { ?>
templates/view-scan.php CHANGED
@@ -29,7 +29,6 @@ $component_runtime_chart_id = substr( md5( uniqid() ), -8 );
29
 
30
  // Set up the tabs
31
  jQuery( document ).ready( function( $) {
32
- $( "#p3-tabs" ).tabs();
33
  $( "#results-table tr:even" ).addClass( "even" );
34
  $( "#p3-email-sending-dialog" ).dialog({
35
  'autoOpen' : false,
@@ -41,6 +40,26 @@ $component_runtime_chart_id = substr( md5( uniqid() ), -8 );
41
  'height' : 120,
42
  'dialogClass' : 'noTitle'
43
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
  $( "#p3-email-results-dialog" ).dialog({
45
  'autoOpen' : false,
46
  'closeOnEscape' : true,
@@ -260,12 +279,12 @@ $component_runtime_chart_id = substr( md5( uniqid() ), -8 );
260
  });
261
 
262
  // zoom buttons
263
- $( '<div class="button" style="float: left; position: relative; left: 440px; top: -290px;">-</div>' )
264
  .appendTo( $( "#p3-holder_<?php echo $runtime_chart_id; ?>" ).parent() ).click( function ( e ) {
265
  e.preventDefault();
266
  chart_<?php echo $runtime_chart_id; ?>.zoomOut();
267
  });
268
- $( '<div class="button" style="float: left; position: relative; left: 440px; top: -290px;">+</div>' )
269
  .appendTo( $( "#p3-holder_<?php echo $runtime_chart_id; ?>" ).parent() ).click( function ( e ) {
270
  e.preventDefault();
271
  chart_<?php echo $runtime_chart_id; ?>.zoom();
@@ -346,12 +365,12 @@ $component_runtime_chart_id = substr( md5( uniqid() ), -8 );
346
  });
347
 
348
  // zoom buttons
349
- $( '<div class="button" style="float: left; position: relative; left: 440px; top: -290px;">-</div>' )
350
  .appendTo( $( "#p3-holder_<?php echo $query_chart_id; ?>" ).parent() ).click( function ( e ) {
351
  e.preventDefault();
352
  chart_<?php echo $query_chart_id; ?>.zoomOut();
353
  });
354
- $( '<div class="button" style="float: left; position: relative; left: 440px; top: -290px;">+</div>' )
355
  .appendTo( $( "#p3-holder_<?php echo $query_chart_id; ?>" ).parent() ).click( function ( e ) {
356
  e.preventDefault();
357
  chart_<?php echo $query_chart_id; ?>.zoom();
@@ -486,12 +505,12 @@ $component_runtime_chart_id = substr( md5( uniqid() ), -8 );
486
  });
487
 
488
  // zoom buttons
489
- $( '<div class="button" style="float: left; position: relative; left: 440px; top: -290px;">-</div>' )
490
  .appendTo( $( "#p3-holder_<?php echo $component_breakdown_chart_id; ?>" ).parent() ).click( function ( e ) {
491
  e.preventDefault();
492
  chart_<?php echo $component_breakdown_chart_id; ?>.zoomOut();
493
  });
494
- $( '<div class="button" style="float: left; position: relative; left: 440px; top: -290px;">+</div>' )
495
  .appendTo( $( "#p3-holder_<?php echo $component_breakdown_chart_id; ?>" ).parent() ).click( function ( e ) {
496
  e.preventDefault();
497
  chart_<?php echo $component_breakdown_chart_id; ?>.zoom();
@@ -547,32 +566,80 @@ $component_runtime_chart_id = substr( md5( uniqid() ), -8 );
547
  <?php } ?>
548
  <?php } ?>
549
  ];
550
- jQuery( document ).ready( function( $) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
551
  chart_<?php echo $component_runtime_chart_id; ?> = $.plot(
552
  $( "#p3-holder_<?php echo $component_runtime_chart_id; ?>" ),
553
  data_<?php echo $component_runtime_chart_id; ?>,
554
- {
555
- series: {
556
- lines: { show: true },
557
- points: { show: true }
558
- },
559
- grid: {
560
- hoverable: true,
561
- clickable: true
562
- },
563
- legend : {
564
- container: $( "#p3-legend_<?php echo $component_runtime_chart_id; ?>" )
565
- },
566
- zoom: {
567
- interactive: true
568
- },
569
- pan: {
570
- interactive: true
571
- },
572
- xaxis: {
573
- show: false
574
- }
575
- });
576
 
577
  $( "#p3-holder_<?php echo $component_runtime_chart_id; ?>" ).bind( "plothover", function ( event, pos, item ) {
578
  if ( item ) {
@@ -600,16 +667,26 @@ $component_runtime_chart_id = substr( md5( uniqid() ), -8 );
600
  });
601
 
602
  // zoom buttons
603
- $( '<div class="button" style="float: left; position: relative; left: 440px; top: -290px;">-</div>' )
604
  .appendTo( $( "#p3-holder_<?php echo $component_runtime_chart_id; ?>" ).parent() ).click( function ( e ) {
605
  e.preventDefault();
606
  chart_<?php echo $component_runtime_chart_id; ?>.zoomOut();
607
  });
608
- $( '<div class="button" style="float: left; position: relative; left: 440px; top: -290px;">+</div>' )
609
  .appendTo( $( "#p3-holder_<?php echo $component_runtime_chart_id; ?>" ).parent() ).click( function ( e ) {
610
  e.preventDefault();
611
  chart_<?php echo $component_runtime_chart_id; ?>.zoom();
612
  });
 
 
 
 
 
 
 
 
 
 
613
  });
614
 
615
  </script>
@@ -635,7 +712,7 @@ $component_runtime_chart_id = substr( md5( uniqid() ), -8 );
635
  </div>
636
  </td>
637
  <td rowspan="2">
638
- <div class="p3-line p3-graph-holder" id="p3-holder_<?php echo $component_breakdown_chart_id; ?>"></div>
639
  </td>
640
  <td>
641
  <h3>Legend</h3>
@@ -661,11 +738,11 @@ $component_runtime_chart_id = substr( md5( uniqid() ), -8 );
661
  <!-- Plugin pie chart div -->
662
  <div id="p3-tabs-1">
663
  <h2>Runtime by Plugin</h2>
664
- <div class="p3-plugin-graph">
665
  <table>
666
  <tr>
667
  <td rowspan="2">
668
- <div style="width: 370px;" class="p3-line p3-graph-holder" id="p3-holder_<?php echo $pie_chart_id; ?>"></div>
669
  </td>
670
  <td>
671
  <h3>Legend</h3>
@@ -673,7 +750,7 @@ $component_runtime_chart_id = substr( md5( uniqid() ), -8 );
673
  </tr>
674
  <tr>
675
  <td>
676
- <div style="width: 250px;" class="p3-custom-legend" id="p3-legend_<?php echo $pie_chart_id;?>"></div>
677
  </td>
678
  </tr>
679
  </table>
@@ -692,7 +769,7 @@ $component_runtime_chart_id = substr( md5( uniqid() ), -8 );
692
  </div>
693
  </td>
694
  <td rowspan="2">
695
- <div class="p3-line p3-graph-holder" id="p3-holder_<?php echo $runtime_chart_id; ?>"></div>
696
  </td>
697
  <td>
698
  <h3>Legend</h3>
@@ -727,7 +804,7 @@ $component_runtime_chart_id = substr( md5( uniqid() ), -8 );
727
  </div>
728
  </td>
729
  <td rowspan="2">
730
- <div class="p3-line p3-graph-holder" id="p3-holder_<?php echo $query_chart_id; ?>"></div>
731
  </td>
732
  <td>
733
  <h3>Legend</h3>
@@ -762,7 +839,7 @@ $component_runtime_chart_id = substr( md5( uniqid() ), -8 );
762
  </div>
763
  </td>
764
  <td rowspan="2">
765
- <div class="p3-line p3-graph-holder" id="p3-holder_<?php echo $component_runtime_chart_id; ?>"></div>
766
  </td>
767
  <td>
768
  <h3>Legend</h3>
@@ -903,7 +980,7 @@ $component_runtime_chart_id = substr( md5( uniqid() ), -8 );
903
  </td>
904
  </tr>
905
  <tr>
906
- <td class="qtip-tip" title="The count of queries sent to the database. This reported by the WordPress function
907
  get_num_queries(). Lower is better.">
908
  <strong>MySQL Queries: </strong>
909
  </td>
@@ -959,6 +1036,7 @@ to share the results with you. Please take a look at the information below:</te
959
  echo "WordPress Plugin Profile Report\n";
960
  echo "===========================================\n";
961
  echo 'Report date: ' . date( 'D M j, Y', $profile->report_date ) . "\n";
 
962
  echo 'Pages browsed: ' . $profile->visits . "\n";
963
  echo 'Avg. load time: ' . sprintf( '%.4f', $profile->averages['site'] ) . " sec\n";
964
  echo 'Number of plugins: ' . count( $profile->detected_plugins ) . " \n";
@@ -972,7 +1050,9 @@ to share the results with you. Please take a look at the information below:</te
972
  echo 'Margin of error : ' . sprintf( '%.4f', $profile->averages['drift'] ) . " sec\n";
973
  echo "\nPlugin list:\n";
974
  echo "===========================================\n";
975
- echo implode( "\n", $profile->detected_plugins ) . "\n";
 
 
976
  ?></textarea>
977
  </div>
978
  <input type="hidden" id="p3-email-results-scan" value="<?php echo basename( $scan ); ?>" />
@@ -993,3 +1073,9 @@ to share the results with you. Please take a look at the information below:</te
993
  <input type="checkbox" id="p3-email-sending-close-submit" checked="checked" /><label for="p3-email-sending-close-submit">Done</label>
994
  </div>
995
  </div>
 
 
 
 
 
 
29
 
30
  // Set up the tabs
31
  jQuery( document ).ready( function( $) {
 
32
  $( "#results-table tr:even" ).addClass( "even" );
33
  $( "#p3-email-sending-dialog" ).dialog({
34
  'autoOpen' : false,
40
  'height' : 120,
41
  'dialogClass' : 'noTitle'
42
  });
43
+ $( "#p3-detailed-series-toggle" ).dialog({
44
+ 'autoOpen' : false,
45
+ 'closeOnEscape' : true,
46
+ 'draggable' : false,
47
+ 'resizable' : false,
48
+ 'modal' : true,
49
+ 'width' : 400,
50
+ 'height' : 'auto',
51
+ 'title' : "Toggle Series",
52
+ 'buttons' :
53
+ [
54
+ {
55
+ text: 'Ok',
56
+ 'class' : 'button-secondary',
57
+ click: function() {
58
+ $(this).dialog( "close" );
59
+ }
60
+ }
61
+ ]
62
+ });
63
  $( "#p3-email-results-dialog" ).dialog({
64
  'autoOpen' : false,
65
  'closeOnEscape' : true,
279
  });
280
 
281
  // zoom buttons
282
+ $( '<div class="button" style="float: left; position: relative; left: 490px; top: -290px;">-</div>' )
283
  .appendTo( $( "#p3-holder_<?php echo $runtime_chart_id; ?>" ).parent() ).click( function ( e ) {
284
  e.preventDefault();
285
  chart_<?php echo $runtime_chart_id; ?>.zoomOut();
286
  });
287
+ $( '<div class="button" style="float: left; position: relative; left: 490px; top: -290px;">+</div>' )
288
  .appendTo( $( "#p3-holder_<?php echo $runtime_chart_id; ?>" ).parent() ).click( function ( e ) {
289
  e.preventDefault();
290
  chart_<?php echo $runtime_chart_id; ?>.zoom();
365
  });
366
 
367
  // zoom buttons
368
+ $( '<div class="button" style="float: left; position: relative; left: 490px; top: -290px;">-</div>' )
369
  .appendTo( $( "#p3-holder_<?php echo $query_chart_id; ?>" ).parent() ).click( function ( e ) {
370
  e.preventDefault();
371
  chart_<?php echo $query_chart_id; ?>.zoomOut();
372
  });
373
+ $( '<div class="button" style="float: left; position: relative; left: 490px; top: -290px;">+</div>' )
374
  .appendTo( $( "#p3-holder_<?php echo $query_chart_id; ?>" ).parent() ).click( function ( e ) {
375
  e.preventDefault();
376
  chart_<?php echo $query_chart_id; ?>.zoom();
505
  });
506
 
507
  // zoom buttons
508
+ $( '<div class="button" style="float: left; position: relative; left: 490px; top: -290px;">-</div>' )
509
  .appendTo( $( "#p3-holder_<?php echo $component_breakdown_chart_id; ?>" ).parent() ).click( function ( e ) {
510
  e.preventDefault();
511
  chart_<?php echo $component_breakdown_chart_id; ?>.zoomOut();
512
  });
513
+ $( '<div class="button" style="float: left; position: relative; left: 490px; top: -290px;">+</div>' )
514
  .appendTo( $( "#p3-holder_<?php echo $component_breakdown_chart_id; ?>" ).parent() ).click( function ( e ) {
515
  e.preventDefault();
516
  chart_<?php echo $component_breakdown_chart_id; ?>.zoom();
566
  <?php } ?>
567
  <?php } ?>
568
  ];
569
+
570
+ var detailed_timeline_options = {};
571
+
572
+ jQuery( document ).ready( function ( $ ) {
573
+ <?php if ( !empty( $profile ) && !empty( $profile->detected_plugins ) ) { ?>
574
+ jQuery( "#p3-detailed-series-toggle" ).append( '<div><label><input type="checkbox" checked="checked" class="p3-detailed-series-toggle" data-key="WP Core Time" />WP Core Time</label></div>' );
575
+ jQuery( "#p3-detailed-series-toggle" ).append( '<div><label><input type="checkbox" checked="checked" class="p3-detailed-series-toggle" data-key="Theme" />Theme</label></div>' );
576
+ <?php foreach ( $profile->detected_plugins as $plugin ) { ?>
577
+ jQuery( "#p3-detailed-series-toggle" ).append( '<div><label><input type="checkbox" checked="checked" class="p3-detailed-series-toggle" data-key="<?php echo $plugin; ?>" /><?php echo $plugin ;?></label></div>' );
578
+ <?php } ?>
579
+ <?php } ?>
580
+ jQuery( "input.p3-detailed-series-toggle" ).click( function() {
581
+ data = [];
582
+ keys = [];
583
+ jQuery( "input.p3-detailed-series-toggle:checked" ).each(function() {
584
+ keys.push( $( this ).attr( "data-key" ) );
585
+ });
586
+ for ( i = 0 ; i < keys.length ; i++ ) {
587
+ tmp = [];
588
+ for ( j = 0 ; j < data_<?php echo $component_runtime_chart_id; ?>.length ; j++ ) {
589
+ if ( keys[i] == data_<?php echo $component_runtime_chart_id; ?>[j]['label'] ) {
590
+ for ( k = 0 ; k < data_<?php echo $component_runtime_chart_id; ?>[j]['data'].length ; k++ ) {
591
+ tmp.push( data_<?php echo $component_runtime_chart_id; ?>[j]['data'][k] );
592
+ }
593
+ }
594
+ }
595
+ data.push( {
596
+ data: tmp,
597
+ label: keys[i]
598
+ } );
599
+ }
600
+ if ( data.length == 0 ) {
601
+ data = [
602
+ {
603
+ data: [],
604
+ label: 'No data'
605
+ }
606
+ ]
607
+ }
608
+ chart_<?php echo $component_runtime_chart_id; ?> = $.plot(
609
+ $( "#p3-holder_<?php echo $component_runtime_chart_id; ?>" ),
610
+ data,
611
+ detailed_timeline_options
612
+ );
613
+ });
614
+ });
615
+ jQuery( document ).ready( function( $ ) {
616
+ detailed_timeline_options = {
617
+ series: {
618
+ lines: { show: true },
619
+ points: { show: true }
620
+ },
621
+ grid: {
622
+ hoverable: true,
623
+ clickable: true
624
+ },
625
+ legend : {
626
+ container: jQuery( "#p3-legend_<?php echo $component_runtime_chart_id; ?>" )
627
+ },
628
+ zoom: {
629
+ interactive: true
630
+ },
631
+ pan: {
632
+ interactive: true
633
+ },
634
+ xaxis: {
635
+ show: false
636
+ }
637
+ }
638
  chart_<?php echo $component_runtime_chart_id; ?> = $.plot(
639
  $( "#p3-holder_<?php echo $component_runtime_chart_id; ?>" ),
640
  data_<?php echo $component_runtime_chart_id; ?>,
641
+ detailed_timeline_options
642
+ );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
643
 
644
  $( "#p3-holder_<?php echo $component_runtime_chart_id; ?>" ).bind( "plothover", function ( event, pos, item ) {
645
  if ( item ) {
667
  });
668
 
669
  // zoom buttons
670
+ $( '<div class="button" style="float: left; position: relative; left: 460px; top: -290px;">-</div>' )
671
  .appendTo( $( "#p3-holder_<?php echo $component_runtime_chart_id; ?>" ).parent() ).click( function ( e ) {
672
  e.preventDefault();
673
  chart_<?php echo $component_runtime_chart_id; ?>.zoomOut();
674
  });
675
+ $( '<div class="button" style="float: left; position: relative; left: 460px; top: -290px;">+</div>' )
676
  .appendTo( $( "#p3-holder_<?php echo $component_runtime_chart_id; ?>" ).parent() ).click( function ( e ) {
677
  e.preventDefault();
678
  chart_<?php echo $component_runtime_chart_id; ?>.zoom();
679
  });
680
+ $( '<div class="button" style="float: left; position: relative; left: 460px; top: -290px;"><input type="checkbox" checked="checked" style="padding: 0; margin: 0; width: 15px;" /></div>' )
681
+ .appendTo( $( "#p3-holder_<?php echo $component_runtime_chart_id; ?>" ).parent() ).click( function ( e ) {
682
+ e.preventDefault();
683
+ $( "#p3-detailed-series-toggle" ).dialog( "open" );
684
+ });
685
+
686
+ });
687
+
688
+ jQuery( document ).ready( function( $ ) {
689
+ $( "#p3-tabs" ).tabs();
690
  });
691
 
692
  </script>
712
  </div>
713
  </td>
714
  <td rowspan="2">
715
+ <div class="p3-graph-holder" id="p3-holder_<?php echo $component_breakdown_chart_id; ?>"></div>
716
  </td>
717
  <td>
718
  <h3>Legend</h3>
738
  <!-- Plugin pie chart div -->
739
  <div id="p3-tabs-1">
740
  <h2>Runtime by Plugin</h2>
741
+ <div class="p3-plugin-graph" style="width: 570px;">
742
  <table>
743
  <tr>
744
  <td rowspan="2">
745
+ <div style="width: 370px;" class="p3-graph-holder" id="p3-holder_<?php echo $pie_chart_id; ?>"></div>
746
  </td>
747
  <td>
748
  <h3>Legend</h3>
750
  </tr>
751
  <tr>
752
  <td>
753
+ <div class="p3-custom-legend" id="p3-legend_<?php echo $pie_chart_id;?>"></div>
754
  </td>
755
  </tr>
756
  </table>
769
  </div>
770
  </td>
771
  <td rowspan="2">
772
+ <div class="p3-graph-holder" id="p3-holder_<?php echo $runtime_chart_id; ?>"></div>
773
  </td>
774
  <td>
775
  <h3>Legend</h3>
804
  </div>
805
  </td>
806
  <td rowspan="2">
807
+ <div class="p3-graph-holder" id="p3-holder_<?php echo $query_chart_id; ?>"></div>
808
  </td>
809
  <td>
810
  <h3>Legend</h3>
839
  </div>
840
  </td>
841
  <td rowspan="2">
842
+ <div class="p3-graph-holder" id="p3-holder_<?php echo $component_runtime_chart_id; ?>"></div>
843
  </td>
844
  <td>
845
  <h3>Legend</h3>
980
  </td>
981
  </tr>
982
  <tr>
983
+ <td class="qtip-tip" title="The count of queries sent to the database. This is reported by the WordPress function
984
  get_num_queries(). Lower is better.">
985
  <strong>MySQL Queries: </strong>
986
  </td>
1036
  echo "WordPress Plugin Profile Report\n";
1037
  echo "===========================================\n";
1038
  echo 'Report date: ' . date( 'D M j, Y', $profile->report_date ) . "\n";
1039
+ echo 'Theme name: ' . $profile->theme_name . "\n";
1040
  echo 'Pages browsed: ' . $profile->visits . "\n";
1041
  echo 'Avg. load time: ' . sprintf( '%.4f', $profile->averages['site'] ) . " sec\n";
1042
  echo 'Number of plugins: ' . count( $profile->detected_plugins ) . " \n";
1050
  echo 'Margin of error : ' . sprintf( '%.4f', $profile->averages['drift'] ) . " sec\n";
1051
  echo "\nPlugin list:\n";
1052
  echo "===========================================\n";
1053
+ foreach ( $profile->plugin_times as $k => $v) {
1054
+ echo $k . ' - ' . sprintf('%.4f sec', $v) . ' - ' . sprintf( '%.2f%%', $v * 100 / array_sum( $profile->plugin_times ) ) . "\n";
1055
+ }
1056
  ?></textarea>
1057
  </div>
1058
  <input type="hidden" id="p3-email-results-scan" value="<?php echo basename( $scan ); ?>" />
1073
  <input type="checkbox" id="p3-email-sending-close-submit" checked="checked" /><label for="p3-email-sending-close-submit">Done</label>
1074
  </div>
1075
  </div>
1076
+
1077
+ <!-- Enable / disable series dialog -->
1078
+ <div id="p3-detailed-series-toggle" class="p3-dialog">
1079
+
1080
+ </div>
1081
+ </div>