PluginProbe
Search Atlas SEO – OTTO AI SEO Automation for WordPress / 2.7.1
Search Atlas SEO – OTTO AI SEO Automation for WordPress v2.7.1
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 | includes/class-metasync-opengraph.php +18 -8 2.7.0 → 2.7.1 View file →
@@ -178,9 +178,9 @@
178 178 if ($value === '') {
179 179 return false;
180 180 }
181 181 # 'default' text domain, matching the __() call core itself uses.
182 - if ($value === 'Auto Draft' || $value === trim(__('Auto Draft'))) {
182 + if ($value === 'Auto Draft' || $value === trim(__('Auto Draft', 'default'))) { // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch -- resolves core's own 'Auto Draft' placeholder, which only exists in core's 'default' domain; the plugin text domain cannot reproduce it
183 183 return true;
184 184 }
185 185 # Registry arm: a variant captured in another locale's admin request.
186 186 # Without it the guard above is English-only on every non-admin request,
@@ -241,9 +241,9 @@
241 241 *
242 242 * @return void
243 243 */
244 244 public static function seed_auto_draft_placeholder() {
245 - self::remember_auto_draft_placeholder(__('Auto Draft'));
245 + self::remember_auto_draft_placeholder(__('Auto Draft', 'default')); // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch -- resolves core's own 'Auto Draft' placeholder, which only exists in core's 'default' domain; the plugin text domain cannot reproduce it
246 246 }
247 247
248 248 /**
249 249 * Read a persisted social meta value, collapsing the "Auto Draft" placeholder
@@ -730,9 +730,9 @@
730 730
731 731 # LPS / custom-HTML pages bake their own OG/social tags into their HTML bundle,
732 732 # served before wp_head — so this box does nothing on them. Hide it; the SEO
733 733 # read-only notice covers the messaging.
734 - $lps_post_id = isset($_GET['post']) ? intval($_GET['post']) : (isset($_POST['post_ID']) ? intval($_POST['post_ID']) : 0);
734 + $lps_post_id = isset($_GET['post']) ? intval($_GET['post']) : (isset($_POST['post_ID']) ? intval($_POST['post_ID']) : 0); // phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.NonceVerification.Recommended -- read-only post ID to pick meta boxes
735 735 if (function_exists('metasync_is_custom_or_lps_page') && $lps_post_id > 0 && metasync_is_custom_or_lps_page($lps_post_id)) {
736 736 return;
737 737 }
738 738
@@ -742,8 +742,9 @@
742 742
743 743 foreach ($post_types as $post_type) {
744 744 add_meta_box(
745 745 self::META_BOX_ID,
746 + /* translators: %s: effective plugin name (whitelabel-aware). */
746 747 sprintf(esc_html__('Social Media & Open Graph by %s', 'metasync'), $plugin_name),
747 748 [$this, 'render_meta_box'],
748 749 $post_type,
749 750 'normal',
@@ -1044,9 +1045,9 @@
1044 1045 # remember_auto_draft_placeholder() already skips. Verified against
1045 1046 # __( 'Auto Draft' ), never trusted as a bare string, so a builder's
1046 1047 # custom-seeded auto-draft title is never captured.
1047 1048 if ($post->post_status === 'auto-draft'
1048 - && $title !== '' && $title === trim(__('Auto Draft'))) {
1049 + && $title !== '' && $title === trim(__('Auto Draft', 'default'))) { // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch -- resolves core's own 'Auto Draft' placeholder, which only exists in core's 'default' domain; the plugin text domain cannot reproduce it
1049 1050 self::remember_auto_draft_placeholder($title);
1050 1051 }
1051 1052
1052 1053 # Flag maintenance: recognition is context-independent thanks to the
@@ -1785,9 +1786,9 @@
1785 1786 private function generate_preview_html($title, $description, $image, $url, $twitter_title = '', $twitter_description = '', $twitter_image = '') {
1786 1787 # Parse domain from URL
1787 1788 $domain = '';
1788 1789 if (!empty($url)) {
1789 - $parsed = parse_url($url);
1790 + $parsed = wp_parse_url($url);
1790 1791 $domain = $parsed['host'] ?? '';
1791 1792 }
1792 1793
1793 1794 # Fallback to site URL if no domain found
@@ -1792,9 +1793,9 @@
1792 1793
1793 1794 # Fallback to site URL if no domain found
1794 1795 if (empty($domain)) {
1795 1796 $site_url = get_site_url();
1796 - $parsed = parse_url($site_url);
1797 + $parsed = wp_parse_url($site_url);
1797 1798 $domain = $parsed['host'] ?? 'your-site.com';
1798 1799 }
1799 1800
1800 1801 # Provide fallbacks for empty values
@@ -2371,11 +2372,20 @@
2371 2372 /**
2372 2373 * Check if post slug changed via edit slug functionality
2373 2374 */
2374 2375 public function check_slug_change() {
2376 + # Fires on the same admin-ajax request as core's sample-permalink
2377 + # handler, but at priority 5 — before core validates the nonce and
2378 + # capability at its own priority-10 callback. Verify them ourselves
2379 + # before any post-meta write. Return (not die) so core still serves
2380 + # the preview request normally.
2381 + if (!check_ajax_referer('samplepermalink', 'samplepermalinknonce', false)) {
2382 + return;
2383 + }
2384 +
2375 2385 # Get the post ID from the request
2376 2386 $post_id = isset($_POST['post_id']) ? intval($_POST['post_id']) : 0;
2377 - if (!$post_id) {
2387 + if (!$post_id || !current_user_can('edit_post', $post_id)) {
2378 2388 return;
2379 2389 }
2380 2390
2381 2391 # Only check for supported post types
@@ -2408,9 +2418,9 @@
2408 2418 # This means the og:url was set to the post permalink (not a custom URL)
2409 2419 if ($current_og_url !== $current_permalink && strpos($current_og_url, '?p=') === false) {
2410 2420 # Check if the og:url was the old permalink by comparing with a generated old permalink
2411 2421 $old_post = clone $post;
2412 - $old_slug = isset($_POST['new_slug']) ? sanitize_title($_POST['new_slug']) : $post->post_name;
2422 + $old_slug = isset($_POST['new_slug']) ? sanitize_title(wp_unslash($_POST['new_slug'])) : $post->post_name;
2413 2423
2414 2424 # If the og:url doesn't match the current permalink, it might be the old one
2415 2425 # We'll update it to the new permalink
2416 2426 if ($current_og_url !== $current_permalink) {