PluginProbe
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO / 2.14.0
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO v2.14.0
2.14.0 2.13.0 2.12.0 2.11.0 2.10.0 2.9.0 2.8.0 2.7.0 2.6.0 2.5.0 2.4.0 2.3.0 2.2.0 2.1.1 2.1.0 2.0.2 2.0.1 2.0.0 1.32.0 1.31.0 1.30.0 1.29.0 1.28.0 1.27.0 1.26.0 All 55 releases
← All changes | includes/seo/class-global-seo-post-types.php +59 -2 2.11.0 → 2.14.0 View file →
@@ -34,9 +34,10 @@
34 34 * Whether a post type may receive Global SEO settings.
35 35 *
36 36 * Policy: the type must be public; a non-built-in type must also be
37 37 * front-end viewable (excludes builder/utility CPTs that register
38 - * `public => true` only for previews); and it must not be on the filterable
38 + * `public => true` only for previews); WordPress must actually render a page
39 + * for it; and it must not be on the filterable
39 40 * `thinkrank_global_seo_excluded_post_types` deny list.
40 41 *
41 42 * @param \WP_Post_Type|string $post_type Post type object or name.
42 43 * @return bool
@@ -49,14 +50,70 @@
49 50 }
50 51
51 52 // Builder/utility CPTs that register public => true for preview purposes
52 53 // but aren't front-end viewable content (e.g. Elementor's "Floating
53 - // Elements"). Built-in types (post/page/attachment) are always kept.
54 + // Elements"). Built-in types (post/page) are always kept.
54 55 if ($object->_builtin === false && !is_post_type_viewable($object)) {
55 56 return false;
56 57 }
57 58
59 + // Attachment is built-in and public, so the rule above keeps it, but on
60 + // a site that does not serve attachment pages there is no document for
61 + // any of these settings to reach (#843).
62 + if ('attachment' === $object->name && !self::renders_a_page($object)) {
63 + return false;
64 + }
65 +
58 66 return !in_array($object->name, self::excluded_post_types($object), true);
67 + }
68 +
69 + /**
70 + * Whether WordPress renders an HTML page for this post type on this site.
71 + *
72 + * Only `attachment` can answer no. Core has redirected attachment URLs
73 + * straight to the file since WordPress 6.4, and does so by default on a new
74 + * install: the request 301s to the uploads path, so there is no <head> for a
75 + * title, a robots meta, a canonical or JSON-LD to appear in. Every Global
76 + * SEO control for the type is therefore inert, while the screen presents
77 + * itself exactly like the ones that work.
78 + *
79 + * Read from the option core itself consults rather than hardcoded, and kept
80 + * in one place so the admin nav, the REST validator and the ability
81 + * validators cannot disagree about it. A site with attachment pages enabled
82 + * is unaffected and keeps every setting it has.
83 + *
84 + * Deliberately not applied to any other type: `is_post_type_viewable()`
85 + * already covers the general case, and this is a core quirk specific to
86 + * attachments.
87 + *
88 + * @since 2.14.0
89 + *
90 + * @param \WP_Post_Type|string $post_type Post type object or name.
91 + * @return bool
92 + */
93 + public static function renders_a_page($post_type): bool {
94 + $object = is_string($post_type) ? get_post_type_object($post_type) : $post_type;
95 +
96 + if (!$object instanceof \WP_Post_Type) {
97 + return false;
98 + }
99 +
100 + if ('attachment' !== $object->name) {
101 + return true;
102 + }
103 +
104 + // The same test core's own redirect makes, in wp-includes/canonical.php:
105 + // if ( is_attachment() && ! get_option( 'wp_attachment_pages_enabled' ) )
106 + // so this agrees with what actually happens to the request. Core has no
107 + // accessor for it; several core files read the option directly, and two
108 + // of them compare against '1' rather than testing truthiness. The
109 + // redirect uses the truthy form, and the redirect is what decides
110 + // whether a document exists, so that is the form matched here.
111 + //
112 + // The default is false because core's is: schema.php seeds a fresh
113 + // install with 0, while upgrade.php sets 1 for a site upgrading from
114 + // before 6.4, which keeps its attachment pages and is unaffected.
115 + return (bool) get_option('wp_attachment_pages_enabled', false);
59 116 }
60 117
61 118 /**
62 119 * Every post type that passes {@see self::is_allowed()}.