/**
  * Constructor
  * Initialize the object, figure out if profiling is enabled, and if so,
  * start the profile.
  * @return p3_profiler
  */
 public function __construct()
 {
     // Set up paths
     $this->_P3_PATH = realpath(dirname(__FILE__));
     // Debug mode
     $this->_debug_entry = array('profiling_enabled' => false, 'recording_ip' => '', 'scan_name' => '', 'recording' => false, 'disable_optimizers' => false, 'url' => $this->_get_url(), 'visitor_ip' => p3_profiler_get_ip(), 'time' => time(), 'pid' => getmypid());
     // Check to see if we should profile
     $opts = array();
     if (function_exists('get_option')) {
         $opts = get_option('p3-profiler_options');
         if (!empty($opts['profiling_enabled'])) {
             if (isset($this->_debug_entry)) {
                 $this->_debug_entry['profiling_enabled'] = true;
                 $this->_debug_entry['scan_name'] = $opts['profiling_enabled']['name'];
                 $this->_debug_entry['recording_ip'] = $opts['profiling_enabled']['ip'];
                 $this->_debug_entry['disable_optimizers'] = $opts['profiling_enabled']['disable_opcode_cache'];
             }
         }
     }
     // Add a global flag to let everyone know we're profiling
     if (!empty($opts) && preg_match('/' . $opts['profiling_enabled']['ip'] . '/', p3_profiler_get_ip())) {
         define('WPP_PROFILING_STARTED', true);
     }
     // Save the debug info
     $this->_debug_entry['recording'] = defined('WPP_PROFILING_STARTED');
     // Check the profiling flag
     if (!defined('WPP_PROFILING_STARTED')) {
         return $this;
     }
     // Emergency shut off switch
     if (isset($_REQUEST['P3_SHUTOFF']) && !empty($_REQUEST['P3_SHUTOFF'])) {
         p3_profiler_disable();
         return $this;
     }
     // Hook shutdown
     register_shutdown_function(array($this, 'shutdown_handler'));
     // Error detection
     $flag = get_option('p3_profiler-error_detection');
     if (!empty($flag) && $flag > time() + 60) {
         p3_profiler_disable();
         return $this;
     }
     // Set the error detection flag
     if (empty($flag)) {
         update_option('p3_profiler-error_detection', time());
     }
     // Kludge memory limit / time limit
     if ((int) @ini_get('memory_limit') < 256) {
         @ini_set('memory_limit', '256M');
     }
     @set_time_limit(90);
     // Set the profile file
     $this->_profile_filename = $opts['profiling_enabled']['name'] . '.json';
     // Start timing
     $this->_start_time = microtime(true);
     $this->_last_call_start = microtime(true);
     // Reset state
     $this->_last_call_time = 0;
     $this->_runtime = 0;
     $this->_plugin_runtime = 0;
     $this->_core = 0;
     $this->_theme = 0;
     $this->_last_call_category = self::CATEGORY_CORE;
     $this->_last_stack = array();
     // Add some startup information
     $this->_profile = array('url' => $this->_get_url(), 'ip' => p3_profiler_get_ip(), 'pid' => getmypid(), 'date' => @date('c'), 'stack' => array());
     // Disable opcode optimizers.  These "optimize" calls out of the stack
     // and hide calls from the tick handler and backtraces
     if ($opts['profiling_enabled']['disable_opcode_cache']) {
         if (extension_loaded('xcache')) {
             @ini_set('xcache.optimizer', false);
             // Will be implemented in 2.0, here for future proofing
             // XCache seems to do some optimizing, anyway.  The recorded stack size is smaller with xcache.cacher enabled than without.
         } elseif (extension_loaded('apc')) {
             @ini_set('apc.optimization', 0);
             // Removed in APC 3.0.13 (2007-02-24)
             apc_clear_cache();
         } elseif (extension_loaded('eaccelerator')) {
             @ini_set('eaccelerator.optimizer', 0);
             if (function_exists('eaccelerator_optimizer')) {
                 @eaccelerator_optimizer(false);
             }
             // If you're reading this, try setting eaccelerator.optimizer = 0 in a .user.ini or .htaccess file
         } elseif (extension_loaded('Zend Optimizer+')) {
             @ini_set('zend_optimizerplus.optimization_level', 0);
         }
         // Tested with wincache
         // Tested with ioncube
         // Tested with zend guard loader
     }
     // Monitor all function-calls
     declare (ticks=1);
     register_tick_function(array($this, 'tick_handler'));
 }
 /**
  * Stop scan
  */
 public static function ajax_stop_scan()
 {
     // Check nonce
     if (!check_admin_referer('p3_ajax_stop_scan', 'p3_nonce')) {
         wp_die(__('You do not have sufficient permissions to access this page.'));
     }
     // Get current options
     $opts = get_option('p3-profiler_options');
     $opts = $opts['profiling_enabled'];
     // Turn off scanning
     p3_profiler_disable();
     // Tell the user what happened
     self::add_notice(__('Turned off performance scanning.', 'p3-profiler'));
     // Return the last filename
     if (!empty($opts) && is_array($opts) && array_key_exists('name', $opts)) {
         echo $opts['name'] . '.json';
         self::ajax_die('');
     } else {
         self::ajax_die(0);
     }
 }