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
📄general-template.php
1<?php
2/**
3 * General template tags that can go anywhere in a template.
4 *
5 * @package WordPress
6 * @subpackage Template
7 */
8
9/**
10 * Loads header template.
11 *
12 * Includes the header template for a theme or if a name is specified then a
13 * specialized header will be included.
14 *
15 * For the parameter, if the file is called "header-special.php" then specify
16 * "special".
17 *
18 * @since 1.5.0
19 * @since 5.5.0 A return value was added.
20 * @since 5.5.0 The `$args` parameter was added.
21 *
22 * @param string|null $name The name of the specialized header. Default null.
23 * @param array $args Optional. Additional arguments passed to the header template.
24 * Default empty array.
25 * @return void|false Void on success, false if the template does not exist.
26 */
27function get_header( $name = null, $args = array() ) {
28 /**
29 * Fires before the header template file is loaded.
30 *
31 * @since 2.1.0
32 * @since 2.8.0 The `$name` parameter was added.
33 * @since 5.5.0 The `$args` parameter was added.
34 *
35 * @param string|null $name Name of the specific header file to use. Null for the default header.
36 * @param array $args Additional arguments passed to the header template.
37 */
38 do_action( 'get_header', $name, $args );
39
40 $templates = array();
41 $name = (string) $name;
42 if ( '' !== $name ) {
43 $templates[] = "header-{$name}.php";
44 }
45
46 $templates[] = 'header.php';
47
48 if ( ! locate_template( $templates, true, true, $args ) ) {
49 return false;
50 }
51}
52
53/**
54 * Loads footer template.
55 *
56 * Includes the footer template for a theme or if a name is specified then a
57 * specialized footer will be included.
58 *
59 * For the parameter, if the file is called "footer-special.php" then specify
60 * "special".
61 *
62 * @since 1.5.0
63 * @since 5.5.0 A return value was added.
64 * @since 5.5.0 The `$args` parameter was added.
65 *
66 * @param string|null $name The name of the specialized footer. Default null.
67 * @param array $args Optional. Additional arguments passed to the footer template.
68 * Default empty array.
69 * @return void|false Void on success, false if the template does not exist.
70 */
71function get_footer( $name = null, $args = array() ) {
72 /**
73 * Fires before the footer template file is loaded.
74 *
75 * @since 2.1.0
76 * @since 2.8.0 The `$name` parameter was added.
77 * @since 5.5.0 The `$args` parameter was added.
78 *
79 * @param string|null $name Name of the specific footer file to use. Null for the default footer.
80 * @param array $args Additional arguments passed to the footer template.
81 */
82 do_action( 'get_footer', $name, $args );
83
84 $templates = array();
85 $name = (string) $name;
86 if ( '' !== $name ) {
87 $templates[] = "footer-{$name}.php";
88 }
89
90 $templates[] = 'footer.php';
91
92 if ( ! locate_template( $templates, true, true, $args ) ) {
93 return false;
94 }
95}
96
97/**
98 * Loads sidebar template.
99 *
100 * Includes the sidebar template for a theme or if a name is specified then a
101 * specialized sidebar will be included.
102 *
103 * For the parameter, if the file is called "sidebar-special.php" then specify
104 * "special".
105 *
106 * @since 1.5.0
107 * @since 5.5.0 A return value was added.
108 * @since 5.5.0 The `$args` parameter was added.
109 *
110 * @param string|null $name The name of the specialized sidebar. Default null.
111 * @param array $args Optional. Additional arguments passed to the sidebar template.
112 * Default empty array.
113 * @return void|false Void on success, false if the template does not exist.
114 */
115function get_sidebar( $name = null, $args = array() ) {
116 /**
117 * Fires before the sidebar template file is loaded.
118 *
119 * @since 2.2.0
120 * @since 2.8.0 The `$name` parameter was added.
121 * @since 5.5.0 The `$args` parameter was added.
122 *
123 * @param string|null $name Name of the specific sidebar file to use. Null for the default sidebar.
124 * @param array $args Additional arguments passed to the sidebar template.
125 */
126 do_action( 'get_sidebar', $name, $args );
127
128 $templates = array();
129 $name = (string) $name;
130 if ( '' !== $name ) {
131 $templates[] = "sidebar-{$name}.php";
132 }
133
134 $templates[] = 'sidebar.php';
135
136 if ( ! locate_template( $templates, true, true, $args ) ) {
137 return false;
138 }
139}
140
141/**
142 * Loads a template part into a template.
143 *
144 * Provides a simple mechanism for child themes to overload reusable sections of code
145 * in the theme.
146 *
147 * Includes the named template part for a theme or if a name is specified then a
148 * specialized part will be included. If the theme contains no {slug}.php file
149 * then no template will be included.
150 *
151 * The template is included using require, not require_once, so you may include the
152 * same template part multiple times.
153 *
154 * For the $name parameter, if the file is called "{slug}-special.php" then specify
155 * "special".
156 *
157 * @since 3.0.0
158 * @since 5.5.0 A return value was added.
159 * @since 5.5.0 The `$args` parameter was added.
160 *
161 * @param string $slug The slug name for the generic template.
162 * @param string|null $name Optional. The name of the specialized template. Default null.
163 * @param array $args Optional. Additional arguments passed to the template.
164 * Default empty array.
165 * @return void|false Void on success, false if the template does not exist.
166 */
167function get_template_part( $slug, $name = null, $args = array() ) {
168 /**
169 * Fires before the specified template part file is loaded.
170 *
171 * The dynamic portion of the hook name, `$slug`, refers to the slug name
172 * for the generic template part.
173 *
174 * @since 3.0.0
175 * @since 5.5.0 The `$args` parameter was added.
176 *
177 * @param string $slug The slug name for the generic template.
178 * @param string|null $name The name of the specialized template
179 * or null if there is none.
180 * @param array $args Additional arguments passed to the template.
181 */
182 do_action( "get_template_part_{$slug}", $slug, $name, $args );
183
184 $templates = array();
185 $name = (string) $name;
186 if ( '' !== $name ) {
187 $templates[] = "{$slug}-{$name}.php";
188 }
189
190 $templates[] = "{$slug}.php";
191
192 /**
193 * Fires before an attempt is made to locate and load a template part.
194 *
195 * @since 5.2.0
196 * @since 5.5.0 The `$args` parameter was added.
197 *
198 * @param string $slug The slug name for the generic template.
199 * @param string $name The name of the specialized template
200 * or an empty string if there is none.
201 * @param string[] $templates Array of template files to search for, in order.
202 * @param array $args Additional arguments passed to the template.
203 */
204 do_action( 'get_template_part', $slug, $name, $templates, $args );
205
206 if ( ! locate_template( $templates, true, false, $args ) ) {
207 return false;
208 }
209}
210
211/**
212 * Displays search form.
213 *
214 * Will first attempt to locate the searchform.php file in either the child or
215 * the parent, then load it. If it doesn't exist, then the default search form
216 * will be displayed. The default search form is HTML, which will be displayed.
217 * There is a filter applied to the search form HTML in order to edit or replace
218 * it. The filter is {@see 'get_search_form'}.
219 *
220 * This function is primarily used by themes which want to hardcode the search
221 * form into the sidebar and also by the search widget in WordPress.
222 *
223 * There is also an action that is called whenever the function is run called,
224 * {@see 'pre_get_search_form'}. This can be useful for outputting JavaScript that the
225 * search relies on or various formatting that applies to the beginning of the
226 * search. To give a few examples of what it can be used for.
227 *
228 * @since 2.7.0
229 * @since 5.2.0 The `$args` array parameter was added in place of an `$echo` boolean flag.
230 *
231 * @param array $args {
232 * Optional. Array of display arguments.
233 *
234 * @type bool $echo Whether to echo or return the form. Default true.
235 * @type string $aria_label ARIA label for the search form. Useful to distinguish
236 * multiple search forms on the same page and improve
237 * accessibility. Default empty.
238 * }
239 * @return void|string Void if 'echo' argument is true, search form HTML if 'echo' is false.
240 */
241function get_search_form( $args = array() ) {
242 /**
243 * Fires before the search form is retrieved, at the start of get_search_form().
244 *
245 * @since 2.7.0 as 'get_search_form' action.
246 * @since 3.6.0
247 * @since 5.5.0 The `$args` parameter was added.
248 *
249 * @link https://core.trac.wordpress.org/ticket/19321
250 *
251 * @param array $args The array of arguments for building the search form.
252 * See get_search_form() for information on accepted arguments.
253 */
254 do_action( 'pre_get_search_form', $args );
255
256 $echo = true;
257
258 if ( ! is_array( $args ) ) {
259 /*
260 * Back compat: to ensure previous uses of get_search_form() continue to
261 * function as expected, we handle a value for the boolean $echo param removed
262 * in 5.2.0. Then we deal with the $args array and cast its defaults.
263 */
264 $echo = (bool) $args;
265
266 // Set an empty array and allow default arguments to take over.
267 $args = array();
268 }
269
270 // Defaults are to echo and to output no custom label on the form.
271 $defaults = array(
272 'echo' => $echo,
273 'aria_label' => '',
274 );
275
276 $args = wp_parse_args( $args, $defaults );
277
278 /**
279 * Filters the array of arguments used when generating the search form.
280 *
281 * @since 5.2.0
282 *
283 * @param array $args The array of arguments for building the search form.
284 * See get_search_form() for information on accepted arguments.
285 */
286 $args = apply_filters( 'search_form_args', $args );
287
288 // Ensure that the filtered arguments contain all required default values.
289 $args = array_merge( $defaults, $args );
290
291 $format = current_theme_supports( 'html5', 'search-form' ) ? 'html5' : 'xhtml';
292
293 /**
294 * Filters the HTML format of the search form.
295 *
296 * @since 3.6.0
297 * @since 5.5.0 The `$args` parameter was added.
298 *
299 * @param string $format The type of markup to use in the search form.
300 * Accepts 'html5', 'xhtml'.
301 * @param array $args The array of arguments for building the search form.
302 * See get_search_form() for information on accepted arguments.
303 */
304 $format = apply_filters( 'search_form_format', $format, $args );
305
306 $search_form_template = locate_template( 'searchform.php' );
307
308 if ( '' !== $search_form_template ) {
309 ob_start();
310 require $search_form_template;
311 $form = ob_get_clean();
312 } else {
313 // Build a string containing an aria-label to use for the search form.
314 if ( $args['aria_label'] ) {
315 $aria_label = 'aria-label="' . esc_attr( $args['aria_label'] ) . '" ';
316 } else {
317 /*
318 * If there's no custom aria-label, we can set a default here. At the
319 * moment it's empty as there's uncertainty about what the default should be.
320 */
321 $aria_label = '';
322 }
323
324 if ( 'html5' === $format ) {
325 $form = '<form role="search" ' . $aria_label . 'method="get" class="search-form" action="' . esc_url( home_url( '/' ) ) . '">
326 <label>
327 <span class="screen-reader-text">' .
328 /* translators: Hidden accessibility text. */
329 _x( 'Search for:', 'label' ) .
330 '</span>
331 <input type="search" class="search-field" placeholder="' . esc_attr_x( 'Search &hellip;', 'placeholder' ) . '" value="' . get_search_query() . '" name="s" />
332 </label>
333 <input type="submit" class="search-submit" value="' . esc_attr_x( 'Search', 'submit button' ) . '" />
334 </form>';
335 } else {
336 $form = '<form role="search" ' . $aria_label . 'method="get" id="searchform" class="searchform" action="' . esc_url( home_url( '/' ) ) . '">
337 <div>
338 <label class="screen-reader-text" for="s">' .
339 /* translators: Hidden accessibility text. */
340 _x( 'Search for:', 'label' ) .
341 '</label>
342 <input type="text" value="' . get_search_query() . '" name="s" id="s" />
343 <input type="submit" id="searchsubmit" value="' . esc_attr_x( 'Search', 'submit button' ) . '" />
344 </div>
345 </form>';
346 }
347 }
348
349 /**
350 * Filters the HTML output of the search form.
351 *
352 * @since 2.7.0
353 * @since 5.5.0 The `$args` parameter was added.
354 *
355 * @param string $form The search form HTML output.
356 * @param array $args The array of arguments for building the search form.
357 * See get_search_form() for information on accepted arguments.
358 */
359 $result = apply_filters( 'get_search_form', $form, $args );
360
361 if ( null === $result ) {
362 $result = $form;
363 }
364
365 if ( $args['echo'] ) {
366 echo $result;
367 } else {
368 return $result;
369 }
370}
371
372/**
373 * Displays the Log In/Out link.
374 *
375 * Displays a link, which allows users to navigate to the Log In page to log in
376 * or log out depending on whether they are currently logged in.
377 *
378 * @since 1.5.0
379 *
380 * @param string $redirect Optional path to redirect to on login/logout.
381 * @param bool $display Default to echo and not return the link.
382 * @return void|string Void if `$display` argument is true, log in/out link if `$display` is false.
383 */
384function wp_loginout( $redirect = '', $display = true ) {
385 if ( ! is_user_logged_in() ) {
386 $link = '<a href="' . esc_url( wp_login_url( $redirect ) ) . '">' . __( 'Log in' ) . '</a>';
387 } else {
388 $link = '<a href="' . esc_url( wp_logout_url( $redirect ) ) . '">' . __( 'Log out' ) . '</a>';
389 }
390
391 if ( $display ) {
392 /**
393 * Filters the HTML output for the Log In/Log Out link.
394 *
395 * @since 1.5.0
396 *
397 * @param string $link The HTML link content.
398 */
399 echo apply_filters( 'loginout', $link );
400 } else {
401 /** This filter is documented in wp-includes/general-template.php */
402 return apply_filters( 'loginout', $link );
403 }
404}
405
406/**
407 * Retrieves the logout URL.
408 *
409 * Returns the URL that allows the user to log out of the site.
410 *
411 * @since 2.7.0
412 *
413 * @param string $redirect Path to redirect to on logout.
414 * @return string The logout URL. Note: HTML-encoded via esc_html() in wp_nonce_url().
415 */
416function wp_logout_url( $redirect = '' ) {
417 $args = array();
418 if ( ! empty( $redirect ) ) {
419 $args['redirect_to'] = urlencode( $redirect );
420 }
421
422 $logout_url = add_query_arg( $args, site_url( 'wp-login.php?action=logout', 'login' ) );
423 $logout_url = wp_nonce_url( $logout_url, 'log-out' );
424
425 /**
426 * Filters the logout URL.
427 *
428 * @since 2.8.0
429 *
430 * @param string $logout_url The HTML-encoded logout URL.
431 * @param string $redirect Path to redirect to on logout.
432 */
433 return apply_filters( 'logout_url', $logout_url, $redirect );
434}
435
436/**
437 * Retrieves the login URL.
438 *
439 * @since 2.7.0
440 *
441 * @param string $redirect Path to redirect to on log in.
442 * @param bool $force_reauth Whether to force reauthorization, even if a cookie is present.
443 * Default false.
444 * @return string The login URL. Not HTML-encoded.
445 */
446function wp_login_url( $redirect = '', $force_reauth = false ) {
447 $login_url = site_url( 'wp-login.php', 'login' );
448
449 if ( ! empty( $redirect ) ) {
450 $login_url = add_query_arg( 'redirect_to', urlencode( $redirect ), $login_url );
451 }
452
453 if ( $force_reauth ) {
454 $login_url = add_query_arg( 'reauth', '1', $login_url );
455 }
456
457 /**
458 * Filters the login URL.
459 *
460 * @since 2.8.0
461 * @since 4.2.0 The `$force_reauth` parameter was added.
462 *
463 * @param string $login_url The login URL. Not HTML-encoded.
464 * @param string $redirect The path to redirect to on login, if supplied.
465 * @param bool $force_reauth Whether to force reauthorization, even if a cookie is present.
466 */
467 return apply_filters( 'login_url', $login_url, $redirect, $force_reauth );
468}
469
470/**
471 * Returns the URL that allows the user to register on the site.
472 *
473 * @since 3.6.0
474 *
475 * @return string User registration URL.
476 */
477function wp_registration_url() {
478 /**
479 * Filters the user registration URL.
480 *
481 * @since 3.6.0
482 *
483 * @param string $register The user registration URL.
484 */
485 return apply_filters( 'register_url', site_url( 'wp-login.php?action=register', 'login' ) );
486}
487
488/**
489 * Provides a simple login form for use anywhere within WordPress.
490 *
491 * The login form HTML is echoed by default. Pass a false value for `$echo` to return it instead.
492 *
493 * @since 3.0.0
494 * @since 6.6.0 Added `required_username` and `required_password` arguments.
495 *
496 * @param array $args {
497 * Optional. Array of options to control the form output. Default empty array.
498 *
499 * @type bool $echo Whether to display the login form or return the form HTML code.
500 * Default true (echo).
501 * @type string $redirect URL to redirect to. Must be absolute, as in "https://example.com/mypage/".
502 * Default is to redirect back to the request URI.
503 * @type string $form_id ID attribute value for the form. Default 'loginform'.
504 * @type string $label_username Label for the username or email address field. Default 'Username or Email Address'.
505 * @type string $label_password Label for the password field. Default 'Password'.
506 * @type string $label_remember Label for the remember field. Default 'Remember Me'.
507 * @type string $label_log_in Label for the submit button. Default 'Log In'.
508 * @type string $id_username ID attribute value for the username field. Default 'user_login'.
509 * @type string $id_password ID attribute value for the password field. Default 'user_pass'.
510 * @type string $id_remember ID attribute value for the remember field. Default 'rememberme'.
511 * @type string $id_submit ID attribute value for the submit button. Default 'wp-submit'.
512 * @type bool $remember Whether to display the "rememberme" checkbox in the form.
513 * @type string $value_username Default value for the username field. Default empty.
514 * @type bool $value_remember Whether the "Remember Me" checkbox should be checked by default.
515 * Default false (unchecked).
516 * @type bool $required_username Whether the username field has the 'required' attribute.
517 * Default false.
518 * @type bool $required_password Whether the password field has the 'required' attribute.
519 * Default false.
520 *
521 * }
522 * @return void|string Void if 'echo' argument is true, login form HTML if 'echo' is false.
523 */
524function wp_login_form( $args = array() ) {
525 $defaults = array(
526 'echo' => true,
527 // Default 'redirect' value takes the user back to the request URI.
528 'redirect' => ( is_ssl() ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'],
529 'form_id' => 'loginform',
530 'label_username' => __( 'Username or Email Address' ),
531 'label_password' => __( 'Password' ),
532 'label_remember' => __( 'Remember Me' ),
533 'label_log_in' => __( 'Log In' ),
534 'id_username' => 'user_login',
535 'id_password' => 'user_pass',
536 'id_remember' => 'rememberme',
537 'id_submit' => 'wp-submit',
538 'remember' => true,
539 'value_username' => '',
540 // Set 'value_remember' to true to default the "Remember me" checkbox to checked.
541 'value_remember' => false,
542 // Set 'required_username' to true to add the required attribute to username field.
543 'required_username' => false,
544 // Set 'required_password' to true to add the required attribute to password field.
545 'required_password' => false,
546 );
547
548 /**
549 * Filters the default login form output arguments.
550 *
551 * @since 3.0.0
552 *
553 * @see wp_login_form()
554 *
555 * @param array $defaults An array of default login form arguments.
556 */
557 $args = wp_parse_args( $args, apply_filters( 'login_form_defaults', $defaults ) );
558
559 /**
560 * Filters content to display at the top of the login form.
561 *
562 * The filter evaluates just following the opening form tag element.
563 *
564 * @since 3.0.0
565 *
566 * @param string $content Content to display. Default empty.
567 * @param array $args Array of login form arguments.
568 */
569 $login_form_top = apply_filters( 'login_form_top', '', $args );
570
571 /**
572 * Filters content to display in the middle of the login form.
573 *
574 * The filter evaluates just following the location where the 'login-password'
575 * field is displayed.
576 *
577 * @since 3.0.0
578 *
579 * @param string $content Content to display. Default empty.
580 * @param array $args Array of login form arguments.
581 */
582 $login_form_middle = apply_filters( 'login_form_middle', '', $args );
583
584 /**
585 * Filters content to display at the bottom of the login form.
586 *
587 * The filter evaluates just preceding the closing form tag element.
588 *
589 * @since 3.0.0
590 *
591 * @param string $content Content to display. Default empty.
592 * @param array $args Array of login form arguments.
593 */
594 $login_form_bottom = apply_filters( 'login_form_bottom', '', $args );
595
596 $form =
597 sprintf(
598 '<form name="%1$s" id="%1$s" action="%2$s" method="post">',
599 esc_attr( $args['form_id'] ),
600 esc_url( site_url( 'wp-login.php', 'login_post' ) )
601 ) .
602 $login_form_top .
603 sprintf(
604 '<p class="login-username">
605 <label for="%1$s">%2$s</label>
606 <input type="text" name="log" id="%1$s" autocomplete="username" class="input" value="%3$s" size="20"%4$s />
607 </p>',
608 esc_attr( $args['id_username'] ),
609 esc_html( $args['label_username'] ),
610 esc_attr( $args['value_username'] ),
611 ( $args['required_username'] ? ' required="required"' : '' )
612 ) .
613 sprintf(
614 '<p class="login-password">
615 <label for="%1$s">%2$s</label>
616 <input type="password" name="pwd" id="%1$s" autocomplete="current-password" spellcheck="false" class="input" value="" size="20"%3$s />
617 </p>',
618 esc_attr( $args['id_password'] ),
619 esc_html( $args['label_password'] ),
620 ( $args['required_password'] ? ' required="required"' : '' )
621 ) .
622 $login_form_middle .
623 ( $args['remember'] ?
624 sprintf(
625 '<p class="login-remember"><label><input name="rememberme" type="checkbox" id="%1$s" value="forever"%2$s /> %3$s</label></p>',
626 esc_attr( $args['id_remember'] ),
627 ( $args['value_remember'] ? ' checked="checked"' : '' ),
628 esc_html( $args['label_remember'] )
629 ) : ''
630 ) .
631 sprintf(
632 '<p class="login-submit">
633 <input type="submit" name="wp-submit" id="%1$s" class="button button-primary" value="%2$s" />
634 <input type="hidden" name="redirect_to" value="%3$s" />
635 </p>',
636 esc_attr( $args['id_submit'] ),
637 esc_attr( $args['label_log_in'] ),
638 esc_url( $args['redirect'] )
639 ) .
640 $login_form_bottom .
641 '</form>';
642
643 if ( $args['echo'] ) {
644 echo $form;
645 } else {
646 return $form;
647 }
648}
649
650/**
651 * Returns the URL that allows the user to reset the lost password.
652 *
653 * @since 2.8.0
654 *
655 * @param string $redirect Path to redirect to on login.
656 * @return string Lost password URL.
657 */
658function wp_lostpassword_url( $redirect = '' ) {
659 $args = array(
660 'action' => 'lostpassword',
661 );
662
663 if ( ! empty( $redirect ) ) {
664 $args['redirect_to'] = urlencode( $redirect );
665 }
666
667 if ( is_multisite() ) {
668 $blog_details = get_site();
669 $wp_login_path = $blog_details->path . 'wp-login.php';
670 } else {
671 $wp_login_path = 'wp-login.php';
672 }
673
674 $lostpassword_url = add_query_arg( $args, network_site_url( $wp_login_path, 'login' ) );
675
676 /**
677 * Filters the Lost Password URL.
678 *
679 * @since 2.8.0
680 *
681 * @param string $lostpassword_url The lost password page URL.
682 * @param string $redirect The path to redirect to on login.
683 */
684 return apply_filters( 'lostpassword_url', $lostpassword_url, $redirect );
685}
686
687/**
688 * Displays the Registration or Admin link.
689 *
690 * Display a link which allows the user to navigate to the registration page if
691 * not logged in and registration is enabled or to the dashboard if logged in.
692 *
693 * @since 1.5.0
694 *
695 * @param string $before Text to output before the link. Default `<li>`.
696 * @param string $after Text to output after the link. Default `</li>`.
697 * @param bool $display Default to echo and not return the link.
698 * @return void|string Void if `$display` argument is true, registration or admin link
699 * if `$display` is false.
700 */
701function wp_register( $before = '<li>', $after = '</li>', $display = true ) {
702 if ( ! is_user_logged_in() ) {
703 if ( get_option( 'users_can_register' ) ) {
704 $link = $before . '<a href="' . esc_url( wp_registration_url() ) . '">' . __( 'Register' ) . '</a>' . $after;
705 } else {
706 $link = '';
707 }
708 } elseif ( current_user_can( 'read' ) ) {
709 $link = $before . '<a href="' . admin_url() . '">' . __( 'Site Admin' ) . '</a>' . $after;
710 } else {
711 $link = '';
712 }
713
714 /**
715 * Filters the HTML link to the Registration or Admin page.
716 *
717 * Users are sent to the admin page if logged-in, or the registration page
718 * if enabled and logged-out.
719 *
720 * @since 1.5.0
721 *
722 * @param string $link The HTML code for the link to the Registration or Admin page.
723 */
724 $link = apply_filters( 'register', $link );
725
726 if ( $display ) {
727 echo $link;
728 } else {
729 return $link;
730 }
731}
732
733/**
734 * Theme container function for the 'wp_meta' action.
735 *
736 * The {@see 'wp_meta'} action can have several purposes, depending on how you use it,
737 * but one purpose might have been to allow for theme switching.
738 *
739 * @since 1.5.0
740 *
741 * @link https://core.trac.wordpress.org/ticket/1458 Explanation of 'wp_meta' action.
742 */
743function wp_meta() {
744 /**
745 * Fires before displaying echoed content in the sidebar.
746 *
747 * @since 1.5.0
748 */
749 do_action( 'wp_meta' );
750}
751
752/**
753 * Displays information about the current site.
754 *
755 * @since 0.71
756 *
757 * @see get_bloginfo() For possible `$show` values
758 *
759 * @param string $show Optional. Site information to display. Default empty.
760 */
761function bloginfo( $show = '' ) {
762 echo get_bloginfo( $show, 'display' );
763}
764
765/**
766 * Retrieves information about the current site.
767 *
768 * Possible values for `$show` include:
769 *
770 * - 'name' - Site title (set in Settings > General)
771 * - 'description' - Site tagline (set in Settings > General)
772 * - 'wpurl' - The WordPress address (URL) (set in Settings > General)
773 * - 'url' - The Site address (URL) (set in Settings > General)
774 * - 'admin_email' - Admin email (set in Settings > General)
775 * - 'charset' - The "Encoding for pages and feeds" (set in Settings > Reading)
776 * - 'version' - The current WordPress version
777 * - 'html_type' - The Content-Type (default: "text/html"). Themes and plugins
778 * can override the default value using the {@see 'pre_option_html_type'} filter
779 * - 'text_direction' - The text direction determined by the site's language. is_rtl()
780 * should be used instead
781 * - 'language' - Language code for the current site
782 * - 'stylesheet_url' - URL to the stylesheet for the active theme. An active child theme
783 * will take precedence over this value
784 * - 'stylesheet_directory' - Directory path for the active theme. An active child theme
785 * will take precedence over this value
786 * - 'template_url' / 'template_directory' - URL of the active theme's directory. An active
787 * child theme will NOT take precedence over this value
788 * - 'pingback_url' - The pingback XML-RPC file URL (xmlrpc.php)
789 * - 'atom_url' - The Atom feed URL (/feed/atom)
790 * - 'rdf_url' - The RDF/RSS 1.0 feed URL (/feed/rdf)
791 * - 'rss_url' - The RSS 0.92 feed URL (/feed/rss)
792 * - 'rss2_url' - The RSS 2.0 feed URL (/feed)
793 * - 'comments_atom_url' - The comments Atom feed URL (/comments/feed)
794 * - 'comments_rss2_url' - The comments RSS 2.0 feed URL (/comments/feed)
795 *
796 * Some `$show` values are deprecated and will be removed in future versions.
797 * These options will trigger the _deprecated_argument() function.
798 *
799 * Deprecated arguments include:
800 *
801 * - 'siteurl' - Use 'url' instead
802 * - 'home' - Use 'url' instead
803 *
804 * @since 0.71
805 *
806 * @global string $wp_version The WordPress version string.
807 *
808 * @param string $show Optional. Site info to retrieve. Default empty (site name).
809 * @param string $filter Optional. How to filter what is retrieved. Default 'raw'.
810 * @return string Mostly string values, might be empty.
811 */
812function get_bloginfo( $show = '', $filter = 'raw' ) {
813 switch ( $show ) {
814 case 'home': // Deprecated.
815 case 'siteurl': // Deprecated.
816 _deprecated_argument(
817 __FUNCTION__,
818 '2.2.0',
819 sprintf(
820 /* translators: 1: 'siteurl'/'home' argument, 2: bloginfo() function name, 3: 'url' argument. */
821 __( 'The %1$s option is deprecated for the family of %2$s functions. Use the %3$s option instead.' ),
822 '<code>' . $show . '</code>',
823 '<code>bloginfo()</code>',
824 '<code>url</code>'
825 )
826 );
827 // Intentional fall-through to be handled by the 'url' case.
828 case 'url':
829 $output = home_url();
830 break;
831 case 'wpurl':
832 $output = site_url();
833 break;
834 case 'description':
835 $output = get_option( 'blogdescription' );
836 break;
837 case 'rdf_url':
838 $output = get_feed_link( 'rdf' );
839 break;
840 case 'rss_url':
841 $output = get_feed_link( 'rss' );
842 break;
843 case 'rss2_url':
844 $output = get_feed_link( 'rss2' );
845 break;
846 case 'atom_url':
847 $output = get_feed_link( 'atom' );
848 break;
849 case 'comments_atom_url':
850 $output = get_feed_link( 'comments_atom' );
851 break;
852 case 'comments_rss2_url':
853 $output = get_feed_link( 'comments_rss2' );
854 break;
855 case 'pingback_url':
856 $output = site_url( 'xmlrpc.php' );
857 break;
858 case 'stylesheet_url':
859 $output = get_stylesheet_uri();
860 break;
861 case 'stylesheet_directory':
862 $output = get_stylesheet_directory_uri();
863 break;
864 case 'template_directory':
865 case 'template_url':
866 $output = get_template_directory_uri();
867 break;
868 case 'admin_email':
869 $output = get_option( 'admin_email' );
870 break;
871 case 'charset':
872 $output = get_option( 'blog_charset' );
873 if ( '' === $output ) {
874 $output = 'UTF-8';
875 }
876 break;
877 case 'html_type':
878 $output = get_option( 'html_type' );
879 break;
880 case 'version':
881 global $wp_version;
882 $output = $wp_version;
883 break;
884 case 'language':
885 /*
886 * translators: Translate this to the correct language tag for your locale,
887 * see https://www.w3.org/International/articles/language-tags/ for reference.
888 * Do not translate into your own language.
889 */
890 $output = __( 'html_lang_attribute' );
891 if ( 'html_lang_attribute' === $output || preg_match( '/[^a-zA-Z0-9-]/', $output ) ) {
892 $output = determine_locale();
893 $output = str_replace( '_', '-', $output );
894 }
895 break;
896 case 'text_direction':
897 _deprecated_argument(
898 __FUNCTION__,
899 '2.2.0',
900 sprintf(
901 /* translators: 1: 'text_direction' argument, 2: bloginfo() function name, 3: is_rtl() function name. */
902 __( 'The %1$s option is deprecated for the family of %2$s functions. Use the %3$s function instead.' ),
903 '<code>' . $show . '</code>',
904 '<code>bloginfo()</code>',
905 '<code>is_rtl()</code>'
906 )
907 );
908 if ( function_exists( 'is_rtl' ) ) {
909 $output = is_rtl() ? 'rtl' : 'ltr';
910 } else {
911 $output = 'ltr';
912 }
913 break;
914 case 'name':
915 default:
916 $output = get_option( 'blogname' );
917 break;
918 }
919
920 if ( 'display' === $filter ) {
921 if (
922 str_contains( $show, 'url' )
923 || str_contains( $show, 'directory' )
924 || str_contains( $show, 'home' )
925 ) {
926 /**
927 * Filters the URL returned by get_bloginfo().
928 *
929 * @since 2.0.5
930 *
931 * @param string $output The URL returned by bloginfo().
932 * @param string $show Type of information requested.
933 */
934 $output = apply_filters( 'bloginfo_url', $output, $show );
935 } else {
936 /**
937 * Filters the site information returned by get_bloginfo().
938 *
939 * @since 0.71
940 *
941 * @param mixed $output The requested non-URL site information.
942 * @param string $show Type of information requested.
943 */
944 $output = apply_filters( 'bloginfo', $output, $show );
945 }
946 }
947
948 return $output;
949}
950
951/**
952 * Returns the Site Icon URL.
953 *
954 * @since 4.3.0
955 *
956 * @param int $size Optional. Size of the site icon. Default 512 (pixels).
957 * @param string $url Optional. Fallback url if no site icon is found. Default empty.
958 * @param int $blog_id Optional. ID of the blog to get the site icon for. Default current blog.
959 * @return string Site Icon URL.
960 */
961function get_site_icon_url( $size = 512, $url = '', $blog_id = 0 ) {
962 $switched_blog = false;
963
964 if ( is_multisite() && ! empty( $blog_id ) && get_current_blog_id() !== (int) $blog_id ) {
965 switch_to_blog( $blog_id );
966 $switched_blog = true;
967 }
968
969 $site_icon_id = (int) get_option( 'site_icon' );
970
971 if ( $site_icon_id ) {
972 if ( $size >= 512 ) {
973 $size_data = 'full';
974 } else {
975 $size_data = array( $size, $size );
976 }
977 $url = wp_get_attachment_image_url( $site_icon_id, $size_data );
978 }
979
980 if ( $switched_blog ) {
981 restore_current_blog();
982 }
983
984 /**
985 * Filters the site icon URL.
986 *
987 * @since 4.4.0
988 *
989 * @param string $url Site icon URL.
990 * @param int $size Size of the site icon.
991 * @param int $blog_id ID of the blog to get the site icon for.
992 */
993 return apply_filters( 'get_site_icon_url', $url, $size, $blog_id );
994}
995
996/**
997 * Displays the Site Icon URL.
998 *
999 * @since 4.3.0
1000 *
1001 * @param int $size Optional. Size of the site icon. Default 512 (pixels).
1002 * @param string $url Optional. Fallback url if no site icon is found. Default empty.
1003 * @param int $blog_id Optional. ID of the blog to get the site icon for. Default current blog.
1004 */
1005function site_icon_url( $size = 512, $url = '', $blog_id = 0 ) {
1006 echo esc_url( get_site_icon_url( $size, $url, $blog_id ) );
1007}
1008
1009/**
1010 * Determines whether the site has a Site Icon.
1011 *
1012 * @since 4.3.0
1013 *
1014 * @param int $blog_id Optional. ID of the blog in question. Default current blog.
1015 * @return bool Whether the site has a site icon or not.
1016 */
1017function has_site_icon( $blog_id = 0 ) {
1018 return (bool) get_site_icon_url( 512, '', $blog_id );
1019}
1020
1021/**
1022 * Determines whether the site has a custom logo.
1023 *
1024 * @since 4.5.0
1025 *
1026 * @param int $blog_id Optional. ID of the blog in question. Default is the ID of the current blog.
1027 * @return bool Whether the site has a custom logo or not.
1028 */
1029function has_custom_logo( $blog_id = 0 ) {
1030 $switched_blog = false;
1031
1032 if ( is_multisite() && ! empty( $blog_id ) && get_current_blog_id() !== (int) $blog_id ) {
1033 switch_to_blog( $blog_id );
1034 $switched_blog = true;
1035 }
1036
1037 $custom_logo_id = get_theme_mod( 'custom_logo' );
1038 $is_image = ( $custom_logo_id ) ? wp_attachment_is_image( $custom_logo_id ) : false;
1039
1040 if ( $switched_blog ) {
1041 restore_current_blog();
1042 }
1043
1044 return $is_image;
1045}
1046
1047/**
1048 * Returns a custom logo, linked to home unless the theme supports removing the link on the home page.
1049 *
1050 * @since 4.5.0
1051 * @since 5.5.0 Added option to remove the link on the home page with `unlink-homepage-logo` theme support
1052 * for the `custom-logo` theme feature.
1053 * @since 5.5.1 Disabled lazy-loading by default.
1054 *
1055 * @param int $blog_id Optional. ID of the blog in question. Default is the ID of the current blog.
1056 * @return string Custom logo markup.
1057 */
1058function get_custom_logo( $blog_id = 0 ) {
1059 $html = '';
1060 $switched_blog = false;
1061
1062 if ( is_multisite() && ! empty( $blog_id ) && get_current_blog_id() !== (int) $blog_id ) {
1063 switch_to_blog( $blog_id );
1064 $switched_blog = true;
1065 }
1066
1067 // We have a logo. Logo is go.
1068 if ( has_custom_logo() ) {
1069 $custom_logo_id = get_theme_mod( 'custom_logo' );
1070 $custom_logo_attr = array(
1071 'class' => 'custom-logo',
1072 'loading' => false,
1073 );
1074
1075 $unlink_homepage_logo = (bool) get_theme_support( 'custom-logo', 'unlink-homepage-logo' );
1076
1077 if ( $unlink_homepage_logo && is_front_page() && ! is_paged() ) {
1078 /*
1079 * If on the home page, set the logo alt attribute to an empty string,
1080 * as the image is decorative and doesn't need its purpose to be described.
1081 */
1082 $custom_logo_attr['alt'] = '';
1083 } else {
1084 /*
1085 * If the logo alt attribute is empty, get the site title and explicitly pass it
1086 * to the attributes used by wp_get_attachment_image().
1087 */
1088 $image_alt = get_post_meta( $custom_logo_id, '_wp_attachment_image_alt', true );
1089 if ( empty( $image_alt ) ) {
1090 $custom_logo_attr['alt'] = get_bloginfo( 'name', 'display' );
1091 }
1092 }
1093
1094 /**
1095 * Filters the list of custom logo image attributes.
1096 *
1097 * @since 5.5.0
1098 *
1099 * @param array $custom_logo_attr Custom logo image attributes.
1100 * @param int $custom_logo_id Custom logo attachment ID.
1101 * @param int $blog_id ID of the blog to get the custom logo for.
1102 */
1103 $custom_logo_attr = apply_filters( 'get_custom_logo_image_attributes', $custom_logo_attr, $custom_logo_id, $blog_id );
1104
1105 /*
1106 * If the alt attribute is not empty, there's no need to explicitly pass it
1107 * because wp_get_attachment_image() already adds the alt attribute.
1108 */
1109 $image = wp_get_attachment_image( $custom_logo_id, 'full', false, $custom_logo_attr );
1110
1111 // Check that we have a proper HTML img element.
1112 if ( $image ) {
1113
1114 if ( $unlink_homepage_logo && is_front_page() && ! is_paged() ) {
1115 // If on the home page, don't link the logo to home.
1116 $html = sprintf(
1117 '<span class="custom-logo-link">%1$s</span>',
1118 $image
1119 );
1120 } else {
1121 $aria_current = ! is_paged() && ( is_front_page() || is_home() && ( (int) get_option( 'page_for_posts' ) !== get_queried_object_id() ) ) ? ' aria-current="page"' : '';
1122
1123 $html = sprintf(
1124 '<a href="%1$s" class="custom-logo-link" rel="home"%2$s>%3$s</a>',
1125 esc_url( home_url( '/' ) ),
1126 $aria_current,
1127 $image
1128 );
1129 }
1130 }
1131 } elseif ( is_customize_preview() ) {
1132 // If no logo is set but we're in the Customizer, leave a placeholder (needed for the live preview).
1133 $html = sprintf(
1134 '<a href="%1$s" class="custom-logo-link" style="display:none;"><img class="custom-logo" alt="" /></a>',
1135 esc_url( home_url( '/' ) )
1136 );
1137 }
1138
1139 if ( $switched_blog ) {
1140 restore_current_blog();
1141 }
1142
1143 /**
1144 * Filters the custom logo output.
1145 *
1146 * @since 4.5.0
1147 * @since 4.6.0 Added the `$blog_id` parameter.
1148 *
1149 * @param string $html Custom logo HTML output.
1150 * @param int $blog_id ID of the blog to get the custom logo for.
1151 */
1152 return apply_filters( 'get_custom_logo', $html, $blog_id );
1153}
1154
1155/**
1156 * Displays a custom logo, linked to home unless the theme supports removing the link on the home page.
1157 *
1158 * @since 4.5.0
1159 *
1160 * @param int $blog_id Optional. ID of the blog in question. Default is the ID of the current blog.
1161 */
1162function the_custom_logo( $blog_id = 0 ) {
1163 echo get_custom_logo( $blog_id );
1164}
1165
1166/**
1167 * Returns document title for the current page.
1168 *
1169 * @since 4.4.0
1170 *
1171 * @global int $page Page number of a single post.
1172 * @global int $paged Page number of a list of posts.
1173 *
1174 * @return string Tag with the document title.
1175 */
1176function wp_get_document_title() {
1177
1178 /**
1179 * Filters the document title before it is generated.
1180 *
1181 * Passing a non-empty value will short-circuit wp_get_document_title(),
1182 * returning that value instead.
1183 *
1184 * @since 4.4.0
1185 *
1186 * @param string $title The document title. Default empty string.
1187 */
1188 $title = apply_filters( 'pre_get_document_title', '' );
1189 if ( ! empty( $title ) ) {
1190 return $title;
1191 }
1192
1193 global $page, $paged;
1194
1195 $title = array(
1196 'title' => '',
1197 );
1198
1199 // If it's a 404 page, use a "Page not found" title.
1200 if ( is_404() ) {
1201 $title['title'] = __( 'Page not found' );
1202
1203 // If it's a search, use a dynamic search results title.
1204 } elseif ( is_search() ) {
1205 /* translators: %s: Search query. */
1206 $title['title'] = sprintf( __( 'Search Results for &#8220;%s&#8221;' ), get_search_query() );
1207
1208 // If on the front page, use the site title.
1209 } elseif ( is_front_page() ) {
1210 $title['title'] = get_bloginfo( 'name', 'display' );
1211
1212 // If on a post type archive, use the post type archive title.
1213 } elseif ( is_post_type_archive() ) {
1214 $title['title'] = post_type_archive_title( '', false );
1215
1216 // If on a taxonomy archive, use the term title.
1217 } elseif ( is_tax() ) {
1218 $title['title'] = single_term_title( '', false );
1219
1220 /*
1221 * If we're on the blog page that is not the homepage
1222 * or a single post of any post type, use the post title.
1223 */
1224 } elseif ( is_home() || is_singular() ) {
1225 $title['title'] = single_post_title( '', false );
1226
1227 // If on a category or tag archive, use the term title.
1228 } elseif ( is_category() || is_tag() ) {
1229 $title['title'] = single_term_title( '', false );
1230
1231 // If on an author archive, use the author's display name.
1232 } elseif ( is_author() && get_queried_object() ) {
1233 $author = get_queried_object();
1234 $title['title'] = $author->display_name;
1235
1236 // If it's a date archive, use the date as the title.
1237 } elseif ( is_year() ) {
1238 $title['title'] = get_the_date( _x( 'Y', 'yearly archives date format' ) );
1239
1240 } elseif ( is_month() ) {
1241 $title['title'] = get_the_date( _x( 'F Y', 'monthly archives date format' ) );
1242
1243 } elseif ( is_day() ) {
1244 $title['title'] = get_the_date();
1245 }
1246
1247 // Add a page number if necessary.
1248 if ( ( $paged >= 2 || $page >= 2 ) && ! is_404() ) {
1249 /* translators: %s: Page number. */
1250 $title['page'] = sprintf( __( 'Page %s' ), max( $paged, $page ) );
1251 }
1252
1253 // Append the description or site title to give context.
1254 if ( is_front_page() ) {
1255 $title['tagline'] = get_bloginfo( 'description', 'display' );
1256 } else {
1257 $title['site'] = get_bloginfo( 'name', 'display' );
1258 }
1259
1260 /**
1261 * Filters the separator for the document title.
1262 *
1263 * @since 4.4.0
1264 *
1265 * @param string $sep Document title separator. Default '-'.
1266 */
1267 $sep = apply_filters( 'document_title_separator', '-' );
1268
1269 /**
1270 * Filters the parts of the document title.
1271 *
1272 * @since 4.4.0
1273 *
1274 * @param array $title {
1275 * The document title parts.
1276 *
1277 * @type string $title Title of the viewed page.
1278 * @type string $page Optional. Page number if paginated.
1279 * @type string $tagline Optional. Site description when on home page.
1280 * @type string $site Optional. Site title when not on home page.
1281 * }
1282 */
1283 $title = apply_filters( 'document_title_parts', $title );
1284
1285 $title = implode( " $sep ", array_filter( $title ) );
1286
1287 /**
1288 * Filters the document title.
1289 *
1290 * @since 5.8.0
1291 *
1292 * @param string $title Document title.
1293 */
1294 $title = apply_filters( 'document_title', $title );
1295
1296 return $title;
1297}
1298
1299/**
1300 * Displays title tag with content.
1301 *
1302 * @since 4.1.0
1303 * @since 4.4.0 Improved title output replaced `wp_title()`.
1304 * @access private
1305 */
1306function _wp_render_title_tag() {
1307 if ( ! current_theme_supports( 'title-tag' ) ) {
1308 return;
1309 }
1310
1311 echo '<title>' . wp_get_document_title() . '</title>' . "\n";
1312}
1313
1314/**
1315 * Displays or retrieves page title for all areas of blog.
1316 *
1317 * By default, the page title will display the separator before the page title,
1318 * so that the blog title will be before the page title. This is not good for
1319 * title display, since the blog title shows up on most tabs and not what is
1320 * important, which is the page that the user is looking at.
1321 *
1322 * There are also SEO benefits to having the blog title after or to the 'right'
1323 * of the page title. However, it is mostly common sense to have the blog title
1324 * to the right with most browsers supporting tabs. You can achieve this by
1325 * using the seplocation parameter and setting the value to 'right'. This change
1326 * was introduced around 2.5.0, in case backward compatibility of themes is
1327 * important.
1328 *
1329 * @since 1.0.0
1330 *
1331 * @global WP_Locale $wp_locale WordPress date and time locale object.
1332 *
1333 * @param string $sep Optional. How to separate the various items within the page title.
1334 * Default '&raquo;'.
1335 * @param bool $display Optional. Whether to display or retrieve title. Default true.
1336 * @param string $seplocation Optional. Location of the separator (either 'left' or 'right').
1337 * @return string|void String when `$display` is false, nothing otherwise.
1338 */
1339function wp_title( $sep = '&raquo;', $display = true, $seplocation = '' ) {
1340 global $wp_locale;
1341
1342 $m = get_query_var( 'm' );
1343 $year = get_query_var( 'year' );
1344 $monthnum = get_query_var( 'monthnum' );
1345 $day = get_query_var( 'day' );
1346 $search = get_query_var( 's' );
1347 $title = '';
1348
1349 $t_sep = '%WP_TITLE_SEP%'; // Temporary separator, for accurate flipping, if necessary.
1350
1351 // If there is a post.
1352 if ( is_single() || ( is_home() && ! is_front_page() ) || ( is_page() && ! is_front_page() ) ) {
1353 $title = single_post_title( '', false );
1354 }
1355
1356 // If there's a post type archive.
1357 if ( is_post_type_archive() ) {
1358 $post_type = get_query_var( 'post_type' );
1359 if ( is_array( $post_type ) ) {
1360 $post_type = reset( $post_type );
1361 }
1362 $post_type_object = get_post_type_object( $post_type );
1363 if ( ! $post_type_object->has_archive ) {
1364 $title = post_type_archive_title( '', false );
1365 }
1366 }
1367
1368 // If there's a category or tag.
1369 if ( is_category() || is_tag() ) {
1370 $title = single_term_title( '', false );
1371 }
1372
1373 // If there's a taxonomy.
1374 if ( is_tax() ) {
1375 $term = get_queried_object();
1376 if ( $term ) {
1377 $tax = get_taxonomy( $term->taxonomy );
1378 $title = single_term_title( $tax->labels->name . $t_sep, false );
1379 }
1380 }
1381
1382 // If there's an author.
1383 if ( is_author() && ! is_post_type_archive() ) {
1384 $author = get_queried_object();
1385 if ( $author ) {
1386 $title = $author->display_name;
1387 }
1388 }
1389
1390 // Post type archives with has_archive should override terms.
1391 if ( is_post_type_archive() && $post_type_object->has_archive ) {
1392 $title = post_type_archive_title( '', false );
1393 }
1394
1395 // If there's a month.
1396 if ( is_archive() && ! empty( $m ) ) {
1397 $my_year = substr( $m, 0, 4 );
1398 $my_month = substr( $m, 4, 2 );
1399 $my_day = (int) substr( $m, 6, 2 );
1400 $title = $my_year .
1401 ( $my_month ? $t_sep . $wp_locale->get_month( $my_month ) : '' ) .
1402 ( $my_day ? $t_sep . $my_day : '' );
1403 }
1404
1405 // If there's a year.
1406 if ( is_archive() && ! empty( $year ) ) {
1407 $title = $year;
1408 if ( ! empty( $monthnum ) ) {
1409 $title .= $t_sep . $wp_locale->get_month( $monthnum );
1410 }
1411 if ( ! empty( $day ) ) {
1412 $title .= $t_sep . zeroise( $day, 2 );
1413 }
1414 }
1415
1416 // If it's a search.
1417 if ( is_search() ) {
1418 /* translators: 1: Separator, 2: Search query. */
1419 $title = sprintf( __( 'Search Results %1$s %2$s' ), $t_sep, strip_tags( $search ) );
1420 }
1421
1422 // If it's a 404 page.
1423 if ( is_404() ) {
1424 $title = __( 'Page not found' );
1425 }
1426
1427 if ( ! is_string( $title ) ) {
1428 $title = '';
1429 }
1430
1431 $prefix = '';
1432 $title_array = array();
1433 if ( '' !== $title ) {
1434 $prefix = " $sep ";
1435 $title_array = explode( $t_sep, $title );
1436 }
1437
1438 /**
1439 * Filters the parts of the page title.
1440 *
1441 * @since 4.0.0
1442 *
1443 * @param string[] $title_array Array of parts of the page title.
1444 */
1445 $title_array = apply_filters( 'wp_title_parts', $title_array );
1446
1447 // Determines position of the separator and direction of the breadcrumb.
1448 if ( 'right' === $seplocation ) { // Separator on right, so reverse the order.
1449 $title_array = array_reverse( $title_array );
1450 $title = implode( " $sep ", $title_array ) . $prefix;
1451 } else {
1452 $title = $prefix . implode( " $sep ", $title_array );
1453 }
1454
1455 /**
1456 * Filters the text of the page title.
1457 *
1458 * @since 2.0.0
1459 *
1460 * @param string $title Page title.
1461 * @param string $sep Title separator.
1462 * @param string $seplocation Location of the separator (either 'left' or 'right').
1463 */
1464 $title = apply_filters( 'wp_title', $title, $sep, $seplocation );
1465
1466 // Send it out.
1467 if ( $display ) {
1468 echo $title;
1469 } else {
1470 return $title;
1471 }
1472}
1473
1474/**
1475 * Displays or retrieves page title for post.
1476 *
1477 * This is optimized for single.php template file for displaying the post title.
1478 *
1479 * It does not support placing the separator after the title, but by leaving the
1480 * prefix parameter empty, you can set the title separator manually. The prefix
1481 * does not automatically place a space between the prefix, so if there should
1482 * be a space, the parameter value will need to have it at the end.
1483 *
1484 * @since 0.71
1485 *
1486 * @param string $prefix Optional. What to display before the title.
1487 * @param bool $display Optional. Whether to display or retrieve title. Default true.
1488 * @return string|void Title when retrieving.
1489 */
1490function single_post_title( $prefix = '', $display = true ) {
1491 $_post = get_queried_object();
1492
1493 if ( ! isset( $_post->post_title ) ) {
1494 return;
1495 }
1496
1497 /**
1498 * Filters the page title for a single post.
1499 *
1500 * @since 0.71
1501 *
1502 * @param string $_post_title The single post page title.
1503 * @param WP_Post $_post The current post.
1504 */
1505 $title = apply_filters( 'single_post_title', $_post->post_title, $_post );
1506 if ( $display ) {
1507 echo $prefix . $title;
1508 } else {
1509 return $prefix . $title;
1510 }
1511}
1512
1513/**
1514 * Displays or retrieves title for a post type archive.
1515 *
1516 * This is optimized for archive.php and archive-{$post_type}.php template files
1517 * for displaying the title of the post type.
1518 *
1519 * @since 3.1.0
1520 *
1521 * @param string $prefix Optional. What to display before the title.
1522 * @param bool $display Optional. Whether to display or retrieve title. Default true.
1523 * @return string|void Title when retrieving, null when displaying or failure.
1524 */
1525function post_type_archive_title( $prefix = '', $display = true ) {
1526 if ( ! is_post_type_archive() ) {
1527 return;
1528 }
1529
1530 $post_type = get_query_var( 'post_type' );
1531 if ( is_array( $post_type ) ) {
1532 $post_type = reset( $post_type );
1533 }
1534
1535 $post_type_obj = get_post_type_object( $post_type );
1536
1537 /**
1538 * Filters the post type archive title.
1539 *
1540 * @since 3.1.0
1541 *
1542 * @param string $post_type_name Post type 'name' label.
1543 * @param string $post_type Post type.
1544 */
1545 $title = apply_filters( 'post_type_archive_title', $post_type_obj->labels->name, $post_type );
1546
1547 if ( $display ) {
1548 echo $prefix . $title;
1549 } else {
1550 return $prefix . $title;
1551 }
1552}
1553
1554/**
1555 * Displays or retrieves page title for category archive.
1556 *
1557 * Useful for category template files for displaying the category page title.
1558 * The prefix does not automatically place a space between the prefix, so if
1559 * there should be a space, the parameter value will need to have it at the end.
1560 *
1561 * @since 0.71
1562 *
1563 * @param string $prefix Optional. What to display before the title.
1564 * @param bool $display Optional. Whether to display or retrieve title. Default true.
1565 * @return string|void Title when retrieving.
1566 */
1567function single_cat_title( $prefix = '', $display = true ) {
1568 return single_term_title( $prefix, $display );
1569}
1570
1571/**
1572 * Displays or retrieves page title for tag post archive.
1573 *
1574 * Useful for tag template files for displaying the tag page title. The prefix
1575 * does not automatically place a space between the prefix, so if there should
1576 * be a space, the parameter value will need to have it at the end.
1577 *
1578 * @since 2.3.0
1579 *
1580 * @param string $prefix Optional. What to display before the title.
1581 * @param bool $display Optional. Whether to display or retrieve title. Default true.
1582 * @return string|void Title when retrieving.
1583 */
1584function single_tag_title( $prefix = '', $display = true ) {
1585 return single_term_title( $prefix, $display );
1586}
1587
1588/**
1589 * Displays or retrieves page title for taxonomy term archive.
1590 *
1591 * Useful for taxonomy term template files for displaying the taxonomy term page title.
1592 * The prefix does not automatically place a space between the prefix, so if there should
1593 * be a space, the parameter value will need to have it at the end.
1594 *
1595 * @since 3.1.0
1596 *
1597 * @param string $prefix Optional. What to display before the title.
1598 * @param bool $display Optional. Whether to display or retrieve title. Default true.
1599 * @return string|void Title when retrieving.
1600 */
1601function single_term_title( $prefix = '', $display = true ) {
1602 $term = get_queried_object();
1603
1604 if ( ! $term ) {
1605 return;
1606 }
1607
1608 if ( is_category() ) {
1609 /**
1610 * Filters the category archive page title.
1611 *
1612 * @since 2.0.10
1613 *
1614 * @param string $term_name Category name for archive being displayed.
1615 */
1616 $term_name = apply_filters( 'single_cat_title', $term->name );
1617 } elseif ( is_tag() ) {
1618 /**
1619 * Filters the tag archive page title.
1620 *
1621 * @since 2.3.0
1622 *
1623 * @param string $term_name Tag name for archive being displayed.
1624 */
1625 $term_name = apply_filters( 'single_tag_title', $term->name );
1626 } elseif ( is_tax() ) {
1627 /**
1628 * Filters the custom taxonomy archive page title.
1629 *
1630 * @since 3.1.0
1631 *
1632 * @param string $term_name Term name for archive being displayed.
1633 */
1634 $term_name = apply_filters( 'single_term_title', $term->name );
1635 } else {
1636 return;
1637 }
1638
1639 if ( empty( $term_name ) ) {
1640 return;
1641 }
1642
1643 if ( $display ) {
1644 echo $prefix . $term_name;
1645 } else {
1646 return $prefix . $term_name;
1647 }
1648}
1649
1650/**
1651 * Displays or retrieves page title for post archive based on date.
1652 *
1653 * Useful for when the template only needs to display the month and year,
1654 * if either are available. The prefix does not automatically place a space
1655 * between the prefix, so if there should be a space, the parameter value
1656 * will need to have it at the end.
1657 *
1658 * @since 0.71
1659 *
1660 * @global WP_Locale $wp_locale WordPress date and time locale object.
1661 *
1662 * @param string $prefix Optional. What to display before the title.
1663 * @param bool $display Optional. Whether to display or retrieve title. Default true.
1664 * @return string|false|void False if there's no valid title for the month. Title when retrieving.
1665 */
1666function single_month_title( $prefix = '', $display = true ) {
1667 global $wp_locale;
1668
1669 $m = get_query_var( 'm' );
1670 $year = get_query_var( 'year' );
1671 $monthnum = get_query_var( 'monthnum' );
1672
1673 if ( ! empty( $monthnum ) && ! empty( $year ) ) {
1674 $my_year = $year;
1675 $my_month = $wp_locale->get_month( $monthnum );
1676 } elseif ( ! empty( $m ) ) {
1677 $my_year = substr( $m, 0, 4 );
1678 $my_month = $wp_locale->get_month( substr( $m, 4, 2 ) );
1679 }
1680
1681 if ( empty( $my_month ) ) {
1682 return false;
1683 }
1684
1685 $result = $prefix . $my_month . $prefix . $my_year;
1686
1687 if ( ! $display ) {
1688 return $result;
1689 }
1690 echo $result;
1691}
1692
1693/**
1694 * Displays the archive title based on the queried object.
1695 *
1696 * @since 4.1.0
1697 *
1698 * @see get_the_archive_title()
1699 *
1700 * @param string $before Optional. Content to prepend to the title. Default empty.
1701 * @param string $after Optional. Content to append to the title. Default empty.
1702 */
1703function the_archive_title( $before = '', $after = '' ) {
1704 $title = get_the_archive_title();
1705
1706 if ( ! empty( $title ) ) {
1707 echo $before . $title . $after;
1708 }
1709}
1710
1711/**
1712 * Retrieves the archive title based on the queried object.
1713 *
1714 * @since 4.1.0
1715 * @since 5.5.0 The title part is wrapped in a `<span>` element.
1716 *
1717 * @return string Archive title.
1718 */
1719function get_the_archive_title() {
1720 $title = __( 'Archives' );
1721 $prefix = '';
1722
1723 if ( is_category() ) {
1724 $title = single_cat_title( '', false );
1725 $prefix = _x( 'Category:', 'category archive title prefix' );
1726 } elseif ( is_tag() ) {
1727 $title = single_tag_title( '', false );
1728 $prefix = _x( 'Tag:', 'tag archive title prefix' );
1729 } elseif ( is_author() ) {
1730 $title = get_the_author();
1731 $prefix = _x( 'Author:', 'author archive title prefix' );
1732 } elseif ( is_year() ) {
1733 /* translators: See https://www.php.net/manual/datetime.format.php */
1734 $title = get_the_date( _x( 'Y', 'yearly archives date format' ) );
1735 $prefix = _x( 'Year:', 'date archive title prefix' );
1736 } elseif ( is_month() ) {
1737 /* translators: See https://www.php.net/manual/datetime.format.php */
1738 $title = get_the_date( _x( 'F Y', 'monthly archives date format' ) );
1739 $prefix = _x( 'Month:', 'date archive title prefix' );
1740 } elseif ( is_day() ) {
1741 /* translators: See https://www.php.net/manual/datetime.format.php */
1742 $title = get_the_date( _x( 'F j, Y', 'daily archives date format' ) );
1743 $prefix = _x( 'Day:', 'date archive title prefix' );
1744 } elseif ( is_tax( 'post_format' ) ) {
1745 if ( is_tax( 'post_format', 'post-format-aside' ) ) {
1746 $title = _x( 'Asides', 'post format archive title' );
1747 } elseif ( is_tax( 'post_format', 'post-format-gallery' ) ) {
1748 $title = _x( 'Galleries', 'post format archive title' );
1749 } elseif ( is_tax( 'post_format', 'post-format-image' ) ) {
1750 $title = _x( 'Images', 'post format archive title' );
1751 } elseif ( is_tax( 'post_format', 'post-format-video' ) ) {
1752 $title = _x( 'Videos', 'post format archive title' );
1753 } elseif ( is_tax( 'post_format', 'post-format-quote' ) ) {
1754 $title = _x( 'Quotes', 'post format archive title' );
1755 } elseif ( is_tax( 'post_format', 'post-format-link' ) ) {
1756 $title = _x( 'Links', 'post format archive title' );
1757 } elseif ( is_tax( 'post_format', 'post-format-status' ) ) {
1758 $title = _x( 'Statuses', 'post format archive title' );
1759 } elseif ( is_tax( 'post_format', 'post-format-audio' ) ) {
1760 $title = _x( 'Audio', 'post format archive title' );
1761 } elseif ( is_tax( 'post_format', 'post-format-chat' ) ) {
1762 $title = _x( 'Chats', 'post format archive title' );
1763 }
1764 } elseif ( is_post_type_archive() ) {
1765 $title = post_type_archive_title( '', false );
1766 $prefix = _x( 'Archives:', 'post type archive title prefix' );
1767 } elseif ( is_tax() ) {
1768 $queried_object = get_queried_object();
1769 if ( $queried_object ) {
1770 $tax = get_taxonomy( $queried_object->taxonomy );
1771 $title = single_term_title( '', false );
1772 $prefix = sprintf(
1773 /* translators: %s: Taxonomy singular name. */
1774 _x( '%s:', 'taxonomy term archive title prefix' ),
1775 $tax->labels->singular_name
1776 );
1777 }
1778 }
1779
1780 $original_title = $title;
1781
1782 /**
1783 * Filters the archive title prefix.
1784 *
1785 * @since 5.5.0
1786 *
1787 * @param string $prefix Archive title prefix.
1788 */
1789 $prefix = apply_filters( 'get_the_archive_title_prefix', $prefix );
1790 if ( $prefix ) {
1791 $title = sprintf(
1792 /* translators: 1: Title prefix. 2: Title. */
1793 _x( '%1$s %2$s', 'archive title' ),
1794 $prefix,
1795 '<span>' . $title . '</span>'
1796 );
1797 }
1798
1799 /**
1800 * Filters the archive title.
1801 *
1802 * @since 4.1.0
1803 * @since 5.5.0 Added the `$prefix` and `$original_title` parameters.
1804 *
1805 * @param string $title Archive title to be displayed.
1806 * @param string $original_title Archive title without prefix.
1807 * @param string $prefix Archive title prefix.
1808 */
1809 return apply_filters( 'get_the_archive_title', $title, $original_title, $prefix );
1810}
1811
1812/**
1813 * Displays category, tag, term, or author description.
1814 *
1815 * @since 4.1.0
1816 *
1817 * @see get_the_archive_description()
1818 *
1819 * @param string $before Optional. Content to prepend to the description. Default empty.
1820 * @param string $after Optional. Content to append to the description. Default empty.
1821 */
1822function the_archive_description( $before = '', $after = '' ) {
1823 $description = get_the_archive_description();
1824 if ( $description ) {
1825 echo $before . $description . $after;
1826 }
1827}
1828
1829/**
1830 * Retrieves the description for an author, post type, or term archive.
1831 *
1832 * @since 4.1.0
1833 * @since 4.7.0 Added support for author archives.
1834 * @since 4.9.0 Added support for post type archives.
1835 *
1836 * @see term_description()
1837 *
1838 * @return string Archive description.
1839 */
1840function get_the_archive_description() {
1841 if ( is_author() ) {
1842 $description = get_the_author_meta( 'description' );
1843 } elseif ( is_post_type_archive() ) {
1844 $description = get_the_post_type_description();
1845 } else {
1846 $description = term_description();
1847 }
1848
1849 /**
1850 * Filters the archive description.
1851 *
1852 * @since 4.1.0
1853 *
1854 * @param string $description Archive description to be displayed.
1855 */
1856 return apply_filters( 'get_the_archive_description', $description );
1857}
1858
1859/**
1860 * Retrieves the description for a post type archive.
1861 *
1862 * @since 4.9.0
1863 *
1864 * @return string The post type description.
1865 */
1866function get_the_post_type_description() {
1867 $post_type = get_query_var( 'post_type' );
1868
1869 if ( is_array( $post_type ) ) {
1870 $post_type = reset( $post_type );
1871 }
1872
1873 $post_type_obj = get_post_type_object( $post_type );
1874
1875 // Check if a description is set.
1876 if ( isset( $post_type_obj->description ) ) {
1877 $description = $post_type_obj->description;
1878 } else {
1879 $description = '';
1880 }
1881
1882 /**
1883 * Filters the description for a post type archive.
1884 *
1885 * @since 4.9.0
1886 *
1887 * @param string $description The post type description.
1888 * @param WP_Post_Type $post_type_obj The post type object.
1889 */
1890 return apply_filters( 'get_the_post_type_description', $description, $post_type_obj );
1891}
1892
1893/**
1894 * Retrieves archive link content based on predefined or custom code.
1895 *
1896 * The format can be one of four styles. The 'link' for head element, 'option'
1897 * for use in the select element, 'html' for use in list (either ol or ul HTML
1898 * elements). Custom content is also supported using the before and after
1899 * parameters.
1900 *
1901 * The 'link' format uses the `<link>` HTML element with the **archives**
1902 * relationship. The before and after parameters are not used. The text
1903 * parameter is used to describe the link.
1904 *
1905 * The 'option' format uses the option HTML element for use in select element.
1906 * The value is the url parameter and the before and after parameters are used
1907 * between the text description.
1908 *
1909 * The 'html' format, which is the default, uses the li HTML element for use in
1910 * the list HTML elements. The before parameter is before the link and the after
1911 * parameter is after the closing link.
1912 *
1913 * The custom format uses the before parameter before the link ('a' HTML
1914 * element) and the after parameter after the closing link tag. If the above
1915 * three values for the format are not used, then custom format is assumed.
1916 *
1917 * @since 1.0.0
1918 * @since 5.2.0 Added the `$selected` parameter.
1919 *
1920 * @param string $url URL to archive.
1921 * @param string $text Archive text description.
1922 * @param string $format Optional. Can be 'link', 'option', 'html', or custom. Default 'html'.
1923 * @param string $before Optional. Content to prepend to the description. Default empty.
1924 * @param string $after Optional. Content to append to the description. Default empty.
1925 * @param bool $selected Optional. Set to true if the current page is the selected archive page. Default false.
1926 * @return string HTML link content for archive.
1927 */
1928function get_archives_link( $url, $text, $format = 'html', $before = '', $after = '', $selected = false ) {
1929 $text = wptexturize( $text );
1930 $url = esc_url( $url );
1931 $aria_current = $selected ? ' aria-current="page"' : '';
1932
1933 if ( 'link' === $format ) {
1934 $link_html = "\t<link rel='archives' title='" . esc_attr( $text ) . "' href='$url' />\n";
1935 } elseif ( 'option' === $format ) {
1936 $selected_attr = $selected ? " selected='selected'" : '';
1937 $link_html = "\t<option value='$url'$selected_attr>$before $text $after</option>\n";
1938 } elseif ( 'html' === $format ) {
1939 $link_html = "\t<li>$before<a href='$url'$aria_current>$text</a>$after</li>\n";
1940 } else { // Custom.
1941 $link_html = "\t$before<a href='$url'$aria_current>$text</a>$after\n";
1942 }
1943
1944 /**
1945 * Filters the archive link content.
1946 *
1947 * @since 2.6.0
1948 * @since 4.5.0 Added the `$url`, `$text`, `$format`, `$before`, and `$after` parameters.
1949 * @since 5.2.0 Added the `$selected` parameter.
1950 *
1951 * @param string $link_html The archive HTML link content.
1952 * @param string $url URL to archive.
1953 * @param string $text Archive text description.
1954 * @param string $format Link format. Can be 'link', 'option', 'html', or custom.
1955 * @param string $before Content to prepend to the description.
1956 * @param string $after Content to append to the description.
1957 * @param bool $selected True if the current page is the selected archive.
1958 */
1959 return apply_filters( 'get_archives_link', $link_html, $url, $text, $format, $before, $after, $selected );
1960}
1961
1962/**
1963 * Displays archive links based on type and format.
1964 *
1965 * @since 1.2.0
1966 * @since 4.4.0 The `$post_type` argument was added.
1967 * @since 5.2.0 The `$year`, `$monthnum`, `$day`, and `$w` arguments were added.
1968 *
1969 * @see get_archives_link()
1970 *
1971 * @global wpdb $wpdb WordPress database abstraction object.
1972 * @global WP_Locale $wp_locale WordPress date and time locale object.
1973 *
1974 * @param string|array $args {
1975 * Default archive links arguments. Optional.
1976 *
1977 * @type string $type Type of archive to retrieve. Accepts 'daily', 'weekly', 'monthly',
1978 * 'yearly', 'postbypost', or 'alpha'. Both 'postbypost' and 'alpha'
1979 * display the same archive link list as well as post titles instead
1980 * of displaying dates. The difference between the two is that 'alpha'
1981 * will order by post title and 'postbypost' will order by post date.
1982 * Default 'monthly'.
1983 * @type string|int $limit Number of links to limit the query to. Default empty (no limit).
1984 * @type string $format Format each link should take using the $before and $after args.
1985 * Accepts 'link' (`<link>` tag), 'option' (`<option>` tag), 'html'
1986 * (`<li>` tag), or a custom format, which generates a link anchor
1987 * with $before preceding and $after succeeding. Default 'html'.
1988 * @type string $before Markup to prepend to the beginning of each link. Default empty.
1989 * @type string $after Markup to append to the end of each link. Default empty.
1990 * @type bool $show_post_count Whether to display the post count alongside the link. Default false.
1991 * @type bool|int $echo Whether to echo or return the links list. Default 1|true to echo.
1992 * @type string $order Whether to use ascending or descending order. Accepts 'ASC', or 'DESC'.
1993 * Default 'DESC'.
1994 * @type string $post_type Post type. Default 'post'.
1995 * @type string $year Year. Default current year.
1996 * @type string $monthnum Month number. Default current month number.
1997 * @type string $day Day. Default current day.
1998 * @type string $w Week. Default current week.
1999 * }
2000 * @return void|string Void if 'echo' argument is true, archive links if 'echo' is false.
2001 */
2002function wp_get_archives( $args = '' ) {
2003 global $wpdb, $wp_locale;
2004
2005 $defaults = array(
2006 'type' => 'monthly',
2007 'limit' => '',
2008 'format' => 'html',
2009 'before' => '',
2010 'after' => '',
2011 'show_post_count' => false,
2012 'echo' => 1,
2013 'order' => 'DESC',
2014 'post_type' => 'post',
2015 'year' => get_query_var( 'year' ),
2016 'monthnum' => get_query_var( 'monthnum' ),
2017 'day' => get_query_var( 'day' ),
2018 'w' => get_query_var( 'w' ),
2019 );
2020
2021 $parsed_args = wp_parse_args( $args, $defaults );
2022
2023 $post_type_object = get_post_type_object( $parsed_args['post_type'] );
2024 if ( ! is_post_type_viewable( $post_type_object ) ) {
2025 return;
2026 }
2027
2028 $parsed_args['post_type'] = $post_type_object->name;
2029
2030 if ( '' === $parsed_args['type'] ) {
2031 $parsed_args['type'] = 'monthly';
2032 }
2033
2034 if ( ! empty( $parsed_args['limit'] ) ) {
2035 $parsed_args['limit'] = absint( $parsed_args['limit'] );
2036 $parsed_args['limit'] = ' LIMIT ' . $parsed_args['limit'];
2037 }
2038
2039 $order = strtoupper( $parsed_args['order'] );
2040 if ( 'ASC' !== $order ) {
2041 $order = 'DESC';
2042 }
2043
2044 // This is what will separate dates on weekly archive links.
2045 $archive_week_separator = '&#8211;';
2046
2047 $sql_where = $wpdb->prepare( "WHERE post_type = %s AND post_status = 'publish'", $parsed_args['post_type'] );
2048
2049 /**
2050 * Filters the SQL WHERE clause for retrieving archives.
2051 *
2052 * @since 2.2.0
2053 *
2054 * @param string $sql_where Portion of SQL query containing the WHERE clause.
2055 * @param array $parsed_args An array of default arguments.
2056 */
2057 $where = apply_filters( 'getarchives_where', $sql_where, $parsed_args );
2058
2059 /**
2060 * Filters the SQL JOIN clause for retrieving archives.
2061 *
2062 * @since 2.2.0
2063 *
2064 * @param string $sql_join Portion of SQL query containing JOIN clause.
2065 * @param array $parsed_args An array of default arguments.
2066 */
2067 $join = apply_filters( 'getarchives_join', '', $parsed_args );
2068
2069 $output = '';
2070
2071 $last_changed = wp_cache_get_last_changed( 'posts' );
2072
2073 $limit = $parsed_args['limit'];
2074
2075 if ( 'monthly' === $parsed_args['type'] ) {
2076 $query = "SELECT YEAR(post_date) AS `year`, MONTH(post_date) AS `month`, count(ID) as posts FROM $wpdb->posts $join $where GROUP BY YEAR(post_date), MONTH(post_date) ORDER BY post_date $order $limit";
2077 $key = md5( $query );
2078 $key = "wp_get_archives:$key";
2079 $results = wp_cache_get_salted( $key, 'post-queries', $last_changed );
2080 if ( ! $results ) {
2081 $results = $wpdb->get_results( $query );
2082 wp_cache_set_salted( $key, $results, 'post-queries', $last_changed );
2083 }
2084 if ( $results ) {
2085 $after = $parsed_args['after'];
2086 foreach ( (array) $results as $result ) {
2087 $url = get_month_link( $result->year, $result->month );
2088 if ( 'post' !== $parsed_args['post_type'] ) {
2089 $url = add_query_arg( 'post_type', $parsed_args['post_type'], $url );
2090 }
2091 /* translators: 1: Month name, 2: 4-digit year. */
2092 $text = sprintf( __( '%1$s %2$d' ), $wp_locale->get_month( $result->month ), $result->year );
2093 if ( $parsed_args['show_post_count'] ) {
2094 $parsed_args['after'] = '&nbsp;(' . $result->posts . ')' . $after;
2095 }
2096 $selected = is_archive() && (string) $parsed_args['year'] === $result->year && (string) $parsed_args['monthnum'] === $result->month;
2097 $output .= get_archives_link( $url, $text, $parsed_args['format'], $parsed_args['before'], $parsed_args['after'], $selected );
2098 }
2099 }
2100 } elseif ( 'yearly' === $parsed_args['type'] ) {
2101 $query = "SELECT YEAR(post_date) AS `year`, count(ID) as posts FROM $wpdb->posts $join $where GROUP BY YEAR(post_date) ORDER BY post_date $order $limit";
2102 $key = md5( $query );
2103 $key = "wp_get_archives:$key";
2104 $results = wp_cache_get_salted( $key, 'post-queries', $last_changed );
2105 if ( ! $results ) {
2106 $results = $wpdb->get_results( $query );
2107 wp_cache_set_salted( $key, $results, 'post-queries', $last_changed );
2108 }
2109 if ( $results ) {
2110 $after = $parsed_args['after'];
2111 foreach ( (array) $results as $result ) {
2112 $url = get_year_link( $result->year );
2113 if ( 'post' !== $parsed_args['post_type'] ) {
2114 $url = add_query_arg( 'post_type', $parsed_args['post_type'], $url );
2115 }
2116 $text = sprintf( '%d', $result->year );
2117 if ( $parsed_args['show_post_count'] ) {
2118 $parsed_args['after'] = '&nbsp;(' . $result->posts . ')' . $after;
2119 }
2120 $selected = is_archive() && (string) $parsed_args['year'] === $result->year;
2121 $output .= get_archives_link( $url, $text, $parsed_args['format'], $parsed_args['before'], $parsed_args['after'], $selected );
2122 }
2123 }
2124 } elseif ( 'daily' === $parsed_args['type'] ) {
2125 $query = "SELECT YEAR(post_date) AS `year`, MONTH(post_date) AS `month`, DAYOFMONTH(post_date) AS `dayofmonth`, count(ID) as posts FROM $wpdb->posts $join $where GROUP BY YEAR(post_date), MONTH(post_date), DAYOFMONTH(post_date) ORDER BY post_date $order $limit";
2126 $key = md5( $query );
2127 $key = "wp_get_archives:$key";
2128 $results = wp_cache_get_salted( $key, 'post-queries', $last_changed );
2129 if ( ! $results ) {
2130 $results = $wpdb->get_results( $query );
2131 wp_cache_set_salted( $key, $results, 'post-queries', $last_changed );
2132 }
2133 if ( $results ) {
2134 $after = $parsed_args['after'];
2135 foreach ( (array) $results as $result ) {
2136 $url = get_day_link( $result->year, $result->month, $result->dayofmonth );
2137 if ( 'post' !== $parsed_args['post_type'] ) {
2138 $url = add_query_arg( 'post_type', $parsed_args['post_type'], $url );
2139 }
2140 $date = sprintf( '%1$d-%2$02d-%3$02d 00:00:00', $result->year, $result->month, $result->dayofmonth );
2141 $text = mysql2date( get_option( 'date_format' ), $date );
2142 if ( $parsed_args['show_post_count'] ) {
2143 $parsed_args['after'] = '&nbsp;(' . $result->posts . ')' . $after;
2144 }
2145 $selected = is_archive() && (string) $parsed_args['year'] === $result->year && (string) $parsed_args['monthnum'] === $result->month && (string) $parsed_args['day'] === $result->dayofmonth;
2146 $output .= get_archives_link( $url, $text, $parsed_args['format'], $parsed_args['before'], $parsed_args['after'], $selected );
2147 }
2148 }
2149 } elseif ( 'weekly' === $parsed_args['type'] ) {
2150 $week = _wp_mysql_week( '`post_date`' );
2151 $query = "SELECT DISTINCT $week AS `week`, YEAR( `post_date` ) AS `yr`, DATE_FORMAT( `post_date`, '%Y-%m-%d' ) AS `yyyymmdd`, count( `ID` ) AS `posts` FROM `$wpdb->posts` $join $where GROUP BY $week, YEAR( `post_date` ) ORDER BY `post_date` $order $limit";
2152 $key = md5( $query );
2153 $key = "wp_get_archives:$key";
2154 $results = wp_cache_get_salted( $key, 'post-queries', $last_changed );
2155 if ( ! $results ) {
2156 $results = $wpdb->get_results( $query );
2157 wp_cache_set_salted( $key, $results, 'post-queries', $last_changed );
2158 }
2159 $arc_w_last = '';
2160 if ( $results ) {
2161 $after = $parsed_args['after'];
2162 foreach ( (array) $results as $result ) {
2163 if ( $result->week !== $arc_w_last ) {
2164 $arc_year = $result->yr;
2165 $arc_w_last = $result->week;
2166 $arc_week = get_weekstartend( $result->yyyymmdd, get_option( 'start_of_week' ) );
2167 $arc_week_start = date_i18n( get_option( 'date_format' ), $arc_week['start'] );
2168 $arc_week_end = date_i18n( get_option( 'date_format' ), $arc_week['end'] );
2169 $url = add_query_arg(
2170 array(
2171 'm' => $arc_year,
2172 'w' => $result->week,
2173 ),
2174 home_url( '/' )
2175 );
2176 if ( 'post' !== $parsed_args['post_type'] ) {
2177 $url = add_query_arg( 'post_type', $parsed_args['post_type'], $url );
2178 }
2179 $text = $arc_week_start . $archive_week_separator . $arc_week_end;
2180 if ( $parsed_args['show_post_count'] ) {
2181 $parsed_args['after'] = '&nbsp;(' . $result->posts . ')' . $after;
2182 }
2183 $selected = is_archive() && (string) $parsed_args['year'] === $result->yr && (string) $parsed_args['w'] === $result->week;
2184 $output .= get_archives_link( $url, $text, $parsed_args['format'], $parsed_args['before'], $parsed_args['after'], $selected );
2185 }
2186 }
2187 }
2188 } elseif ( ( 'postbypost' === $parsed_args['type'] ) || ( 'alpha' === $parsed_args['type'] ) ) {
2189 $orderby = ( 'alpha' === $parsed_args['type'] ) ? 'post_title ASC ' : 'post_date DESC, ID DESC ';
2190 $query = "SELECT * FROM $wpdb->posts $join $where ORDER BY $orderby $limit";
2191 $key = md5( $query );
2192 $key = "wp_get_archives:$key";
2193 $results = wp_cache_get_salted( $key, 'post-queries', $last_changed );
2194 if ( ! $results ) {
2195 $results = $wpdb->get_results( $query );
2196 wp_cache_set_salted( $key, $results, 'post-queries', $last_changed );
2197 }
2198 if ( $results ) {
2199 foreach ( (array) $results as $result ) {
2200 if ( '0000-00-00 00:00:00' !== $result->post_date ) {
2201 $url = get_permalink( $result );
2202 if ( $result->post_title ) {
2203 /** This filter is documented in wp-includes/post-template.php */
2204 $text = strip_tags( apply_filters( 'the_title', $result->post_title, $result->ID ) );
2205 } else {
2206 $text = $result->ID;
2207 }
2208 $selected = get_the_ID() === $result->ID;
2209 $output .= get_archives_link( $url, $text, $parsed_args['format'], $parsed_args['before'], $parsed_args['after'], $selected );
2210 }
2211 }
2212 }
2213 }
2214
2215 if ( $parsed_args['echo'] ) {
2216 echo $output;
2217 } else {
2218 return $output;
2219 }
2220}
2221
2222/**
2223 * Gets number of days since the start of the week.
2224 *
2225 * @since 1.5.0
2226 *
2227 * @param int $num Number of day.
2228 * @return float Days since the start of the week.
2229 */
2230function calendar_week_mod( $num ) {
2231 $base = 7;
2232 return ( $num - $base * floor( $num / $base ) );
2233}
2234
2235/**
2236 * Displays calendar with days that have posts as links.
2237 *
2238 * The calendar is cached, which will be retrieved, if it exists. If there are
2239 * no posts for the month, then it will not be displayed.
2240 *
2241 * @since 1.0.0
2242 * @since 6.8.0 Added the `$args` parameter, with backward compatibility
2243 * for the replaced `$initial` and `$display` parameters.
2244 *
2245 * @global wpdb $wpdb WordPress database abstraction object.
2246 * @global int $m
2247 * @global int $monthnum
2248 * @global int $year
2249 * @global WP_Locale $wp_locale WordPress date and time locale object.
2250 * @global array $posts
2251 *
2252 * @param array $args {
2253 * Optional. Arguments for the `get_calendar` function.
2254 *
2255 * @type bool $initial Whether to use initial calendar names. Default true.
2256 * @type bool $display Whether to display the calendar output. Default true.
2257 * @type string $post_type Optional. Post type. Default 'post'.
2258 * }
2259 * @return void|string Void if `$display` argument is true, calendar HTML if `$display` is false.
2260 */
2261function get_calendar( $args = array() ) {
2262 global $wpdb, $m, $monthnum, $year, $wp_locale, $posts;
2263
2264 $defaults = array(
2265 'initial' => true,
2266 'display' => true,
2267 'post_type' => 'post',
2268 );
2269
2270 $original_args = func_get_args();
2271 $args = array();
2272
2273 if ( ! empty( $original_args ) ) {
2274 if ( ! is_array( $original_args[0] ) ) {
2275 if ( isset( $original_args[0] ) && is_bool( $original_args[0] ) ) {
2276 $defaults['initial'] = $original_args[0];
2277 }
2278 if ( isset( $original_args[1] ) && is_bool( $original_args[1] ) ) {
2279 $defaults['display'] = $original_args[1];
2280 }
2281 } else {
2282 $args = $original_args[0];
2283 }
2284 }
2285
2286 /**
2287 * Filter the `get_calendar` function arguments before they are used.
2288 *
2289 * @since 6.8.0
2290 *
2291 * @param array $args {
2292 * Optional. Arguments for the `get_calendar` function.
2293 *
2294 * @type bool $initial Whether to use initial calendar names. Default true.
2295 * @type bool $display Whether to display the calendar output. Default true.
2296 * @type string $post_type Optional. Post type. Default 'post'.
2297 * }
2298 */
2299 $args = apply_filters( 'get_calendar_args', wp_parse_args( $args, $defaults ) );
2300
2301 if ( ! post_type_exists( $args['post_type'] ) ) {
2302 $args['post_type'] = 'post';
2303 }
2304
2305 $w = 0;
2306 if ( isset( $_GET['w'] ) ) {
2307 $w = (int) $_GET['w'];
2308 }
2309
2310 /*
2311 * Normalize the cache key.
2312 *
2313 * The following ensures the same cache key is used for the same parameter
2314 * and parameter equivalents. This prevents `post_type > post, initial > true`
2315 * from generating a different key from the same values in the reverse order.
2316 *
2317 * `display` is excluded from the cache key as the cache contains the same
2318 * HTML regardless of this function's need to echo or return the output.
2319 *
2320 * The global values contain data generated by the URL query string variables.
2321 */
2322 $cache_args = $args;
2323 unset( $cache_args['display'] );
2324
2325 $cache_args['globals'] = array(
2326 'm' => $m,
2327 'monthnum' => $monthnum,
2328 'year' => $year,
2329 'week' => $w,
2330 );
2331
2332 wp_recursive_ksort( $cache_args );
2333 $key = md5( serialize( $cache_args ) );
2334 $cache = wp_cache_get( 'get_calendar', 'calendar' );
2335
2336 if ( $cache && is_array( $cache ) && isset( $cache[ $key ] ) ) {
2337 /** This filter is documented in wp-includes/general-template.php */
2338 $output = apply_filters( 'get_calendar', $cache[ $key ], $args );
2339
2340 if ( $args['display'] ) {
2341 echo $output;
2342 return;
2343 }
2344
2345 return $output;
2346 }
2347
2348 if ( ! is_array( $cache ) ) {
2349 $cache = array();
2350 }
2351
2352 $post_type = $args['post_type'];
2353
2354 // Quick check. If we have no posts at all, abort!
2355 if ( ! $posts ) {
2356 $gotsome = $wpdb->get_var(
2357 $wpdb->prepare(
2358 "SELECT 1 as test
2359 FROM $wpdb->posts
2360 WHERE post_type = %s
2361 AND post_status = 'publish'
2362 LIMIT 1",
2363 $post_type
2364 )
2365 );
2366
2367 if ( ! $gotsome ) {
2368 $cache[ $key ] = '';
2369 wp_cache_set( 'get_calendar', $cache, 'calendar' );
2370 return;
2371 }
2372 }
2373
2374 // week_begins = 0 stands for Sunday.
2375 $week_begins = (int) get_option( 'start_of_week' );
2376
2377 // Let's figure out when we are.
2378 if ( ! empty( $monthnum ) && ! empty( $year ) ) {
2379 $thismonth = (int) $monthnum;
2380 $thisyear = (int) $year;
2381 } elseif ( ! empty( $w ) ) {
2382 // We need to get the month from MySQL.
2383 $thisyear = (int) substr( $m, 0, 4 );
2384 // It seems MySQL's weeks disagree with PHP's.
2385 $d = ( ( $w - 1 ) * 7 ) + 6;
2386 $thismonth = (int) $wpdb->get_var(
2387 $wpdb->prepare(
2388 "SELECT DATE_FORMAT((DATE_ADD('%d0101', INTERVAL %d DAY) ), '%%m')",
2389 $thisyear,
2390 $d
2391 )
2392 );
2393 } elseif ( ! empty( $m ) ) {
2394 $thisyear = (int) substr( $m, 0, 4 );
2395 if ( strlen( $m ) < 6 ) {
2396 $thismonth = 1;
2397 } else {
2398 $thismonth = (int) substr( $m, 4, 2 );
2399 }
2400 } else {
2401 $thisyear = (int) current_time( 'Y' );
2402 $thismonth = (int) current_time( 'm' );
2403 }
2404
2405 $unixmonth = mktime( 0, 0, 0, $thismonth, 1, $thisyear );
2406 $last_day = gmdate( 't', $unixmonth );
2407
2408 // Get the next and previous month and year with at least one post.
2409 $previous = $wpdb->get_row(
2410 $wpdb->prepare(
2411 "SELECT MONTH(post_date) AS month, YEAR(post_date) AS year
2412 FROM $wpdb->posts
2413 WHERE post_date < '%d-%d-01'
2414 AND post_type = %s AND post_status = 'publish'
2415 ORDER BY post_date DESC
2416 LIMIT 1",
2417 $thisyear,
2418 zeroise( $thismonth, 2 ),
2419 $post_type
2420 )
2421 );
2422
2423 $next = $wpdb->get_row(
2424 $wpdb->prepare(
2425 "SELECT MONTH(post_date) AS month, YEAR(post_date) AS year
2426 FROM $wpdb->posts
2427 WHERE post_date > '%d-%d-%d 23:59:59'
2428 AND post_type = %s AND post_status = 'publish'
2429 ORDER BY post_date ASC
2430 LIMIT 1",
2431 $thisyear,
2432 zeroise( $thismonth, 2 ),
2433 $last_day,
2434 $post_type
2435 )
2436 );
2437
2438 /* translators: Calendar caption: 1: Month name, 2: 4-digit year. */
2439 $calendar_caption = _x( '%1$s %2$s', 'calendar caption' );
2440 $calendar_output = '<table id="wp-calendar" class="wp-calendar-table">
2441 <caption>' . sprintf(
2442 $calendar_caption,
2443 $wp_locale->get_month( $thismonth ),
2444 gmdate( 'Y', $unixmonth )
2445 ) . '</caption>
2446 <thead>
2447 <tr>';
2448
2449 $myweek = array();
2450
2451 for ( $wdcount = 0; $wdcount <= 6; $wdcount++ ) {
2452 $myweek[] = $wp_locale->get_weekday( ( $wdcount + $week_begins ) % 7 );
2453 }
2454
2455 foreach ( $myweek as $wd ) {
2456 $day_name = $args['initial'] ? $wp_locale->get_weekday_initial( $wd ) : $wp_locale->get_weekday_abbrev( $wd );
2457 $wd = esc_attr( $wd );
2458 $calendar_output .= "\n\t\t<th scope=\"col\" aria-label=\"$wd\">$day_name</th>";
2459 }
2460
2461 $calendar_output .= '
2462 </tr>
2463 </thead>
2464 <tbody>
2465 <tr>';
2466
2467 $daywithpost = array();
2468
2469 // Get days with posts.
2470 $dayswithposts = $wpdb->get_results(
2471 $wpdb->prepare(
2472 "SELECT DISTINCT DAYOFMONTH(post_date)
2473 FROM $wpdb->posts WHERE post_date >= '%d-%d-01 00:00:00'
2474 AND post_type = %s AND post_status = 'publish'
2475 AND post_date <= '%d-%d-%d 23:59:59'",
2476 $thisyear,
2477 zeroise( $thismonth, 2 ),
2478 $post_type,
2479 $thisyear,
2480 zeroise( $thismonth, 2 ),
2481 $last_day
2482 ),
2483 ARRAY_N
2484 );
2485
2486 if ( $dayswithposts ) {
2487 foreach ( (array) $dayswithposts as $daywith ) {
2488 $daywithpost[] = (int) $daywith[0];
2489 }
2490 }
2491
2492 // See how much we should pad in the beginning.
2493 $pad = calendar_week_mod( (int) gmdate( 'w', $unixmonth ) - $week_begins );
2494 if ( $pad > 0 ) {
2495 $calendar_output .= "\n\t\t" . '<td colspan="' . esc_attr( $pad ) . '" class="pad">&nbsp;</td>';
2496 }
2497
2498 $newrow = false;
2499 $daysinmonth = (int) gmdate( 't', $unixmonth );
2500
2501 for ( $day = 1; $day <= $daysinmonth; ++$day ) {
2502 if ( $newrow ) {
2503 $calendar_output .= "\n\t</tr>\n\t<tr>\n\t\t";
2504 }
2505
2506 $newrow = false;
2507
2508 if ( (int) current_time( 'j' ) === $day
2509 && (int) current_time( 'm' ) === $thismonth
2510 && (int) current_time( 'Y' ) === $thisyear
2511 ) {
2512 $calendar_output .= '<td id="today">';
2513 } else {
2514 $calendar_output .= '<td>';
2515 }
2516
2517 if ( in_array( $day, $daywithpost, true ) ) {
2518 // Any posts today?
2519 $date_format = gmdate( _x( 'F j, Y', 'daily archives date format' ), strtotime( "{$thisyear}-{$thismonth}-{$day}" ) );
2520 /* translators: Post calendar label. %s: Date. */
2521 $label = sprintf( __( 'Posts published on %s' ), $date_format );
2522 $calendar_output .= sprintf(
2523 '<a href="%s" aria-label="%s">%s</a>',
2524 get_day_link( $thisyear, $thismonth, $day ),
2525 esc_attr( $label ),
2526 $day
2527 );
2528 } else {
2529 $calendar_output .= $day;
2530 }
2531
2532 $calendar_output .= '</td>';
2533
2534 if ( 6 === (int) calendar_week_mod( (int) gmdate( 'w', mktime( 0, 0, 0, $thismonth, $day, $thisyear ) ) - $week_begins ) ) {
2535 $newrow = true;
2536 }
2537 }
2538
2539 $pad = 7 - calendar_week_mod( (int) gmdate( 'w', mktime( 0, 0, 0, $thismonth, $day, $thisyear ) ) - $week_begins );
2540 if ( 0 < $pad && $pad < 7 ) {
2541 $calendar_output .= "\n\t\t" . '<td class="pad" colspan="' . esc_attr( $pad ) . '">&nbsp;</td>';
2542 }
2543
2544 $calendar_output .= "\n\t</tr>\n\t</tbody>";
2545
2546 $calendar_output .= "\n\t</table>";
2547
2548 $calendar_output .= '<nav aria-label="' . __( 'Previous and next months' ) . '" class="wp-calendar-nav">';
2549
2550 if ( $previous ) {
2551 $calendar_output .= "\n\t\t" . sprintf(
2552 '<span class="wp-calendar-nav-prev"><a href="%1$s">&laquo; %2$s</a></span>',
2553 get_month_link( $previous->year, $previous->month ),
2554 $wp_locale->get_month_abbrev( $wp_locale->get_month( $previous->month ) )
2555 );
2556 } else {
2557 $calendar_output .= "\n\t\t" . '<span class="wp-calendar-nav-prev">&nbsp;</span>';
2558 }
2559
2560 $calendar_output .= "\n\t\t" . '<span class="pad">&nbsp;</span>';
2561
2562 if ( $next ) {
2563 $calendar_output .= "\n\t\t" . sprintf(
2564 '<span class="wp-calendar-nav-next"><a href="%1$s">%2$s &raquo;</a></span>',
2565 get_month_link( $next->year, $next->month ),
2566 $wp_locale->get_month_abbrev( $wp_locale->get_month( $next->month ) )
2567 );
2568 } else {
2569 $calendar_output .= "\n\t\t" . '<span class="wp-calendar-nav-next">&nbsp;</span>';
2570 }
2571
2572 $calendar_output .= '
2573 </nav>';
2574
2575 $cache[ $key ] = $calendar_output;
2576 wp_cache_set( 'get_calendar', $cache, 'calendar' );
2577
2578 /**
2579 * Filters the HTML calendar output.
2580 *
2581 * @since 3.0.0
2582 * @since 6.8.0 Added the `$args` parameter.
2583 *
2584 * @param string $calendar_output HTML output of the calendar.
2585 * @param array $args {
2586 * Optional. Array of display arguments.
2587 *
2588 * @type bool $initial Whether to use initial calendar names. Default true.
2589 * @type bool $display Whether to display the calendar output. Default true.
2590 * @type string $post_type Optional. Post type. Default 'post'.
2591 * }
2592 */
2593 $calendar_output = apply_filters( 'get_calendar', $calendar_output, $args );
2594
2595 if ( $args['display'] ) {
2596 echo $calendar_output;
2597 return;
2598 }
2599
2600 return $calendar_output;
2601}
2602
2603/**
2604 * Purges the cached results of get_calendar.
2605 *
2606 * @see get_calendar()
2607 * @since 2.1.0
2608 */
2609function delete_get_calendar_cache() {
2610 wp_cache_delete( 'get_calendar', 'calendar' );
2611}
2612
2613/**
2614 * Displays all of the allowed tags in HTML format with attributes.
2615 *
2616 * This is useful for displaying in the comment area, which elements and
2617 * attributes are supported. As well as any plugins which want to display it.
2618 *
2619 * @since 1.0.1
2620 * @since 4.4.0 No longer used in core.
2621 *
2622 * @global array $allowedtags
2623 *
2624 * @return string HTML allowed tags entity encoded.
2625 */
2626function allowed_tags() {
2627 global $allowedtags;
2628 $allowed = '';
2629 foreach ( (array) $allowedtags as $tag => $attributes ) {
2630 $allowed .= '<' . $tag;
2631 if ( 0 < count( $attributes ) ) {
2632 foreach ( $attributes as $attribute => $limits ) {
2633 $allowed .= ' ' . $attribute . '=""';
2634 }
2635 }
2636 $allowed .= '> ';
2637 }
2638 return htmlentities( $allowed );
2639}
2640
2641/***** Date/Time tags */
2642
2643/**
2644 * Outputs the date in iso8601 format for xml files.
2645 *
2646 * @since 1.0.0
2647 */
2648function the_date_xml() {
2649 echo mysql2date( 'Y-m-d', get_post()->post_date, false );
2650}
2651
2652/**
2653 * Displays or retrieves the date of the post (once per date).
2654 *
2655 * Will only output the date if the current post's date is different from the
2656 * previous one output.
2657 *
2658 * i.e. Only one date listing will show per day worth of posts shown in the loop, even if the
2659 * function is called several times for each post.
2660 *
2661 * HTML output can be filtered with {@see 'the_date'}.
2662 * Date string output can be filtered with {@see 'get_the_date'}.
2663 *
2664 * @since 0.71
2665 *
2666 * @global string $currentday The day of the current post in the loop.
2667 * @global string $previousday The day of the previous post in the loop.
2668 *
2669 * @param string $format Optional. PHP date format. Defaults to the 'date_format' option.
2670 * @param string $before Optional. Output before the date. Default empty.
2671 * @param string $after Optional. Output after the date. Default empty.
2672 * @param bool $display Optional. Whether to echo the date or return it. Default true.
2673 * @return string|void String if retrieving.
2674 */
2675function the_date( $format = '', $before = '', $after = '', $display = true ) {
2676 global $currentday, $previousday;
2677
2678 $the_date = '';
2679
2680 if ( is_new_day() ) {
2681 $the_date = $before . get_the_date( $format ) . $after;
2682 $previousday = $currentday;
2683 }
2684
2685 /**
2686 * Filters the date of the post, for display.
2687 *
2688 * @since 0.71
2689 *
2690 * @param string $the_date The formatted date string.
2691 * @param string $format PHP date format.
2692 * @param string $before HTML output before the date.
2693 * @param string $after HTML output after the date.
2694 */
2695 $the_date = apply_filters( 'the_date', $the_date, $format, $before, $after );
2696
2697 if ( $display ) {
2698 echo $the_date;
2699 } else {
2700 return $the_date;
2701 }
2702}
2703
2704/**
2705 * Retrieves the date of the post.
2706 *
2707 * Unlike the_date() this function will always return the date.
2708 * Modify output with the {@see 'get_the_date'} filter.
2709 *
2710 * @since 3.0.0
2711 *
2712 * @param string $format Optional. PHP date format. Defaults to the 'date_format' option.
2713 * @param int|WP_Post $post Optional. Post ID or WP_Post object. Default current post.
2714 * @return string|int|false Date the current post was written. False on failure.
2715 */
2716function get_the_date( $format = '', $post = null ) {
2717 $post = get_post( $post );
2718
2719 if ( ! $post ) {
2720 return false;
2721 }
2722
2723 $_format = ! empty( $format ) ? $format : get_option( 'date_format' );
2724
2725 $the_date = get_post_time( $_format, false, $post, true );
2726
2727 /**
2728 * Filters the date of the post.
2729 *
2730 * @since 3.0.0
2731 *
2732 * @param string|int $the_date Formatted date string or Unix timestamp if `$format` is 'U' or 'G'.
2733 * @param string $format PHP date format.
2734 * @param WP_Post $post The post object.
2735 */
2736 return apply_filters( 'get_the_date', $the_date, $format, $post );
2737}
2738
2739/**
2740 * Displays the date on which the post was last modified.
2741 *
2742 * @since 2.1.0
2743 *
2744 * @param string $format Optional. PHP date format. Defaults to the 'date_format' option.
2745 * @param string $before Optional. Output before the date. Default empty.
2746 * @param string $after Optional. Output after the date. Default empty.
2747 * @param bool $display Optional. Whether to echo the date or return it. Default true.
2748 * @return string|void String if retrieving.
2749 */
2750function the_modified_date( $format = '', $before = '', $after = '', $display = true ) {
2751 $the_modified_date = $before . get_the_modified_date( $format ) . $after;
2752
2753 /**
2754 * Filters the date a post was last modified, for display.
2755 *
2756 * @since 2.1.0
2757 *
2758 * @param string $the_modified_date The last modified date.
2759 * @param string $format PHP date format.
2760 * @param string $before HTML output before the date.
2761 * @param string $after HTML output after the date.
2762 */
2763 $the_modified_date = apply_filters( 'the_modified_date', $the_modified_date, $format, $before, $after );
2764
2765 if ( $display ) {
2766 echo $the_modified_date;
2767 } else {
2768 return $the_modified_date;
2769 }
2770}
2771
2772/**
2773 * Retrieves the date on which the post was last modified.
2774 *
2775 * @since 2.1.0
2776 * @since 4.6.0 Added the `$post` parameter.
2777 *
2778 * @param string $format Optional. PHP date format. Defaults to the 'date_format' option.
2779 * @param int|WP_Post $post Optional. Post ID or WP_Post object. Default current post.
2780 * @return string|int|false Date the current post was modified. False on failure.
2781 */
2782function get_the_modified_date( $format = '', $post = null ) {
2783 $post = get_post( $post );
2784
2785 if ( ! $post ) {
2786 // For backward compatibility, failures go through the filter below.
2787 $the_time = false;
2788 } else {
2789 $_format = ! empty( $format ) ? $format : get_option( 'date_format' );
2790
2791 $the_time = get_post_modified_time( $_format, false, $post, true );
2792 }
2793
2794 /**
2795 * Filters the date a post was last modified.
2796 *
2797 * @since 2.1.0
2798 * @since 4.6.0 Added the `$post` parameter.
2799 *
2800 * @param string|int|false $the_time The formatted date or false if no post is found.
2801 * @param string $format PHP date format.
2802 * @param WP_Post|null $post WP_Post object or null if no post is found.
2803 */
2804 return apply_filters( 'get_the_modified_date', $the_time, $format, $post );
2805}
2806
2807/**
2808 * Displays the time of the post.
2809 *
2810 * @since 0.71
2811 *
2812 * @param string $format Optional. Format to use for retrieving the time the post
2813 * was written. Accepts 'G', 'U', or PHP date format.
2814 * Defaults to the 'time_format' option.
2815 */
2816function the_time( $format = '' ) {
2817 /**
2818 * Filters the time of the post, for display.
2819 *
2820 * @since 0.71
2821 *
2822 * @param string $get_the_time The formatted time.
2823 * @param string $format Format to use for retrieving the time the post
2824 * was written. Accepts 'G', 'U', or PHP date format.
2825 */
2826 echo apply_filters( 'the_time', get_the_time( $format ), $format );
2827}
2828
2829/**
2830 * Retrieves the time of the post.
2831 *
2832 * @since 1.5.0
2833 *
2834 * @param string $format Optional. Format to use for retrieving the time the post
2835 * was written. Accepts 'G', 'U', or PHP date format.
2836 * Defaults to the 'time_format' option.
2837 * @param int|WP_Post $post Post ID or post object. Default is global `$post` object.
2838 * @return string|int|false Formatted date string or Unix timestamp if `$format` is 'U' or 'G'.
2839 * False on failure.
2840 */
2841function get_the_time( $format = '', $post = null ) {
2842 $post = get_post( $post );
2843
2844 if ( ! $post ) {
2845 return false;
2846 }
2847
2848 $_format = ! empty( $format ) ? $format : get_option( 'time_format' );
2849
2850 $the_time = get_post_time( $_format, false, $post, true );
2851
2852 /**
2853 * Filters the time of the post.
2854 *
2855 * @since 1.5.0
2856 *
2857 * @param string|int $the_time Formatted date string or Unix timestamp if `$format` is 'U' or 'G'.
2858 * @param string $format Format to use for retrieving the time the post
2859 * was written. Accepts 'G', 'U', or PHP date format.
2860 * @param WP_Post $post Post object.
2861 */
2862 return apply_filters( 'get_the_time', $the_time, $format, $post );
2863}
2864
2865/**
2866 * Retrieves the localized time of the post.
2867 *
2868 * @since 2.0.0
2869 *
2870 * @param string $format Optional. Format to use for retrieving the time the post
2871 * was written. Accepts 'G', 'U', or PHP date format. Default 'U'.
2872 * @param bool $gmt Optional. Whether to retrieve the GMT time. Default false.
2873 * @param int|WP_Post $post Post ID or post object. Default is global `$post` object.
2874 * @param bool $translate Whether to translate the time string. Default false.
2875 * @return string|int|false Formatted date string or Unix timestamp if `$format` is 'U' or 'G'.
2876 * False on failure.
2877 */
2878function get_post_time( $format = 'U', $gmt = false, $post = null, $translate = false ) {
2879 $post = get_post( $post );
2880
2881 if ( ! $post ) {
2882 return false;
2883 }
2884
2885 $source = ( $gmt ) ? 'gmt' : 'local';
2886 $datetime = get_post_datetime( $post, 'date', $source );
2887
2888 if ( false === $datetime ) {
2889 return false;
2890 }
2891
2892 if ( 'U' === $format || 'G' === $format ) {
2893 $time = $datetime->getTimestamp();
2894
2895 // Returns a sum of timestamp with timezone offset. Ideally should never be used.
2896 if ( ! $gmt ) {
2897 $time += $datetime->getOffset();
2898 }
2899 } elseif ( $translate ) {
2900 $time = wp_date( $format, $datetime->getTimestamp(), $gmt ? new DateTimeZone( 'UTC' ) : null );
2901 } else {
2902 if ( $gmt ) {
2903 $datetime = $datetime->setTimezone( new DateTimeZone( 'UTC' ) );
2904 }
2905
2906 $time = $datetime->format( $format );
2907 }
2908
2909 /**
2910 * Filters the localized time of the post.
2911 *
2912 * @since 2.6.0
2913 *
2914 * @param string|int $time Formatted date string or Unix timestamp if `$format` is 'U' or 'G'.
2915 * @param string $format Format to use for retrieving the date of the post.
2916 * Accepts 'G', 'U', or PHP date format.
2917 * @param bool $gmt Whether to retrieve the GMT time.
2918 */
2919 return apply_filters( 'get_post_time', $time, $format, $gmt );
2920}
2921
2922/**
2923 * Retrieves post published or modified time as a `DateTimeImmutable` object instance.
2924 *
2925 * The object will be set to the timezone from WordPress settings.
2926 *
2927 * For legacy reasons, this function allows to choose to instantiate from local or UTC time in database.
2928 * Normally this should make no difference to the result. However, the values might get out of sync in database,
2929 * typically because of timezone setting changes. The parameter ensures the ability to reproduce backwards
2930 * compatible behaviors in such cases.
2931 *
2932 * @since 5.3.0
2933 *
2934 * @param int|WP_Post $post Optional. Post ID or post object. Default is global `$post` object.
2935 * @param string $field Optional. Published or modified time to use from database. Accepts 'date' or 'modified'.
2936 * Default 'date'.
2937 * @param string $source Optional. Local or UTC time to use from database. Accepts 'local' or 'gmt'.
2938 * Default 'local'.
2939 * @return DateTimeImmutable|false Time object on success, false on failure.
2940 */
2941function get_post_datetime( $post = null, $field = 'date', $source = 'local' ) {
2942 $post = get_post( $post );
2943
2944 if ( ! $post ) {
2945 return false;
2946 }
2947
2948 $wp_timezone = wp_timezone();
2949
2950 if ( 'gmt' === $source ) {
2951 $time = ( 'modified' === $field ) ? $post->post_modified_gmt : $post->post_date_gmt;
2952 $timezone = new DateTimeZone( 'UTC' );
2953 } else {
2954 $time = ( 'modified' === $field ) ? $post->post_modified : $post->post_date;
2955 $timezone = $wp_timezone;
2956 }
2957
2958 if ( empty( $time ) || '0000-00-00 00:00:00' === $time ) {
2959 return false;
2960 }
2961
2962 $datetime = date_create_immutable_from_format( 'Y-m-d H:i:s', $time, $timezone );
2963
2964 if ( false === $datetime ) {
2965 return false;
2966 }
2967
2968 return $datetime->setTimezone( $wp_timezone );
2969}
2970
2971/**
2972 * Retrieves post published or modified time as a Unix timestamp.
2973 *
2974 * Note that this function returns a true Unix timestamp, not summed with timezone offset
2975 * like older WP functions.
2976 *
2977 * @since 5.3.0
2978 *
2979 * @param int|WP_Post $post Optional. Post ID or post object. Default is global `$post` object.
2980 * @param string $field Optional. Published or modified time to use from database. Accepts 'date' or 'modified'.
2981 * Default 'date'.
2982 * @return int|false Unix timestamp on success, false on failure.
2983 */
2984function get_post_timestamp( $post = null, $field = 'date' ) {
2985 $datetime = get_post_datetime( $post, $field );
2986
2987 if ( false === $datetime ) {
2988 return false;
2989 }
2990
2991 return $datetime->getTimestamp();
2992}
2993
2994/**
2995 * Displays the time at which the post was last modified.
2996 *
2997 * @since 2.0.0
2998 *
2999 * @param string $format Optional. Format to use for retrieving the time the post
3000 * was modified. Accepts 'G', 'U', or PHP date format.
3001 * Defaults to the 'time_format' option.
3002 */
3003function the_modified_time( $format = '' ) {
3004 /**
3005 * Filters the localized time a post was last modified, for display.
3006 *
3007 * @since 2.0.0
3008 *
3009 * @param string|false $get_the_modified_time The formatted time or false if no post is found.
3010 * @param string $format Format to use for retrieving the time the post
3011 * was modified. Accepts 'G', 'U', or PHP date format.
3012 */
3013 echo apply_filters( 'the_modified_time', get_the_modified_time( $format ), $format );
3014}
3015
3016/**
3017 * Retrieves the time at which the post was last modified.
3018 *
3019 * @since 2.0.0
3020 * @since 4.6.0 Added the `$post` parameter.
3021 *
3022 * @param string $format Optional. Format to use for retrieving the time the post
3023 * was modified. Accepts 'G', 'U', or PHP date format.
3024 * Defaults to the 'time_format' option.
3025 * @param int|WP_Post $post Optional. Post ID or WP_Post object. Default current post.
3026 * @return string|int|false Formatted date string or Unix timestamp. False on failure.
3027 */
3028function get_the_modified_time( $format = '', $post = null ) {
3029 $post = get_post( $post );
3030
3031 if ( ! $post ) {
3032 // For backward compatibility, failures go through the filter below.
3033 $the_time = false;
3034 } else {
3035 $_format = ! empty( $format ) ? $format : get_option( 'time_format' );
3036
3037 $the_time = get_post_modified_time( $_format, false, $post, true );
3038 }
3039
3040 /**
3041 * Filters the localized time a post was last modified.
3042 *
3043 * @since 2.0.0
3044 * @since 4.6.0 Added the `$post` parameter.
3045 *
3046 * @param string|int|false $the_time The formatted time or false if no post is found.
3047 * @param string $format Format to use for retrieving the time the post
3048 * was modified. Accepts 'G', 'U', or PHP date format.
3049 * @param WP_Post|null $post WP_Post object or null if no post is found.
3050 */
3051 return apply_filters( 'get_the_modified_time', $the_time, $format, $post );
3052}
3053
3054/**
3055 * Retrieves the time at which the post was last modified.
3056 *
3057 * @since 2.0.0
3058 *
3059 * @param string $format Optional. Format to use for retrieving the time the post
3060 * was modified. Accepts 'G', 'U', or PHP date format. Default 'U'.
3061 * @param bool $gmt Optional. Whether to retrieve the GMT time. Default false.
3062 * @param int|WP_Post $post Post ID or post object. Default is global `$post` object.
3063 * @param bool $translate Whether to translate the time string. Default false.
3064 * @return string|int|false Formatted date string or Unix timestamp if `$format` is 'U' or 'G'.
3065 * False on failure.
3066 */
3067function get_post_modified_time( $format = 'U', $gmt = false, $post = null, $translate = false ) {
3068 $post = get_post( $post );
3069
3070 if ( ! $post ) {
3071 return false;
3072 }
3073
3074 $source = ( $gmt ) ? 'gmt' : 'local';
3075 $datetime = get_post_datetime( $post, 'modified', $source );
3076
3077 if ( false === $datetime ) {
3078 return false;
3079 }
3080
3081 if ( 'U' === $format || 'G' === $format ) {
3082 $time = $datetime->getTimestamp();
3083
3084 // Returns a sum of timestamp with timezone offset. Ideally should never be used.
3085 if ( ! $gmt ) {
3086 $time += $datetime->getOffset();
3087 }
3088 } elseif ( $translate ) {
3089 $time = wp_date( $format, $datetime->getTimestamp(), $gmt ? new DateTimeZone( 'UTC' ) : null );
3090 } else {
3091 if ( $gmt ) {
3092 $datetime = $datetime->setTimezone( new DateTimeZone( 'UTC' ) );
3093 }
3094
3095 $time = $datetime->format( $format );
3096 }
3097
3098 /**
3099 * Filters the localized time a post was last modified.
3100 *
3101 * @since 2.8.0
3102 *
3103 * @param string|int $time Formatted date string or Unix timestamp if `$format` is 'U' or 'G'.
3104 * @param string $format Format to use for retrieving the time the post was modified.
3105 * Accepts 'G', 'U', or PHP date format. Default 'U'.
3106 * @param bool $gmt Whether to retrieve the GMT time. Default false.
3107 */
3108 return apply_filters( 'get_post_modified_time', $time, $format, $gmt );
3109}
3110
3111/**
3112 * Displays the localized weekday for the post.
3113 *
3114 * @since 0.71
3115 *
3116 * @global WP_Locale $wp_locale WordPress date and time locale object.
3117 */
3118function the_weekday() {
3119 global $wp_locale;
3120
3121 $post = get_post();
3122
3123 if ( ! $post ) {
3124 return;
3125 }
3126
3127 $the_weekday = $wp_locale->get_weekday( get_post_time( 'w', false, $post ) );
3128
3129 /**
3130 * Filters the localized weekday of the post, for display.
3131 *
3132 * @since 0.71
3133 *
3134 * @param string $the_weekday
3135 */
3136 echo apply_filters( 'the_weekday', $the_weekday );
3137}
3138
3139/**
3140 * Displays the localized weekday for the post.
3141 *
3142 * Will only output the weekday if the current post's weekday is different from
3143 * the previous one output.
3144 *
3145 * @since 0.71
3146 *
3147 * @global WP_Locale $wp_locale WordPress date and time locale object.
3148 * @global string $currentday The day of the current post in the loop.
3149 * @global string $previousweekday The day of the previous post in the loop.
3150 *
3151 * @param string $before Optional. Output before the date. Default empty.
3152 * @param string $after Optional. Output after the date. Default empty.
3153 */
3154function the_weekday_date( $before = '', $after = '' ) {
3155 global $wp_locale, $currentday, $previousweekday;
3156
3157 $post = get_post();
3158
3159 if ( ! $post ) {
3160 return;
3161 }
3162
3163 $the_weekday_date = '';
3164
3165 if ( $currentday !== $previousweekday ) {
3166 $the_weekday_date .= $before;
3167 $the_weekday_date .= $wp_locale->get_weekday( get_post_time( 'w', false, $post ) );
3168 $the_weekday_date .= $after;
3169 $previousweekday = $currentday;
3170 }
3171
3172 /**
3173 * Filters the localized weekday of the post, for display.
3174 *
3175 * @since 0.71
3176 *
3177 * @param string $the_weekday_date The weekday on which the post was written.
3178 * @param string $before The HTML to output before the date.
3179 * @param string $after The HTML to output after the date.
3180 */
3181 echo apply_filters( 'the_weekday_date', $the_weekday_date, $before, $after );
3182}
3183
3184/**
3185 * Fires the wp_head action.
3186 *
3187 * See {@see 'wp_head'}.
3188 *
3189 * @since 1.2.0
3190 */
3191function wp_head() {
3192 /**
3193 * Prints scripts or data in the head tag on the front end.
3194 *
3195 * @since 1.5.0
3196 */
3197 do_action( 'wp_head' );
3198}
3199
3200/**
3201 * Fires the wp_footer action.
3202 *
3203 * See {@see 'wp_footer'}.
3204 *
3205 * @since 1.5.1
3206 */
3207function wp_footer() {
3208 /**
3209 * Prints scripts or data before the closing body tag on the front end.
3210 *
3211 * @since 1.5.1
3212 */
3213 do_action( 'wp_footer' );
3214}
3215
3216/**
3217 * Fires the wp_body_open action.
3218 *
3219 * See {@see 'wp_body_open'}.
3220 *
3221 * @since 5.2.0
3222 */
3223function wp_body_open() {
3224 /**
3225 * Triggered after the opening body tag.
3226 *
3227 * @since 5.2.0
3228 */
3229 do_action( 'wp_body_open' );
3230}
3231
3232/**
3233 * Displays the links to the general feeds.
3234 *
3235 * @since 2.8.0
3236 *
3237 * @param array $args Optional arguments.
3238 */
3239function feed_links( $args = array() ) {
3240 if ( ! current_theme_supports( 'automatic-feed-links' ) ) {
3241 return;
3242 }
3243
3244 $defaults = array(
3245 /* translators: Separator between site name and feed type in feed links. */
3246 'separator' => _x( '&raquo;', 'feed link' ),
3247 /* translators: 1: Site title, 2: Separator (raquo). */
3248 'feedtitle' => __( '%1$s %2$s Feed' ),
3249 /* translators: 1: Site title, 2: Separator (raquo). */
3250 'comstitle' => __( '%1$s %2$s Comments Feed' ),
3251 );
3252
3253 $args = wp_parse_args( $args, $defaults );
3254
3255 /**
3256 * Filters the feed links arguments.
3257 *
3258 * @since 6.7.0
3259 *
3260 * @param array $args An array of feed links arguments.
3261 */
3262 $args = apply_filters( 'feed_links_args', $args );
3263
3264 /**
3265 * Filters whether to display the posts feed link.
3266 *
3267 * @since 4.4.0
3268 *
3269 * @param bool $show Whether to display the posts feed link. Default true.
3270 */
3271 if ( apply_filters( 'feed_links_show_posts_feed', true ) ) {
3272 printf(
3273 '<link rel="alternate" type="%s" title="%s" href="%s" />' . "\n",
3274 feed_content_type(),
3275 esc_attr( sprintf( $args['feedtitle'], get_bloginfo( 'name' ), $args['separator'] ) ),
3276 esc_url( get_feed_link() )
3277 );
3278 }
3279
3280 /**
3281 * Filters whether to display the comments feed link.
3282 *
3283 * @since 4.4.0
3284 *
3285 * @param bool $show Whether to display the comments feed link. Default true.
3286 */
3287 if ( apply_filters( 'feed_links_show_comments_feed', true ) ) {
3288 printf(
3289 '<link rel="alternate" type="%s" title="%s" href="%s" />' . "\n",
3290 feed_content_type(),
3291 esc_attr( sprintf( $args['comstitle'], get_bloginfo( 'name' ), $args['separator'] ) ),
3292 esc_url( get_feed_link( 'comments_' . get_default_feed() ) )
3293 );
3294 }
3295}
3296
3297/**
3298 * Displays the links to the extra feeds such as category feeds.
3299 *
3300 * @since 2.8.0
3301 *
3302 * @param array $args Optional arguments.
3303 */
3304function feed_links_extra( $args = array() ) {
3305 $defaults = array(
3306 /* translators: Separator between site name and feed type in feed links. */
3307 'separator' => _x( '&raquo;', 'feed link' ),
3308 /* translators: 1: Site name, 2: Separator (raquo), 3: Post title. */
3309 'singletitle' => __( '%1$s %2$s %3$s Comments Feed' ),
3310 /* translators: 1: Site name, 2: Separator (raquo), 3: Category name. */
3311 'cattitle' => __( '%1$s %2$s %3$s Category Feed' ),
3312 /* translators: 1: Site name, 2: Separator (raquo), 3: Tag name. */
3313 'tagtitle' => __( '%1$s %2$s %3$s Tag Feed' ),
3314 /* translators: 1: Site name, 2: Separator (raquo), 3: Term name, 4: Taxonomy singular name. */
3315 'taxtitle' => __( '%1$s %2$s %3$s %4$s Feed' ),
3316 /* translators: 1: Site name, 2: Separator (raquo), 3: Author name. */
3317 'authortitle' => __( '%1$s %2$s Posts by %3$s Feed' ),
3318 /* translators: 1: Site name, 2: Separator (raquo), 3: Search query. */
3319 'searchtitle' => __( '%1$s %2$s Search Results for &#8220;%3$s&#8221; Feed' ),
3320 /* translators: 1: Site name, 2: Separator (raquo), 3: Post type name. */
3321 'posttypetitle' => __( '%1$s %2$s %3$s Feed' ),
3322 );
3323
3324 $args = wp_parse_args( $args, $defaults );
3325
3326 /**
3327 * Filters the extra feed links arguments.
3328 *
3329 * @since 6.7.0
3330 *
3331 * @param array $args An array of extra feed links arguments.
3332 */
3333 $args = apply_filters( 'feed_links_extra_args', $args );
3334
3335 /*
3336 * The template conditionals are referring to the global query, so the queried object is used rather than
3337 * depending on a global $post being set.
3338 */
3339 $queried_object = get_queried_object();
3340 if ( is_singular() && $queried_object instanceof WP_Post ) {
3341 $post = $queried_object;
3342
3343 /** This filter is documented in wp-includes/general-template.php */
3344 $show_comments_feed = apply_filters( 'feed_links_show_comments_feed', true );
3345
3346 /**
3347 * Filters whether to display the post comments feed link.
3348 *
3349 * This filter allows to enable or disable the feed link for a singular post
3350 * in a way that is independent of {@see 'feed_links_show_comments_feed'}
3351 * (which controls the global comments feed). The result of that filter
3352 * is accepted as a parameter.
3353 *
3354 * @since 6.1.0
3355 *
3356 * @param bool $show_comments_feed Whether to display the post comments feed link. Defaults to
3357 * the {@see 'feed_links_show_comments_feed'} filter result.
3358 */
3359 $show_post_comments_feed = apply_filters( 'feed_links_extra_show_post_comments_feed', $show_comments_feed );
3360
3361 if ( $show_post_comments_feed && ( comments_open( $post ) || pings_open( $post ) || (int) $post->comment_count > 0 ) ) {
3362 $title = sprintf(
3363 $args['singletitle'],
3364 get_bloginfo( 'name' ),
3365 $args['separator'],
3366 the_title_attribute(
3367 array(
3368 'echo' => false,
3369 'post' => $post,
3370 )
3371 )
3372 );
3373
3374 $feed_link = get_post_comments_feed_link( $post->ID );
3375
3376 if ( $feed_link ) {
3377 $href = $feed_link;
3378 }
3379 }
3380 } elseif ( is_post_type_archive() ) {
3381 /**
3382 * Filters whether to display the post type archive feed link.
3383 *
3384 * @since 6.1.0
3385 *
3386 * @param bool $show Whether to display the post type archive feed link. Default true.
3387 */
3388 $show_post_type_archive_feed = apply_filters( 'feed_links_extra_show_post_type_archive_feed', true );
3389
3390 if ( $show_post_type_archive_feed ) {
3391 $post_type = get_query_var( 'post_type' );
3392
3393 if ( is_array( $post_type ) ) {
3394 $post_type = reset( $post_type );
3395 }
3396
3397 $post_type_obj = get_post_type_object( $post_type );
3398
3399 $title = sprintf(
3400 $args['posttypetitle'],
3401 get_bloginfo( 'name' ),
3402 $args['separator'],
3403 $post_type_obj->labels->name
3404 );
3405
3406 $href = get_post_type_archive_feed_link( $post_type_obj->name );
3407 }
3408 } elseif ( is_category() ) {
3409 /**
3410 * Filters whether to display the category feed link.
3411 *
3412 * @since 6.1.0
3413 *
3414 * @param bool $show Whether to display the category feed link. Default true.
3415 */
3416 $show_category_feed = apply_filters( 'feed_links_extra_show_category_feed', true );
3417
3418 if ( $show_category_feed ) {
3419 $term = get_queried_object();
3420
3421 if ( $term ) {
3422 $title = sprintf(
3423 $args['cattitle'],
3424 get_bloginfo( 'name' ),
3425 $args['separator'],
3426 $term->name
3427 );
3428
3429 $href = get_category_feed_link( $term->term_id );
3430 }
3431 }
3432 } elseif ( is_tag() ) {
3433 /**
3434 * Filters whether to display the tag feed link.
3435 *
3436 * @since 6.1.0
3437 *
3438 * @param bool $show Whether to display the tag feed link. Default true.
3439 */
3440 $show_tag_feed = apply_filters( 'feed_links_extra_show_tag_feed', true );
3441
3442 if ( $show_tag_feed ) {
3443 $term = get_queried_object();
3444
3445 if ( $term ) {
3446 $title = sprintf(
3447 $args['tagtitle'],
3448 get_bloginfo( 'name' ),
3449 $args['separator'],
3450 $term->name
3451 );
3452
3453 $href = get_tag_feed_link( $term->term_id );
3454 }
3455 }
3456 } elseif ( is_tax() ) {
3457 /**
3458 * Filters whether to display the custom taxonomy feed link.
3459 *
3460 * @since 6.1.0
3461 *
3462 * @param bool $show Whether to display the custom taxonomy feed link. Default true.
3463 */
3464 $show_tax_feed = apply_filters( 'feed_links_extra_show_tax_feed', true );
3465
3466 if ( $show_tax_feed ) {
3467 $term = get_queried_object();
3468
3469 if ( $term ) {
3470 $tax = get_taxonomy( $term->taxonomy );
3471
3472 $title = sprintf(
3473 $args['taxtitle'],
3474 get_bloginfo( 'name' ),
3475 $args['separator'],
3476 $term->name,
3477 $tax->labels->singular_name
3478 );
3479
3480 $href = get_term_feed_link( $term->term_id, $term->taxonomy );
3481 }
3482 }
3483 } elseif ( is_author() ) {
3484 /**
3485 * Filters whether to display the author feed link.
3486 *
3487 * @since 6.1.0
3488 *
3489 * @param bool $show Whether to display the author feed link. Default true.
3490 */
3491 $show_author_feed = apply_filters( 'feed_links_extra_show_author_feed', true );
3492
3493 if ( $show_author_feed ) {
3494 $author_id = (int) get_query_var( 'author' );
3495
3496 $title = sprintf(
3497 $args['authortitle'],
3498 get_bloginfo( 'name' ),
3499 $args['separator'],
3500 get_the_author_meta( 'display_name', $author_id )
3501 );
3502
3503 $href = get_author_feed_link( $author_id );
3504 }
3505 } elseif ( is_search() ) {
3506 /**
3507 * Filters whether to display the search results feed link.
3508 *
3509 * @since 6.1.0
3510 *
3511 * @param bool $show Whether to display the search results feed link. Default true.
3512 */
3513 $show_search_feed = apply_filters( 'feed_links_extra_show_search_feed', true );
3514
3515 if ( $show_search_feed ) {
3516 $title = sprintf(
3517 $args['searchtitle'],
3518 get_bloginfo( 'name' ),
3519 $args['separator'],
3520 get_search_query( false )
3521 );
3522
3523 $href = get_search_feed_link();
3524 }
3525 }
3526
3527 if ( isset( $title ) && isset( $href ) ) {
3528 printf(
3529 '<link rel="alternate" type="%s" title="%s" href="%s" />' . "\n",
3530 feed_content_type(),
3531 esc_attr( $title ),
3532 esc_url( $href )
3533 );
3534 }
3535}
3536
3537/**
3538 * Displays the link to the Really Simple Discovery service endpoint.
3539 *
3540 * @link http://archipelago.phrasewise.com/rsd
3541 * @since 2.0.0
3542 */
3543function rsd_link() {
3544 printf(
3545 '<link rel="EditURI" type="application/rsd+xml" title="RSD" href="%s" />' . "\n",
3546 esc_url( site_url( 'xmlrpc.php?rsd', 'rpc' ) )
3547 );
3548}
3549
3550/**
3551 * Displays a referrer `strict-origin-when-cross-origin` meta tag.
3552 *
3553 * Outputs a referrer `strict-origin-when-cross-origin` meta tag that tells the browser not to send
3554 * the full URL as a referrer to other sites when cross-origin assets are loaded.
3555 *
3556 * Typical usage is as a {@see 'wp_head'} callback:
3557 *
3558 * add_action( 'wp_head', 'wp_strict_cross_origin_referrer' );
3559 *
3560 * @since 5.7.0
3561 */
3562function wp_strict_cross_origin_referrer() {
3563 ?>
3564 <meta name='referrer' content='strict-origin-when-cross-origin' />
3565 <?php
3566}
3567
3568/**
3569 * Displays site icon meta tags.
3570 *
3571 * @since 4.3.0
3572 *
3573 * @link https://www.whatwg.org/specs/web-apps/current-work/multipage/links.html#rel-icon HTML5 specification link icon.
3574 */
3575function wp_site_icon() {
3576 if ( ! has_site_icon() && ! is_customize_preview() ) {
3577 return;
3578 }
3579
3580 $meta_tags = array();
3581 $icon_32 = get_site_icon_url( 32 );
3582 if ( empty( $icon_32 ) && is_customize_preview() ) {
3583 $icon_32 = '/favicon.ico'; // Serve default favicon URL in customizer so element can be updated for preview.
3584 }
3585 if ( $icon_32 ) {
3586 $meta_tags[] = sprintf( '<link rel="icon" href="%s" sizes="32x32" />', esc_url( $icon_32 ) );
3587 }
3588 $icon_192 = get_site_icon_url( 192 );
3589 if ( $icon_192 ) {
3590 $meta_tags[] = sprintf( '<link rel="icon" href="%s" sizes="192x192" />', esc_url( $icon_192 ) );
3591 }
3592 $icon_180 = get_site_icon_url( 180 );
3593 if ( $icon_180 ) {
3594 $meta_tags[] = sprintf( '<link rel="apple-touch-icon" href="%s" />', esc_url( $icon_180 ) );
3595 }
3596 $icon_270 = get_site_icon_url( 270 );
3597 if ( $icon_270 ) {
3598 $meta_tags[] = sprintf( '<meta name="msapplication-TileImage" content="%s" />', esc_url( $icon_270 ) );
3599 }
3600
3601 /**
3602 * Filters the site icon meta tags, so plugins can add their own.
3603 *
3604 * @since 4.3.0
3605 *
3606 * @param string[] $meta_tags Array of Site Icon meta tags.
3607 */
3608 $meta_tags = apply_filters( 'site_icon_meta_tags', $meta_tags );
3609 $meta_tags = array_filter( $meta_tags );
3610
3611 foreach ( $meta_tags as $meta_tag ) {
3612 echo "$meta_tag\n";
3613 }
3614}
3615
3616/**
3617 * Prints resource hints to browsers for pre-fetching, pre-rendering
3618 * and pre-connecting to websites.
3619 *
3620 * Gives hints to browsers to prefetch specific pages or render them
3621 * in the background, to perform DNS lookups or to begin the connection
3622 * handshake (DNS, TCP, TLS) in the background.
3623 *
3624 * These performance improving indicators work by using `<link rel"…">`.
3625 *
3626 * @since 4.6.0
3627 */
3628function wp_resource_hints() {
3629 $hints = array(
3630 'dns-prefetch' => wp_dependencies_unique_hosts(),
3631 'preconnect' => array(),
3632 'prefetch' => array(),
3633 'prerender' => array(),
3634 );
3635
3636 foreach ( $hints as $relation_type => $urls ) {
3637 $unique_urls = array();
3638
3639 /**
3640 * Filters domains and URLs for resource hints of the given relation type.
3641 *
3642 * @since 4.6.0
3643 * @since 4.7.0 The `$urls` parameter accepts arrays of specific HTML attributes
3644 * as its child elements.
3645 *
3646 * @param array $urls {
3647 * Array of resources and their attributes, or URLs to print for resource hints.
3648 *
3649 * @type array|string ...$0 {
3650 * Array of resource attributes, or a URL string.
3651 *
3652 * @type string $href URL to include in resource hints. Required.
3653 * @type string $as How the browser should treat the resource
3654 * (`script`, `style`, `image`, `document`, etc).
3655 * @type string $crossorigin Indicates the CORS policy of the specified resource.
3656 * @type float $pr Expected probability that the resource hint will be used.
3657 * @type string $type Type of the resource (`text/html`, `text/css`, etc).
3658 * }
3659 * }
3660 * @param string $relation_type The relation type the URLs are printed for. One of
3661 * 'dns-prefetch', 'preconnect', 'prefetch', or 'prerender'.
3662 */
3663 $urls = apply_filters( 'wp_resource_hints', $urls, $relation_type );
3664
3665 foreach ( $urls as $key => $url ) {
3666 $atts = array();
3667
3668 if ( is_array( $url ) ) {
3669 if ( isset( $url['href'] ) ) {
3670 $atts = $url;
3671 $url = $url['href'];
3672 } else {
3673 continue;
3674 }
3675 }
3676
3677 $url = esc_url( $url, array( 'http', 'https' ) );
3678
3679 if ( ! $url ) {
3680 continue;
3681 }
3682
3683 if ( isset( $unique_urls[ $url ] ) ) {
3684 continue;
3685 }
3686
3687 if ( in_array( $relation_type, array( 'preconnect', 'dns-prefetch' ), true ) ) {
3688 $parsed = wp_parse_url( $url );
3689
3690 if ( empty( $parsed['host'] ) ) {
3691 continue;
3692 }
3693
3694 if ( 'preconnect' === $relation_type && ! empty( $parsed['scheme'] ) ) {
3695 $url = $parsed['scheme'] . '://' . $parsed['host'];
3696 } else {
3697 // Use protocol-relative URLs for dns-prefetch or if scheme is missing.
3698 $url = '//' . $parsed['host'];
3699 }
3700 }
3701
3702 $atts['rel'] = $relation_type;
3703 $atts['href'] = $url;
3704
3705 $unique_urls[ $url ] = $atts;
3706 }
3707
3708 foreach ( $unique_urls as $atts ) {
3709 $html = '';
3710
3711 foreach ( $atts as $attr => $value ) {
3712 if ( ! is_scalar( $value )
3713 || ( ! in_array( $attr, array( 'as', 'crossorigin', 'href', 'pr', 'rel', 'type' ), true ) && ! is_numeric( $attr ) )
3714 ) {
3715
3716 continue;
3717 }
3718
3719 $value = ( 'href' === $attr ) ? esc_url( $value ) : esc_attr( $value );
3720
3721 if ( ! is_string( $attr ) ) {
3722 $html .= " $value";
3723 } else {
3724 $html .= " $attr='$value'";
3725 }
3726 }
3727
3728 $html = trim( $html );
3729
3730 echo "<link $html />\n";
3731 }
3732 }
3733}
3734
3735/**
3736 * Prints resource preloads directives to browsers.
3737 *
3738 * Gives directive to browsers to preload specific resources that website will
3739 * need very soon, this ensures that they are available earlier and are less
3740 * likely to block the page's render. Preload directives should not be used for
3741 * non-render-blocking elements, as then they would compete with the
3742 * render-blocking ones, slowing down the render.
3743 *
3744 * These performance improving indicators work by using `<link rel="preload">`.
3745 *
3746 * @link https://developer.mozilla.org/en-US/docs/Web/HTML/Link_types/preload
3747 * @link https://web.dev/preload-responsive-images/
3748 *
3749 * @since 6.1.0
3750 */
3751function wp_preload_resources() {
3752 /**
3753 * Filters domains and URLs for resource preloads.
3754 *
3755 * @since 6.1.0
3756 * @since 6.6.0 Added the `$fetchpriority` attribute.
3757 *
3758 * @param array $preload_resources {
3759 * Array of resources and their attributes, or URLs to print for resource preloads.
3760 *
3761 * @type array ...$0 {
3762 * Array of resource attributes.
3763 *
3764 * @type string $href URL to include in resource preloads. Required.
3765 * @type string $as How the browser should treat the resource
3766 * (`script`, `style`, `image`, `document`, etc).
3767 * @type string $crossorigin Indicates the CORS policy of the specified resource.
3768 * @type string $type Type of the resource (`text/html`, `text/css`, etc).
3769 * @type string $media Accepts media types or media queries. Allows responsive preloading.
3770 * @type string $imagesizes Responsive source size to the source Set.
3771 * @type string $imagesrcset Responsive image sources to the source set.
3772 * @type string $fetchpriority Fetchpriority value for the resource.
3773 * }
3774 * }
3775 */
3776 $preload_resources = apply_filters( 'wp_preload_resources', array() );
3777
3778 if ( ! is_array( $preload_resources ) ) {
3779 return;
3780 }
3781
3782 $unique_resources = array();
3783
3784 // Parse the complete resource list and extract unique resources.
3785 foreach ( $preload_resources as $resource ) {
3786 if ( ! is_array( $resource ) ) {
3787 continue;
3788 }
3789
3790 $attributes = $resource;
3791 if ( isset( $resource['href'] ) ) {
3792 $href = $resource['href'];
3793 if ( isset( $unique_resources[ $href ] ) ) {
3794 continue;
3795 }
3796 $unique_resources[ $href ] = $attributes;
3797 // Media can use imagesrcset and not href.
3798 } elseif ( ( 'image' === $resource['as'] ) &&
3799 ( isset( $resource['imagesrcset'] ) || isset( $resource['imagesizes'] ) )
3800 ) {
3801 if ( isset( $unique_resources[ $resource['imagesrcset'] ] ) ) {
3802 continue;
3803 }
3804 $unique_resources[ $resource['imagesrcset'] ] = $attributes;
3805 } else {
3806 continue;
3807 }
3808 }
3809
3810 // Build and output the HTML for each unique resource.
3811 foreach ( $unique_resources as $unique_resource ) {
3812 $html = '';
3813
3814 foreach ( $unique_resource as $resource_key => $resource_value ) {
3815 if ( ! is_scalar( $resource_value ) ) {
3816 continue;
3817 }
3818
3819 // Ignore non-supported attributes.
3820 $non_supported_attributes = array( 'as', 'crossorigin', 'href', 'imagesrcset', 'imagesizes', 'type', 'media', 'fetchpriority' );
3821 if ( ! in_array( $resource_key, $non_supported_attributes, true ) && ! is_numeric( $resource_key ) ) {
3822 continue;
3823 }
3824
3825 // imagesrcset only usable when preloading image, ignore otherwise.
3826 if ( ( 'imagesrcset' === $resource_key ) && ( ! isset( $unique_resource['as'] ) || ( 'image' !== $unique_resource['as'] ) ) ) {
3827 continue;
3828 }
3829
3830 // imagesizes only usable when preloading image and imagesrcset present, ignore otherwise.
3831 if ( ( 'imagesizes' === $resource_key ) &&
3832 ( ! isset( $unique_resource['as'] ) || ( 'image' !== $unique_resource['as'] ) || ! isset( $unique_resource['imagesrcset'] ) )
3833 ) {
3834 continue;
3835 }
3836
3837 $resource_value = ( 'href' === $resource_key ) ? esc_url( $resource_value, array( 'http', 'https' ) ) : esc_attr( $resource_value );
3838
3839 if ( ! is_string( $resource_key ) ) {
3840 $html .= " $resource_value";
3841 } else {
3842 $html .= " $resource_key='$resource_value'";
3843 }
3844 }
3845 $html = trim( $html );
3846
3847 printf( "<link rel='preload' %s />\n", $html );
3848 }
3849}
3850
3851/**
3852 * Retrieves a list of unique hosts of all enqueued scripts and styles.
3853 *
3854 * @since 4.6.0
3855 *
3856 * @global WP_Scripts $wp_scripts The WP_Scripts object for printing scripts.
3857 * @global WP_Styles $wp_styles The WP_Styles object for printing styles.
3858 *
3859 * @return string[] A list of unique hosts of enqueued scripts and styles.
3860 */
3861function wp_dependencies_unique_hosts() {
3862 global $wp_scripts, $wp_styles;
3863
3864 $unique_hosts = array();
3865
3866 foreach ( array( $wp_scripts, $wp_styles ) as $dependencies ) {
3867 if ( $dependencies instanceof WP_Dependencies && ! empty( $dependencies->queue ) ) {
3868 foreach ( $dependencies->queue as $handle ) {
3869 if ( ! isset( $dependencies->registered[ $handle ] ) ) {
3870 continue;
3871 }
3872
3873 /* @var _WP_Dependency $dependency */
3874 $dependency = $dependencies->registered[ $handle ];
3875 $parsed = wp_parse_url( $dependency->src );
3876
3877 if ( ! empty( $parsed['host'] )
3878 && ! in_array( $parsed['host'], $unique_hosts, true ) && $parsed['host'] !== $_SERVER['SERVER_NAME']
3879 ) {
3880 $unique_hosts[] = $parsed['host'];
3881 }
3882 }
3883 }
3884 }
3885
3886 return $unique_hosts;
3887}
3888
3889/**
3890 * Determines whether the user can access the visual editor.
3891 *
3892 * Checks if the user can access the visual editor and that it's supported by the user's browser.
3893 *
3894 * @since 2.0.0
3895 *
3896 * @global bool $wp_rich_edit Whether the user can access the visual editor.
3897 * @global bool $is_gecko Whether the browser is Gecko-based.
3898 * @global bool $is_opera Whether the browser is Opera.
3899 * @global bool $is_safari Whether the browser is Safari.
3900 * @global bool $is_chrome Whether the browser is Chrome.
3901 * @global bool $is_IE Whether the browser is Internet Explorer.
3902 * @global bool $is_edge Whether the browser is Microsoft Edge.
3903 *
3904 * @return bool True if the user can access the visual editor, false otherwise.
3905 */
3906function user_can_richedit() {
3907 global $wp_rich_edit, $is_gecko, $is_opera, $is_safari, $is_chrome, $is_IE, $is_edge;
3908
3909 if ( ! isset( $wp_rich_edit ) ) {
3910 $wp_rich_edit = false;
3911
3912 if ( 'true' === get_user_option( 'rich_editing' ) || ! is_user_logged_in() ) { // Default to 'true' for logged out users.
3913 if ( $is_safari ) {
3914 $wp_rich_edit = ! wp_is_mobile() || ( preg_match( '!AppleWebKit/(\d+)!', $_SERVER['HTTP_USER_AGENT'], $match ) && (int) $match[1] >= 534 );
3915 } elseif ( $is_IE ) {
3916 $wp_rich_edit = str_contains( $_SERVER['HTTP_USER_AGENT'], 'Trident/7.0;' );
3917 } elseif ( $is_gecko || $is_chrome || $is_edge || ( $is_opera && ! wp_is_mobile() ) ) {
3918 $wp_rich_edit = true;
3919 }
3920 }
3921 }
3922
3923 /**
3924 * Filters whether the user can access the visual editor.
3925 *
3926 * @since 2.1.0
3927 *
3928 * @param bool $wp_rich_edit Whether the user can access the visual editor.
3929 */
3930 return apply_filters( 'user_can_richedit', $wp_rich_edit );
3931}
3932
3933/**
3934 * Finds out which editor should be displayed by default.
3935 *
3936 * Works out which of the editors to display as the current editor for a
3937 * user. The 'html' setting is for the "Code" editor tab.
3938 *
3939 * @since 2.5.0
3940 *
3941 * @return string Either 'tinymce', 'html', or 'test'
3942 */
3943function wp_default_editor() {
3944 $r = user_can_richedit() ? 'tinymce' : 'html'; // Defaults.
3945 if ( wp_get_current_user() ) { // Look for cookie.
3946 $ed = get_user_setting( 'editor', 'tinymce' );
3947 $r = ( in_array( $ed, array( 'tinymce', 'html', 'test' ), true ) ) ? $ed : $r;
3948 }
3949
3950 /**
3951 * Filters which editor should be displayed by default.
3952 *
3953 * @since 2.5.0
3954 *
3955 * @param string $r Which editor should be displayed by default. Either 'tinymce', 'html', or 'test'.
3956 */
3957 return apply_filters( 'wp_default_editor', $r );
3958}
3959
3960/**
3961 * Renders an editor.
3962 *
3963 * Using this function is the proper way to output all needed components for both TinyMCE and Quicktags.
3964 * _WP_Editors should not be used directly. See https://core.trac.wordpress.org/ticket/17144.
3965 *
3966 * NOTE: Once initialized the TinyMCE editor cannot be safely moved in the DOM. For that reason
3967 * running wp_editor() inside of a meta box is not a good idea unless only Quicktags is used.
3968 * On the post edit screen several actions can be used to include additional editors
3969 * containing TinyMCE: 'edit_page_form', 'edit_form_advanced' and 'dbx_post_sidebar'.
3970 * See https://core.trac.wordpress.org/ticket/19173 for more information.
3971 *
3972 * @see _WP_Editors::editor()
3973 * @see _WP_Editors::parse_settings()
3974 * @since 3.3.0
3975 *
3976 * @param string $content Initial content for the editor.
3977 * @param string $editor_id HTML ID attribute value for the textarea and TinyMCE.
3978 * Should not contain square brackets.
3979 * @param array $settings See _WP_Editors::parse_settings() for description.
3980 */
3981function wp_editor( $content, $editor_id, $settings = array() ) {
3982 if ( ! class_exists( '_WP_Editors', false ) ) {
3983 require ABSPATH . WPINC . '/class-wp-editor.php';
3984 }
3985 _WP_Editors::editor( $content, $editor_id, $settings );
3986}
3987
3988/**
3989 * Outputs the editor scripts, stylesheets, and default settings.
3990 *
3991 * The editor can be initialized when needed after page load.
3992 * See wp.editor.initialize() in wp-admin/js/editor.js for initialization options.
3993 *
3994 * @uses _WP_Editors
3995 * @since 4.8.0
3996 */
3997function wp_enqueue_editor() {
3998 if ( ! class_exists( '_WP_Editors', false ) ) {
3999 require ABSPATH . WPINC . '/class-wp-editor.php';
4000 }
4001
4002 _WP_Editors::enqueue_default_editor();
4003}
4004
4005/**
4006 * Enqueues assets needed by the code editor for the given settings.
4007 *
4008 * @since 4.9.0
4009 *
4010 * @see wp_enqueue_editor()
4011 * @see wp_get_code_editor_settings();
4012 * @see _WP_Editors::parse_settings()
4013 *
4014 * @param array $args {
4015 * Args.
4016 *
4017 * @type string $type The MIME type of the file to be edited.
4018 * @type string $file Filename to be edited. Extension is used to sniff the type. Can be supplied as alternative to `$type` param.
4019 * @type WP_Theme $theme Theme being edited when on the theme file editor.
4020 * @type string $plugin Plugin being edited when on the plugin file editor.
4021 * @type array $codemirror Additional CodeMirror setting overrides.
4022 * @type array $csslint CSSLint rule overrides.
4023 * @type array $jshint JSHint rule overrides.
4024 * @type array $htmlhint HTMLHint rule overrides.
4025 * }
4026 * @return array|false Settings for the enqueued code editor, or false if the editor was not enqueued.
4027 */
4028function wp_enqueue_code_editor( $args ) {
4029 if ( is_user_logged_in() && 'false' === wp_get_current_user()->syntax_highlighting ) {
4030 return false;
4031 }
4032
4033 $settings = wp_get_code_editor_settings( $args );
4034
4035 if ( empty( $settings ) || empty( $settings['codemirror'] ) ) {
4036 return false;
4037 }
4038
4039 wp_enqueue_script( 'code-editor' );
4040 wp_enqueue_style( 'code-editor' );
4041
4042 if ( isset( $settings['codemirror']['mode'] ) ) {
4043 $mode = $settings['codemirror']['mode'];
4044 if ( is_string( $mode ) ) {
4045 $mode = array(
4046 'name' => $mode,
4047 );
4048 }
4049
4050 if ( ! empty( $settings['codemirror']['lint'] ) ) {
4051 switch ( $mode['name'] ) {
4052 case 'css':
4053 case 'text/css':
4054 case 'text/x-scss':
4055 case 'text/x-less':
4056 wp_enqueue_script( 'csslint' );
4057 break;
4058 case 'htmlmixed':
4059 case 'text/html':
4060 case 'php':
4061 case 'application/x-httpd-php':
4062 case 'text/x-php':
4063 wp_enqueue_script( 'htmlhint' );
4064 wp_enqueue_script( 'csslint' );
4065 wp_enqueue_script( 'jshint' );
4066 if ( ! current_user_can( 'unfiltered_html' ) ) {
4067 wp_enqueue_script( 'htmlhint-kses' );
4068 }
4069 break;
4070 case 'javascript':
4071 case 'application/ecmascript':
4072 case 'application/json':
4073 case 'application/javascript':
4074 case 'application/ld+json':
4075 case 'text/typescript':
4076 case 'application/typescript':
4077 wp_enqueue_script( 'jshint' );
4078 wp_enqueue_script( 'jsonlint' );
4079 break;
4080 }
4081 }
4082 }
4083
4084 wp_add_inline_script( 'code-editor', sprintf( 'jQuery.extend( wp.codeEditor.defaultSettings, %s );', wp_json_encode( $settings, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ) ) );
4085
4086 /**
4087 * Fires when scripts and styles are enqueued for the code editor.
4088 *
4089 * @since 4.9.0
4090 *
4091 * @param array $settings Settings for the enqueued code editor.
4092 */
4093 do_action( 'wp_enqueue_code_editor', $settings );
4094
4095 return $settings;
4096}
4097
4098/**
4099 * Generates and returns code editor settings.
4100 *
4101 * @since 5.0.0
4102 *
4103 * @see wp_enqueue_code_editor()
4104 *
4105 * @param array $args {
4106 * Args.
4107 *
4108 * @type string $type The MIME type of the file to be edited.
4109 * @type string $file Filename to be edited. Extension is used to sniff the type. Can be supplied as alternative to `$type` param.
4110 * @type WP_Theme $theme Theme being edited when on the theme file editor.
4111 * @type string $plugin Plugin being edited when on the plugin file editor.
4112 * @type array $codemirror Additional CodeMirror setting overrides.
4113 * @type array $csslint CSSLint rule overrides.
4114 * @type array $jshint JSHint rule overrides.
4115 * @type array $htmlhint HTMLHint rule overrides.
4116 * }
4117 * @return array|false Settings for the code editor.
4118 */
4119function wp_get_code_editor_settings( $args ) {
4120 $settings = array(
4121 'codemirror' => array(
4122 'indentUnit' => 4,
4123 'indentWithTabs' => true,
4124 'inputStyle' => 'contenteditable',
4125 'lineNumbers' => true,
4126 'lineWrapping' => true,
4127 'styleActiveLine' => true,
4128 'continueComments' => true,
4129 'extraKeys' => array(
4130 'Ctrl-Space' => 'autocomplete',
4131 'Ctrl-/' => 'toggleComment',
4132 'Cmd-/' => 'toggleComment',
4133 'Alt-F' => 'findPersistent',
4134 'Ctrl-F' => 'findPersistent',
4135 'Cmd-F' => 'findPersistent',
4136 ),
4137 'direction' => 'ltr', // Code is shown in LTR even in RTL languages.
4138 'gutters' => array(),
4139 ),
4140 'csslint' => array(
4141 'errors' => true, // Parsing errors.
4142 'box-model' => true,
4143 'display-property-grouping' => true,
4144 'duplicate-properties' => true,
4145 'known-properties' => true,
4146 'outline-none' => true,
4147 ),
4148 'jshint' => array(
4149 // The following are copied from <https://github.com/WordPress/wordpress-develop/blob/4.8.1/.jshintrc>.
4150 'boss' => true,
4151 'curly' => true,
4152 'eqeqeq' => true,
4153 'eqnull' => true,
4154 'es3' => true,
4155 'expr' => true,
4156 'immed' => true,
4157 'noarg' => true,
4158 'nonbsp' => true,
4159 'onevar' => true,
4160 'quotmark' => 'single',
4161 'trailing' => true,
4162 'undef' => true,
4163 'unused' => true,
4164
4165 'browser' => true,
4166
4167 'globals' => array(
4168 '_' => false,
4169 'Backbone' => false,
4170 'jQuery' => false,
4171 'JSON' => false,
4172 'wp' => false,
4173 ),
4174 ),
4175 'htmlhint' => array(
4176 'tagname-lowercase' => true,
4177 'attr-lowercase' => true,
4178 'attr-value-double-quotes' => false,
4179 'doctype-first' => false,
4180 'tag-pair' => true,
4181 'spec-char-escape' => true,
4182 'id-unique' => true,
4183 'src-not-empty' => true,
4184 'attr-no-duplication' => true,
4185 'alt-require' => true,
4186 'space-tab-mixed-disabled' => 'tab',
4187 'attr-unsafe-chars' => true,
4188 ),
4189 );
4190
4191 $type = '';
4192 if ( isset( $args['type'] ) ) {
4193 $type = $args['type'];
4194
4195 // Remap MIME types to ones that CodeMirror modes will recognize.
4196 if ( 'application/x-patch' === $type || 'text/x-patch' === $type ) {
4197 $type = 'text/x-diff';
4198 }
4199 } elseif ( isset( $args['file'] ) && str_contains( basename( $args['file'] ), '.' ) ) {
4200 $extension = strtolower( pathinfo( $args['file'], PATHINFO_EXTENSION ) );
4201 foreach ( wp_get_mime_types() as $exts => $mime ) {
4202 if ( preg_match( '!^(' . $exts . ')$!i', $extension ) ) {
4203 $type = $mime;
4204 break;
4205 }
4206 }
4207
4208 // Supply any types that are not matched by wp_get_mime_types().
4209 if ( empty( $type ) ) {
4210 switch ( $extension ) {
4211 case 'conf':
4212 $type = 'text/nginx';
4213 break;
4214 case 'css':
4215 $type = 'text/css';
4216 break;
4217 case 'diff':
4218 case 'patch':
4219 $type = 'text/x-diff';
4220 break;
4221 case 'html':
4222 case 'htm':
4223 $type = 'text/html';
4224 break;
4225 case 'http':
4226 $type = 'message/http';
4227 break;
4228 case 'js':
4229 $type = 'text/javascript';
4230 break;
4231 case 'json':
4232 $type = 'application/json';
4233 break;
4234 case 'jsx':
4235 $type = 'text/jsx';
4236 break;
4237 case 'less':
4238 $type = 'text/x-less';
4239 break;
4240 case 'md':
4241 $type = 'text/x-gfm';
4242 break;
4243 case 'php':
4244 case 'phtml':
4245 case 'php3':
4246 case 'php4':
4247 case 'php5':
4248 case 'php7':
4249 case 'phps':
4250 $type = 'application/x-httpd-php';
4251 break;
4252 case 'scss':
4253 $type = 'text/x-scss';
4254 break;
4255 case 'sass':
4256 $type = 'text/x-sass';
4257 break;
4258 case 'sh':
4259 case 'bash':
4260 $type = 'text/x-sh';
4261 break;
4262 case 'sql':
4263 $type = 'text/x-sql';
4264 break;
4265 case 'svg':
4266 $type = 'application/svg+xml';
4267 break;
4268 case 'xml':
4269 $type = 'text/xml';
4270 break;
4271 case 'yml':
4272 case 'yaml':
4273 $type = 'text/x-yaml';
4274 break;
4275 case 'txt':
4276 default:
4277 $type = 'text/plain';
4278 break;
4279 }
4280 }
4281 }
4282
4283 if ( in_array( $type, array( 'text/css', 'text/x-scss', 'text/x-less', 'text/x-sass' ), true ) ) {
4284 $settings['codemirror'] = array_merge(
4285 $settings['codemirror'],
4286 array(
4287 'mode' => $type,
4288 'lint' => false,
4289 'autoCloseBrackets' => true,
4290 'matchBrackets' => true,
4291 )
4292 );
4293 } elseif ( 'text/x-diff' === $type ) {
4294 $settings['codemirror'] = array_merge(
4295 $settings['codemirror'],
4296 array(
4297 'mode' => 'diff',
4298 )
4299 );
4300 } elseif ( 'text/html' === $type ) {
4301 $settings['codemirror'] = array_merge(
4302 $settings['codemirror'],
4303 array(
4304 'mode' => 'htmlmixed',
4305 'lint' => true,
4306 'autoCloseBrackets' => true,
4307 'autoCloseTags' => true,
4308 'matchTags' => array(
4309 'bothTags' => true,
4310 ),
4311 )
4312 );
4313
4314 if ( ! current_user_can( 'unfiltered_html' ) ) {
4315 $settings['htmlhint']['kses'] = wp_kses_allowed_html( 'post' );
4316 }
4317 } elseif ( 'text/x-gfm' === $type ) {
4318 $settings['codemirror'] = array_merge(
4319 $settings['codemirror'],
4320 array(
4321 'mode' => 'gfm',
4322 'highlightFormatting' => true,
4323 )
4324 );
4325 } elseif ( 'application/javascript' === $type || 'text/javascript' === $type ) {
4326 $settings['codemirror'] = array_merge(
4327 $settings['codemirror'],
4328 array(
4329 'mode' => 'javascript',
4330 'lint' => true,
4331 'autoCloseBrackets' => true,
4332 'matchBrackets' => true,
4333 )
4334 );
4335 } elseif ( str_contains( $type, 'json' ) ) {
4336 $settings['codemirror'] = array_merge(
4337 $settings['codemirror'],
4338 array(
4339 'mode' => array(
4340 'name' => 'javascript',
4341 ),
4342 'lint' => true,
4343 'autoCloseBrackets' => true,
4344 'matchBrackets' => true,
4345 )
4346 );
4347 if ( 'application/ld+json' === $type ) {
4348 $settings['codemirror']['mode']['jsonld'] = true;
4349 } else {
4350 $settings['codemirror']['mode']['json'] = true;
4351 }
4352 } elseif ( str_contains( $type, 'jsx' ) ) {
4353 $settings['codemirror'] = array_merge(
4354 $settings['codemirror'],
4355 array(
4356 'mode' => 'jsx',
4357 'autoCloseBrackets' => true,
4358 'matchBrackets' => true,
4359 )
4360 );
4361 } elseif ( 'text/x-markdown' === $type ) {
4362 $settings['codemirror'] = array_merge(
4363 $settings['codemirror'],
4364 array(
4365 'mode' => 'markdown',
4366 'highlightFormatting' => true,
4367 )
4368 );
4369 } elseif ( 'text/nginx' === $type ) {
4370 $settings['codemirror'] = array_merge(
4371 $settings['codemirror'],
4372 array(
4373 'mode' => 'nginx',
4374 )
4375 );
4376 } elseif ( 'application/x-httpd-php' === $type ) {
4377 $settings['codemirror'] = array_merge(
4378 $settings['codemirror'],
4379 array(
4380 'mode' => 'php',
4381 'autoCloseBrackets' => true,
4382 'autoCloseTags' => true,
4383 'matchBrackets' => true,
4384 'matchTags' => array(
4385 'bothTags' => true,
4386 ),
4387 )
4388 );
4389 } elseif ( 'text/x-sql' === $type || 'text/x-mysql' === $type ) {
4390 $settings['codemirror'] = array_merge(
4391 $settings['codemirror'],
4392 array(
4393 'mode' => 'sql',
4394 'autoCloseBrackets' => true,
4395 'matchBrackets' => true,
4396 )
4397 );
4398 } elseif ( str_contains( $type, 'xml' ) ) {
4399 $settings['codemirror'] = array_merge(
4400 $settings['codemirror'],
4401 array(
4402 'mode' => 'xml',
4403 'autoCloseBrackets' => true,
4404 'autoCloseTags' => true,
4405 'matchTags' => array(
4406 'bothTags' => true,
4407 ),
4408 )
4409 );
4410 } elseif ( 'text/x-yaml' === $type ) {
4411 $settings['codemirror'] = array_merge(
4412 $settings['codemirror'],
4413 array(
4414 'mode' => 'yaml',
4415 )
4416 );
4417 } else {
4418 $settings['codemirror']['mode'] = $type;
4419 }
4420
4421 if ( ! empty( $settings['codemirror']['lint'] ) ) {
4422 $settings['codemirror']['gutters'][] = 'CodeMirror-lint-markers';
4423 }
4424
4425 // Let settings supplied via args override any defaults.
4426 foreach ( wp_array_slice_assoc( $args, array( 'codemirror', 'csslint', 'jshint', 'htmlhint' ) ) as $key => $value ) {
4427 $settings[ $key ] = array_merge(
4428 $settings[ $key ],
4429 $value
4430 );
4431 }
4432
4433 /**
4434 * Filters settings that are passed into the code editor.
4435 *
4436 * Returning a falsey value will disable the syntax-highlighting code editor.
4437 *
4438 * @since 4.9.0
4439 *
4440 * @param array $settings The array of settings passed to the code editor.
4441 * A falsey value disables the editor.
4442 * @param array $args {
4443 * Args passed when calling `get_code_editor_settings()`.
4444 *
4445 * @type string $type The MIME type of the file to be edited.
4446 * @type string $file Filename being edited.
4447 * @type WP_Theme $theme Theme being edited when on the theme file editor.
4448 * @type string $plugin Plugin being edited when on the plugin file editor.
4449 * @type array $codemirror Additional CodeMirror setting overrides.
4450 * @type array $csslint CSSLint rule overrides.
4451 * @type array $jshint JSHint rule overrides.
4452 * @type array $htmlhint HTMLHint rule overrides.
4453 * }
4454 */
4455 return apply_filters( 'wp_code_editor_settings', $settings, $args );
4456}
4457
4458/**
4459 * Retrieves the contents of the search WordPress query variable.
4460 *
4461 * The search query string is passed through esc_attr() to ensure that it is safe
4462 * for placing in an HTML attribute.
4463 *
4464 * @since 2.3.0
4465 *
4466 * @param bool $escaped Whether the result is escaped. Default true.
4467 * Only use when you are later escaping it. Do not use unescaped.
4468 * @return string
4469 */
4470function get_search_query( $escaped = true ) {
4471 /**
4472 * Filters the contents of the search query variable.
4473 *
4474 * @since 2.3.0
4475 *
4476 * @param mixed $search Contents of the search query variable.
4477 */
4478 $query = apply_filters( 'get_search_query', get_query_var( 's' ) );
4479
4480 if ( $escaped ) {
4481 $query = esc_attr( $query );
4482 }
4483 return $query;
4484}
4485
4486/**
4487 * Displays the contents of the search query variable.
4488 *
4489 * The search query string is passed through esc_attr() to ensure that it is safe
4490 * for placing in an HTML attribute.
4491 *
4492 * @since 2.1.0
4493 */
4494function the_search_query() {
4495 /**
4496 * Filters the contents of the search query variable, for display.
4497 *
4498 * @since 2.3.0
4499 *
4500 * @param mixed $search Contents of the search query variable.
4501 */
4502 echo esc_attr( apply_filters( 'the_search_query', get_search_query( false ) ) );
4503}
4504
4505/**
4506 * Gets the language attributes for the 'html' tag.
4507 *
4508 * Builds up a set of HTML attributes containing the text direction and language
4509 * information for the page.
4510 *
4511 * @since 4.3.0
4512 *
4513 * @param string $doctype Optional. The type of HTML document. Accepts 'xhtml' or 'html'. Default 'html'.
4514 * @return string A space-separated list of language attributes.
4515 */
4516function get_language_attributes( $doctype = 'html' ) {
4517 $attributes = array();
4518
4519 if ( function_exists( 'is_rtl' ) && is_rtl() ) {
4520 $attributes[] = 'dir="rtl"';
4521 }
4522
4523 $lang = get_bloginfo( 'language' );
4524 if ( $lang ) {
4525 if ( 'text/html' === get_option( 'html_type' ) || 'html' === $doctype ) {
4526 $attributes[] = 'lang="' . esc_attr( $lang ) . '"';
4527 }
4528
4529 if ( 'text/html' !== get_option( 'html_type' ) || 'xhtml' === $doctype ) {
4530 $attributes[] = 'xml:lang="' . esc_attr( $lang ) . '"';
4531 }
4532 }
4533
4534 $output = implode( ' ', $attributes );
4535
4536 /**
4537 * Filters the language attributes for display in the 'html' tag.
4538 *
4539 * @since 2.5.0
4540 * @since 4.3.0 Added the `$doctype` parameter.
4541 *
4542 * @param string $output A space-separated list of language attributes.
4543 * @param string $doctype The type of HTML document (xhtml|html).
4544 */
4545 return apply_filters( 'language_attributes', $output, $doctype );
4546}
4547
4548/**
4549 * Displays the language attributes for the 'html' tag.
4550 *
4551 * Builds up a set of HTML attributes containing the text direction and language
4552 * information for the page.
4553 *
4554 * @since 2.1.0
4555 * @since 4.3.0 Converted into a wrapper for get_language_attributes().
4556 *
4557 * @param string $doctype Optional. The type of HTML document. Accepts 'xhtml' or 'html'. Default 'html'.
4558 */
4559function language_attributes( $doctype = 'html' ) {
4560 echo get_language_attributes( $doctype );
4561}
4562
4563/**
4564 * Retrieves paginated links for archive post pages.
4565 *
4566 * Technically, the function can be used to create paginated link list for any
4567 * area. The 'base' argument is used to reference the url, which will be used to
4568 * create the paginated links. The 'format' argument is then used for replacing
4569 * the page number. It is however, most likely and by default, to be used on the
4570 * archive post pages.
4571 *
4572 * The 'type' argument controls format of the returned value. The default is
4573 * 'plain', which is just a string with the links separated by a newline
4574 * character. The other possible values are either 'array' or 'list'. The
4575 * 'array' value will return an array of the paginated link list to offer full
4576 * control of display. The 'list' value will place all of the paginated links in
4577 * an unordered HTML list.
4578 *
4579 * The 'total' argument is the total amount of pages and is an integer. The
4580 * 'current' argument is the current page number and is also an integer.
4581 *
4582 * An example of the 'base' argument is "http://example.com/all_posts.php%_%"
4583 * and the '%_%' is required. The '%_%' will be replaced by the contents of in
4584 * the 'format' argument. An example for the 'format' argument is "?page=%#%"
4585 * and the '%#%' is also required. The '%#%' will be replaced with the page
4586 * number.
4587 *
4588 * You can include the previous and next links in the list by setting the
4589 * 'prev_next' argument to true, which it is by default. You can set the
4590 * previous text, by using the 'prev_text' argument. You can set the next text
4591 * by setting the 'next_text' argument.
4592 *
4593 * If the 'show_all' argument is set to true, then it will show all of the pages
4594 * instead of a short list of the pages near the current page. By default, the
4595 * 'show_all' is set to false and controlled by the 'end_size' and 'mid_size'
4596 * arguments. The 'end_size' argument is how many numbers on either the start
4597 * and the end list edges, by default is 1. The 'mid_size' argument is how many
4598 * numbers to either side of current page, but not including current page.
4599 *
4600 * It is possible to add query vars to the link by using the 'add_args' argument
4601 * and see add_query_arg() for more information.
4602 *
4603 * The 'before_page_number' and 'after_page_number' arguments allow users to
4604 * augment the links themselves. Typically this might be to add context to the
4605 * numbered links so that screen reader users understand what the links are for.
4606 * The text strings are added before and after the page number - within the
4607 * anchor tag.
4608 *
4609 * @since 2.1.0
4610 * @since 4.9.0 Added the `aria_current` argument.
4611 *
4612 * @global WP_Query $wp_query WordPress Query object.
4613 * @global WP_Rewrite $wp_rewrite WordPress rewrite component.
4614 *
4615 * @param string|array $args {
4616 * Optional. Array or string of arguments for generating paginated links for archives.
4617 *
4618 * @type string $base Base of the paginated url. Default empty.
4619 * @type string $format Format for the pagination structure. Default empty.
4620 * @type int $total The total amount of pages. Default is the value WP_Query's
4621 * `max_num_pages` or 1.
4622 * @type int $current The current page number. Default is 'paged' query var or 1.
4623 * @type string $aria_current The value for the aria-current attribute. Possible values are 'page',
4624 * 'step', 'location', 'date', 'time', 'true', 'false'. Default is 'page'.
4625 * @type bool $show_all Whether to show all pages. Default false.
4626 * @type int $end_size How many numbers on either the start and the end list edges.
4627 * Default 1.
4628 * @type int $mid_size How many numbers to either side of the current pages. Default 2.
4629 * @type bool $prev_next Whether to include the previous and next links in the list. Default true.
4630 * @type string $prev_text The previous page text. Default '&laquo; Previous'.
4631 * @type string $next_text The next page text. Default 'Next &raquo;'.
4632 * @type string $type Controls format of the returned value. Possible values are 'plain',
4633 * 'array' and 'list'. Default is 'plain'.
4634 * @type array $add_args An array of query args to add. Default false.
4635 * @type string $add_fragment A string to append to each link. Default empty.
4636 * @type string $before_page_number A string to appear before the page number. Default empty.
4637 * @type string $after_page_number A string to append after the page number. Default empty.
4638 * }
4639 * @return string|string[]|void String of page links or array of page links, depending on 'type' argument.
4640 * Void if total number of pages is less than 2.
4641 */
4642function paginate_links( $args = '' ) {
4643 global $wp_query, $wp_rewrite;
4644
4645 // Setting up default values based on the current URL.
4646 $pagenum_link = html_entity_decode( get_pagenum_link() );
4647 $url_parts = explode( '?', $pagenum_link );
4648
4649 // Get max pages and current page out of the current query, if available.
4650 $total = isset( $wp_query->max_num_pages ) ? $wp_query->max_num_pages : 1;
4651 $current = get_query_var( 'paged' ) ? (int) get_query_var( 'paged' ) : 1;
4652
4653 // Append the format placeholder to the base URL.
4654 $pagenum_link = trailingslashit( $url_parts[0] ) . '%_%';
4655
4656 // URL base depends on permalink settings.
4657 $format = $wp_rewrite->using_index_permalinks() && ! strpos( $pagenum_link, 'index.php' ) ? 'index.php/' : '';
4658 $format .= $wp_rewrite->using_permalinks() ? user_trailingslashit( $wp_rewrite->pagination_base . '/%#%', 'paged' ) : '?paged=%#%';
4659
4660 $defaults = array(
4661 'base' => $pagenum_link, // http://example.com/all_posts.php%_% : %_% is replaced by format (below).
4662 'format' => $format, // ?page=%#% : %#% is replaced by the page number.
4663 'total' => $total,
4664 'current' => $current,
4665 'aria_current' => 'page',
4666 'show_all' => false,
4667 'prev_next' => true,
4668 'prev_text' => __( '&laquo; Previous' ),
4669 'next_text' => __( 'Next &raquo;' ),
4670 'end_size' => 1,
4671 'mid_size' => 2,
4672 'type' => 'plain',
4673 'add_args' => array(), // Array of query args to add.
4674 'add_fragment' => '',
4675 'before_page_number' => '',
4676 'after_page_number' => '',
4677 );
4678
4679 $args = wp_parse_args( $args, $defaults );
4680
4681 if ( ! is_array( $args['add_args'] ) ) {
4682 $args['add_args'] = array();
4683 }
4684
4685 // Merge additional query vars found in the original URL into 'add_args' array.
4686 if ( isset( $url_parts[1] ) ) {
4687 // Find the format argument.
4688 $format = explode( '?', str_replace( '%_%', $args['format'], $args['base'] ) );
4689 $format_query = isset( $format[1] ) ? $format[1] : '';
4690 wp_parse_str( $format_query, $format_args );
4691
4692 // Find the query args of the requested URL.
4693 wp_parse_str( $url_parts[1], $url_query_args );
4694
4695 // Remove the format argument from the array of query arguments, to avoid overwriting custom format.
4696 foreach ( $format_args as $format_arg => $format_arg_value ) {
4697 unset( $url_query_args[ $format_arg ] );
4698 }
4699
4700 $args['add_args'] = array_merge( $args['add_args'], urlencode_deep( $url_query_args ) );
4701 }
4702
4703 // Who knows what else people pass in $args.
4704 $total = (int) $args['total'];
4705 if ( $total < 2 ) {
4706 return;
4707 }
4708 $current = (int) $args['current'];
4709 $end_size = (int) $args['end_size']; // Out of bounds? Make it the default.
4710 if ( $end_size < 1 ) {
4711 $end_size = 1;
4712 }
4713 $mid_size = (int) $args['mid_size'];
4714 if ( $mid_size < 0 ) {
4715 $mid_size = 2;
4716 }
4717
4718 $add_args = $args['add_args'];
4719 $r = '';
4720 $page_links = array();
4721 $dots = false;
4722
4723 if ( $args['prev_next'] && $current && 1 < $current ) :
4724 $link = str_replace( '%_%', 2 === $current ? '' : $args['format'], $args['base'] );
4725 $link = str_replace( '%#%', $current - 1, $link );
4726 if ( $add_args ) {
4727 $link = add_query_arg( $add_args, $link );
4728 }
4729 $link .= $args['add_fragment'];
4730
4731 $page_links[] = sprintf(
4732 '<a class="prev page-numbers" href="%s">%s</a>',
4733 /**
4734 * Filters the paginated links for the given archive pages.
4735 *
4736 * @since 3.0.0
4737 *
4738 * @param string $link The paginated link URL.
4739 */
4740 esc_url( apply_filters( 'paginate_links', $link ) ),
4741 $args['prev_text']
4742 );
4743 endif;
4744
4745 for ( $n = 1; $n <= $total; $n++ ) :
4746 if ( $n === $current ) :
4747 $page_links[] = sprintf(
4748 '<span aria-current="%s" class="page-numbers current">%s</span>',
4749 esc_attr( $args['aria_current'] ),
4750 $args['before_page_number'] . number_format_i18n( $n ) . $args['after_page_number']
4751 );
4752
4753 $dots = true;
4754 else :
4755 if ( $args['show_all'] || ( $n <= $end_size || ( $current && $n >= $current - $mid_size && $n <= $current + $mid_size ) || $n > $total - $end_size ) ) :
4756 $link = str_replace( '%_%', 1 === $n ? '' : $args['format'], $args['base'] );
4757 $link = str_replace( '%#%', $n, $link );
4758 if ( $add_args ) {
4759 $link = add_query_arg( $add_args, $link );
4760 }
4761 $link .= $args['add_fragment'];
4762
4763 $page_links[] = sprintf(
4764 '<a class="page-numbers" href="%s">%s</a>',
4765 /** This filter is documented in wp-includes/general-template.php */
4766 esc_url( apply_filters( 'paginate_links', $link ) ),
4767 $args['before_page_number'] . number_format_i18n( $n ) . $args['after_page_number']
4768 );
4769
4770 $dots = true;
4771 elseif ( $dots && ! $args['show_all'] ) :
4772 $page_links[] = '<span class="page-numbers dots">' . __( '&hellip;' ) . '</span>';
4773
4774 $dots = false;
4775 endif;
4776 endif;
4777 endfor;
4778
4779 if ( $args['prev_next'] && $current && $current < $total ) :
4780 $link = str_replace( '%_%', $args['format'], $args['base'] );
4781 $link = str_replace( '%#%', $current + 1, $link );
4782 if ( $add_args ) {
4783 $link = add_query_arg( $add_args, $link );
4784 }
4785 $link .= $args['add_fragment'];
4786
4787 $page_links[] = sprintf(
4788 '<a class="next page-numbers" href="%s">%s</a>',
4789 /** This filter is documented in wp-includes/general-template.php */
4790 esc_url( apply_filters( 'paginate_links', $link ) ),
4791 $args['next_text']
4792 );
4793 endif;
4794
4795 switch ( $args['type'] ) {
4796 case 'array':
4797 return $page_links;
4798
4799 case 'list':
4800 $r .= "<ul class='page-numbers'>\n\t<li>";
4801 $r .= implode( "</li>\n\t<li>", $page_links );
4802 $r .= "</li>\n</ul>\n";
4803 break;
4804
4805 default:
4806 $r = implode( "\n", $page_links );
4807 break;
4808 }
4809
4810 /**
4811 * Filters the HTML output of paginated links for archives.
4812 *
4813 * @since 5.7.0
4814 *
4815 * @param string $r HTML output.
4816 * @param array $args An array of arguments. See paginate_links()
4817 * for information on accepted arguments.
4818 */
4819 $r = apply_filters( 'paginate_links_output', $r, $args );
4820
4821 return $r;
4822}
4823
4824/**
4825 * Registers an admin color scheme css file.
4826 *
4827 * Allows a plugin to register a new admin color scheme. For example:
4828 *
4829 * wp_admin_css_color( 'classic', __( 'Classic' ), admin_url( "css/colors-classic.css" ), array(
4830 * '#07273E', '#14568A', '#D54E21', '#2683AE'
4831 * ) );
4832 *
4833 * @since 2.5.0
4834 *
4835 * @global array $_wp_admin_css_colors
4836 *
4837 * @param string $key The unique key for this theme.
4838 * @param string $name The name of the theme.
4839 * @param string $url The URL of the CSS file containing the color scheme.
4840 * @param array $colors Optional. An array of CSS color definition strings which are used
4841 * to give the user a feel for the theme.
4842 * @param array $icons {
4843 * Optional. CSS color definitions used to color any SVG icons.
4844 *
4845 * @type string $base SVG icon base color.
4846 * @type string $focus SVG icon color on focus.
4847 * @type string $current SVG icon color of current admin menu link.
4848 * }
4849 */
4850function wp_admin_css_color( $key, $name, $url, $colors = array(), $icons = array() ) {
4851 global $_wp_admin_css_colors;
4852
4853 if ( ! isset( $_wp_admin_css_colors ) ) {
4854 $_wp_admin_css_colors = array();
4855 }
4856
4857 $_wp_admin_css_colors[ $key ] = (object) array(
4858 'name' => $name,
4859 'url' => $url,
4860 'colors' => $colors,
4861 'icon_colors' => $icons,
4862 );
4863}
4864
4865/**
4866 * Registers the default admin color schemes.
4867 *
4868 * Registers the initial set of eight color schemes in the Profile section
4869 * of the dashboard which allows for styling the admin menu and toolbar.
4870 *
4871 * @see wp_admin_css_color()
4872 *
4873 * @since 3.0.0
4874 */
4875function register_admin_color_schemes() {
4876 $suffix = is_rtl() ? '-rtl' : '';
4877 $suffix .= SCRIPT_DEBUG ? '' : '.min';
4878
4879 wp_admin_css_color(
4880 'fresh',
4881 _x( 'Default', 'admin color scheme' ),
4882 false,
4883 array( '#1d2327', '#2c3338', '#2271b1', '#72aee6' ),
4884 array(
4885 'base' => '#a7aaad',
4886 'focus' => '#72aee6',
4887 'current' => '#fff',
4888 )
4889 );
4890
4891 wp_admin_css_color(
4892 'light',
4893 _x( 'Light', 'admin color scheme' ),
4894 admin_url( "css/colors/light/colors$suffix.css" ),
4895 array( '#e5e5e5', '#999', '#d64e07', '#04a4cc' ),
4896 array(
4897 'base' => '#999',
4898 'focus' => '#ccc',
4899 'current' => '#ccc',
4900 )
4901 );
4902
4903 wp_admin_css_color(
4904 'modern',
4905 _x( 'Modern', 'admin color scheme' ),
4906 admin_url( "css/colors/modern/colors$suffix.css" ),
4907 array( '#1e1e1e', '#3858e9', '#7b90ff' ),
4908 array(
4909 'base' => '#f3f1f1',
4910 'focus' => '#fff',
4911 'current' => '#fff',
4912 )
4913 );
4914
4915 wp_admin_css_color(
4916 'blue',
4917 _x( 'Blue', 'admin color scheme' ),
4918 admin_url( "css/colors/blue/colors$suffix.css" ),
4919 array( '#096484', '#4796b3', '#52accc', '#74B6CE' ),
4920 array(
4921 'base' => '#e5f8ff',
4922 'focus' => '#fff',
4923 'current' => '#fff',
4924 )
4925 );
4926
4927 wp_admin_css_color(
4928 'midnight',
4929 _x( 'Midnight', 'admin color scheme' ),
4930 admin_url( "css/colors/midnight/colors$suffix.css" ),
4931 array( '#25282b', '#363b3f', '#69a8bb', '#e14d43' ),
4932 array(
4933 'base' => '#f1f2f3',
4934 'focus' => '#fff',
4935 'current' => '#fff',
4936 )
4937 );
4938
4939 wp_admin_css_color(
4940 'sunrise',
4941 _x( 'Sunrise', 'admin color scheme' ),
4942 admin_url( "css/colors/sunrise/colors$suffix.css" ),
4943 array( '#b43c38', '#cf4944', '#dd823b', '#ccaf0b' ),
4944 array(
4945 'base' => '#f3f1f1',
4946 'focus' => '#fff',
4947 'current' => '#fff',
4948 )
4949 );
4950
4951 wp_admin_css_color(
4952 'ectoplasm',
4953 _x( 'Ectoplasm', 'admin color scheme' ),
4954 admin_url( "css/colors/ectoplasm/colors$suffix.css" ),
4955 array( '#413256', '#523f6d', '#a3b745', '#d46f15' ),
4956 array(
4957 'base' => '#ece6f6',
4958 'focus' => '#fff',
4959 'current' => '#fff',
4960 )
4961 );
4962
4963 wp_admin_css_color(
4964 'ocean',
4965 _x( 'Ocean', 'admin color scheme' ),
4966 admin_url( "css/colors/ocean/colors$suffix.css" ),
4967 array( '#627c83', '#738e96', '#9ebaa0', '#aa9d88' ),
4968 array(
4969 'base' => '#f2fcff',
4970 'focus' => '#fff',
4971 'current' => '#fff',
4972 )
4973 );
4974
4975 wp_admin_css_color(
4976 'coffee',
4977 _x( 'Coffee', 'admin color scheme' ),
4978 admin_url( "css/colors/coffee/colors$suffix.css" ),
4979 array( '#46403c', '#59524c', '#c7a589', '#9ea476' ),
4980 array(
4981 'base' => '#f3f2f1',
4982 'focus' => '#fff',
4983 'current' => '#fff',
4984 )
4985 );
4986}
4987
4988/**
4989 * Displays the URL of a WordPress admin CSS file.
4990 *
4991 * @see WP_Styles::_css_href() and its {@see 'style_loader_src'} filter.
4992 *
4993 * @since 2.3.0
4994 *
4995 * @param string $file file relative to wp-admin/ without its ".css" extension.
4996 * @return string
4997 */
4998function wp_admin_css_uri( $file = 'wp-admin' ) {
4999 if ( defined( 'WP_INSTALLING' ) ) {
5000 $_file = "./$file.css";
5001 } else {
5002 $_file = admin_url( "$file.css" );
5003 }
5004 $_file = add_query_arg( 'version', get_bloginfo( 'version' ), $_file );
5005
5006 /**
5007 * Filters the URI of a WordPress admin CSS file.
5008 *
5009 * @since 2.3.0
5010 *
5011 * @param string $_file Relative path to the file with query arguments attached.
5012 * @param string $file Relative path to the file, minus its ".css" extension.
5013 */
5014 return apply_filters( 'wp_admin_css_uri', $_file, $file );
5015}
5016
5017/**
5018 * Enqueues or directly prints a stylesheet link to the specified CSS file.
5019 *
5020 * "Intelligently" decides to enqueue or to print the CSS file. If the
5021 * {@see 'wp_print_styles'} action has *not* yet been called, the CSS file will be
5022 * enqueued. If the {@see 'wp_print_styles'} action has been called, the CSS link will
5023 * be printed. Printing may be forced by passing true as the $force_echo
5024 * (second) parameter.
5025 *
5026 * For backward compatibility with WordPress 2.3 calling method: If the $file
5027 * (first) parameter does not correspond to a registered CSS file, we assume
5028 * $file is a file relative to wp-admin/ without its ".css" extension. A
5029 * stylesheet link to that generated URL is printed.
5030 *
5031 * @since 2.3.0
5032 *
5033 * @param string $file Optional. Style handle name or file name (without ".css" extension) relative
5034 * to wp-admin/. Defaults to 'wp-admin'.
5035 * @param bool $force_echo Optional. Force the stylesheet link to be printed rather than enqueued.
5036 */
5037function wp_admin_css( $file = 'wp-admin', $force_echo = false ) {
5038 // For backward compatibility.
5039 $handle = str_starts_with( $file, 'css/' ) ? substr( $file, 4 ) : $file;
5040
5041 if ( wp_styles()->query( $handle ) ) {
5042 if ( $force_echo || did_action( 'wp_print_styles' ) ) {
5043 // We already printed the style queue. Print this one immediately.
5044 wp_print_styles( $handle );
5045 } else {
5046 // Add to style queue.
5047 wp_enqueue_style( $handle );
5048 }
5049 return;
5050 }
5051
5052 $stylesheet_link = sprintf(
5053 "<link rel='stylesheet' href='%s' type='text/css' />\n",
5054 esc_url( wp_admin_css_uri( $file ) )
5055 );
5056
5057 /**
5058 * Filters the stylesheet link to the specified CSS file.
5059 *
5060 * If the site is set to display right-to-left, the RTL stylesheet link
5061 * will be used instead.
5062 *
5063 * @since 2.3.0
5064 * @param string $stylesheet_link HTML link element for the stylesheet.
5065 * @param string $file Style handle name or filename (without ".css" extension)
5066 * relative to wp-admin/. Defaults to 'wp-admin'.
5067 */
5068 echo apply_filters( 'wp_admin_css', $stylesheet_link, $file );
5069
5070 if ( function_exists( 'is_rtl' ) && is_rtl() ) {
5071 $rtl_stylesheet_link = sprintf(
5072 "<link rel='stylesheet' href='%s' type='text/css' />\n",
5073 esc_url( wp_admin_css_uri( "$file-rtl" ) )
5074 );
5075
5076 /** This filter is documented in wp-includes/general-template.php */
5077 echo apply_filters( 'wp_admin_css', $rtl_stylesheet_link, "$file-rtl" );
5078 }
5079}
5080
5081/**
5082 * Enqueues the default ThickBox js and css.
5083 *
5084 * If any of the settings need to be changed, this can be done with another js
5085 * file similar to media-upload.js. That file should
5086 * require array('thickbox') to ensure it is loaded after.
5087 *
5088 * @since 2.5.0
5089 */
5090function add_thickbox() {
5091 wp_enqueue_script( 'thickbox' );
5092 wp_enqueue_style( 'thickbox' );
5093
5094 if ( is_network_admin() ) {
5095 add_action( 'admin_head', '_thickbox_path_admin_subfolder' );
5096 }
5097}
5098
5099/**
5100 * Displays the XHTML generator that is generated on the wp_head hook.
5101 *
5102 * See {@see 'wp_head'}.
5103 *
5104 * @since 2.5.0
5105 */
5106function wp_generator() {
5107 /**
5108 * Filters the output of the XHTML generator tag.
5109 *
5110 * @since 2.5.0
5111 *
5112 * @param string $generator_type The XHTML generator.
5113 */
5114 the_generator( apply_filters( 'wp_generator_type', 'xhtml' ) );
5115}
5116
5117/**
5118 * Displays the generator XML or Comment for RSS, ATOM, etc.
5119 *
5120 * Returns the correct generator type for the requested output format. Allows
5121 * for a plugin to filter generators overall the {@see 'the_generator'} filter.
5122 *
5123 * @since 2.5.0
5124 *
5125 * @param string $type The type of generator to output - (html|xhtml|atom|rss2|rdf|comment|export).
5126 */
5127function the_generator( $type ) {
5128 /**
5129 * Filters the output of the XHTML generator tag, for display.
5130 *
5131 * @since 2.5.0
5132 *
5133 * @param string $generator_type The generator output.
5134 * @param string $type The type of generator to output. Accepts 'html',
5135 * 'xhtml', 'atom', 'rss2', 'rdf', 'comment', 'export'.
5136 */
5137 echo apply_filters( 'the_generator', get_the_generator( $type ), $type ) . "\n";
5138}
5139
5140/**
5141 * Creates the generator XML or Comment for RSS, ATOM, etc.
5142 *
5143 * Returns the correct generator type for the requested output format. Allows
5144 * for a plugin to filter generators on an individual basis using the
5145 * {@see 'get_the_generator_$type'} filter.
5146 *
5147 * @since 2.5.0
5148 *
5149 * @param string $type The type of generator to return - (html|xhtml|atom|rss2|rdf|comment|export).
5150 * @return string|void The HTML content for the generator.
5151 */
5152function get_the_generator( $type = '' ) {
5153 if ( empty( $type ) ) {
5154
5155 $current_filter = current_filter();
5156 if ( empty( $current_filter ) ) {
5157 return;
5158 }
5159
5160 switch ( $current_filter ) {
5161 case 'rss2_head':
5162 case 'commentsrss2_head':
5163 $type = 'rss2';
5164 break;
5165 case 'rss_head':
5166 case 'opml_head':
5167 $type = 'comment';
5168 break;
5169 case 'rdf_header':
5170 $type = 'rdf';
5171 break;
5172 case 'atom_head':
5173 case 'comments_atom_head':
5174 case 'app_head':
5175 $type = 'atom';
5176 break;
5177 }
5178 }
5179
5180 switch ( $type ) {
5181 case 'html':
5182 $gen = '<meta name="generator" content="WordPress ' . esc_attr( get_bloginfo( 'version' ) ) . '">';
5183 break;
5184 case 'xhtml':
5185 $gen = '<meta name="generator" content="WordPress ' . esc_attr( get_bloginfo( 'version' ) ) . '" />';
5186 break;
5187 case 'atom':
5188 $gen = '<generator uri="https://wordpress.org/" version="' . esc_attr( get_bloginfo_rss( 'version' ) ) . '">WordPress</generator>';
5189 break;
5190 case 'rss2':
5191 $gen = '<generator>' . sanitize_url( 'https://wordpress.org/?v=' . get_bloginfo_rss( 'version' ) ) . '</generator>';
5192 break;
5193 case 'rdf':
5194 $gen = '<admin:generatorAgent rdf:resource="' . sanitize_url( 'https://wordpress.org/?v=' . get_bloginfo_rss( 'version' ) ) . '" />';
5195 break;
5196 case 'comment':
5197 $gen = '<!-- generator="WordPress/' . esc_attr( get_bloginfo( 'version' ) ) . '" -->';
5198 break;
5199 case 'export':
5200 $gen = '<!-- generator="WordPress/' . esc_attr( get_bloginfo_rss( 'version' ) ) . '" created="' . gmdate( 'Y-m-d H:i' ) . '" -->';
5201 break;
5202 }
5203
5204 /**
5205 * Filters the HTML for the retrieved generator type.
5206 *
5207 * The dynamic portion of the hook name, `$type`, refers to the generator type.
5208 *
5209 * Possible hook names include:
5210 *
5211 * - `get_the_generator_atom`
5212 * - `get_the_generator_comment`
5213 * - `get_the_generator_export`
5214 * - `get_the_generator_html`
5215 * - `get_the_generator_rdf`
5216 * - `get_the_generator_rss2`
5217 * - `get_the_generator_xhtml`
5218 *
5219 * @since 2.5.0
5220 *
5221 * @param string $gen The HTML markup output to wp_head().
5222 * @param string $type The type of generator. Accepts 'html', 'xhtml', 'atom',
5223 * 'rss2', 'rdf', 'comment', 'export'.
5224 */
5225 return apply_filters( "get_the_generator_{$type}", $gen, $type );
5226}
5227
5228/**
5229 * Outputs the HTML checked attribute.
5230 *
5231 * Compares the first two arguments and if identical marks as checked.
5232 *
5233 * @since 1.0.0
5234 *
5235 * @param mixed $checked One of the values to compare.
5236 * @param mixed $current Optional. The other value to compare if not just true.
5237 * Default true.
5238 * @param bool $display Optional. Whether to echo or just return the string.
5239 * Default true.
5240 * @return string HTML attribute or empty string.
5241 */
5242function checked( $checked, $current = true, $display = true ) {
5243 return __checked_selected_helper( $checked, $current, $display, 'checked' );
5244}
5245
5246/**
5247 * Outputs the HTML selected attribute.
5248 *
5249 * Compares the first two arguments and if identical marks as selected.
5250 *
5251 * @since 1.0.0
5252 *
5253 * @param mixed $selected One of the values to compare.
5254 * @param mixed $current Optional. The other value to compare if not just true.
5255 * Default true.
5256 * @param bool $display Optional. Whether to echo or just return the string.
5257 * Default true.
5258 * @return string HTML attribute or empty string.
5259 */
5260function selected( $selected, $current = true, $display = true ) {
5261 return __checked_selected_helper( $selected, $current, $display, 'selected' );
5262}
5263
5264/**
5265 * Outputs the HTML disabled attribute.
5266 *
5267 * Compares the first two arguments and if identical marks as disabled.
5268 *
5269 * @since 3.0.0
5270 *
5271 * @param mixed $disabled One of the values to compare.
5272 * @param mixed $current Optional. The other value to compare if not just true.
5273 * Default true.
5274 * @param bool $display Optional. Whether to echo or just return the string.
5275 * Default true.
5276 * @return string HTML attribute or empty string.
5277 */
5278function disabled( $disabled, $current = true, $display = true ) {
5279 return __checked_selected_helper( $disabled, $current, $display, 'disabled' );
5280}
5281
5282/**
5283 * Outputs the HTML readonly attribute.
5284 *
5285 * Compares the first two arguments and if identical marks as readonly.
5286 *
5287 * @since 5.9.0
5288 *
5289 * @param mixed $readonly_value One of the values to compare.
5290 * @param mixed $current Optional. The other value to compare if not just true.
5291 * Default true.
5292 * @param bool $display Optional. Whether to echo or just return the string.
5293 * Default true.
5294 * @return string HTML attribute or empty string.
5295 */
5296function wp_readonly( $readonly_value, $current = true, $display = true ) {
5297 return __checked_selected_helper( $readonly_value, $current, $display, 'readonly' );
5298}
5299
5300/*
5301 * Include a compat `readonly()` function on PHP < 8.1. Since PHP 8.1,
5302 * `readonly` is a reserved keyword and cannot be used as a function name.
5303 * In order to avoid PHP parser errors, this function was extracted
5304 * to a separate file and is only included conditionally on PHP < 8.1.
5305 */
5306if ( PHP_VERSION_ID < 80100 ) {
5307 require_once __DIR__ . '/php-compat/readonly.php';
5308}
5309
5310/**
5311 * Private helper function for checked, selected, disabled and readonly.
5312 *
5313 * Compares the first two arguments and if identical marks as `$type`.
5314 *
5315 * @since 2.8.0
5316 * @access private
5317 *
5318 * @param mixed $helper One of the values to compare.
5319 * @param mixed $current The other value to compare if not just true.
5320 * @param bool $display Whether to echo or just return the string.
5321 * @param string $type The type of checked|selected|disabled|readonly we are doing.
5322 * @return string HTML attribute or empty string.
5323 */
5324function __checked_selected_helper( $helper, $current, $display, $type ) { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName.FunctionDoubleUnderscore,PHPCompatibility.FunctionNameRestrictions.ReservedFunctionNames.FunctionDoubleUnderscore
5325 if ( (string) $helper === (string) $current ) {
5326 $result = " $type='$type'";
5327 } else {
5328 $result = '';
5329 }
5330
5331 if ( $display ) {
5332 echo $result;
5333 }
5334
5335 return $result;
5336}
5337
5338/**
5339 * Assigns a visual indicator for required form fields.
5340 *
5341 * @since 6.1.0
5342 *
5343 * @return string Indicator glyph wrapped in a `span` tag.
5344 */
5345function wp_required_field_indicator() {
5346 /* translators: Character to identify required form fields. */
5347 $glyph = __( '*' );
5348 $indicator = '<span class="required">' . esc_html( $glyph ) . '</span>';
5349
5350 /**
5351 * Filters the markup for a visual indicator of required form fields.
5352 *
5353 * @since 6.1.0
5354 *
5355 * @param string $indicator Markup for the indicator element.
5356 */
5357 return apply_filters( 'wp_required_field_indicator', $indicator );
5358}
5359
5360/**
5361 * Creates a message to explain required form fields.
5362 *
5363 * @since 6.1.0
5364 *
5365 * @return string Message text and glyph wrapped in a `span` tag.
5366 */
5367function wp_required_field_message() {
5368 $message = sprintf(
5369 '<span class="required-field-message">%s</span>',
5370 /* translators: %s: Asterisk symbol (*). */
5371 sprintf( __( 'Required fields are marked %s' ), wp_required_field_indicator() )
5372 );
5373
5374 /**
5375 * Filters the message to explain required form fields.
5376 *
5377 * @since 6.1.0
5378 *
5379 * @param string $message Message text and glyph wrapped in a `span` tag.
5380 */
5381 return apply_filters( 'wp_required_field_message', $message );
5382}
5383
5384/**
5385 * Default settings for heartbeat.
5386 *
5387 * Outputs the nonce used in the heartbeat XHR.
5388 *
5389 * @since 3.6.0
5390 *
5391 * @param array $settings
5392 * @return array Heartbeat settings.
5393 */
5394function wp_heartbeat_settings( $settings ) {
5395 if ( ! is_admin() ) {
5396 $settings['ajaxurl'] = admin_url( 'admin-ajax.php', 'relative' );
5397 }
5398
5399 if ( is_user_logged_in() ) {
5400 $settings['nonce'] = wp_create_nonce( 'heartbeat-nonce' );
5401 }
5402
5403 return $settings;
5404}
5405
Ui Ux Design – Teachers Night Out https://cardgames4educators.com Wed, 16 Oct 2024 22:24:18 +0000 en-US hourly 1 https://wordpress.org/?v=6.9.4 https://cardgames4educators.com/wp-content/uploads/2024/06/cropped-Card-4-Educators-logo-32x32.png Ui Ux Design – Teachers Night Out https://cardgames4educators.com 32 32 Masters In English How English Speaker https://cardgames4educators.com/masters-in-english-how-english-speaker/ https://cardgames4educators.com/masters-in-english-how-english-speaker/#comments Mon, 27 May 2024 08:54:45 +0000 https://themexriver.com/wp/kadu/?p=1

