Beispiel #1
0
 public function process()
 {
     $this->data['time_taken'] = self::timer_stop_float();
     $this->data['time_limit'] = ini_get('max_execution_time');
     $this->data['time_start'] = $GLOBALS['timestart'];
     if (!empty($this->data['time_limit'])) {
         $this->data['time_usage'] = 100 / $this->data['time_limit'] * $this->data['time_taken'];
     } else {
         $this->data['time_usage'] = 0;
     }
     if (function_exists('memory_get_peak_usage')) {
         $this->data['memory'] = memory_get_peak_usage();
     } else {
         if (function_exists('memory_get_usage')) {
             $this->data['memory'] = memory_get_usage();
         } else {
             $this->data['memory'] = 0;
         }
     }
     if (is_user_logged_in()) {
         $this->data['current_user'] = self::format_user(wp_get_current_user());
     } else {
         $this->data['current_user'] = false;
     }
     if (function_exists('current_user_switched') && current_user_switched()) {
         $this->data['switched_user'] = self::format_user(current_user_switched());
     } else {
         $this->data['switched_user'] = false;
     }
     $this->data['memory_limit'] = QM_Util::convert_hr_to_bytes(ini_get('memory_limit'));
     $this->data['memory_usage'] = 100 / $this->data['memory_limit'] * $this->data['memory'];
     $this->data['is_admin'] = is_admin();
 }
Beispiel #2
0
 public function after_output()
 {
     # flush once, because we're nice
     if (QM_Util::is_ajax() and ob_get_length()) {
         ob_flush();
     }
 }
 public function deactivate()
 {
     if ($admins = QM_Util::get_admins()) {
         $admins->remove_cap('view_query_monitor');
     }
     # Only delete db.php if it belongs to Query Monitor
     if (class_exists('QM_DB')) {
         unlink(WP_CONTENT_DIR . '/db.php');
     }
 }
Beispiel #4
0
 public function process()
 {
     $this->data['time'] = self::timer_stop_float();
     $this->data['time_limit'] = ini_get('max_execution_time');
     if (!empty($this->data['time_limit'])) {
         $this->data['time_usage'] = 100 / $this->data['time_limit'] * $this->data['time'];
     } else {
         $this->data['time_usage'] = 0;
     }
     $this->data['memory'] = memory_get_peak_usage();
     $this->data['memory_limit'] = QM_Util::convert_hr_to_bytes(ini_get('memory_limit'));
     $this->data['memory_usage'] = 100 / $this->data['memory_limit'] * $this->data['memory'];
 }
Beispiel #5
0
 public function process()
 {
     global $template;
     $template_path = QM_Util::standard_dir($template);
     $stylesheet_directory = QM_Util::standard_dir(get_stylesheet_directory());
     $template_directory = QM_Util::standard_dir(get_template_directory());
     $template_file = str_replace(array($stylesheet_directory, $template_directory), '', $template_path);
     $template_file = ltrim($template_file, '/');
     $this->data['template_path'] = $template_path;
     $this->data['template_file'] = $template_file;
     $this->data['stylesheet'] = get_stylesheet();
     $this->data['template'] = get_template();
     if (isset($this->data['body_class'])) {
         asort($this->data['body_class']);
     }
 }
Beispiel #6
0
 public function output()
 {
     $data = $this->collector->get_data();
     if (empty($data['languages'])) {
         return;
     }
     echo '<div class="qm" id="' . esc_attr($this->collector->id()) . '">';
     echo '<table cellspacing="0">';
     echo '<thead>';
     echo '<tr>';
     echo '<th>' . esc_html__('Languages', 'query-monitor') . '</th>';
     echo '<th colspan="3">' . esc_html__('Language Setting:', 'query-monitor') . ' ' . esc_html(get_locale()) . '</th>';
     echo '</tr>';
     echo '<tr>';
     echo '<td>' . esc_html__('Text Domain', 'query-monitor') . '</td>';
     echo '<td>' . esc_html__('Caller', 'query-monitor') . '</td>';
     echo '<td>' . esc_html__('MO File', 'query-monitor') . '</td>';
     echo '<td>' . esc_html__('Loaded', 'query-monitor') . '</td>';
     echo '</tr>';
     echo '</thead>';
     echo '<tbody>';
     foreach ($data['languages'] as $mofile) {
         echo '<tr>';
         echo '<td>' . esc_html($mofile['domain']) . '</td>';
         echo '<td class="qm-nowrap">';
         echo self::output_filename($mofile['caller']['display'], $mofile['caller']['file'], $mofile['caller']['line']);
         // WPCS: XSS ok.
         echo '</td>';
         echo '<td>';
         echo esc_html(QM_Util::standard_dir($mofile['mofile'], ''));
         echo '</td>';
         if ($mofile['found']) {
             echo '<td class="qm-nowrap">';
             echo esc_html__('Found', 'query-monitor') . '<br />';
             echo esc_html(size_format($mofile['found']));
             echo '</td>';
         } else {
             echo '<td class="qm-warn">';
             echo esc_html__('Not Found', 'query-monitor');
             echo '</td>';
         }
         echo '</tr>';
     }
     echo '</tbody>';
     echo '</table>';
     echo '</div>';
 }
 public function process()
 {
     global $wp_rewrite;
     if (is_admin() or QM_Util::is_async()) {
         return;
     }
     if (!($request = QM_Collectors::get('request'))) {
         return;
     }
     if (empty($wp_rewrite->rules)) {
         return;
     }
     $req = $request->data['request']['request'];
     $matching = array();
     foreach ($wp_rewrite->rules as $match => $query) {
         if (preg_match("#^{$match}#", $req)) {
             $matching[$match] = $query;
         }
     }
     $this->data['matching'] = $matching;
 }
