• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Yoast / wordpress-seo / facad090b719a8bf9288646489cee2f1883c0f5b

28 May 2024 10:35AM UTC coverage: 52.628% (-0.004%) from 52.632%
facad090b719a8bf9288646489cee2f1883c0f5b

push

github

web-flow
Merge pull request #21393 from Yoast/20436-throwing-php-notice-trying-to-get-property-canonical-of-non-object

Adds fallback to main url when the indexable is not available.

7399 of 13455 branches covered (54.99%)

Branch coverage included in aggregate %.

0 of 11 new or added lines in 1 file covered. (0.0%)

1 existing line in 1 file now uncovered.

28318 of 54412 relevant lines covered (52.04%)

41282.08 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/integrations/front-end/feed-improvements.php
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
use Yoast\WP\SEO\Surfaces\Meta_Surface;
9

10
/**
11
 * Class Feed_Improvements
12
 */
13
class Feed_Improvements implements Integration_Interface {
14

15
        /**
16
         * Holds the options helper.
17
         *
18
         * @var Options_Helper
19
         */
20
        private $options;
21

22
        /**
23
         * Holds the meta helper surface.
24
         *
25
         * @var Meta_Surface
26
         */
27
        private $meta;
28

29
        /**
30
         * Canonical_Header constructor.
31
         *
32
         * @codeCoverageIgnore It only sets depedencies.
33
         *
34
         * @param Options_Helper $options The options helper.
35
         * @param Meta_Surface   $meta    The meta surface.
36
         */
37
        public function __construct(
38
                Options_Helper $options,
39
                Meta_Surface $meta
40
        ) {
41
                $this->options = $options;
42
                $this->meta    = $meta;
43
        }
44

45
        /**
46
         * Returns the conditionals based in which this loadable should be active.
47
         *
48
         * @return array
49
         */
50
        public static function get_conditionals() {
×
51
                return [ Front_End_Conditional::class ];
×
52
        }
53

54
        /**
55
         * Registers hooks to WordPress.
56
         *
57
         * @return void
58
         */
59
        public function register_hooks() {
×
60
                \add_filter( 'get_bloginfo_rss', [ $this, 'filter_bloginfo_rss' ], 10, 2 );
×
61
                \add_filter( 'document_title_separator', [ $this, 'filter_document_title_separator' ] );
×
62

63
                \add_action( 'do_feed_rss', [ $this, 'handle_rss_feed' ], 9 );
×
64
                \add_action( 'do_feed_rss2', [ $this, 'send_canonical_header' ], 9 );
×
65
                \add_action( 'do_feed_rss2', [ $this, 'add_robots_headers' ], 9 );
×
66
        }
67

68
        /**
69
         * Filter `bloginfo_rss` output to give the URL for what's being shown instead of just always the homepage.
70
         *
71
         * @param string $show The output so far.
72
         * @param string $what What is being shown.
73
         *
74
         * @return string
75
         */
76
        public function filter_bloginfo_rss( $show, $what ) {
×
77
                if ( $what === 'url' ) {
×
78
                        return $this->get_url_for_queried_object( $show );
×
79
                }
80

81
                return $show;
×
82
        }
83

84
        /**
85
         * Makes sure send canonical header always runs, because this RSS hook does not support the for_comments parameter
86
         *
87
         * @return void
88
         */
89
        public function handle_rss_feed() {
×
90
                $this->send_canonical_header( false );
×
91
        }
92

93
        /**
94
         * Adds a canonical link header to the main canonical URL for the requested feed object. If it is not a comment
95
         * feed.
96
         *
97
         * @param bool $for_comments If the RRS feed is meant for a comment feed.
98
         *
99
         * @return void
100
         */
101
        public function send_canonical_header( $for_comments ) {
×
102

103
                if ( $for_comments || \headers_sent() ) {
×
104
                        return;
×
105
                }
106

NEW
107
                $queried_object = \get_queried_object();
×
108
                // Don't call get_class with null. This gives a warning.
NEW
109
                $class = ( $queried_object !== null ) ? \get_class( $queried_object ) : null;
×
110

111
                $url = $this->get_url_for_queried_object( $this->meta->for_home_page()->canonical );
×
NEW
112
                if ( ( ! empty( $url ) && $url !== $this->meta->for_home_page()->canonical ) || $class === null ) {
×
113
                        \header( \sprintf( 'Link: <%s>; rel="canonical"', $url ), false );
×
114
                }
115
        }
116

117
        /**
118
         * Adds noindex, follow tag for comment feeds.
119
         *
120
         * @param bool $for_comments If the RSS feed is meant for a comment feed.
121
         *
122
         * @return void
123
         */
124
        public function add_robots_headers( $for_comments ) {
×
125
                if ( $for_comments && ! \headers_sent() ) {
×
126
                        \header( 'X-Robots-Tag: noindex, follow', true );
×
127
                }
128
        }
129

130
        /**
131
         * Makes sure the title separator set in Yoast SEO is used for all feeds.
132
         *
133
         * @param string $separator The separator from WordPress.
134
         *
135
         * @return string The separator from Yoast SEO's settings.
136
         */
137
        public function filter_document_title_separator( $separator ) {
×
138
                return \html_entity_decode( $this->options->get_title_separator() );
×
139
        }
140

141
        /**
142
         * Determines the main URL for the queried object.
143
         *
144
         * @param string $url The URL determined so far.
145
         *
146
         * @return string The canonical URL for the queried object.
147
         */
148
        protected function get_url_for_queried_object( $url = '' ) {
×
149
                $queried_object = \get_queried_object();
×
150
                // Don't call get_class with null. This gives a warning.
151
                $class = ( $queried_object !== null ) ? \get_class( $queried_object ) : null;
×
NEW
152
                $meta  = false;
×
153

154
                switch ( $class ) {
155
                        // Post type archive feeds.
156
                        case 'WP_Post_Type':
×
NEW
157
                                $meta = $this->meta->for_post_type_archive( $queried_object->name );
×
158
                                break;
×
159
                        // Post comment feeds.
160
                        case 'WP_Post':
×
NEW
161
                                $meta = $this->meta->for_post( $queried_object->ID );
×
162
                                break;
×
163
                        // Term feeds.
164
                        case 'WP_Term':
×
NEW
165
                                $meta = $this->meta->for_term( $queried_object->term_id );
×
166
                                break;
×
167
                        // Author feeds.
168
                        case 'WP_User':
×
NEW
169
                                $meta = $this->meta->for_author( $queried_object->ID );
×
170
                                break;
×
171
                        // This would be NULL on the home page and on date archive feeds.
172
                        case null:
NEW
173
                                $meta = $this->meta->for_home_page();
×
174
                                break;
×
175
                        default:
176
                                break;
×
177
                }
178

NEW
179
                if ( $meta ) {
×
NEW
180
                        return $meta->canonical;
×
181
                }
182

UNCOV
183
                return $url;
×
184
        }
185
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc