Completed
Branch FET-9046-messages-queue (151284)
by
unknown
558:10 queued 542:05
created

EEH_Debug_Tools   D

Complexity

Total Complexity 83

Size/Duplication

Total Lines 436
Duplicated Lines 3.21 %

Coupling/Cohesion

Components 2
Dependencies 5
Metric Value
wmc 83
lcom 2
cbo 5
dl 14
loc 436
rs 4.8717

16 Methods

Rating   Name   Duplication   Size   Complexity  
A show_db_name() 0 5 4
A registered_filter_callbacks() 0 14 4
A start_timer() 0 3 1
A convert() 0 4 1
A instance() 0 7 2
B __construct() 0 18 7
B espresso_session_footer_dump() 0 9 8
B espresso_list_hooked_functions() 0 27 6
C stop_timer() 0 36 7
A measure_memory() 0 7 2
A show_times() 0 8 2
B ee_plugin_activation_errors() 0 22 5
A doing_it_wrong() 0 18 4
B log() 0 18 6
B strip_objects() 14 21 8
D printr() 0 40 16

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like EEH_Debug_Tools often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use EEH_Debug_Tools, and based on these observations, apply Extract Interface, too.

1
<?php if ( ! defined('EVENT_ESPRESSO_VERSION')) exit('No direct script access allowed');
2
/**
3
 * Class EEH_Debug_Tools
4
 *
5
 * @package 			Event Espresso
6
 * @subpackage 	core
7
 * @author 				Brent Christensen, Michael Nelson
8
 * @since 				4.0
9
 *
10
 */
11
class EEH_Debug_Tools{
12
13
	/**
14
	 * 	instance of the EEH_Autoloader object
15
	 *	@var 	$_instance
16
	 * 	@access 	private
17
	 */
18
	private static $_instance = NULL;
19
20
	/**
21
	 * array containing the start time for the timers
22
	 */
23
	private $_start_times;
24
	/**
25
	 * array containing all the timer'd times, which can be outputted via show_times()
26
	 */
27
	private $_times = array();
28
29
	/**
30
	 *
31
	 * @var array
32
	 */
33
	protected $_memory_usage_points = array();
34
35
36
37
	/**
38
	 *	@singleton method used to instantiate class object
39
	 *	@access public
40
	 *	@return EEH_Debug_Tools
41
	 */
42
	public static function instance() {
43
		// check if class object is instantiated, and instantiated properly
44
		if ( ! self::$_instance instanceof EEH_Debug_Tools ) {
45
			self::$_instance = new self();
46
		}
47
		return self::$_instance;
48
	}
49
50
51
52
	/**
53
	 *    class constructor
54
	 *
55
	 * @access    private
56
	 * @return \EEH_Debug_Tools
0 ignored issues
show
Comprehensibility Best Practice introduced by
Adding a @return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.

Adding a @return annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.

Please refer to the PHP core documentation on constructors.

Loading history...
57
	 */
58
	private function __construct() {
59
		// load Kint PHP debugging library
60
		if ( ! class_exists( 'Kint' ) &&  file_exists( EE_PLUGIN_DIR_PATH . 'tests' . DS . 'kint' . DS . 'Kint.class.php' )){
61
			// despite EE4 having a check for an existing copy of the Kint debugging class,
62
			// if another plugin was loaded AFTER EE4 and they did NOT perform a similar check,
63
			// then hilarity would ensue as PHP throws a "Cannot redeclare class Kint" error
64
			// so we've moved it to our test folder so that it is not included with production releases
65
			// plz use https://wordpress.org/plugins/kint-debugger/  if testing production versions of EE
66
			require_once( EE_PLUGIN_DIR_PATH . 'tests' . DS . 'kint' . DS . 'Kint.class.php' );
67
		}
68
		if ( ! defined('DOING_AJAX') || ! isset( $_REQUEST['noheader'] ) || $_REQUEST['noheader'] != 'true' || ! isset( $_REQUEST['TB_iframe'] )) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
69
			//add_action( 'shutdown', array($this,'espresso_session_footer_dump') );
70
		}
71
		$plugin = basename( EE_PLUGIN_DIR_PATH );
72
		add_action( "activate_{$plugin}", array( 'EEH_Debug_Tools', 'ee_plugin_activation_errors' ));
73
		add_action( 'activated_plugin', array( 'EEH_Debug_Tools', 'ee_plugin_activation_errors' ));
74
		add_action( 'shutdown', array( 'EEH_Debug_Tools', 'show_db_name' ));
75
	}