Beispiel #8
0
 public function process()
 {
     if (!empty($this->data['template_path'])) {
         $template_path = QM_Util::standard_dir($this->data['template_path']);
         $stylesheet_directory = QM_Util::standard_dir(get_stylesheet_directory());
         $template_directory = QM_Util::standard_dir(get_template_directory());
         $theme_directory = QM_Util::standard_dir(get_theme_root());
         $template_file = str_replace(array($stylesheet_directory, $template_directory, ABSPATH), '', $template_path);
         $template_file = ltrim($template_file, '/');
         $theme_template_file = str_replace(array($theme_directory, ABSPATH), '', $template_path);
         $theme_template_file = ltrim($theme_template_file, '/');
         $this->data['template_path'] = $template_path;
         $this->data['template_file'] = $template_file;
         $this->data['theme_template_file'] = $theme_template_file;
         foreach (get_included_files() as $file) {
             $filename = str_replace(array($stylesheet_directory, $template_directory), '', $file);
             if ($filename !== $file) {
                 $slug = trim(str_replace('.php', '', $filename), '/');
                 $display = trim($filename, '/');
                 $theme_display = trim(str_replace($theme_directory, '', $file), '/');
                 if (did_action("get_template_part_{$slug}")) {
                     $this->data['template_parts'][$file] = $display;
                     $this->data['theme_template_parts'][$file] = $theme_display;
                 } else {
                     $slug = trim(preg_replace('|\\-[^\\-]+$|', '', $slug), '/');
                     if (did_action("get_template_part_{$slug}")) {
                         $this->data['template_parts'][$file] = $display;
                         $this->data['theme_template_parts'][$file] = $theme_display;
                     }
                 }
             }
         }
     }
     $this->data['stylesheet'] = get_stylesheet();
     $this->data['template'] = get_template();
     $this->data['is_child_theme'] = $this->data['stylesheet'] != $this->data['template'];
     if (isset($this->data['body_class'])) {
         asort($this->data['body_class']);
     }
 }
 public function error_handler($errno, $message, $file = null, $line = null)
 {
     #if ( !( error_reporting() & $errno ) )
     #	return false;
     switch ($errno) {
         case E_WARNING:
         case E_USER_WARNING:
             $type = 'warning';
             break;
         case E_NOTICE:
         case E_USER_NOTICE:
             $type = 'notice';
             break;
         case E_STRICT:
             $type = 'strict';
             break;
         case QM_E_DEPRECATED:
         case QM_E_USER_DEPRECATED:
             $type = 'deprecated';
             break;
         default:
             return false;
             break;
     }
     if (error_reporting() > 0) {
         if (!class_exists('QM_Backtrace')) {
             return false;
         }
         $trace = new QM_Backtrace(array('ignore_current_filter' => false));
         $caller = $trace->get_caller();
         $key = md5($message . $file . $line . $caller['id']);
         $filename = QM_Util::standard_dir($file, '');
         if (isset($this->data['errors'][$type][$key])) {
             $this->data['errors'][$type][$key]->calls++;
         } else {
             $this->data['errors'][$type][$key] = (object) array('errno' => $errno, 'type' => $type, 'message' => $message, 'file' => $file, 'filename' => $filename, 'line' => $line, 'trace' => $trace, 'calls' => 1);
         }
     }
     return apply_filters('qm/collect/php_errors_return_value', false);
 }
Beispiel #10
0
 public function output()
 {
     if (!QM_Util::is_ajax()) {
         return;
     }
     $data = $this->collector->get_data();
     if (empty($data['errors'])) {
         return;
     }
     $count = 0;
     foreach ($data['errors'] as $type => $errors) {
         foreach ($errors as $key => $error) {
             $count++;
             # @TODO we should calculate the component during process() so we don't need to do it
             # separately in each output.
             $component = $error->trace->get_component();
             $output_error = array('type' => $error->type, 'message' => wp_strip_all_tags($error->message), 'file' => $error->file, 'line' => $error->line, 'stack' => $error->trace->get_stack(), 'component' => $component->name);
             header(sprintf('X-QM-Error-%d: %s', $count, json_encode($output_error)));
         }
     }
     header(sprintf('X-QM-Errors: %d', $count));
 }