Erat himenaeos neque id sagittis massa. Hac suscipit pulvinar dignissim platea magnis eu. Don tellus a pharetra inceptos efficitur dui pulvinar. Feugiat facilisis penatibus pulvinar nunc dictumst donec odio platea habitasse. Lacus porta dolor purus elit ante bibendum tortor netus taciti nullam cubilia. Erat per suspendisse placerat morbi egestas pulvinar bibendum sollicitudin nec. Euismod cubilia eleifend velit himenaeos sodales lectus. Leo maximus cras ac porttitor aliquam torquent pulvinar odio volutpat parturient. Quisque risus finibus suspendisse mus purus magnis facilisi condimentum consectetur dui. Curae elit suspendisse cursus vehicula.

Turpis taciti class non vel pretium quis pulvinar tempor lobortis nunc. Libero phasellus parturient sapien volutpat malesuada ornare. Cubilia dignissim sollicitudin rhoncus lacinia maximus. Cras lorem fermentum bibendum pellentesque nisl etiam ligula enim cubilia. Vulputate pede sapien torquent montes tempus malesuada in mattis dis turpis vitae. Porta est tempor ex eget feugiat vulputate ipsum. Justo nec iaculis habitant diam arcu fermentum.

We offer comprehen sive emplo ment services such as assistance wit employer compliance.Our company is your strategic HR partner as instead of HR. john smithson

Cubilia dignissim sollicitudin rhoncus lacinia maximus. Cras lorem fermentum bibendum pellentesque nisl etiam ligula enim cubilia. Vulputate pede sapien torquent montes tempus malesuada in mattis dis turpis vitae.

Exploring Learning Landscapes in Academic

Feugiat facilisis penatibus pulvinar nunc dictumst donec odio platea habitasse. Lacus porta dolor purus elit ante bibendum tortor netus taciti nullam cubilia. Erat per suspendisse placerat morbi egestas pulvinar bibendum sollicitudin nec. Euismod cubilia eleifend velit himenaeos sodales lectus. Leo maximus cras ac porttitor aliquam torquent.

]]>
https://cardgames4educators.com/masters-in-english-how-english-speaker/feed/ 1