76
77
78
79
	/**
80
	 * 	show_db_name
81
	 *
82
	 * 	@return void
83
	 */
84
	public static function show_db_name() {
85
		if ( ! defined( 'DOING_AJAX' ) && ( defined( 'EE_ERROR_EMAILS' ) && EE_ERROR_EMAILS )) {
86
			echo '<p style="font-size:10px;font-weight:normal;color:#E76700;margin: 1em 2em; text-align: right;">DB_NAME: '. DB_NAME .'</p>';
87
		}
88
	}
89
90
91
92
	/**
93
	 * 	dump EE_Session object at bottom of page after everything else has happened
94
	 *
95
	 * 	@return void
96
	 */
97
	public function espresso_session_footer_dump() {
98
		if ( class_exists('Kint') && function_exists( 'wp_get_current_user' ) && current_user_can('update_core') && ( defined('WP_DEBUG') && WP_DEBUG ) &&  ! defined('DOING_AJAX') && class_exists( 'EE_Registry' )) {
99
			Kint::dump(  EE_Registry::instance()->SSN->id() );
100
			Kint::dump( EE_Registry::instance()->SSN );
101
			//			Kint::dump( EE_Registry::instance()->SSN->get_session_data('cart')->get_tickets() );
102
			$this->espresso_list_hooked_functions();
103
			$this->show_times();
104
		}
105
	}
106
107
108
109
	/**
110
	 *    List All Hooked Functions
111
	 *    to list all functions for a specific hook, add ee_list_hooks={hook-name} to URL
112
	 *    http://wp.smashingmagazine.com/2009/08/18/10-useful-wordpress-hook-hacks/
113
	 *
114
	 * @param bool $tag
115
	 * @return void
116
	 */
117
	public function espresso_list_hooked_functions( $tag=FALSE ){
118
		global $wp_filter;
119
		echo '<br/><br/><br/><h3>Hooked Functions</h3>';
120
		if ( $tag ) {
121
			$hook[$tag]=$wp_filter[$tag];
0 ignored issues
show
Coding Style Comprehensibility introduced by
$hook was never initialized. Although not strictly required by PHP, it is generally a good practice to add $hook = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
122
			if ( ! is_array( $hook[$tag] )) {
123
				trigger_error( "Nothing found for '$tag' hook", E_USER_WARNING );
124
				return;
125
			}
126
			echo '<h5>For Tag: '. $tag .'</h5>';
127
		}
128
		else {
129
			$hook=$wp_filter;
130
			ksort( $hook );
131
		}
132
		foreach( $hook as $tag => $priorities ) {
133
			echo "<br />&gt;&gt;&gt;&gt;&gt;\t<strong>$tag</strong><br />";
134
			ksort( $priorities );
135
			foreach( $priorities as $priority => $function ){
136
				echo $priority;
137
				foreach( $function as $name => $properties ) {
138
					echo "\t$name<br />";
139
				}
140
			}
141
		}
142
		return;
143
	}
144
145
146
147
	/**
148
	 *    registered_filter_callbacks
149
	 *
150
	 * @param string $hook_name
151
	 * @return array
152
	 */
153
	public static function registered_filter_callbacks( $hook_name = '' ) {
154
		$filters = array();
155
		global $wp_filter;
156
		if ( isset( $wp_filter[ $hook_name ] ) ) {
157
			$filters[ $hook_name ] = array();
158
			foreach ( $wp_filter[ $hook_name ] as $priority => $callbacks ) {
159
				$filters[ $hook_name ][ $priority ] = array();
160
				foreach ( $callbacks as $callback ) {
161
					$filters[ $hook_name ][ $priority ][] = $callback['function'];
162
				}
163
			}
164
		}
165
		return $filters;
166
	}
167
168
169
170
	/**
171
	 * 	start_timer
172
	 * @param null $timer_name
173
	 */
174
	public function start_timer( $timer_name = NULL ){
175
		$this->_start_times[$timer_name] = microtime( TRUE );
176
	}
177
178
179
180
	/**
181
	 * stop_timer
182
	 * @param string $timer_name
183
	 */