Beispiel #11
0
 protected function process_action($name, array $wp_filter)
 {
     $actions = $components = array();
     if (isset($wp_filter[$name])) {
         # http://core.trac.wordpress.org/ticket/17817
         $action = $wp_filter[$name];
         foreach ($action as $priority => $callbacks) {
             foreach ($callbacks as $callback) {
                 $callback = QM_Util::populate_callback($callback);
                 if (isset($callback['component'])) {
                     if ($this->hide_qm and 'query-monitor' === $callback['component']->context) {
                         continue;
                     }
                     $components[$callback['component']->name] = $callback['component']->name;
                 }
                 $actions[] = array('priority' => $priority, 'callback' => $callback);
             }
         }
     }
     $parts = array_filter(preg_split('#[_/-]#', $name));
     return array('name' => $name, 'actions' => $actions, 'parts' => $parts, 'components' => $components);
 }
Beispiel #12
0
 public function is_active()
 {
     if (!QM_Util::is_ajax()) {
         return false;
     }
     if (!$this->user_can_view()) {
         return false;
     }
     # If the headers have already been sent then we can't do anything about it
     if (headers_sent()) {
         return false;
     }
     # Don't process if the minimum required actions haven't fired:
     if (is_admin()) {
         if (!did_action('admin_init')) {
             return false;
         }
     } else {
         if (!did_action('wp')) {
             return false;
         }
     }
     return true;
 }
Beispiel #13
0
 public function process()
 {
     global $wp_actions, $wp_filter;
     if (is_admin() and $admin = QueryMonitor::get_collector('admin')) {
         $this->data['screen'] = $admin->data['base'];
     } else {
         $this->data['screen'] = '';
     }
     $hooks = $parts = $components = array();
     foreach ($wp_actions as $name => $count) {
         $actions = array();
         # @TODO better variable name:
         $c = array();
         if (isset($wp_filter[$name])) {
             # http://core.trac.wordpress.org/ticket/17817
             $action = $wp_filter[$name];
             foreach ($action as $priority => $callbacks) {
                 foreach ($callbacks as $callback) {
                     $callback = QM_Util::populate_callback($callback);
                     if (isset($callback['component'])) {
                         $c[$callback['component']->name] = $callback['component']->name;
                     }
                     $actions[] = array('priority' => $priority, 'callback' => $callback);
                 }
             }
         }
         # @TODO better variable name:
         $p = array_filter(preg_split('/[_\\/-]/', $name));
         $parts = array_merge($parts, $p);
         $components = array_merge($components, $c);
         $hooks[$name] = array('name' => $name, 'actions' => $actions, 'parts' => $p, 'components' => $c);
     }
     $this->data['hooks'] = $hooks;
     $this->data['parts'] = array_unique(array_filter($parts));
     $this->data['components'] = array_unique(array_filter($components));
 }
Beispiel #14
0
 public static function populate_callback(array $callback)
 {
     if (is_string($callback['function']) and false !== strpos($callback['function'], '::')) {
         $callback['function'] = explode('::', $callback['function']);
     }
     try {
         if (is_array($callback['function'])) {
             if (is_object($callback['function'][0])) {
                 $class = get_class($callback['function'][0]);
                 $access = '->';
             } else {
                 $class = $callback['function'][0];
                 $access = '::';
             }
             $callback['name'] = $class . $access . $callback['function'][1] . '()';
             $ref = new ReflectionMethod($class, $callback['function'][1]);
         } else {
             if (is_object($callback['function'])) {
                 if (is_a($callback['function'], 'Closure')) {
                     $ref = new ReflectionFunction($callback['function']);
                     $file = QM_Util::standard_dir($ref->getFileName(), '');
                     /* translators: 1: Line number, 2: File name */
                     $callback['name'] = sprintf(__('Closure on line %1$d of %2$s', 'query-monitor'), $ref->getStartLine(), $file);
                 } else {
                     // the object should have a __invoke() method
                     $class = get_class($callback['function']);
                     $callback['name'] = $class . '->__invoke()';
                     $ref = new ReflectionMethod($class, '__invoke');
                 }
             } else {
                 $callback['name'] = $callback['function'] . '()';
                 $ref = new ReflectionFunction($callback['function']);
             }
         }
         $callback['file'] = $ref->getFileName();
         $callback['line'] = $ref->getStartLine();
         // https://github.com/facebook/hhvm/issues/5856
         $name = trim($ref->getName());
         if ('__lambda_func' === $name || 0 === strpos($name, 'lambda_')) {
             if (preg_match('|(?P<file>.*)\\((?P<line>[0-9]+)\\)|', $callback['file'], $matches)) {
                 $callback['file'] = $matches['file'];
                 $callback['line'] = $matches['line'];
                 $file = trim(QM_Util::standard_dir($callback['file'], ''), '/');
                 /* translators: 1: Line number, 2: File name */
                 $callback['name'] = sprintf(__('Anonymous function on line %1$d of %2$s', 'query-monitor'), $callback['line'], $file);
             } else {
                 // https://github.com/facebook/hhvm/issues/5807
                 unset($callback['line'], $callback['file']);
                 $callback['name'] = $name . '()';
                 $callback['error'] = new WP_Error('unknown_lambda', __('Unable to determine source of lambda function', 'query-monitor'));
             }
         }
         if (!empty($callback['file'])) {
             $callback['component'] = self::get_file_component($callback['file']);
         } else {
             $callback['component'] = (object) array('type' => 'php', 'name' => 'PHP', 'context' => '');
         }
     } catch (ReflectionException $e) {
         $callback['error'] = new WP_Error('reflection_exception', $e->getMessage());
     }
     return $callback;
 }
 public function error_handler($errno, $message, $file = null, $line = null)
 {
     switch ($errno) {
         case E_WARNING:
         case E_USER_WARNING:
             $type = 'warning';
             break;
         case E_NOTICE:
         case E_USER_NOTICE:
             $type = 'notice';
             break;
         case E_STRICT:
             $type = 'strict';
             break;
         case QM_E_DEPRECATED:
         case QM_E_USER_DEPRECATED:
             $type = 'deprecated';
             break;
         default:
             return false;
             break;
     }
     if (!class_exists('QM_Backtrace')) {
         return false;
     }
     if (!isset(self::$unexpected_error)) {
         // These strings are from core. They're passed through `__()` as variables so they get translated at runtime
         // but do not get seen by GlotPress when it populates its database of translatable strings for QM.
         $unexpected_error = 'An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="https://wordpress.org/support/">support forums</a>.';
         $wordpress_couldnt = '(WordPress could not establish a secure connection to WordPress.org. Please contact your server administrator.)';
         self::$unexpected_error = __($unexpected_error);
         self::$wordpress_couldnt = __($wordpress_couldnt);
     }
     // Intentionally skip reporting these core warnings. They're a distraction when developing offline.
     // The failed HTTP request will still appear in QM's output so it's not a big problem hiding these warnings.
     if (self::$unexpected_error === $message) {
         return false;
     }
     if (self::$unexpected_error . ' ' . self::$wordpress_couldnt === $message) {
         return false;
     }
     $trace = new QM_Backtrace(array('ignore_current_filter' => false));
     $caller = $trace->get_caller();
     $key = md5($message . $file . $line . $caller['id']);
     $filename = QM_Util::standard_dir($file, '');
     if (isset($this->data['errors'][$type][$key])) {
         $this->data['errors'][$type][$key]->calls++;
     } else {
         $this->data['errors'][$type][$key] = (object) array('errno' => $errno, 'type' => $type, 'message' => $message, 'file' => $file, 'filename' => $filename, 'line' => $line, 'trace' => $trace, 'calls' => 1);
     }
     return apply_filters('qm/collect/php_errors_return_value', false);
 }
 public function testCurrentUrl()
 {
     $url = add_query_arg('foo', 'bar', home_url('baz'));
     $this->go_to($url);
     $this->assertSame(QM_Util::get_current_url(), $url);
 }
Beispiel #17
0
 public function is_active()
 {
     if (!$this->user_can_view()) {
         return false;
     }
     if (!$this->did_footer) {
         return false;
     }
     if (QM_Util::is_async()) {
         return false;
     }
     # Don't process if the minimum required actions haven't fired:
     if (is_admin()) {
         if (!did_action('admin_init')) {
             return false;
         }
     } else {
         if (!(did_action('wp') || did_action('login_init'))) {
             return false;
         }
     }
     # Back-compat filter. Please use `qm/dispatch/html` instead
     if (!apply_filters('qm/process', true, is_admin_bar_showing())) {
         return false;
     }
     return true;
 }
 public function process_db_object($id, wpdb $db)
 {
     global $EZSQL_ERROR;
     $rows = array();
     $types = array();
     $total_time = 0;
     $has_result = false;
     $has_trace = false;
     $i = 0;
     foreach ((array) $db->queries as $query) {
         # @TODO: decide what I want to do with this:
         if (false !== strpos($query[2], 'wp_admin_bar') and !isset($_REQUEST['qm_display_admin_bar'])) {
             continue;
         }
         $sql = $query[0];
         $ltime = $query[1];
         $stack = $query[2];
         $has_trace = isset($query['trace']);
         $has_result = isset($query['result']);
         if (isset($query['result'])) {
             $result = $query['result'];
         } else {
             $result = null;
         }
         $total_time += $ltime;
         if (isset($query['trace'])) {
             $trace = $query['trace'];
             $component = $query['trace']->get_component();
             $caller = $query['trace']->get_caller();
             $caller_name = $caller['id'];
             $caller = $caller['display'];
         } else {
             $trace = null;
             $component = null;
             $callers = explode(',', $stack);
             $caller = trim(end($callers));
             if (false !== strpos($caller, '(')) {
                 $caller_name = substr($caller, 0, strpos($caller, '(')) . '()';
             } else {
                 $caller_name = $caller;
             }
         }
         $sql = trim($sql);
         $type = QM_Util::get_query_type($sql);
         $this->log_type($type);
         $this->log_caller($caller_name, $ltime, $type);
         $this->maybe_log_dupe($sql, $i);
         if ($component) {
             $this->log_component($component, $ltime, $type);
         }
         if (!isset($types[$type]['total'])) {
             $types[$type]['total'] = 1;
         } else {
             $types[$type]['total']++;
         }
         if (!isset($types[$type]['callers'][$caller])) {
             $types[$type]['callers'][$caller] = 1;
         } else {
             $types[$type]['callers'][$caller]++;
         }
         $row = compact('caller', 'caller_name', 'stack', 'sql', 'ltime', 'result', 'type', 'component', 'trace');
         if (is_wp_error($result)) {
             $this->data['errors'][] = $row;
         }
         if (self::is_expensive($row)) {
             $this->data['expensive'][] = $row;
         }
         $rows[$i] = $row;
         $i++;
     }
     if ('$wpdb' === $id && !$has_result && !empty($EZSQL_ERROR) && is_array($EZSQL_ERROR)) {
         // Fallback for displaying database errors when wp-content/db.php isn't in place
         foreach ($EZSQL_ERROR as $error) {
             $row = array('caller' => 'Unknown', 'caller_name' => 'Unknown', 'stack' => '', 'sql' => $error['query'], 'result' => new WP_Error('qmdb', $error['error_str']), 'type' => '', 'component' => false, 'trace' => null);
             $this->data['errors'][] = $row;
         }
     }
     $total_qs = count($rows);
     $this->data['total_qs'] += $total_qs;
     $this->data['total_time'] += $total_time;
     # @TODO put errors in here too:
     # @TODO proper class instead of (object)
     $this->data['dbs'][$id] = (object) compact('rows', 'types', 'has_result', 'has_trace', 'total_time', 'total_qs');
 }
 /**
  * @dataProvider clientVersionData
  *
  */
 public function testClientVersion($client, $expected)
 {
     $ver = QM_Util::get_client_version($client);
     $this->assertEquals($expected, array_values($ver));
 }
