run:R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
23.8 KB
2026-03-11 16:18:51
R W Run
7.8 KB
2026-03-11 16:18:52
R W Run
36.1 KB
2026-03-11 16:18:51
R W Run
11.9 KB
2026-03-11 16:18:52
R W Run
18.94 KB
2026-03-11 16:18:52
R W Run
7.35 KB
2026-03-11 16:18:52
R W Run
28.6 KB
2026-03-11 16:18:51
R W Run
316 By
2026-03-11 16:18:51
R W Run
12.9 KB
2026-03-11 16:18:51
R W Run
61.02 KB
2026-03-11 16:18:52
R W Run
15 KB
2026-03-11 16:18:51
R W Run
112.05 KB
2026-03-11 16:18:51
R W Run
12.47 KB
2026-03-11 16:18:51
R W Run
15.07 KB
2026-03-11 16:18:52
R W Run
9.84 KB
2026-03-11 16:18:52
R W Run
13.17 KB
2026-03-11 16:18:52
R W Run
33.83 KB
2026-03-11 16:18:51
R W Run
42.63 KB
2026-03-11 16:18:51
R W Run
55.71 KB
2026-03-11 16:18:52
R W Run
12.53 KB
2026-03-11 16:18:51
R W Run
2.55 KB
2026-03-11 16:18:52
R W Run
28.92 KB
2026-03-11 16:18:52
R W Run
539 By
2026-03-11 16:18:51
R W Run
367 By
2026-03-11 16:18:52
R W Run
42.65 KB
2026-03-11 16:18:51
R W Run
401 By
2026-03-11 16:18:51
R W Run
6.61 KB
2026-03-11 16:18:51
R W Run
664 By
2026-03-11 16:18:52
R W Run
20.63 KB
2026-03-11 16:18:51
R W Run
2.18 KB
2026-03-11 16:18:52
R W Run
453 By
2026-03-11 16:18:52
R W Run
457 By
2026-03-11 16:18:51
R W Run
36.83 KB
2026-03-11 16:18:52
R W Run
2.41 KB
2026-03-11 16:18:52
R W Run
8.28 KB
2026-03-11 16:18:51
R W Run
13.89 KB
2026-03-11 16:18:51
R W Run
11.76 KB
2026-03-11 16:18:51
R W Run
2.65 KB
2026-03-11 16:18:51
R W Run
7.43 KB
2026-03-11 16:18:51
R W Run
17.46 KB
2026-03-11 16:18:51
R W Run
5.14 KB
2026-03-11 16:18:52
R W Run
16.7 KB
2026-03-11 16:18:51
R W Run
8.28 KB
2026-03-11 16:18:52
R W Run
2.92 KB
2026-03-11 16:18:52
R W Run
1.32 KB
2026-03-11 16:18:51
R W Run
4.6 KB
2026-03-11 16:18:52
R W Run
11.62 KB
2026-03-11 16:18:52
R W Run
2.5 KB
2026-03-11 16:18:51
R W Run
1.97 KB
2026-03-11 16:18:51
R W Run
11.25 KB
2026-03-11 16:18:52
R W Run
5.32 KB
2026-03-11 16:18:51
R W Run
10.99 KB
2026-03-11 16:18:52
R W Run
68.32 KB
2026-03-11 16:18:51
R W Run
6.34 KB
2026-03-11 16:18:51
R W Run
5.49 KB
2026-03-11 16:18:51
R W Run
1.99 KB
2026-03-11 16:18:52
R W Run
7.02 KB
2026-03-11 16:18:51
R W Run
4.91 KB
2026-03-11 16:18:52
R W Run
16.86 KB
2026-03-11 16:18:51
R W Run
24.23 KB
2026-03-11 16:18:51
R W Run
3.97 KB
2026-03-11 16:18:51
R W Run
47.66 KB
2026-03-11 16:18:51
R W Run
9.22 KB
2026-03-11 16:18:51
R W Run
25.51 KB
2026-03-11 16:18:51
R W Run
198.38 KB
2026-03-11 16:18:52
R W Run
56.65 KB
2026-03-11 16:18:51
R W Run
10.46 KB
2026-03-11 16:18:51
R W Run
10.95 KB
2026-03-11 16:18:52
R W Run
29.26 KB
2026-03-11 16:18:51
R W Run
70.91 KB
2026-03-11 16:18:52
R W Run
35.3 KB
2026-03-11 16:18:52
R W Run
16.61 KB
2026-03-11 16:18:52
R W Run
2.57 KB
2026-03-11 16:18:52
R W Run
39.83 KB
2026-03-11 16:18:51
R W Run
70.64 KB
2026-03-11 16:18:51
R W Run
15.56 KB
2026-03-11 16:18:52
R W Run
7.33 KB
2026-03-11 16:18:52
R W Run
253 By
2026-03-11 16:18:51
R W Run
7.96 KB
2026-03-11 16:18:52
R W Run
3.23 KB
2026-03-11 16:18:52
R W Run
969 By
2026-03-11 16:18:52
R W Run
16.28 KB
2026-03-11 16:18:51
R W Run
7.22 KB
2026-03-11 16:18:51
R W Run
12.95 KB
2026-03-11 16:18:51
R W Run
6.53 KB
2026-03-11 16:18:51
R W Run
3.42 KB
2026-03-11 16:18:52
R W Run
5.84 KB
2026-03-11 16:18:51
R W Run
1.97 KB
2026-03-11 16:18:51
R W Run
4.3 KB
2026-03-11 16:18:52
R W Run
2.91 KB
2026-03-11 16:18:51
R W Run
16.46 KB
2026-03-11 16:18:52
R W Run
40.6 KB
2026-03-11 16:18:51
R W Run
20.22 KB
2026-03-11 16:18:51
R W Run
36.11 KB
2026-03-11 16:18:52
R W Run
17.01 KB
2026-03-11 16:18:51
R W Run
7.27 KB
2026-03-11 16:18:52
R W Run
6.62 KB
2026-03-11 16:18:52
R W Run
16.49 KB
2026-03-11 16:18:52
R W Run
1.79 KB
2026-03-11 16:18:52
R W Run
29.82 KB
2026-03-11 16:18:51
R W Run
6.67 KB
2026-03-11 16:18:52
R W Run
8.98 KB
2026-03-11 16:18:52
R W Run
19.42 KB
2026-03-11 16:18:51
R W Run
12.01 KB
2026-03-11 16:18:51
R W Run
17.11 KB
2026-03-11 16:18:51
R W Run
6.74 KB
2026-03-11 16:18:52
R W Run
30.93 KB
2026-03-11 16:18:51
R W Run
4.99 KB
2026-03-11 16:18:51
R W Run
4.25 KB
2026-03-11 16:18:51
R W Run
24.72 KB
2026-03-11 16:18:51
R W Run
29.96 KB
2026-03-11 16:18:52
R W Run
6.41 KB
2026-03-11 16:18:51
R W Run
160 KB
2026-03-11 16:18:51
R W Run
6.72 KB
2026-03-11 16:18:52
R W Run
10.92 KB
2026-03-11 16:18:51
R W Run
4.77 KB
2026-03-11 16:18:51
R W Run
3.38 KB
2026-03-11 16:18:51
R W Run
11.18 KB
2026-03-11 16:18:51
R W Run
62.19 KB
2026-03-11 16:18:51
R W Run
2.46 KB
2026-03-11 16:18:51
R W Run
9.17 KB
2026-03-11 16:18:51
R W Run
32.15 KB
2026-03-11 16:18:51
R W Run
34.05 KB
2026-03-11 16:18:52
R W Run
7.15 KB
2026-03-11 16:18:51
R W Run
3.47 KB
2026-03-11 16:18:52
R W Run
1.87 KB
2026-03-11 16:18:52
R W Run
30.91 KB
2026-03-11 16:18:51
R W Run
7.29 KB
2026-03-11 16:18:52
R W Run
7.35 KB
2026-03-11 16:18:51
R W Run
12.54 KB
2026-03-11 16:18:51
R W Run
19.12 KB
2026-03-11 16:18:51
R W Run
18.12 KB
2026-03-11 16:18:52
R W Run
39.99 KB
2026-03-11 16:18:52
R W Run
5.17 KB
2026-03-11 16:18:52
R W Run
979 By
2026-03-11 16:18:51
R W Run
18.44 KB
2026-03-11 16:18:52
R W Run
10.24 KB
2026-03-11 16:18:51
R W Run
1.77 KB
2026-03-11 16:18:52
R W Run
34.9 KB
2026-03-11 16:18:51
R W Run
7.19 KB
2026-03-11 16:18:52
R W Run
160.5 KB
2026-03-11 16:18:51
R W Run
64.27 KB
2026-03-11 16:18:51
R W Run
27.95 KB
2026-03-11 16:18:51
R W Run
4.69 KB
2026-03-11 16:18:51
R W Run
2.94 KB
2026-03-11 16:18:51
R W Run
43.13 KB
2026-03-11 16:18:52
R W Run
2.25 KB
2026-03-11 16:18:52
R W Run
22.5 KB
2026-03-11 16:18:51
R W Run
13.01 KB
2026-03-11 16:18:52
R W Run
3.27 KB
2026-03-11 16:18:51
R W Run
18 KB
2026-03-11 16:18:51
R W Run
210.4 KB
2026-03-11 16:18:52
R W Run
25.86 KB
2026-03-11 16:18:52
R W Run
115.85 KB
2026-03-11 16:18:51
R W Run
373 By
2026-03-11 16:18:52
R W Run
343 By
2026-03-11 16:18:52
R W Run
338 By
2026-03-11 16:18:51
R W Run
100.73 KB
2026-03-11 16:18:52
R W Run
130.93 KB
2026-03-11 16:18:51
R W Run
19.1 KB
2026-03-11 16:18:51
R W Run
17.41 KB
2026-03-11 16:18:52
R W Run
41.98 KB
2026-03-11 16:18:52
R W Run
400 By
2026-03-11 16:18:52
R W Run
11.1 KB
2026-03-11 16:18:52
R W Run
37.02 KB
2026-03-11 16:18:51
R W Run
2.24 KB
2026-03-11 16:18:51
R W Run
188.13 KB
2026-03-11 16:18:51
R W Run
338 By
2026-03-11 16:18:51
R W Run
38 KB
2026-03-11 16:18:51
R W Run
4.02 KB
2026-03-11 16:18:52
R W Run
5.38 KB
2026-03-11 16:18:51
R W Run
3.05 KB
2026-03-11 16:18:52
R W Run
2.61 KB
2026-03-11 16:18:51
R W Run
1.16 KB
2026-03-11 16:18:52
R W Run
4.04 KB
2026-03-11 16:18:51
R W Run
3.71 KB
2026-03-11 16:18:51
R W Run
24.6 KB
2026-03-11 16:18:51
R W Run
9.56 KB
2026-03-11 16:18:51
R W Run
346.43 KB
2026-03-11 16:18:52
R W Run
281.84 KB
2026-03-11 16:18:52
R W Run
14.95 KB
2026-03-11 16:18:51
R W Run
8.44 KB
2026-03-11 16:18:52
R W Run
168.95 KB
2026-03-11 16:18:52
R W Run
20.71 KB
2026-03-11 16:18:52
R W Run
25.27 KB
2026-03-11 16:18:51
R W Run
5.72 KB
2026-03-11 16:18:51
R W Run
4.63 KB
2026-03-11 16:18:52
R W Run
81.73 KB
2026-03-11 16:18:51
R W Run
67.18 KB
2026-03-11 16:18:51
R W Run
156.36 KB
2026-03-11 16:18:52
R W Run
55.19 KB
2026-03-11 16:18:51
R W Run
162 By
2026-03-11 16:18:51
R W Run
61.72 KB
2026-03-11 16:18:51
R W Run
216.06 KB
2026-03-11 16:18:52
R W Run
65.09 KB
2026-03-11 16:18:51
R W Run
25.24 KB
2026-03-11 16:18:52
R W Run
4.81 KB
2026-03-11 16:18:51
R W Run
6.48 KB
2026-03-11 16:18:52
R W Run
21.25 KB
2026-03-11 16:18:51
R W Run
2.79 KB
2026-03-11 16:18:52
R W Run
89.69 KB
2026-03-11 16:18:52
R W Run
19.42 KB
2026-03-11 16:18:52
R W Run
3.69 KB
2026-03-11 16:18:52
R W Run
4.11 KB
2026-03-11 16:18:51
R W Run
40.74 KB
2026-03-11 16:18:51
R W Run
25.38 KB
2026-03-11 16:18:51
R W Run
43.31 KB
2026-03-11 16:18:52
R W Run
102.57 KB
2026-03-11 16:18:52
R W Run
6.18 KB
2026-03-11 16:18:51
R W Run
124.47 KB
2026-03-11 16:18:52
R W Run
35.65 KB
2026-03-11 16:18:52
R W Run
6.94 KB
2026-03-11 16:18:52
R W Run
67.04 KB
2026-03-11 16:18:52
R W Run
10.62 KB
2026-03-11 16:18:51
R W Run
289.35 KB
2026-03-11 16:18:52
R W Run
36.23 KB
2026-03-11 16:18:51
R W Run
200 By
2026-03-11 16:18:52
R W Run
200 By
2026-03-11 16:18:52
R W Run
98.29 KB
2026-03-11 16:18:52
R W Run
30.02 KB
2026-03-11 16:18:52
R W Run
19.03 KB
2026-03-11 16:18:52
R W Run
5.06 KB
2026-03-11 16:18:52
R W Run
255 By
2026-03-11 16:18:51
R W Run
22.66 KB
2026-03-11 16:18:52
R W Run
154.63 KB
2026-03-11 16:18:51
R W Run
9.68 KB
2026-03-11 16:18:51
R W Run
258 By
2026-03-11 16:18:51
R W Run
23.49 KB
2026-03-11 16:18:51
R W Run
3.16 KB
2026-03-11 16:18:51
R W Run
8.4 KB
2026-03-11 16:18:52
R W Run
441 By
2026-03-11 16:18:51
R W Run
7.39 KB
2026-03-11 16:18:51
R W Run
173 KB
2026-03-11 16:18:52
R W Run
544 By
2026-03-11 16:18:52
R W Run
4.17 KB
2026-03-11 16:18:51
R W Run
35.97 KB
2026-03-11 16:18:52
R W Run
1.69 KB
2026-03-11 16:18:51
R W Run
2.84 KB
2026-03-11 16:18:52
R W Run
6.09 KB
2026-03-11 16:18:51
R W Run
8.71 KB
2026-03-11 16:18:51
R W Run
131.84 KB
2026-03-11 16:18:51
R W Run
37.45 KB
2026-03-11 16:18:51
R W Run
173.89 KB
2026-03-11 16:18:51
R W Run
7.09 KB
2026-03-11 16:18:51
R W Run
6.41 KB
2026-03-11 16:18:51
R W Run
1.08 KB
2026-03-11 16:18:51
R W Run
69.46 KB
2026-03-11 16:18:52
R W Run
445 By
2026-03-11 16:18:51
R W Run
799 By
2026-03-11 16:18:52
R W Run
error_log
📄template.php
1<?php
2/**
3 * Template loading functions.
4 *
5 * @package WordPress
6 * @subpackage Template
7 */
8
9/**
10 * Retrieves path to a template.
11 *
12 * Used to quickly retrieve the path of a template without including the file
13 * extension. It will also check the parent theme, if the file exists, with
14 * the use of locate_template(). Allows for more generic template location
15 * without the use of the other get_*_template() functions.
16 *
17 * @since 1.5.0
18 *
19 * @param string $type Filename without extension.
20 * @param string[] $templates An optional list of template candidates.
21 * @return string Full path to template file.
22 */
23function get_query_template( $type, $templates = array() ) {
24 $type = preg_replace( '|[^a-z0-9-]+|', '', $type );
25
26 if ( empty( $templates ) ) {
27 $templates = array( "{$type}.php" );
28 }
29
30 /**
31 * Filters the list of template filenames that are searched for when retrieving a template to use.
32 *
33 * The dynamic portion of the hook name, `$type`, refers to the filename -- minus the file
34 * extension and any non-alphanumeric characters delimiting words -- of the file to load.
35 * The last element in the array should always be the fallback template for this query type.
36 *
37 * Possible hook names include:
38 *
39 * - `404_template_hierarchy`
40 * - `archive_template_hierarchy`
41 * - `attachment_template_hierarchy`
42 * - `author_template_hierarchy`
43 * - `category_template_hierarchy`
44 * - `date_template_hierarchy`
45 * - `embed_template_hierarchy`
46 * - `frontpage_template_hierarchy`
47 * - `home_template_hierarchy`
48 * - `index_template_hierarchy`
49 * - `page_template_hierarchy`
50 * - `paged_template_hierarchy`
51 * - `privacypolicy_template_hierarchy`
52 * - `search_template_hierarchy`
53 * - `single_template_hierarchy`
54 * - `singular_template_hierarchy`
55 * - `tag_template_hierarchy`
56 * - `taxonomy_template_hierarchy`
57 *
58 * @since 4.7.0
59 *
60 * @param string[] $templates A list of template candidates, in descending order of priority.
61 */
62 $templates = apply_filters( "{$type}_template_hierarchy", $templates );
63
64 $template = locate_template( $templates );
65
66 $template = locate_block_template( $template, $type, $templates );
67
68 /**
69 * Filters the path of the queried template by type.
70 *
71 * The dynamic portion of the hook name, `$type`, refers to the filename -- minus the file
72 * extension and any non-alphanumeric characters delimiting words -- of the file to load.
73 * This hook also applies to various types of files loaded as part of the Template Hierarchy.
74 *
75 * Possible hook names include:
76 *
77 * - `404_template`
78 * - `archive_template`
79 * - `attachment_template`
80 * - `author_template`
81 * - `category_template`
82 * - `date_template`
83 * - `embed_template`
84 * - `frontpage_template`
85 * - `home_template`
86 * - `index_template`
87 * - `page_template`
88 * - `paged_template`
89 * - `privacypolicy_template`
90 * - `search_template`
91 * - `single_template`
92 * - `singular_template`
93 * - `tag_template`
94 * - `taxonomy_template`
95 *
96 * @since 1.5.0
97 * @since 4.8.0 The `$type` and `$templates` parameters were added.
98 *
99 * @param string $template Path to the template. See locate_template().
100 * @param string $type Sanitized filename without extension.
101 * @param string[] $templates A list of template candidates, in descending order of priority.
102 */
103 return apply_filters( "{$type}_template", $template, $type, $templates );
104}
105
106/**
107 * Retrieves path of index template in current or parent template.
108 *
109 * The template hierarchy and template path are filterable via the {@see '$type_template_hierarchy'}
110 * and {@see '$type_template'} dynamic hooks, where `$type` is 'index'.
111 *
112 * @since 3.0.0
113 *
114 * @see get_query_template()
115 *
116 * @return string Full path to index template file.
117 */
118function get_index_template() {
119 return get_query_template( 'index' );
120}
121
122/**
123 * Retrieves path of 404 template in current or parent template.
124 *
125 * The template hierarchy and template path are filterable via the {@see '$type_template_hierarchy'}
126 * and {@see '$type_template'} dynamic hooks, where `$type` is '404'.
127 *
128 * @since 1.5.0
129 *
130 * @see get_query_template()
131 *
132 * @return string Full path to 404 template file.
133 */
134function get_404_template() {
135 return get_query_template( '404' );
136}
137
138/**
139 * Retrieves path of archive template in current or parent template.
140 *
141 * The template hierarchy and template path are filterable via the {@see '$type_template_hierarchy'}
142 * and {@see '$type_template'} dynamic hooks, where `$type` is 'archive'.
143 *
144 * @since 1.5.0
145 *
146 * @see get_query_template()
147 *
148 * @return string Full path to archive template file.
149 */
150function get_archive_template() {
151 $post_types = array_filter( (array) get_query_var( 'post_type' ) );
152
153 $templates = array();
154
155 if ( count( $post_types ) === 1 ) {
156 $post_type = reset( $post_types );
157 $templates[] = "archive-{$post_type}.php";
158 }
159 $templates[] = 'archive.php';
160
161 return get_query_template( 'archive', $templates );
162}
163
164/**
165 * Retrieves path of post type archive template in current or parent template.
166 *
167 * The template hierarchy and template path are filterable via the {@see '$type_template_hierarchy'}
168 * and {@see '$type_template'} dynamic hooks, where `$type` is 'archive'.
169 *
170 * @since 3.7.0
171 *
172 * @see get_archive_template()
173 *
174 * @return string Full path to archive template file.
175 */
176function get_post_type_archive_template() {
177 $post_type = get_query_var( 'post_type' );
178 if ( is_array( $post_type ) ) {
179 $post_type = reset( $post_type );
180 }
181
182 $obj = get_post_type_object( $post_type );
183 if ( ! ( $obj instanceof WP_Post_Type ) || ! $obj->has_archive ) {
184 return '';
185 }
186
187 return get_archive_template();
188}
189
190/**
191 * Retrieves path of author template in current or parent template.
192 *
193 * The hierarchy for this template looks like:
194 *
195 * 1. author-{nicename}.php
196 * 2. author-{id}.php
197 * 3. author.php
198 *
199 * An example of this is:
200 *
201 * 1. author-john.php
202 * 2. author-1.php
203 * 3. author.php
204 *
205 * The template hierarchy and template path are filterable via the {@see '$type_template_hierarchy'}
206 * and {@see '$type_template'} dynamic hooks, where `$type` is 'author'.
207 *
208 * @since 1.5.0
209 *
210 * @see get_query_template()
211 *
212 * @return string Full path to author template file.
213 */
214function get_author_template() {
215 $author = get_queried_object();
216
217 $templates = array();
218
219 if ( $author instanceof WP_User ) {
220 $templates[] = "author-{$author->user_nicename}.php";
221 $templates[] = "author-{$author->ID}.php";
222 }
223 $templates[] = 'author.php';
224
225 return get_query_template( 'author', $templates );
226}
227
228/**
229 * Retrieves path of category template in current or parent template.
230 *
231 * The hierarchy for this template looks like:
232 *
233 * 1. category-{slug}.php
234 * 2. category-{id}.php
235 * 3. category.php
236 *
237 * An example of this is:
238 *
239 * 1. category-news.php
240 * 2. category-2.php
241 * 3. category.php
242 *
243 * The template hierarchy and template path are filterable via the {@see '$type_template_hierarchy'}
244 * and {@see '$type_template'} dynamic hooks, where `$type` is 'category'.
245 *
246 * @since 1.5.0
247 * @since 4.7.0 The decoded form of `category-{slug}.php` was added to the top of the
248 * template hierarchy when the category slug contains multibyte characters.
249 *
250 * @see get_query_template()
251 *
252 * @return string Full path to category template file.
253 */
254function get_category_template() {
255 $category = get_queried_object();
256
257 $templates = array();
258
259 if ( ! empty( $category->slug ) ) {
260
261 $slug_decoded = urldecode( $category->slug );
262 if ( $slug_decoded !== $category->slug ) {
263 $templates[] = "category-{$slug_decoded}.php";
264 }
265
266 $templates[] = "category-{$category->slug}.php";
267 $templates[] = "category-{$category->term_id}.php";
268 }
269 $templates[] = 'category.php';
270
271 return get_query_template( 'category', $templates );
272}
273
274/**
275 * Retrieves path of tag template in current or parent template.
276 *
277 * The hierarchy for this template looks like:
278 *
279 * 1. tag-{slug}.php
280 * 2. tag-{id}.php
281 * 3. tag.php
282 *
283 * An example of this is:
284 *
285 * 1. tag-wordpress.php
286 * 2. tag-3.php
287 * 3. tag.php
288 *
289 * The template hierarchy and template path are filterable via the {@see '$type_template_hierarchy'}
290 * and {@see '$type_template'} dynamic hooks, where `$type` is 'tag'.
291 *
292 * @since 2.3.0
293 * @since 4.7.0 The decoded form of `tag-{slug}.php` was added to the top of the
294 * template hierarchy when the tag slug contains multibyte characters.
295 *
296 * @see get_query_template()
297 *
298 * @return string Full path to tag template file.
299 */
300function get_tag_template() {
301 $tag = get_queried_object();
302
303 $templates = array();
304
305 if ( ! empty( $tag->slug ) ) {
306
307 $slug_decoded = urldecode( $tag->slug );
308 if ( $slug_decoded !== $tag->slug ) {
309 $templates[] = "tag-{$slug_decoded}.php";
310 }
311
312 $templates[] = "tag-{$tag->slug}.php";
313 $templates[] = "tag-{$tag->term_id}.php";
314 }
315 $templates[] = 'tag.php';
316
317 return get_query_template( 'tag', $templates );
318}
319
320/**
321 * Retrieves path of custom taxonomy term template in current or parent template.
322 *
323 * The hierarchy for this template looks like:
324 *
325 * 1. taxonomy-{taxonomy_slug}-{term_slug}.php
326 * 2. taxonomy-{taxonomy_slug}-{term_id}.php
327 * 3. taxonomy-{taxonomy_slug}.php
328 * 4. taxonomy.php
329 *
330 * An example of this is:
331 *
332 * 1. taxonomy-location-texas.php
333 * 2. taxonomy-location-67.php
334 * 3. taxonomy-location.php
335 * 4. taxonomy.php
336 *
337 * The template hierarchy and template path are filterable via the {@see '$type_template_hierarchy'}
338 * and {@see '$type_template'} dynamic hooks, where `$type` is 'taxonomy'.
339 *
340 * @since 2.5.0
341 * @since 4.7.0 The decoded form of `taxonomy-{taxonomy_slug}-{term_slug}.php` was added to the top of the
342 * template hierarchy when the term slug contains multibyte characters.
343 * @since 6.9.0 Added `taxonomy-{taxonomy_slug}-{term_id}.php` to the hierarchy.
344 *
345 * @see get_query_template()
346 *
347 * @return string Full path to custom taxonomy term template file.
348 */
349function get_taxonomy_template() {
350 $term = get_queried_object();
351
352 $templates = array();
353
354 if ( ! empty( $term->slug ) ) {
355 $taxonomy = $term->taxonomy;
356
357 $slug_decoded = urldecode( $term->slug );
358 if ( $slug_decoded !== $term->slug ) {
359 $templates[] = "taxonomy-$taxonomy-{$slug_decoded}.php";
360 }
361
362 $templates[] = "taxonomy-$taxonomy-{$term->slug}.php";
363 $templates[] = "taxonomy-$taxonomy-{$term->term_id}.php";
364 $templates[] = "taxonomy-$taxonomy.php";
365 }
366 $templates[] = 'taxonomy.php';
367
368 return get_query_template( 'taxonomy', $templates );
369}
370
371/**
372 * Retrieves path of date template in current or parent template.
373 *
374 * The template hierarchy and template path are filterable via the {@see '$type_template_hierarchy'}
375 * and {@see '$type_template'} dynamic hooks, where `$type` is 'date'.
376 *
377 * @since 1.5.0
378 *
379 * @see get_query_template()
380 *
381 * @return string Full path to date template file.
382 */
383function get_date_template() {
384 return get_query_template( 'date' );
385}
386
387/**
388 * Retrieves path of home template in current or parent template.
389 *
390 * The template hierarchy and template path are filterable via the {@see '$type_template_hierarchy'}
391 * and {@see '$type_template'} dynamic hooks, where `$type` is 'home'.
392 *
393 * @since 1.5.0
394 *
395 * @see get_query_template()
396 *
397 * @return string Full path to home template file.
398 */
399function get_home_template() {
400 $templates = array( 'home.php', 'index.php' );
401
402 return get_query_template( 'home', $templates );
403}
404
405/**
406 * Retrieves path of front page template in current or parent template.
407 *
408 * The template hierarchy and template path are filterable via the {@see '$type_template_hierarchy'}
409 * and {@see '$type_template'} dynamic hooks, where `$type` is 'frontpage'.
410 *
411 * @since 3.0.0
412 *
413 * @see get_query_template()
414 *
415 * @return string Full path to front page template file.
416 */
417function get_front_page_template() {
418 $templates = array( 'front-page.php' );
419
420 return get_query_template( 'frontpage', $templates );
421}
422
423/**
424 * Retrieves path of Privacy Policy page template in current or parent template.
425 *
426 * The template hierarchy and template path are filterable via the {@see '$type_template_hierarchy'}
427 * and {@see '$type_template'} dynamic hooks, where `$type` is 'privacypolicy'.
428 *
429 * @since 5.2.0
430 *
431 * @see get_query_template()
432 *
433 * @return string Full path to privacy policy template file.
434 */
435function get_privacy_policy_template() {
436 $templates = array( 'privacy-policy.php' );
437
438 return get_query_template( 'privacypolicy', $templates );
439}
440
441/**
442 * Retrieves path of page template in current or parent template.
443 *
444 * Note: For block themes, use locate_block_template() function instead.
445 *
446 * The hierarchy for this template looks like:
447 *
448 * 1. {Page Template}.php
449 * 2. page-{page_name}.php
450 * 3. page-{id}.php
451 * 4. page.php
452 *
453 * An example of this is:
454 *
455 * 1. page-templates/full-width.php
456 * 2. page-about.php
457 * 3. page-4.php
458 * 4. page.php
459 *
460 * The template hierarchy and template path are filterable via the {@see '$type_template_hierarchy'}
461 * and {@see '$type_template'} dynamic hooks, where `$type` is 'page'.
462 *
463 * @since 1.5.0
464 * @since 4.7.0 The decoded form of `page-{page_name}.php` was added to the top of the
465 * template hierarchy when the page name contains multibyte characters.
466 *
467 * @see get_query_template()
468 *
469 * @return string Full path to page template file.
470 */
471function get_page_template() {
472 $id = get_queried_object_id();
473 $template = get_page_template_slug();
474 $pagename = get_query_var( 'pagename' );
475
476 if ( ! $pagename && $id ) {
477 /*
478 * If a static page is set as the front page, $pagename will not be set.
479 * Retrieve it from the queried object.
480 */
481 $post = get_queried_object();
482 if ( $post ) {
483 $pagename = $post->post_name;
484 }
485 }
486
487 $templates = array();
488 if ( $template && 0 === validate_file( $template ) ) {
489 $templates[] = $template;
490 }
491 if ( $pagename ) {
492 $pagename_decoded = urldecode( $pagename );
493 if ( $pagename_decoded !== $pagename ) {
494 $templates[] = "page-{$pagename_decoded}.php";
495 }
496 $templates[] = "page-{$pagename}.php";
497 }
498 if ( $id ) {
499 $templates[] = "page-{$id}.php";
500 }
501 $templates[] = 'page.php';
502
503 return get_query_template( 'page', $templates );
504}
505
506/**
507 * Retrieves path of search template in current or parent template.
508 *
509 * The template hierarchy and template path are filterable via the {@see '$type_template_hierarchy'}
510 * and {@see '$type_template'} dynamic hooks, where `$type` is 'search'.
511 *
512 * @since 1.5.0
513 *
514 * @see get_query_template()
515 *
516 * @return string Full path to search template file.
517 */
518function get_search_template() {
519 return get_query_template( 'search' );
520}
521
522/**
523 * Retrieves path of single template in current or parent template. Applies to single Posts,
524 * single Attachments, and single custom post types.
525 *
526 * The hierarchy for this template looks like:
527 *
528 * 1. {Post Type Template}.php
529 * 2. single-{post_type}-{post_name}.php
530 * 3. single-{post_type}.php
531 * 4. single.php
532 *
533 * An example of this is:
534 *
535 * 1. templates/full-width.php
536 * 2. single-post-hello-world.php
537 * 3. single-post.php
538 * 4. single.php
539 *
540 * The template hierarchy and template path are filterable via the {@see '$type_template_hierarchy'}
541 * and {@see '$type_template'} dynamic hooks, where `$type` is 'single'.
542 *
543 * @since 1.5.0
544 * @since 4.4.0 `single-{post_type}-{post_name}.php` was added to the top of the template hierarchy.
545 * @since 4.7.0 The decoded form of `single-{post_type}-{post_name}.php` was added to the top of the
546 * template hierarchy when the post name contains multibyte characters.
547 * @since 4.7.0 `{Post Type Template}.php` was added to the top of the template hierarchy.
548 *
549 * @see get_query_template()
550 *
551 * @return string Full path to single template file.
552 */
553function get_single_template() {
554 $object = get_queried_object();
555
556 $templates = array();
557
558 if ( ! empty( $object->post_type ) ) {
559 $template = get_page_template_slug( $object );
560 if ( $template && 0 === validate_file( $template ) ) {
561 $templates[] = $template;
562 }
563
564 $name_decoded = urldecode( $object->post_name );
565 if ( $name_decoded !== $object->post_name ) {
566 $templates[] = "single-{$object->post_type}-{$name_decoded}.php";
567 }
568
569 $templates[] = "single-{$object->post_type}-{$object->post_name}.php";
570 $templates[] = "single-{$object->post_type}.php";
571 }
572
573 $templates[] = 'single.php';
574
575 return get_query_template( 'single', $templates );
576}
577
578/**
579 * Retrieves an embed template path in the current or parent template.
580 *
581 * The hierarchy for this template looks like:
582 *
583 * 1. embed-{post_type}-{post_format}.php
584 * 2. embed-{post_type}.php
585 * 3. embed.php
586 *
587 * An example of this is:
588 *
589 * 1. embed-post-audio.php
590 * 2. embed-post.php
591 * 3. embed.php
592 *
593 * The template hierarchy and template path are filterable via the {@see '$type_template_hierarchy'}
594 * and {@see '$type_template'} dynamic hooks, where `$type` is 'embed'.
595 *
596 * @since 4.5.0
597 *
598 * @see get_query_template()
599 *
600 * @return string Full path to embed template file.
601 */
602function get_embed_template() {
603 $object = get_queried_object();
604
605 $templates = array();
606
607 if ( ! empty( $object->post_type ) ) {
608 $post_format = get_post_format( $object );
609 if ( $post_format ) {
610 $templates[] = "embed-{$object->post_type}-{$post_format}.php";
611 }
612 $templates[] = "embed-{$object->post_type}.php";
613 }
614
615 $templates[] = 'embed.php';
616
617 return get_query_template( 'embed', $templates );
618}
619
620/**
621 * Retrieves the path of the singular template in current or parent template.
622 *
623 * The template hierarchy and template path are filterable via the {@see '$type_template_hierarchy'}
624 * and {@see '$type_template'} dynamic hooks, where `$type` is 'singular'.
625 *
626 * @since 4.3.0
627 *
628 * @see get_query_template()
629 *
630 * @return string Full path to singular template file.
631 */
632function get_singular_template() {
633 return get_query_template( 'singular' );
634}
635
636/**
637 * Retrieves path of attachment template in current or parent template.
638 *
639 * The hierarchy for this template looks like:
640 *
641 * 1. {mime_type}-{sub_type}.php
642 * 2. {sub_type}.php
643 * 3. {mime_type}.php
644 * 4. attachment.php
645 *
646 * An example of this is:
647 *
648 * 1. image-jpeg.php
649 * 2. jpeg.php
650 * 3. image.php
651 * 4. attachment.php
652 *
653 * The template hierarchy and template path are filterable via the {@see '$type_template_hierarchy'}
654 * and {@see '$type_template'} dynamic hooks, where `$type` is 'attachment'.
655 *
656 * @since 2.0.0
657 * @since 4.3.0 The order of the mime type logic was reversed so the hierarchy is more logical.
658 *
659 * @see get_query_template()
660 *
661 * @return string Full path to attachment template file.
662 */
663function get_attachment_template() {
664 $attachment = get_queried_object();
665
666 $templates = array();
667
668 if ( $attachment ) {
669 if ( str_contains( $attachment->post_mime_type, '/' ) ) {
670 list( $type, $subtype ) = explode( '/', $attachment->post_mime_type );
671 } else {
672 list( $type, $subtype ) = array( $attachment->post_mime_type, '' );
673 }
674
675 if ( ! empty( $subtype ) ) {
676 $templates[] = "{$type}-{$subtype}.php";
677 $templates[] = "{$subtype}.php";
678 }
679 $templates[] = "{$type}.php";
680 }
681 $templates[] = 'attachment.php';
682
683 return get_query_template( 'attachment', $templates );
684}
685
686/**
687 * Set up the globals used for template loading.
688 *
689 * @since 6.5.0
690 *
691 * @global string $wp_stylesheet_path Path to current theme's stylesheet directory.
692 * @global string $wp_template_path Path to current theme's template directory.
693 */
694function wp_set_template_globals() {
695 global $wp_stylesheet_path, $wp_template_path;
696
697 $wp_stylesheet_path = get_stylesheet_directory();
698 $wp_template_path = get_template_directory();
699}
700
701/**
702 * Retrieves the name of the highest priority template file that exists.
703 *
704 * Searches in the stylesheet directory before the template directory and
705 * wp-includes/theme-compat so that themes which inherit from a parent theme
706 * can just overload one file.
707 *
708 * @since 2.7.0
709 * @since 5.5.0 The `$args` parameter was added.
710 *
711 * @global string $wp_stylesheet_path Path to current theme's stylesheet directory.
712 * @global string $wp_template_path Path to current theme's template directory.
713 *
714 * @param string|array $template_names Template file(s) to search for, in order.
715 * @param bool $load If true the template file will be loaded if it is found.
716 * @param bool $load_once Whether to require_once or require. Has no effect if `$load` is false.
717 * Default true.
718 * @param array $args Optional. Additional arguments passed to the template.
719 * Default empty array.
720 * @return string The template filename if one is located.
721 */
722function locate_template( $template_names, $load = false, $load_once = true, $args = array() ) {
723 global $wp_stylesheet_path, $wp_template_path;
724
725 if ( ! isset( $wp_stylesheet_path ) || ! isset( $wp_template_path ) ) {
726 wp_set_template_globals();
727 }
728
729 $is_child_theme = is_child_theme();
730
731 $located = '';
732 foreach ( (array) $template_names as $template_name ) {
733 if ( ! $template_name ) {
734 continue;
735 }
736 if ( file_exists( $wp_stylesheet_path . '/' . $template_name ) ) {
737 $located = $wp_stylesheet_path . '/' . $template_name;
738 break;
739 } elseif ( $is_child_theme && file_exists( $wp_template_path . '/' . $template_name ) ) {
740 $located = $wp_template_path . '/' . $template_name;
741 break;
742 } elseif ( file_exists( ABSPATH . WPINC . '/theme-compat/' . $template_name ) ) {
743 $located = ABSPATH . WPINC . '/theme-compat/' . $template_name;
744 break;
745 }
746 }
747
748 if ( $load && '' !== $located ) {
749 load_template( $located, $load_once, $args );
750 }
751
752 return $located;
753}
754
755/**
756 * Requires the template file with WordPress environment.
757 *
758 * The globals are set up for the template file to ensure that the WordPress
759 * environment is available from within the function. The query variables are
760 * also available.
761 *
762 * @since 1.5.0
763 * @since 5.5.0 The `$args` parameter was added.
764 *
765 * @global array $posts
766 * @global WP_Post $post Global post object.
767 * @global bool $wp_did_header
768 * @global WP_Query $wp_query WordPress Query object.
769 * @global WP_Rewrite $wp_rewrite WordPress rewrite component.
770 * @global wpdb $wpdb WordPress database abstraction object.
771 * @global string $wp_version
772 * @global WP $wp Current WordPress environment instance.
773 * @global int $id
774 * @global WP_Comment $comment Global comment object.
775 * @global int $user_ID
776 *
777 * @param string $_template_file Path to template file.
778 * @param bool $load_once Whether to require_once or require. Default true.
779 * @param array $args Optional. Additional arguments passed to the template.
780 * Default empty array.
781 */
782function load_template( $_template_file, $load_once = true, $args = array() ) {
783 global $posts, $post, $wp_did_header, $wp_query, $wp_rewrite, $wpdb, $wp_version, $wp, $id, $comment, $user_ID;
784
785 if ( is_array( $wp_query->query_vars ) ) {
786 /*
787 * This use of extract() cannot be removed. There are many possible ways that
788 * templates could depend on variables that it creates existing, and no way to
789 * detect and deprecate it.
790 *
791 * Passing the EXTR_SKIP flag is the safest option, ensuring globals and
792 * function variables cannot be overwritten.
793 */
794 // phpcs:ignore WordPress.PHP.DontExtract.extract_extract
795 extract( $wp_query->query_vars, EXTR_SKIP );
796 }
797
798 if ( isset( $s ) ) {
799 $s = esc_attr( $s );
800 }
801
802 /**
803 * Fires before a template file is loaded.
804 *
805 * @since 6.1.0
806 *
807 * @param string $_template_file The full path to the template file.
808 * @param bool $load_once Whether to require_once or require.
809 * @param array $args Additional arguments passed to the template.
810 */
811 do_action( 'wp_before_load_template', $_template_file, $load_once, $args );
812
813 if ( $load_once ) {
814 require_once $_template_file;
815 } else {
816 require $_template_file;
817 }
818
819 /**
820 * Fires after a template file is loaded.
821 *
822 * @since 6.1.0
823 *
824 * @param string $_template_file The full path to the template file.
825 * @param bool $load_once Whether to require_once or require.
826 * @param array $args Additional arguments passed to the template.
827 */
828 do_action( 'wp_after_load_template', $_template_file, $load_once, $args );
829}
830
831/**
832 * Checks whether the template should be output buffered for enhancement.
833 *
834 * By default, an output buffer is only started if a {@see 'wp_template_enhancement_output_buffer'} filter has been
835 * added by the time a template is included at the {@see 'wp_before_include_template'} action. This allows template
836 * responses to be streamed as much as possible when no template enhancements are registered to apply.
837 *
838 * @since 6.9.0
839 *
840 * @return bool Whether the template should be output-buffered for enhancement.
841 */
842function wp_should_output_buffer_template_for_enhancement(): bool {
843 /**
844 * Filters whether the template should be output-buffered for enhancement.
845 *
846 * By default, an output buffer is only started if a {@see 'wp_template_enhancement_output_buffer'} filter has been
847 * added or if a plugin has added a {@see 'wp_finalized_template_enhancement_output_buffer'} action. For this
848 * default to apply, either of the hooks must be added by the time the template is included at the
849 * {@see 'wp_before_include_template'} action. This allows template responses to be streamed unless the there is
850 * code which depends on an output buffer being opened. This filter allows a site to opt in to adding such template
851 * enhancement filters later during the rendering of the template.
852 *
853 * @since 6.9.0
854 *
855 * @param bool $use_output_buffer Whether an output buffer is started.
856 */
857 return (bool) apply_filters( 'wp_should_output_buffer_template_for_enhancement', has_filter( 'wp_template_enhancement_output_buffer' ) || has_action( 'wp_finalized_template_enhancement_output_buffer' ) );
858}
859
860/**
861 * Starts the template enhancement output buffer.
862 *
863 * This function is called immediately before the template is included.
864 *
865 * @since 6.9.0
866 *
867 * @return bool Whether the output buffer successfully started.
868 */
869function wp_start_template_enhancement_output_buffer(): bool {
870 if ( ! wp_should_output_buffer_template_for_enhancement() ) {
871 return false;
872 }
873
874 $started = ob_start(
875 'wp_finalize_template_enhancement_output_buffer',
876 0, // Unlimited buffer size so that entire output is passed to the filter.
877 /*
878 * Instead of the default PHP_OUTPUT_HANDLER_STDFLAGS (cleanable, flushable, and removable) being used for
879 * flags, the PHP_OUTPUT_HANDLER_FLUSHABLE flag must be omitted. If the buffer were flushable, then each time
880 * that ob_flush() is called, a fragment of the output would be sent into the output buffer callback. This
881 * output buffer is intended to capture the entire response for processing, as indicated by the chunk size of 0.
882 * So the buffer does not allow flushing to ensure the entire buffer can be processed, such as for optimizing an
883 * entire HTML document, where markup in the HEAD may need to be adjusted based on markup that appears late in
884 * the BODY.
885 *
886 * If this ends up being problematic, then PHP_OUTPUT_HANDLER_FLUSHABLE could be added to the $flags and the
887 * output buffer callback could check if the phase is PHP_OUTPUT_HANDLER_FLUSH and abort any subsequent
888 * processing while also emitting a _doing_it_wrong().
889 *
890 * The output buffer needs to be removable because WordPress calls wp_ob_end_flush_all() and then calls
891 * wp_cache_close(). If the buffers are not all flushed before wp_cache_close() is closed, then some output buffer
892 * handlers (e.g. for caching plugins) may fail to be able to store the page output in the object cache.
893 * See <https://github.com/WordPress/performance/pull/1317#issuecomment-2271955356>.
894 */
895 PHP_OUTPUT_HANDLER_STDFLAGS ^ PHP_OUTPUT_HANDLER_FLUSHABLE
896 );
897
898 if ( $started ) {
899 /**
900 * Fires when the template enhancement output buffer has started.
901 *
902 * @since 6.9.0
903 */
904 do_action( 'wp_template_enhancement_output_buffer_started' );
905 }
906
907 return $started;
908}
909
910/**
911 * Finalizes the template enhancement output buffer.
912 *
913 * Checks to see if the output buffer is complete and contains HTML. If so, runs the content through
914 * the `wp_template_enhancement_output_buffer` filter. If not, the original content is returned.
915 *
916 * @since 6.9.0
917 *
918 * @see wp_start_template_enhancement_output_buffer()
919 *
920 * @param string $output Output buffer.
921 * @param int $phase Phase.
922 * @return string Finalized output buffer.
923 */
924function wp_finalize_template_enhancement_output_buffer( string $output, int $phase ): string {
925 // When the output is being cleaned (e.g. pending template is replaced with error page), do not send it through the filter.
926 if ( ( $phase & PHP_OUTPUT_HANDLER_CLEAN ) !== 0 ) {
927 return $output;
928 }
929
930 // Detect if the response is an HTML content type.
931 $is_html_content_type = null;
932 $html_content_types = array( 'text/html', 'application/xhtml+xml' );
933 foreach ( headers_list() as $header ) {
934 $header_parts = explode( ':', strtolower( $header ), 2 );
935 if (
936 count( $header_parts ) === 2 &&
937 'content-type' === $header_parts[0]
938 ) {
939 /*
940 * This is looking for very specific content types, therefore it
941 * doesn’t need to fully parse the header’s value. Instead, it needs
942 * only assert that the content type is one of the static HTML types.
943 *
944 * Example:
945 *
946 * Content-Type: text/html; charset=utf8
947 * Content-Type: text/html ;charset=latin4
948 * Content-Type:application/xhtml+xml
949 */
950 $media_type = trim( strtok( $header_parts[1], ';' ), " \t" );
951 $is_html_content_type = in_array( $media_type, $html_content_types, true );
952 break; // PHP only sends the first Content-Type header in the list.
953 }
954 }
955 if ( null === $is_html_content_type ) {
956 $is_html_content_type = in_array( ini_get( 'default_mimetype' ), $html_content_types, true );
957 }
958
959 // If the content type is not HTML, short-circuit since it is not relevant for enhancement.
960 if ( ! $is_html_content_type ) {
961 /** This action is documented in wp-includes/template.php */
962 do_action( 'wp_finalized_template_enhancement_output_buffer', $output );
963 return $output;
964 }
965
966 $filtered_output = $output;
967
968 $did_just_catch = false;
969
970 $error_log = array();
971 set_error_handler(
972 static function ( int $level, string $message, ?string $file = null, ?int $line = null ) use ( &$error_log, &$did_just_catch ) {
973 // Switch a user error to an exception so that it can be caught and the buffer can be returned.
974 if ( E_USER_ERROR === $level ) {
975 throw new Exception( __( 'User error triggered:' ) . ' ' . $message );
976 }
977
978 // Display a caught exception as an error since it prevents any of the output buffer filters from applying.
979 if ( $did_just_catch ) { // @phpstan-ignore if.alwaysFalse (The variable is set in the catch block below.)
980 $level = E_USER_ERROR;
981 }
982
983 // Capture a reported error to be displayed by appending to the processed output buffer if display_errors is enabled.
984 if ( error_reporting() & $level ) {
985 $error_log[] = compact( 'level', 'message', 'file', 'line' );
986 }
987 return false;
988 }
989 );
990 $original_display_errors = ini_get( 'display_errors' );
991 if ( $original_display_errors ) {
992 ini_set( 'display_errors', 0 );
993 }
994
995 try {
996 /**
997 * Filters the template enhancement output buffer prior to sending to the client.
998 *
999 * This filter only applies the HTML output of an included template. This filter is a progressive enhancement
1000 * intended for applications such as optimizing markup to improve frontend page load performance. Sites must not
1001 * depend on this filter applying since they may opt to stream the responses instead. Callbacks for this filter
1002 * are highly discouraged from using regular expressions to do any kind of replacement on the output. Use the
1003 * HTML API (either `WP_HTML_Tag_Processor` or `WP_HTML_Processor`), or else use {@see DOM\HtmlDocument} as of
1004 * PHP 8.4 which fully supports HTML5.
1005 *
1006 * Do not print any output during this filter. While filters normally don't print anything, this is especially
1007 * important since this applies during an output buffer callback. Prior to PHP 8.5, the output will be silently
1008 * omitted, whereas afterward a deprecation notice will be emitted.
1009 *
1010 * Important: Because this filter is applied inside an output buffer callback (i.e. display handler), any
1011 * callbacks added to the filter must not attempt to start their own output buffers. Otherwise, PHP will raise a
1012 * fatal error: "Cannot use output buffering in output buffering display handlers."
1013 *
1014 * @since 6.9.0
1015 *
1016 * @param string $filtered_output HTML template enhancement output buffer.
1017 * @param string $output Original HTML template output buffer.
1018 */
1019 $filtered_output = (string) apply_filters( 'wp_template_enhancement_output_buffer', $filtered_output, $output );
1020 } catch ( Throwable $throwable ) {
1021 // Emit to the error log as a warning not as an error to prevent halting execution.
1022 $did_just_catch = true;
1023 trigger_error(
1024 sprintf(
1025 /* translators: %s is the throwable class name */
1026 __( 'Uncaught "%s" thrown:' ),
1027 get_class( $throwable )
1028 ) . ' ' . $throwable->getMessage(),
1029 E_USER_WARNING
1030 );
1031 $did_just_catch = false;
1032 }
1033
1034 try {
1035 /**
1036 * Fires after the template enhancement output buffer has been finalized.
1037 *
1038 * This happens immediately before the template enhancement output buffer is flushed. No output may be printed
1039 * at this action; prior to PHP 8.5, the output will be silently omitted, whereas afterward a deprecation notice
1040 * will be emitted. Nevertheless, HTTP headers may be sent, which makes this action complimentary to the
1041 * {@see 'send_headers'} action, in which headers may be sent before the template has started rendering. In
1042 * contrast, this `wp_finalized_template_enhancement_output_buffer` action is the possible point at which HTTP
1043 * headers can be sent. This action does not fire if the "template enhancement output buffer" was not started.
1044 * This output buffer is automatically started if this action is added before
1045 * {@see wp_start_template_enhancement_output_buffer()} runs at the {@see 'wp_before_include_template'} action
1046 * with priority 1000. Before this point, the output buffer will also be started automatically if there was a
1047 * {@see 'wp_template_enhancement_output_buffer'} filter added, or if the
1048 * {@see 'wp_should_output_buffer_template_for_enhancement'} filter is made to return `true`.
1049 *
1050 * Important: Because this action fires inside an output buffer callback (i.e. display handler), any callbacks
1051 * added to the action must not attempt to start their own output buffers. Otherwise, PHP will raise a fatal
1052 * error: "Cannot use output buffering in output buffering display handlers."
1053 *
1054 * @since 6.9.0
1055 *
1056 * @param string $output Finalized output buffer.
1057 */
1058 do_action( 'wp_finalized_template_enhancement_output_buffer', $filtered_output );
1059 } catch ( Throwable $throwable ) {
1060 // Emit to the error log as a warning not as an error to prevent halting execution.
1061 $did_just_catch = true;
1062 trigger_error(
1063 sprintf(
1064 /* translators: %s is the class name */
1065 __( 'Uncaught "%s" thrown:' ),
1066 get_class( $throwable )
1067 ) . ' ' . $throwable->getMessage(),
1068 E_USER_WARNING
1069 );
1070 $did_just_catch = false;
1071 }
1072
1073 // Append any errors to be displayed before returning flushing the buffer.
1074 if ( $original_display_errors && 'stderr' !== $original_display_errors ) {
1075 foreach ( $error_log as $error ) {
1076 switch ( $error['level'] ) {
1077 case E_USER_NOTICE:
1078 $type = 'Notice';
1079 break;
1080 case E_USER_DEPRECATED:
1081 $type = 'Deprecated';
1082 break;
1083 case E_USER_WARNING:
1084 $type = 'Warning';
1085 break;
1086 default:
1087 $type = 'Error';
1088 }
1089
1090 if ( ini_get( 'html_errors' ) ) {
1091 /*
1092 * Adapted from PHP internals: <https://github.com/php/php-src/blob/a979e9f897a90a580e883b1f39ce5673686ffc67/main/main.c#L1478>.
1093 * The self-closing tags are a vestige of the XHTML past!
1094 */
1095 $format = "%s<br />\n<b>%s</b>: %s in <b>%s</b> on line <b>%s</b><br />\n%s";
1096 } else {
1097 // Adapted from PHP internals: <https://github.com/php/php-src/blob/a979e9f897a90a580e883b1f39ce5673686ffc67/main/main.c#L1492>.
1098 $format = "%s\n%s: %s in %s on line %s\n%s";
1099 }
1100 $filtered_output .= sprintf(
1101 $format,
1102 ini_get( 'error_prepend_string' ),
1103 $type,
1104 $error['message'],
1105 $error['file'],
1106 $error['line'],
1107 ini_get( 'error_append_string' )
1108 );
1109 }
1110
1111 ini_set( 'display_errors', $original_display_errors );
1112 }
1113
1114 restore_error_handler();
1115
1116 return $filtered_output;
1117}
1118