184
	public function stop_timer($timer_name = 'default'){
185
		if( isset( $this->_start_times[ $timer_name ] ) ){
186
			$start_time = $this->_start_times[ $timer_name ];
187
			unset( $this->_start_times[ $timer_name ] );
188
		}else{
189
			$start_time = array_pop( $this->_start_times );
190
		}
191
		$total_time = microtime( TRUE ) - $start_time;
192
		switch ( $total_time ) {
193
			case $total_time < 0.00001 :
194
				$color = '#8A549A';
195
				$bold = 'normal';
196
				break;
197
			case $total_time < 0.0001 :
198
				$color = '#00B1CA';
199
				$bold = 'normal';
200
				break;
201
			case $total_time < 0.001 :
202
				$color = '#70CC50';
203
				$bold = 'normal';
204
				break;
205
			case $total_time < 0.01 :
206
				$color = '#FCC600';
207
				$bold = 'bold';
208
				break;
209
			case $total_time < 0.1 :
210
				$color = '#E76700';
211
				$bold = 'bold';
212
				break;
213
			default :
214
				$color = '#E44064';
215
				$bold = 'bold';
216
				break;
217
		}
218
		$this->_times[] = '<hr /><div style="display: inline-block; min-width: 10px; margin:0 1em; color:'.$color.'; font-weight:'.$bold.'; font-size:1.2em;">' . number_format( $total_time, 8 ) . '</div> ' . $timer_name;
219
	}
220
	/**
221
	 * Measure the memory usage by PHP so far.
222
	 * @param string $label The label to show for this time eg "Start of calling Some_Class::some_function"
223
	 * @param boolean $output_now whether to echo now, or wait until EEH_Debug_Tools::show_times() is called
224
	 * @return void
225
	 */
226
	public function measure_memory( $label, $output_now = false ) {
227
		$memory_used = $this->convert( memory_get_peak_usage( true ) );
228
		$this->_memory_usage_points[ $label ] = $memory_used;
229
		if( $output_now ) {
230
			echo "\r\n<br>$label : $memory_used";
231
		}
232
	}
233
234
	/**
235
	 * Converts a measure of memory bytes into the most logical units (eg kb, mb, etc)
236
	 * @param int $size
237
	 * @return string
238
	 */
239
	public function convert( $size ) {
240
		$unit=array('b','kb','mb','gb','tb','pb');
241
		return @round($size/pow(1024,($i=floor(log($size,1024)))),2).' '.$unit[ absint( $i ) ];
242
	}
243
244
245
246
	/**
247
	 * show_times
248
	 * @param bool $output_now
249
	 * @return string
250
	 */
251
	public function show_times($output_now=true){
252
		$output = '<h2>Times:</h2>' . implode("<br>",$this->_times) . '<h2>Memory</h2>' . implode('<br>', $this->_memory_usage_points );
253
		if($output_now){
254
			echo $output;
255
			return '';
256
		}
257
		return $output;
258
	}
259
260
261
262
	/**
263
	 * 	captures plugin activation errors for debugging
264
	 *
265
	 * 	@return void
266
	 */
267
	public static function ee_plugin_activation_errors() {
268
		if ( WP_DEBUG ) {
269
			$activation_errors = ob_get_contents();
270
			if ( ! empty( $activation_errors ) ) {
271
				$activation_errors = date( 'Y-m-d H:i:s' ) . "\n" . $activation_errors;
272
			}
273
			espresso_load_required( 'EEH_File', EE_HELPERS . 'EEH_File.helper.php' );
274
			if ( class_exists( 'EEH_File' )) {
275
				try {
276
					EEH_File::ensure_file_exists_and_is_writable( EVENT_ESPRESSO_UPLOAD_DIR . 'logs' . DS . 'espresso_plugin_activation_errors.html' );
277
					EEH_File::write_to_file( EVENT_ESPRESSO_UPLOAD_DIR . 'logs' . DS . 'espresso_plugin_activation_errors.html', $activation_errors );
278
				} catch( EE_Error $e ){
279
					EE_Error::add_error( sprintf( __(  'The Event Espresso activation errors file could not be setup because: %s', 'event_espresso' ), $e->getMessage() ), __FILE__, __FUNCTION__, __LINE__ );
280
				}
281
			} else {
282
				// old school attempt
283
				file_put_contents( EVENT_ESPRESSO_UPLOAD_DIR . 'logs' . DS . 'espresso_plugin_activation_errors.html', $activation_errors );
284
			}
285
			$activation_errors = get_option( 'ee_plugin_activation_errors', '' ) . $activation_errors;
286
			update_option( 'ee_plugin_activation_errors', $activation_errors );
287
		}
288
	}