Beispiel #20
0
 public static function populate_callback(array $callback)
 {
     if (is_string($callback['function']) and false !== strpos($callback['function'], '::')) {
         $callback['function'] = explode('::', $callback['function']);
     }
     try {
         if (is_array($callback['function'])) {
             if (is_object($callback['function'][0])) {
                 $class = get_class($callback['function'][0]);
                 $access = '->';
             } else {
                 $class = $callback['function'][0];
                 $access = '::';
             }
             $callback['name'] = $class . $access . $callback['function'][1] . '()';
             $ref = new ReflectionMethod($class, $callback['function'][1]);
         } else {
             if (is_object($callback['function'])) {
                 if (is_a($callback['function'], 'Closure')) {
                     $ref = new ReflectionFunction($callback['function']);
                     $file = trim(QM_Util::standard_dir($ref->getFileName(), ''), '/');
                     $callback['name'] = sprintf(__('Closure on line %1$d of %2$s', 'query-monitor'), $ref->getStartLine(), $file);
                 } else {
                     // the object should have a __invoke() method
                     $class = get_class($callback['function']);
                     $callback['name'] = $class . '->__invoke()';
                     $ref = new ReflectionMethod($class, '__invoke');
                 }
             } else {
                 $callback['name'] = $callback['function'] . '()';
                 $ref = new ReflectionFunction($callback['function']);
             }
         }
         $callback['file'] = $ref->getFileName();
         $callback['line'] = $ref->getStartLine();
         if ('__lambda_func' === $ref->getName()) {
             if (preg_match('|(?P<file>.*)\\((?P<line>[0-9]+)\\)|', $callback['file'], $matches)) {
                 $callback['file'] = $matches['file'];
                 $callback['line'] = $matches['line'];
                 $file = trim(QM_Util::standard_dir($callback['file'], ''), '/');
                 $callback['name'] = sprintf(__('Anonymous function on line %1$d of %2$s', 'query-monitor'), $callback['line'], $file);
             }
         }
         $callback['component'] = self::get_file_component($callback['file']);
     } catch (ReflectionException $e) {
         $callback['error'] = new WP_Error('reflection_exception', $e->getMessage());
     }
     return $callback;
 }
Beispiel #21
0
 public function active()
 {
     if (!$this->qm->user_can_view()) {
         return false;
     }
     if (!(did_action('wp_footer') or did_action('admin_footer') or did_action('login_footer'))) {
         return false;
     }
     if (QM_Util::is_async()) {
         return false;
     }
     return true;
 }
