Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 46
0.00% covered (danger)
0.00%
0 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
WP_Template
0.00% covered (danger)
0.00%
0 / 46
0.00% covered (danger)
0.00%
0 / 7
380
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 is_supported_template_type
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 get_template_id
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
20
 get_template_content
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
20
 get_page_template_content
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
12
 get_template_blocks
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 output_template_content
0.00% covered (danger)
0.00%
0 / 14
0.00% covered (danger)
0.00%
0 / 1
12
1<?php
2/**
3 * WP Template file.
4 *
5 * @package A8C\FSE
6 */
7
8namespace Automattic\Jetpack\Jetpack_Mu_Wpcom\Wpcom_Legacy_FSE;
9
10/**
11 * Class WP_Template
12 */
13class WP_Template {
14    /**
15     * Header template type constant.
16     *
17     * @var string HEADER
18     */
19    const HEADER = 'header';
20
21    /**
22     * Footer template type constant
23     *
24     * @var string FOOTER
25     */
26    const FOOTER = 'footer';
27
28    /**
29     * Name of the currently active theme that is used to reference its template CPTs.
30     *
31     * @var string $current_theme_name Name of currently active theme on the site.
32     */
33    private $current_theme_name;
34
35    /**
36     * List of template types that FSE is currently supporting.
37     *
38     * @var array $supported_template_types Array of strings containing supported template types.
39     */
40    public $supported_template_types = array( self::HEADER, self::FOOTER );
41
42    /**
43     * A8C_WP_Template constructor.
44     *
45     * @param string $theme Defaults to the current theme slug, but can be
46     *                      overriden to use this class with themes which are
47     *                      not currently active.
48     */
49    public function __construct( $theme = null ) {
50        if ( ! isset( $theme ) ) {
51            $theme = get_stylesheet();
52        }
53        $this->current_theme_name = normalize_theme_slug( $theme );
54    }
55
56    /**
57     * Checks whether the provided template type is supported in FSE.
58     *
59     * @param string $template_type String representing the template type.
60     *
61     * @return bool True if provided template type is supported in FSE, false otherwise.
62     */
63    public function is_supported_template_type( $template_type ) {
64        return in_array( $template_type, $this->supported_template_types, true );
65    }
66
67    /**
68     * Returns the post ID of the default template CPT for a given template type.
69     *
70     * @param string $template_type String representing the template type.
71     *
72     * @return null|int Template ID if it exists or null otherwise.
73     */
74    public function get_template_id( $template_type ) {
75        if ( ! $this->is_supported_template_type( $template_type ) ) {
76            return null;
77        }
78
79        $term = get_term_by( 'name', "$this->current_theme_name-$template_type", 'wp_template_part_type', ARRAY_A );
80
81        // Bail if current site doesn't have this term registered.
82        if ( ! isset( $term['term_id'] ) ) {
83            return null;
84        }
85
86        $template_ids = get_objects_in_term( $term['term_id'], $term['taxonomy'], array( 'order' => 'DESC' ) );
87
88        // Bail if we haven't found any post instances for this template type.
89        if ( empty( $template_ids ) ) {
90            return null;
91        }
92
93        /*
94         * Assuming that we'll have just one default template for now.
95         * We'll add support for multiple header and footer variations in future iterations.
96         */
97        return (int) $template_ids[0];
98    }
99
100    /**
101     * Returns template content for given template type.
102     *
103     * @param string $template_type String representing the template type.
104     *
105     * @return null|string Template content if it exists or null otherwise.
106     */
107    public function get_template_content( $template_type ) {
108        if ( ! $this->is_supported_template_type( $template_type ) ) {
109            return null;
110        }
111
112        $template_id = $this->get_template_id( $template_type );
113
114        if ( null === $template_id ) {
115            return null;
116        }
117
118        $template_post = get_post( $template_id );
119
120        if ( null === $template_post ) {
121            return;
122        }
123
124        return $template_post->post_content;
125    }
126
127    /**
128     * Returns full page template content.
129     *
130     * We only support one page template for now with header at the top and footer at the bottom.
131     *
132     * @return null|string
133     */
134    public function get_page_template_content() {
135        $header_id = $this->get_template_id( self::HEADER );
136        $footer_id = $this->get_template_id( self::FOOTER );
137
138        /*
139         * Bail if we are missing header or footer. Otherwise this would cause us to
140         * always return some page template content and show template parts (with empty IDs),
141         * even for themes that don't support FSE.
142         */
143        if ( ! $header_id || ! $footer_id ) {
144            return null;
145        }
146
147        return "<!-- wp:a8c/template {\"templateId\":$header_id,\"label\":\"" . __( 'Header', 'jetpack-mu-wpcom' ) . '","className":"fse-template-part fse-header"} /-->' .
148                '<!-- wp:a8c/post-content /-->' .
149                "<!-- wp:a8c/template {\"templateId\":$footer_id,\"label\":\"" . __( 'Footer', 'jetpack-mu-wpcom' ) . '","className":"fse-template-part fse-footer"} /-->';
150    }
151
152    /**
153     * Returns array of blocks that represent the template.
154     *
155     * @return array
156     */
157    public function get_template_blocks() {
158        $template_content = $this->get_page_template_content();
159        $template_blocks  = parse_blocks( $template_content );
160        return is_array( $template_blocks ) ? $template_blocks : array();
161    }
162
163    /**
164     * Output FSE template markup.
165     *
166     * @param string $template_type String representing the template type.
167     *
168     * @return null|void Null if unsupported template type is passed, outputs content otherwise.
169     */
170    public function output_template_content( $template_type ) {
171        if ( ! $this->is_supported_template_type( $template_type ) ) {
172            return null;
173        }
174
175        // Things that follow are from wp-includes/default-filters.php
176        // not everything is appropriate for template content as opposed to post content.
177        global $wp_embed;
178        $content = $this->get_template_content( $template_type );
179
180        // 8 priority
181        $content = $wp_embed->run_shortcode( $content );
182        $content = $wp_embed->autoembed( $content );
183
184        // 9 priority
185        $content = do_blocks( $content );
186
187        // 10 priority
188        $content = wptexturize( $content );
189
190        // 11 priority
191        $content = do_shortcode( $content );
192
193        $content = prepend_attachment( $content );
194
195        if ( has_filter( 'a8c_fse_make_content_images_responsive' ) ) {
196            $content = apply_filters( 'a8c_fse_make_content_images_responsive', $content );
197        } else {
198            $content = wp_filter_content_tags( $content );
199        }
200
201        // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped
202        echo $content;
203    }
204}