PluginProbe
Search Atlas SEO – OTTO AI SEO Automation for WordPress / 2.7.2
Search Atlas SEO – OTTO AI SEO Automation for WordPress v2.7.2
2.7.1 2.7.2 2.7.0 2.6.26 2.6.25 2.6.24 2.6.23 2.6.22 2.6.21 2.6.20 2.6.19 2.6.18 2.6.17 2.6.16 2.6.15 2.6.14 2.6.13 2.6.12 2.6.11 2.6.10 2.6.9 2.6.8 2.6.7 2.6.6 2.6.5 All 141 releases
← All changes | telemetry/wordpress-error-handler.php +27 -8 2.6.16 → 2.7.2 View file →
@@ -10,8 +10,10 @@
10 10 if (!defined('WPINC')) {
11 11 die;
12 12 }
13 13
14 +require_once __DIR__ . '/privacy.php';
15 +
14 16 /**
15 17 * WordPress Error Handler Class
16 18 */
17 19 class MetaSync_WordPress_Error_Handler {
@@ -87,9 +89,9 @@
87 89 * Setup WordPress error handlers - Only for plugin-specific errors
88 90 */
89 91 private function setup_error_handlers() {
90 92 // Store previous handlers to chain them properly
91 - $this->previous_error_handler = set_error_handler(array($this, 'capture_php_error'), E_ALL);
93 + $this->previous_error_handler = set_error_handler(array($this, 'capture_php_error'), E_ALL); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_set_error_handler -- plugin logger sink / last-resort fallback
92 94 $this->previous_exception_handler = set_exception_handler(array($this, 'capture_exception'));
93 95
94 96 // Hook into WordPress fatal error handler (only for plugin errors)
95 97 add_filter('wp_fatal_error_handler', array($this, 'capture_fatal_error'));
@@ -121,8 +123,14 @@
121 123 if ($this->previous_error_handler && is_callable($this->previous_error_handler)) {
122 124 $handled = call_user_func($this->previous_error_handler, $severity, $message, $file, $line);
123 125 }
124 126
127 + // Respect error_reporting() and the @ suppression operator — never capture masked errors
128 + // phpcs:ignore WordPress.PHP.DevelopmentFunctions.prevent_path_disclosure_error_reporting, PluginCheck.CodeAnalysis.PHPErrorReporting.DirectErrorReportingCall -- reads the current mask, does not print paths; reading the mask is the only way a custom handler can respect the @ operator
129 + if (!(error_reporting() & $severity)) {
130 + return $handled;
131 + }
132 +
125 133 // Only capture fatal-level errors — skip warnings, notices, deprecated, strict
126 134 $fatal_severities = [E_USER_ERROR, E_RECOVERABLE_ERROR];
127 135 if (!in_array($severity, $fatal_severities, true)) {
128 136 return $handled;
@@ -135,9 +143,9 @@
135 143 'severity' => $severity,
136 144 'file' => $file,
137 145 'line' => $line,
138 146 'error_level' => $this->get_error_level($severity),
139 - 'backtrace' => debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 10)
147 + 'backtrace' => debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 10) // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_debug_backtrace -- genuine failure path, bounded, no secrets
140 148 ));
141 149 }
142 150
143 151 // Return the result from the previous handler, or false to continue normal error handling
@@ -148,10 +156,12 @@
148 156 * Capture uncaught exceptions - Only plugin-specific exceptions
149 157 */
150 158 public function capture_exception($exception) {
151 159 // First, call the previous exception handler if it exists
160 + $chained = false;
152 161 if ($this->previous_exception_handler && is_callable($this->previous_exception_handler)) {
153 162 call_user_func($this->previous_exception_handler, $exception);
163 + $chained = true;
154 164 }
155 165
156 166 // Only capture exceptions from our plugin or directly related to our plugin
157 167 if ($this->should_capture_error($exception->getFile())) {
@@ -162,9 +172,16 @@
162 172 'line' => $exception->getLine(),
163 173 'trace' => $exception->getTraceAsString(),
164 174 'exception_object' => $exception
165 175 ));
176 + return;
166 177 }
178 +
179 + // Not our exception and nothing else handled it: restore PHP's default
180 + // uncaught-exception handling instead of swallowing it silently.
181 + if (!$chained) {
182 + throw $exception;
183 + }
167 184 }
168 185
169 186 /**
170 187 * Capture fatal errors
@@ -267,9 +284,9 @@
267 284 /**
268 285 * Check if the current environment is localhost/development
269 286 */
270 287 private function is_localhost() {
271 - $host = parse_url(home_url(), PHP_URL_HOST);
288 + $host = wp_parse_url(home_url(), PHP_URL_HOST);
272 289
273 290 // Check for common localhost patterns
274 291 $localhost_patterns = [
275 292 'localhost',
@@ -282,9 +299,9 @@
282 299 '.localhost'
283 300 ];
284 301
285 302 foreach ($localhost_patterns as $pattern) {
286 - if (strpos($host, $pattern) !== false) {
303 + if ($host !== false && $host !== null && strpos($host, $pattern) !== false) {
287 304 return true;
288 305 }
289 306 }
290 307
@@ -325,9 +342,9 @@
325 342 $context = array_merge($context, array(
326 343 'wp_url' => home_url(),
327 344 'plugin_version' => defined('METASYNC_VERSION') ? METASYNC_VERSION : '1.0.0',
328 345 'plugin_name' => 'Search Engine Labs SEO (MetaSync)',
329 - 'error_timestamp' => date('Y-m-d H:i:s'),
346 + 'error_timestamp' => gmdate('Y-m-d H:i:s'),
330 347 'site_info' => array(
331 348 'site_title' => get_bloginfo('name'),
332 349 'wp_version' => get_bloginfo('version'),
333 350 'admin_email' => get_bloginfo('admin_email'),
@@ -336,12 +353,14 @@
336 353 'memory_limit' => ini_get('memory_limit'),
337 354 'multisite' => is_multisite()
338 355 ),
339 356 'request_info' => array(
340 - 'url' => $_SERVER['REQUEST_URI'] ?? 'unknown',
357 + 'url' => metasync_telemetry_request_path(),
341 358 'method' => $_SERVER['REQUEST_METHOD'] ?? 'unknown',
342 359 'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? 'unknown',
343 - 'referer' => $_SERVER['HTTP_REFERER'] ?? 'none'
360 + 'referer' => isset($_SERVER['HTTP_REFERER'])
361 + ? metasync_telemetry_request_path($_SERVER['HTTP_REFERER'])
362 + : 'none'
344 363 )
345 364 ));
346 365
347 366 // Determine severity level
@@ -501,8 +520,8 @@
501 520
502 521 // Initialize the error handler immediately when this file is loaded
503 522 // This ensures we catch errors that happen during plugin initialization
504 523 // Must be initialized early to catch parse errors and fatal errors
505 -if (class_exists('MetaSync_WordPress_Error_Handler')) {
524 +if (!metasync_telemetry_is_disabled() && class_exists('MetaSync_WordPress_Error_Handler')) {
506 525 new MetaSync_WordPress_Error_Handler();
507 526 }
508 527 ?>