Beispiel #22
0
 public function output()
 {
     $data = $this->collector->get_data();
     if (empty($data['dupes'])) {
         return;
     }
     $colspan = empty($data['dupe_components']) ? 4 : 5;
     echo '<div class="qm" id="' . esc_attr($this->collector->id()) . '">';
     echo '<table cellspacing="0">';
     echo '<thead>';
     echo '<tr>';
     echo '<th colspan="' . absint($colspan) . '">' . esc_html($this->collector->name()) . '</th>';
     echo '</tr>';
     echo '<tr>';
     echo '<th>' . esc_html__('Query', 'query-monitor') . '</th>';
     echo '<th class="qm-num">' . esc_html__('Count', 'query-monitor') . '</th>';
     echo '<th>' . esc_html__('Callers', 'query-monitor') . '</th>';
     if (!empty($data['dupe_components'])) {
         echo '<th>' . esc_html__('Components', 'query-monitor') . '</th>';
     }
     echo '<th>' . esc_html__('Potential Troublemakers', 'query-monitor') . '</th>';
     echo '</tr>';
     echo '</thead>';
     echo '<tbody>';
     /* translators: %s: Number of calls to a PHP function */
     $call_text = _n_noop('%s call', '%s calls', 'query-monitor');
     foreach ($data['dupes'] as $sql => $queries) {
         // This should probably happen in the collector's processor
         $type = QM_Util::get_query_type($sql);
         $sql_out = self::format_sql($sql);
         if ('SELECT' !== $type) {
             $sql_out = "<span class='qm-nonselectsql'>{$sql_out}</span>";
         }
         echo '<tr>';
         echo '<td class="qm-row-sql qm-ltr qm-wrap">';
         echo $sql_out;
         // WPCS: XSS ok;
         echo '</td>';
         echo '<td class="qm-num">';
         echo esc_html(number_format_i18n(count($queries), 0));
         echo '</td>';
         echo '<td class="qm-row-caller qm-nowrap qm-ltr">';
         foreach ($data['dupe_callers'][$sql] as $caller => $calls) {
             printf('<a href="#" class="qm-filter-trigger" data-qm-target="db_queries-wpdb" data-qm-filter="caller" data-qm-value="%s">%s</a><br><span class="qm-info">&nbsp;%s</span><br>', esc_attr($caller), esc_html($caller), esc_html(sprintf(translate_nooped_plural($call_text, $calls, 'query-monitor'), number_format_i18n($calls))));
         }
         echo '</td>';
         if (isset($data['dupe_components'][$sql])) {
             echo '<td class="qm-row-component qm-nowrap">';
             foreach ($data['dupe_components'][$sql] as $component => $calls) {
                 printf('%s<br><span class="qm-info">&nbsp;%s</span><br>', esc_html($component), esc_html(sprintf(translate_nooped_plural($call_text, $calls, 'query-monitor'), number_format_i18n($calls))));
             }
             echo '</td>';
         }
         echo '<td class="qm-row-caller qm-nowrap qm-ltr">';
         foreach ($data['dupe_sources'][$sql] as $source => $calls) {
             printf('%s<br><span class="qm-info">&nbsp;%s</span><br>', esc_html($source), esc_html(sprintf(translate_nooped_plural($call_text, $calls, 'query-monitor'), number_format_i18n($calls))));
         }
         echo '</td>';
         echo '</tr>';
     }
     echo '</tbody>';
     echo '</table>';
     echo '</div>';
 }
 public function process()
 {
     global $wp, $wp_query, $current_blog, $current_site;
     $qo = get_queried_object();
     if (is_multisite()) {
         $this->data['multisite']['current_blog'] = array('title' => sprintf('Current blog: #%d', $current_blog->blog_id), 'data' => $current_blog);
     }
     if (QM_Util::is_multi_network()) {
         $this->data['multisite']['current_site'] = array('title' => sprintf('Current site: #%d', $current_site->id), 'data' => $current_site);
     }
     if (is_admin()) {
         $this->data['request']['request'] = $_SERVER['REQUEST_URI'];
         foreach (array('query_string') as $item) {
             $this->data['request'][$item] = $wp->{$item};
         }
     } else {
         foreach (array('request', 'matched_rule', 'matched_query', 'query_string') as $item) {
             $this->data['request'][$item] = $wp->{$item};
         }
     }
     $plugin_qvars = array_flip(apply_filters('query_vars', array()));
     $qvars = $wp_query->query_vars;
     $query_vars = array();
     foreach ($qvars as $k => $v) {
         if (isset($plugin_qvars[$k])) {
             if ('' !== $v) {
                 $query_vars[$k] = $v;
             }
         } else {
             if (!empty($v)) {
                 $query_vars[$k] = $v;
             }
         }
     }
     ksort($query_vars);
     # First add plugin vars to $this->data['qvars']:
     foreach ($query_vars as $k => $v) {
         if (isset($plugin_qvars[$k])) {
             $this->data['qvars'][$k] = $v;
             $this->data['plugin_qvars'][$k] = $v;
         }
     }
     # Now add all other vars to $this->data['qvars']:
     foreach ($query_vars as $k => $v) {
         if (!isset($plugin_qvars[$k])) {
             $this->data['qvars'][$k] = $v;
         }
     }
     switch (true) {
         case is_null($qo):
             // Nada
             break;
         case is_a($qo, 'WP_Post'):
             // Single post
             $this->data['queried_object']['title'] = sprintf(__('Single %s: #%d', 'query-monitor'), get_post_type_object($qo->post_type)->labels->singular_name, $qo->ID);
             break;
         case is_a($qo, 'WP_User'):
             // Author archive
             $this->data['queried_object']['title'] = sprintf(__('Author archive: %s', 'query-monitor'), $qo->user_nicename);
             break;
         case is_a($qo, 'WP_Term'):
         case property_exists($qo, 'term_id'):
             // Term archive
             $this->data['queried_object']['title'] = sprintf(__('Term archive: %s', 'query-monitor'), $qo->slug);
             break;
         case property_exists($qo, 'has_archive'):
             // Post type archive
             $this->data['queried_object']['title'] = sprintf(__('Post type archive: %s', 'query-monitor'), $qo->name);
             break;
         default:
             // Unknown, but we have a queried object
             $this->data['queried_object']['title'] = __('Unknown queried object', 'query-monitor');
             break;
     }
     if (!is_null($qo)) {
         $this->data['queried_object']['data'] = $qo;
     }
 }