289
290
291
292
	/**
293
	 * This basically mimics the WordPress _doing_it_wrong() function except adds our own messaging etc.  Very useful for providing helpful messages to developers when the method of doing something has been deprecated, or we want to make sure they use something the right way.
294
	 *
295
	 * @access public
296
	 * @param  string $function The function that was called
297
	 * @param  string $message A message explaining what has been done incorrectly
298
	 * @param  string $version The version of Event Espresso where the error was added
299
	 * @param int     $error_type
300
	 * @uses trigger_error()
301
	 */
302
	public function doing_it_wrong( $function, $message, $version, $error_type = E_USER_NOTICE ) {
303
		do_action( 'AHEE__EEH_Debug_Tools__doing_it_wrong_run', $function, $message, $version);
304
		$version = is_null( $version ) ? '' : sprintf( __('(This message was added in version %s of Event Espresso.', 'event_espresso' ), $version );
305
		$error_message = sprintf( esc_html__('%1$s was called %2$sincorrectly%3$s. %4$s %5$s','event_espresso' ), $function, '<strong>', '</strong>', $message, $version );
306
307
		//don't trigger error if doing ajax, instead we'll add a transient EE_Error notice that in theory should show on the next request.
308
		if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
309
			$error_message .= ' ' . esc_html__( 'This is a doing_it_wrong message that was triggered during an ajax request.  The request params on this request were: ', 'event_espresso' );
310
			$error_message .= '<ul><li>';
311
			$error_message .= implode( '</li><li>', EE_Registry::instance()->REQ->params() );
312
			$error_message .= '</ul>';
313
			EE_Error::add_error( $error_message, 'debug::doing_it_wrong', $function, '42' );
314
			//now we set this on the transient so it shows up on the next request.
315
			EE_Error::get_notices( is_admin(), true );
316
		} else {
317
			trigger_error( $error_message, $error_type );
318
		}
319
	}
320
321
322
323
324
	/**
325
	 * Logger helpers
326
	 */
327
328
	/**
329
	 * debug
330
	 *
331
	 * @param string $class
332
	 * @param string $func
333
	 * @param string $line
334
	 * @param array $info
335
	 * @param bool $display_request
336
	 * @param string $debug_index
337
	 * @param string $debug_key
338
	 */
339
	public static function log( $class='', $func = '', $line = '', $info = array(), $display_request = false,  $debug_index = '', $debug_key = 'EE_DEBUG_SPCO' ) {
340
		if ( WP_DEBUG && false ) {
341
			$debug_key = $debug_key . '_' . EE_Session::instance()->id();
342
			$debug_data = get_option( $debug_key, array() );
343
			$default_data = array(
344
				$class => $func . '() : ' . $line,
345
				'REQ'  => $display_request ? $_REQUEST : '',
346
			);
347
			// don't serialize objects
348
			$info = self::strip_objects( $info );
349
			$index = ! empty( $debug_index ) ? $debug_index : 0;
350
			if ( ! isset( $debug_data[$index] ) ) {
351
				$debug_data[$index] = array();
352
			}
353
			$debug_data[$index][microtime()] = array_merge( $default_data, $info );
354
			update_option( $debug_key, $debug_data );
355
		}
356
	}
357
358
359
360
	/**
361
	 * strip_objects
362
	 *
363
	 * @param array $info
364
	 * @return array
365
	 */
