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 | public/class-metasync-hidden-post.php +56 -21 2.6.7 → 2.7.2 View file →
@@ -56,9 +56,9 @@
56 56 $attachment_id = media_handle_sideload($file_array, 0);
57 57
58 58 # Clean up the temp file
59 59 if (file_exists($tmp_file_path)) {
60 - @unlink($tmp_file_path); # Delete only the temp copy, not the original file
60 + @wp_delete_file($tmp_file_path); # Delete only the temp copy, not the original file
61 61 }
62 62
63 63 if (is_wp_error($attachment_id)) {
64 64 return ''; # Return empty if upload fails
@@ -104,18 +104,14 @@
104 104
105 105 # Check if the post already exists by title
106 106 global $wpdb;
107 107
108 - # prepare query
109 - $query = $wpdb->prepare(
108 + # Get the Data (prepare query inline)
109 + $existing_post = $wpdb->get_var($wpdb->prepare( // phpcs:ignore WordPress.DB.DirectDatabaseQuery -- maintenance of the plugin hidden OG post — direct status/content surgery keeps it invisible to WP_Query consumers
110 110 "SELECT ID FROM {$wpdb->posts} WHERE post_title = %s AND (post_type = 'post' OR post_type = 'metasync_post_type') LIMIT 1",
111 111 $this->post_title
112 - );
112 + ));
113 113
114 -
115 - # Get the Data
116 - $existing_post = $wpdb->get_var($query);
117 -
118 114 $this->get_image_url_Data();
119 115 if ($existing_post) {
120 116
121 117 #show post
@@ -170,9 +166,9 @@
170 166 }
171 167
172 168 # Flip to publish via direct DB write — bypasses transition_post_status
173 169 global $wpdb;
174 - $wpdb->update(
170 + $wpdb->update( // phpcs:ignore WordPress.DB.DirectDatabaseQuery -- maintenance of the plugin hidden OG post — direct status/content surgery keeps it invisible to WP_Query consumers
175 171 $wpdb->posts,
176 172 ['post_status' => 'publish'],
177 173 ['ID' => $post_id]
178 174 );
@@ -229,9 +225,9 @@
229 225 private function check_and_fix_page_content($post_id)
230 226 {
231 227 # Switch to page type via direct DB write — bypasses transition_post_status
232 228 global $wpdb;
233 - $wpdb->update(
229 + $wpdb->update( // phpcs:ignore WordPress.DB.DirectDatabaseQuery -- maintenance of the plugin hidden OG post — direct status/content surgery keeps it invisible to WP_Query consumers
234 230 $wpdb->posts,
235 231 [
236 232 'post_type' => 'page',
237 233 'post_status' => 'publish',
@@ -277,8 +273,12 @@
277 273 * add post title and post feature image on the content
278 274 */
279 275 private function check_and_fix_post_content($post_id,$post_type='post')
280 276 {
277 + if (!class_exists('DOMDocument')) {
278 + error_log('MetaSync: skipping check_and_fix_post_content — DOMDocument (php-dom extension) is not available on this server.'); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- genuine failure path, bounded, no secrets
279 + return false;
280 + }
281 281
282 282 # Get the post title
283 283 $post_title = get_the_title($post_id);
284 284
@@ -297,18 +297,23 @@
297 297
298 298 # Get the preview URL of the post
299 299 $post_url = get_permalink($post_id);
300 300
301 - # Initialize cURL to fetch the post HTML
302 - $ch = curl_init();
303 - curl_setopt($ch, CURLOPT_URL, $post_url); # Set the URL to fetch
304 - curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); # Return the response as a string
305 - curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); # Follow redirects if any
306 - $html = curl_exec($ch); # Execute the request and store the HTML response
307 - curl_close($ch); # Close the cURL session
301 + $probe_result = $this->fetch_post_html($post_url);
302 + $html = $probe_result['body'];
303 + $http_code = $probe_result['status'];
308 304
309 - # check that the html object is not empty
310 - if(empty($html)){
305 + # Only trust the probe when we verifiably fetched the test post.
306 + # A cache 404, bot challenge, or security-plugin block used to parse as
307 + # "title not found" and flip title_in_headings to false, which made every
308 + # synced post get an extra <h1> prepended (duplicate H1 on the live page).
309 + # "please do not delete" appears in both the test post title and body.
310 + if (empty($html) || $http_code !== 200 || stripos($html, 'please do not delete') === false) {
311 +
312 + # Inconclusive fetch: keep the previously detected values and record
313 + # the run so the probe is not retried on every request.
314 + $metasyncData['general']['last_run_time'] = time();
315 + Metasync::set_option($metasyncData);
311 316 return false;
312 317 }
313 318
314 319 # Load the HTML content into DOMDocument
@@ -393,8 +398,38 @@
393 398 ];
394 399 }
395 400
396 401 /**
402 + * Fetch the hidden test post for content detection.
403 + *
404 + * @param string $post_url Hidden test post URL.
405 + * @return array{body: string|false, status: int}
406 + */
407 + protected function fetch_post_html($post_url)
408 + {
409 + $response = wp_remote_get(
410 + $post_url,
411 + [
412 + 'timeout' => 15,
413 + 'redirection' => 5,
414 + 'sslverify' => true,
415 + ]
416 + );
417 +
418 + if (is_wp_error($response)) {
419 + return [
420 + 'body' => false,
421 + 'status' => 0,
422 + ];
423 + }
424 +
425 + return [
426 + 'body' => wp_remote_retrieve_body($response),
427 + 'status' => (int) wp_remote_retrieve_response_code($response),
428 + ];
429 + }
430 +
431 + /**
397 432 * Change post type to a post type to hide it from admin
398 433 */
399 434 private function show_post_completely($post_id)
400 435 {
@@ -401,9 +436,9 @@
401 436 global $wpdb;
402 437
403 438 # Single direct DB write for both type + status — bypasses
404 439 # transition_post_status so auto-share plugins never see this post
405 - $wpdb->update(
440 + $wpdb->update( // phpcs:ignore WordPress.DB.DirectDatabaseQuery -- maintenance of the plugin hidden OG post — direct status/content surgery keeps it invisible to WP_Query consumers
406 441 $wpdb->posts,
407 442 [
408 443 'post_type' => 'post',
409 444 'post_status' => 'publish',
@@ -420,9 +455,9 @@
420 455 global $wpdb;
421 456
422 457 # Single direct DB write — bypasses transition_post_status on the
423 458 # publish→draft transition (some plugins hook that direction too)
424 - $wpdb->update(
459 + $wpdb->update( // phpcs:ignore WordPress.DB.DirectDatabaseQuery -- maintenance of the plugin hidden OG post — direct status/content surgery keeps it invisible to WP_Query consumers
425 460 $wpdb->posts,
426 461 [
427 462 'post_status' => 'draft',
428 463 'post_type' => 'metasync_post_type',