Beispiel #24
0
 public function filter_trace(array $trace)
 {
     if (!self::$filtered and function_exists('did_action') and did_action('plugins_loaded')) {
         # Only run apply_filters on these once
         self::$ignore_class = apply_filters('qm/trace/ignore_class', self::$ignore_class);
         self::$ignore_method = apply_filters('qm/trace/ignore_method', self::$ignore_method);
         self::$ignore_func = apply_filters('qm/trace/ignore_func', self::$ignore_func);
         self::$show_args = apply_filters('qm/trace/show_args', self::$show_args);
         self::$filtered = true;
     }
     $return = $trace;
     if (isset($trace['class'])) {
         if (isset(self::$ignore_class[$trace['class']])) {
             $return = null;
         } else {
             if (isset(self::$ignore_method[$trace['class']][$trace['function']])) {
                 $return = null;
             } else {
                 if (0 === strpos($trace['class'], 'QM_')) {
                     $return = null;
                 } else {
                     $return['id'] = $trace['class'] . $trace['type'] . $trace['function'] . '()';
                     $return['display'] = $trace['class'] . $trace['type'] . $trace['function'] . '()';
                 }
             }
         }
     } else {
         if (isset(self::$ignore_func[$trace['function']])) {
             $return = null;
         } else {
             if (isset(self::$show_args[$trace['function']])) {
                 $show = self::$show_args[$trace['function']];
                 if ('dir' === $show) {
                     if (isset($trace['args'][0])) {
                         $arg = QM_Util::standard_dir($trace['args'][0], '~/');
                         $return['id'] = $trace['function'] . '()';
                         $return['display'] = $trace['function'] . "('{$arg}')";
                     }
                 } else {
                     $args = array();
                     for ($i = 0; $i < $show; $i++) {
                         if (isset($trace['args'][$i])) {
                             $args[] = '\'' . $trace['args'][$i] . '\'';
                         }
                     }
                     $return['id'] = $trace['function'] . '()';
                     $return['display'] = $trace['function'] . '(' . implode(',', $args) . ')';
                 }
             } else {
                 $return['id'] = $trace['function'] . '()';
                 $return['display'] = $trace['function'] . '()';
             }
         }
     }
     if ($return) {
         $return['calling_file'] = $this->calling_file;
         $return['calling_line'] = $this->calling_line;
     }
     if (isset($trace['line'])) {
         $this->calling_line = $trace['line'];
     }
     if (isset($trace['file'])) {
         $this->calling_file = $trace['file'];
     }
     return $return;
 }
Beispiel #25
0
 public function process()
 {
     global $wp_version;
     $mysql_vars = array('key_buffer_size' => true, 'max_allowed_packet' => false, 'max_connections' => false, 'query_cache_limit' => true, 'query_cache_size' => true, 'query_cache_type' => 'ON');
     if ($dbq = QM_Collectors::get('db_queries')) {
         foreach ($dbq->db_objects as $id => $db) {
             $variables = $db->get_results("\n\t\t\t\t\tSHOW VARIABLES\n\t\t\t\t\tWHERE Variable_name IN ( '" . implode("', '", array_keys($mysql_vars)) . "' )\n\t\t\t\t");
             if (is_resource($db->dbh)) {
                 # Old mysql extension
                 $extension = 'mysql';
             } else {
                 if (is_object($db->dbh)) {
                     # mysqli or PDO
                     $extension = get_class($db->dbh);
                 } else {
                     # Who knows?
                     $extension = null;
                 }
             }
             if (method_exists($db, 'db_version')) {
                 $server = $db->db_version();
             } else {
                 $server = null;
             }
             if (isset($db->use_mysqli) && $db->use_mysqli) {
                 $client = mysqli_get_client_version();
             } else {
                 if (preg_match('|[0-9]{1,2}\\.[0-9]{1,2}\\.[0-9]{1,2}|', mysql_get_client_info(), $matches)) {
                     $client = $matches[0];
                 } else {
                     $client = null;
                 }
             }
             if ($client) {
                 $client_version = implode('.', QM_Util::get_client_version($client));
                 $client_version = sprintf('%s (%s)', $client, $client_version);
             } else {
                 $client_version = null;
             }
             $info = array('extension' => $extension, 'server version' => $server, 'client version' => $client_version, 'user' => $db->dbuser, 'host' => $db->dbhost, 'database' => $db->dbname);
             $this->data['db'][$id] = array('info' => $info, 'vars' => $mysql_vars, 'variables' => $variables);
         }
     }
     $this->data['php']['version'] = phpversion();
     $this->data['php']['sapi'] = php_sapi_name();
     $this->data['php']['user'] = self::get_current_user();
     if (defined('HHVM_VERSION')) {
         $this->data['php']['hhvm'] = HHVM_VERSION;
     }
     foreach ($this->php_vars as $setting) {
         $this->data['php']['variables'][$setting]['after'] = ini_get($setting);
     }
     $this->data['php']['error_reporting'] = error_reporting();
     $this->data['wp'] = array('version' => $wp_version, 'WP_DEBUG' => self::format_bool_constant('WP_DEBUG'), 'WP_DEBUG_DISPLAY' => self::format_bool_constant('WP_DEBUG_DISPLAY'), 'WP_DEBUG_LOG' => self::format_bool_constant('WP_DEBUG_LOG'), 'SCRIPT_DEBUG' => self::format_bool_constant('SCRIPT_DEBUG'), 'WP_CACHE' => self::format_bool_constant('WP_CACHE'), 'CONCATENATE_SCRIPTS' => self::format_bool_constant('CONCATENATE_SCRIPTS'), 'COMPRESS_SCRIPTS' => self::format_bool_constant('COMPRESS_SCRIPTS'), 'COMPRESS_CSS' => self::format_bool_constant('COMPRESS_CSS'), 'WP_LOCAL_DEV' => self::format_bool_constant('WP_LOCAL_DEV'));
     if (is_multisite()) {
         $this->data['wp']['SUNRISE'] = self::format_bool_constant('SUNRISE');
     }
     $server = explode(' ', $_SERVER['SERVER_SOFTWARE']);
     $server = explode('/', reset($server));
     if (isset($server[1])) {
         $server_version = $server[1];
     } else {
         $server_version = null;
     }
     if (isset($_SERVER['SERVER_ADDR'])) {
         $address = $_SERVER['SERVER_ADDR'];
     } else {
         $address = null;
     }
     $this->data['server'] = array('name' => $server[0], 'version' => $server_version, 'address' => $address, 'host' => php_uname('n'));
 }
Beispiel #26
0
 public static function populate_callback(array $callback)
 {
     $access = '->';
     if (is_string($callback['function']) and false !== strpos($callback['function'], '::')) {
         $callback['function'] = explode('::', $callback['function']);
         $access = '::';
     }
     try {
         if (is_array($callback['function'])) {
             if (is_object($callback['function'][0])) {
                 $class = get_class($callback['function'][0]);
             } else {
                 $class = $callback['function'][0];
             }
             $callback['name'] = $class . $access . $callback['function'][1] . '()';
             $ref = new ReflectionMethod($class, $callback['function'][1]);
         } else {
             if (is_object($callback['function']) and is_a($callback['function'], 'Closure')) {
                 $ref = new ReflectionFunction($callback['function']);
                 $file = trim(QM_Util::standard_dir($ref->getFileName(), ''), '/');
                 $callback['name'] = sprintf(__('{closure}() on line %1$d of %2$s', 'query-monitor'), $ref->getEndLine(), $file);
             } else {
                 $callback['name'] = $callback['function'] . '()';
                 $ref = new ReflectionFunction($callback['function']);
             }
         }
         $callback['file'] = $ref->getFileName();
         $callback['line'] = $ref->getStartLine();
         $callback['component'] = self::get_file_component($ref->getFileName());
     } catch (ReflectionException $e) {
         $callback['error'] = new WP_Error('reflection_exception', $e->getMessage());
     }
     return $callback;
 }
 public function test_populate_callback_invalid_static_class_string()
 {
     $function = 'Invalid_Class::goodbye';
     $callback = self::get_callback($function);
     $actual = QM_Util::populate_callback($callback);
     $this->assertWPError($actual['error']);
 }
Beispiel #28
0
 /**
  * Returns a file path, name, and line number. Safe for output.
  *
  * If clickable file links are enabled, a link such as this is returned:
  *
  *     <a href="subl://open/?line={line}&url={file}">{text}</a>
  *
  * Otherwise, the display text and file details such as this is returned:
  *
  *     {text}<br>{file}:{line}
  *
  * @param  string $text The display text, such as a function name or file name.
  * @param  string $file The full file path and name.
  * @param  int    $line Optional. A line number, if appropriate.
  * @return string The fully formatted file link or file name, safe for output.
  */
 public static function output_filename($text, $file, $line = 0)
 {
     if (empty($file)) {
         return esc_html($text);
     }
     # Further reading:
     # http://simonwheatley.co.uk/2012/07/clickable-stack-traces/
     # https://github.com/grych/subl-handler
     $link_line = $line ? $line : 1;
     if (!isset(self::$file_link_format)) {
         $format = ini_get('xdebug.file_link_format');
         $format = apply_filters('qm/output/file_link_format', $format);
         if (empty($format)) {
             self::$file_link_format = false;
         } else {
             self::$file_link_format = str_replace(array('%f', '%l'), array('%1$s', '%2$d'), $format);
         }
     }
     if (false === self::$file_link_format) {
         $fallback = QM_Util::standard_dir($file, '');
         if ($line) {
             $fallback .= ':' . $line;
         }
         $return = esc_html($text);
         if ($fallback !== $text) {
             $return .= '<br><span class="qm-info">&nbsp;' . esc_html($fallback) . '</span>';
         }
         return $return;
     }
     $link = sprintf(self::$file_link_format, urlencode($file), intval($link_line));
     return sprintf('<a href="%s">%s</a>', esc_attr($link), esc_html($text));
 }