Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 66
0.00% covered (danger)
0.00%
0 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
Jetpack_SEO_Posts
0.00% covered (danger)
0.00%
0 / 66
0.00% covered (danger)
0.00%
0 / 6
462
0.00% covered (danger)
0.00%
0 / 1
 get_post_description
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
42
 get_post_custom_description
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
20
 get_post_custom_html_title
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
20
 get_post_noindex_setting
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
20
 exclude_noindex_posts_from_jetpack_sitemap
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
 register_post_meta
0.00% covered (danger)
0.00%
0 / 30
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2/**
3 * Class containing utility static methods for managing SEO options for Posts and Pages.
4 *
5 * @package automattic/jetpack
6 */
7
8/**
9 * Provides static utility methods for managing SEO options for Posts and Pages.
10 */
11class Jetpack_SEO_Posts {
12    /**
13     * Key of the post meta values that will be used to store post custom data.
14     */
15    const DESCRIPTION_META_KEY = 'advanced_seo_description';
16    const HTML_TITLE_META_KEY  = 'jetpack_seo_html_title';
17    const NOINDEX_META_KEY     = 'jetpack_seo_noindex';
18    const POST_META_KEYS_ARRAY = array(
19        self::DESCRIPTION_META_KEY,
20        self::HTML_TITLE_META_KEY,
21        self::NOINDEX_META_KEY,
22    );
23
24    /**
25     * Build meta description for post SEO.
26     *
27     * @param WP_Post|null $post Source of data for custom description.
28     *
29     * @return string Post description or empty string.
30     */
31    public static function get_post_description( $post = null ) {
32        $post = get_post( $post );
33        if ( ! ( $post instanceof WP_Post ) ) {
34            return '';
35        }
36
37        if ( post_password_required() || ! is_singular() ) {
38            return '';
39        }
40
41        // Business users can overwrite the description.
42        $custom_description = self::get_post_custom_description( $post );
43
44        if ( ! empty( $custom_description ) ) {
45            return $custom_description;
46        }
47
48        if ( ! empty( $post->post_excerpt ) ) {
49            return $post->post_excerpt;
50        }
51
52        // Remove content within wp:query blocks and return.
53        return Jetpack_SEO_Utils::remove_query_blocks( $post->post_content );
54    }
55
56    /**
57     * Returns post's custom meta description if it is set, and if
58     * SEO tools are enabled for current blog.
59     *
60     * @param WP_Post|null $post Source of data for custom description.
61     *
62     * @return string Custom description or empty string
63     */
64    public static function get_post_custom_description( $post = null ) {
65        $post = get_post( $post );
66        if ( ! ( $post instanceof WP_Post ) ) {
67            return '';
68        }
69
70        $custom_description = get_post_meta( $post->ID, self::DESCRIPTION_META_KEY, true );
71
72        if ( empty( $custom_description ) || ! Jetpack_SEO_Utils::is_enabled_jetpack_seo() ) {
73            return '';
74        }
75
76        return $custom_description;
77    }
78
79    /**
80     * Gets a custom HTML title for a post if one is set, and if
81     * SEO tools are enabled for the current blog.
82     *
83     * @param WP_Post|null $post Source of data for the custom HTML title.
84     *
85     * @return string Custom HTML title or an empty string if not set.
86     */
87    public static function get_post_custom_html_title( $post = null ) {
88        $post = get_post( $post );
89        if ( ! ( $post instanceof WP_Post ) ) {
90            return '';
91        }
92
93        $custom_html_title = get_post_meta( $post->ID, self::HTML_TITLE_META_KEY, true );
94
95        if ( empty( $custom_html_title ) || ! Jetpack_SEO_Utils::is_enabled_jetpack_seo() ) {
96            return '';
97        }
98
99        return $custom_html_title;
100    }
101
102    /**
103     * Gets the `jetpack_seo_noindex` setting for a post, if
104     * SEO tools are enabled for the current blog.
105     *
106     * @param WP_Post|null $post Provided post or defaults to the global post.
107     *
108     * @return bool True if post should be marked as noindex, false otherwise.
109     */
110    public static function get_post_noindex_setting( $post = null ) {
111        $post = get_post( $post );
112        if ( ! ( $post instanceof WP_Post ) ) {
113            return false;
114        }
115
116        $mark_as_noindex = get_post_meta( $post->ID, self::NOINDEX_META_KEY, true );
117
118        if ( empty( $mark_as_noindex ) || ! Jetpack_SEO_Utils::is_enabled_jetpack_seo() ) {
119            return false;
120        }
121
122        return (bool) $mark_as_noindex;
123    }
124
125    /**
126     * Filter callback for `jetpack_sitemap_skip_post`; if a post has `jetpack_seo_noindex` set to true,
127     * then exclude that post from the Jetpack sitemap.
128     *
129     * @param bool    $skip Whether to skip the post in the sitemap.
130     * @param WP_Post $post The post to check.
131     *
132     * @return bool
133     */
134    public static function exclude_noindex_posts_from_jetpack_sitemap( $skip, $post ) {
135        $exclude = self::get_post_noindex_setting( $post );
136        if ( $exclude ) {
137            $skip = true;
138        }
139        return $skip;
140    }
141
142    /**
143     * Registers the following meta keys for use in the REST API:
144     *   - self::DESCRIPTION_META_KEY
145     *   - self::HTML_TITLE_META_KEY
146     */
147    public static function register_post_meta() {
148        $description_args = array(
149            'type'         => 'string',
150            'description'  => __( 'Custom post description to be used in HTML <meta /> tag.', 'jetpack' ),
151            'single'       => true,
152            'default'      => '',
153            'show_in_rest' => array(
154                'name' => self::DESCRIPTION_META_KEY,
155            ),
156        );
157
158        $html_title_args = array(
159            'type'         => 'string',
160            'description'  => __( 'Custom title to be used in HTML <title /> tag.', 'jetpack' ),
161            'single'       => true,
162            'default'      => '',
163            'show_in_rest' => array(
164                'name' => self::HTML_TITLE_META_KEY,
165            ),
166        );
167
168        $noindex_args = array(
169            'type'         => 'boolean',
170            'description'  => __( 'Whether to hide the post from search engines and the Jetpack sitemap.', 'jetpack' ),
171            'single'       => true,
172            'default'      => false,
173            'show_in_rest' => array(
174                'name' => self::NOINDEX_META_KEY,
175            ),
176        );
177
178        register_meta( 'post', self::DESCRIPTION_META_KEY, $description_args );
179        register_meta( 'post', self::HTML_TITLE_META_KEY, $html_title_args );
180        register_meta( 'post', self::NOINDEX_META_KEY, $noindex_args );
181    }
182}