366
	public static function strip_objects( $info = array() ) {
367
		foreach ( $info as $key => $value ) {
368
			if ( is_array( $value ) ) {
369
				$info[ $key ] = self::strip_objects( $value );
370 View Code Duplication
			} else if ( is_object( $value ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
371
				$object_class = get_class( $value );
372
				$info[ $object_class ] = array();
373
				$info[ $object_class ][ 'ID' ] = method_exists( $value, 'ID' ) ? $value->ID() : spl_object_hash( $value );
374
				if ( method_exists( $value, 'ID' ) ) {
375
					$info[ $object_class ][ 'ID' ] = $value->ID();
376
				}
377
				if ( method_exists( $value, 'status' ) ) {
378
					$info[ $object_class ][ 'status' ] = $value->status();
379
				} else if ( method_exists( $value, 'status_ID' ) ) {
380
					$info[ $object_class ][ 'status' ] = $value->status_ID();
381
				}
382
				unset( $info[ $key ] );
383
			}
384
		}
385
		return (array)$info;
386
	}
387
388
389
390
	/**
391
	 *    @ print_r an array
392
	 *    @ access public
393
	 *    @ return void
394
	 *
395
	 * @param mixed $var
396
	 * @param bool $var_name
397
	 * @param string $file
398
	 * @param int $line
399
	 * @param string $height
400
	 * @param bool $die
401
	 */
402
	public static function printr( $var, $var_name = false, $file = __FILE__, $line = __LINE__, $height = 'auto', $die = false ) {
403
		//$print_r = false;
404
		if ( is_object( $var ) ) {
405
			$var_name = ! $var_name ? 'object' : $var_name;
406
			//$print_r = true;
407
		} else if ( is_array( $var ) ) {
408
			$var_name = ! $var_name ? 'array' : $var_name;
409
			//$print_r = true;
410
		} else if ( is_numeric( $var ) ) {
411
			$var_name = ! $var_name ? 'numeric' : $var_name;
412
		} else if ( is_string( $var ) ) {
413
			$var_name = ! $var_name ? 'string' : $var_name;
414
		} else if ( is_null( $var ) ) {
415
			$var_name = ! $var_name ? 'null' : $var_name;
416
		} else {
417
			$var_name = ucwords( str_replace( array( '$', '_' ), array( '', ' ' ), $var_name ) );
418
		}
419
		$margin = is_admin() ? 'margin-left:180px;' : '';
420
		ob_start();
421
		echo '<pre style="display:block;width:100%;height:'.$height.';border:2px solid light-blue;'.$margin.'">';
422
		//$print_r ? print_r( $var ) : var_dump( $var );
423
		if ( is_string( $var ) && strpos( $file, $var_name ) !== false ) {
424
			echo '<h3 style="color:#999;line-height:.9em;margin: 1em 0 0;"><span style="color:#2EA2CC">' . $var_name
425
				 . '</span>::<span style="color:#E76700">' . $var . '()</span></h3>';
426
		} else if ( is_string( $var ) ) {
427
			echo '<h4 style="color:#2EA2CC;margin:0;">' . $var_name . ' : <span style="color:#E76700">' . $var . '</span></h4>';
428
		} else {
429
			echo '<h4 style="color:#2EA2CC;"><b>' . $var_name . '</b></h4><span style="color:#E76700">';
430
			var_dump( $var );
0 ignored issues
show
Security Debugging Code introduced by
var_dump($var); looks like debug code. Are you sure you do not want to remove it? This might expose sensitive data.
Loading history...
431
			echo '</span><br />';
432
		}
433
		$file = str_replace( rtrim( EE_PLUGIN_DIR_PATH, '/' ), '', $file );
434
		echo '<span style="color:#666;font-size:10px;font-weight:normal;">' . $file . '&nbsp;:&nbsp;' . $line . '</span></pre>';
435
		$result = ob_get_clean();
436
		if ( $die ) {
437
			die( $result );
438
		} else {
439
			echo $result;
440
		}
441
	}
442
443
444
445
446
}
447
448
449
450
/**
451
 * borrowed from Kint Debugger
452
 * Plugin URI: http://upthemes.com/plugins/kint-debugger/
453
 */
454
if ( class_exists('Kint') && ! function_exists( 'dump_wp_query' ) ) {
455
	function dump_wp_query(){
456
		global $wp_query;
457
		d($wp_query);
458
	}
459
}
460
461
/**
462
 * borrowed from Kint Debugger
463
 * Plugin URI: http://upthemes.com/plugins/kint-debugger/
464
 */
465
if ( class_exists('Kint') && ! function_exists( 'dump_wp' ) ) {
466
	function dump_wp(){
467
		global $wp;
468
		d($wp);
469
	}
470
}
471
472
/**
473
 * borrowed from Kint Debugger
474
 * Plugin URI: http://upthemes.com/plugins/kint-debugger/
475
 */
476
if ( class_exists('Kint') && ! function_exists( 'dump_post' ) ) {
477
	function dump_post(){
478
		global $post;
479
		d($post);
480
	}
481
}
482
483