PluginProbe
Yoast SEO – Advanced SEO with real-time guidance and built-in AI / 27.9
Yoast SEO – Advanced SEO with real-time guidance and built-in AI v27.9
28.5 28.4 28.3 28.2 28.1 28.0 27.9 27.8 27.7 27.6 27.5 trunk 18.0 18.1 18.2 18.3 18.4 18.4.1 18.5 18.5.1 18.6 18.7 18.8 18.9 19.0 All 129 releases
wordpress-seo / src / integrations / front-end / crawl-cleanup-rss.php

crawl-cleanup-rss.php in Yoast SEO – Advanced SEO with real-time guidance and built-in AI 27.9, at src/integrations/front-end/crawl-cleanup-rss.php

213 lines 6.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Yoast\WP\SEO\Integrations\Front_End;
4
5 use Yoast\WP\SEO\Conditionals\Front_End_Conditional;
6 use Yoast\WP\SEO\Helpers\Options_Helper;
7 use Yoast\WP\SEO\Integrations\Integration_Interface;
8
9 /**
10 * Adds actions that cleanup unwanted rss feed links.
11 */
12 class Crawl_Cleanup_Rss implements Integration_Interface {
13
14 /**
15 * The options helper.
16 *
17 * @var Options_Helper
18 */
19 private $options_helper;
20
21 /**
22 * Crawl Cleanup RSS integration constructor.
23 *
24 * @param Options_Helper $options_helper The option helper.
25 */
26 public function __construct( Options_Helper $options_helper ) {
27 $this->options_helper = $options_helper;
28 }
29
30 /**
31 * Returns the conditionals based on which this loadable should be active.
32 *
33 * @return array<string> The conditionals.
34 */
35 public static function get_conditionals() {
36 return [ Front_End_Conditional::class ];
37 }
38
39 /**
40 * Register our RSS related hooks.
41 *
42 * @return void
43 */
44 public function register_hooks() {
45 if ( $this->is_true( 'remove_feed_global' ) ) {
46 \add_filter( 'feed_links_show_posts_feed', '__return_false' );
47 }
48
49 if ( $this->is_true( 'remove_feed_global_comments' ) ) {
50 \add_filter( 'feed_links_show_comments_feed', '__return_false' );
51 }
52
53 \add_action( 'wp', [ $this, 'maybe_disable_feeds' ] );
54 \add_action( 'wp', [ $this, 'maybe_redirect_feeds' ], -10_000 );
55 }
56
57 /**
58 * Disable feeds on selected cases.
59 *
60 * @return void
61 */
62 public function maybe_disable_feeds() {
63 if ( $this->is_true( 'remove_feed_post_comments' ) ) {
64 \add_filter( 'feed_links_extra_show_post_comments_feed', '__return_false' );
65 }
66 if ( $this->is_true( 'remove_feed_authors' ) ) {
67 \add_filter( 'feed_links_extra_show_author_feed', '__return_false' );
68 }
69 if ( $this->is_true( 'remove_feed_categories' ) ) {
70 \add_filter( 'feed_links_extra_show_category_feed', '__return_false' );
71 }
72 if ( $this->is_true( 'remove_feed_tags' ) ) {
73 \add_filter( 'feed_links_extra_show_tag_feed', '__return_false' );
74 }
75 if ( $this->is_true( 'remove_feed_custom_taxonomies' ) ) {
76 \add_filter( 'feed_links_extra_show_tax_feed', '__return_false' );
77 }
78 if ( $this->is_true( 'remove_feed_post_types' ) ) {
79 \add_filter( 'feed_links_extra_show_post_type_archive_feed', '__return_false' );
80 }
81 if ( $this->is_true( 'remove_feed_search' ) ) {
82 \add_filter( 'feed_links_extra_show_search_feed', '__return_false' );
83 }
84 }
85
86 /**
87 * Redirect feeds we don't want away.
88 *
89 * @return void
90 */
91 public function maybe_redirect_feeds() {
92 global $wp_query;
93
94 if ( ! \is_feed() ) {
95 return;
96 }
97
98 if ( \in_array( \get_query_var( 'feed' ), [ 'atom', 'rdf' ], true ) && $this->is_true( 'remove_atom_rdf_feeds' ) ) {
99 $this->redirect_feed( \home_url(), 'We disable Atom/RDF feeds for performance reasons.' );
100 }
101
102 // Only if we're on the global feed, the query is _just_ `'feed' => 'feed'`, hence this check.
103 if ( ( $wp_query->query === [ 'feed' => 'feed' ]
104 || $wp_query->query === [ 'feed' => 'atom' ]
105 || $wp_query->query === [ 'feed' => 'rdf' ] )
106 && $this->is_true( 'remove_feed_global' ) ) {
107 $this->redirect_feed( \home_url(), 'We disable the RSS feed for performance reasons.' );
108 }
109
110 if ( \is_comment_feed() && ! ( \is_singular() || \is_attachment() ) && $this->is_true( 'remove_feed_global_comments' ) ) {
111 $this->redirect_feed( \home_url(), 'We disable comment feeds for performance reasons.' );
112 }
113 elseif ( \is_comment_feed()
114 && \is_singular()
115 && ( $this->is_true( 'remove_feed_post_comments' ) || $this->is_true( 'remove_feed_global_comments' ) ) ) {
116 $url = \get_permalink( \get_queried_object() );
117 $this->redirect_feed( $url, 'We disable post comment feeds for performance reasons.' );
118 }
119
120 if ( \is_author() && $this->is_true( 'remove_feed_authors' ) ) {
121 $author_id = (int) \get_query_var( 'author' );
122 $url = \get_author_posts_url( $author_id );
123 $this->redirect_feed( $url, 'We disable author feeds for performance reasons.' );
124 }
125
126 if ( ( \is_category() && $this->is_true( 'remove_feed_categories' ) )
127 || ( \is_tag() && $this->is_true( 'remove_feed_tags' ) )
128 || ( \is_tax() && $this->is_true( 'remove_feed_custom_taxonomies' ) ) ) {
129 $term = \get_queried_object();
130 $url = \get_term_link( $term, $term->taxonomy );
131 if ( \is_wp_error( $url ) ) {
132 $url = \home_url();
133 }
134 $this->redirect_feed( $url, 'We disable taxonomy feeds for performance reasons.' );
135 }
136
137 if ( ( \is_post_type_archive() ) && $this->is_true( 'remove_feed_post_types' ) ) {
138 $url = \get_post_type_archive_link( $this->get_queried_post_type() );
139 $this->redirect_feed( $url, 'We disable post type feeds for performance reasons.' );
140 }
141
142 if ( \is_search() && $this->is_true( 'remove_feed_search' ) ) {
143 $url = \trailingslashit( \home_url() ) . '?s=' . \get_search_query();
144 $this->redirect_feed( $url, 'We disable search RSS feeds for performance reasons.' );
145 }
146 }
147
148 /**
149 * Sends a cache control header.
150 *
151 * @param int $expiration The expiration time.
152 *
153 * @return void
154 */
155 public function cache_control_header( $expiration ) {
156 \header_remove( 'Expires' );
157
158 // The cacheability of the current request. 'public' allows caching, 'private' would not allow caching by proxies like CloudFlare.
159 $cacheability = 'public';
160 $format = '%1$s, max-age=%2$d, s-maxage=%2$d, stale-while-revalidate=120, stale-if-error=14400';
161
162 if ( \is_user_logged_in() ) {
163 $expiration = 0;
164 $cacheability = 'private';
165 $format = '%1$s, max-age=%2$d';
166 }
167
168 \header( \sprintf( 'Cache-Control: ' . $format, $cacheability, $expiration ), true );
169 }
170
171 /**
172 * Redirect a feed result to somewhere else.
173 *
174 * @param string $url The location we're redirecting to.
175 * @param string $reason The reason we're redirecting.
176 *
177 * @return void
178 */
179 private function redirect_feed( $url, $reason ) {
180 \header_remove( 'Content-Type' );
181 \header_remove( 'Last-Modified' );
182
183 $this->cache_control_header( 7 * \DAY_IN_SECONDS );
184
185 \wp_safe_redirect( $url, 301, 'Yoast SEO: ' . $reason );
186 exit();
187 }
188
189 /**
190 * Retrieves the queried post type.
191 *
192 * @return string The queried post type.
193 */
194 private function get_queried_post_type() {
195 $post_type = \get_query_var( 'post_type' );
196 if ( \is_array( $post_type ) ) {
197 $post_type = \reset( $post_type );
198 }
199 return $post_type;
200 }
201
202 /**
203 * Checks if the value of an option is set to true.
204 *
205 * @param string $option_name The option name.
206 *
207 * @return bool
208 */
209 private function is_true( $option_name ) {
210 return $this->options_helper->get( $option_name ) === true;
211 }
212 }
213