16
|
1 |
<?php |
|
2 |
/** |
|
3 |
* Sitemaps: WP_Sitemaps_Stylesheet class |
|
4 |
* |
|
5 |
* This class provides the XSL stylesheets to style all sitemaps. |
|
6 |
* |
|
7 |
* @package WordPress |
|
8 |
* @subpackage Sitemaps |
|
9 |
* @since 5.5.0 |
|
10 |
*/ |
|
11 |
|
|
12 |
/** |
|
13 |
* Stylesheet provider class. |
|
14 |
* |
|
15 |
* @since 5.5.0 |
|
16 |
*/ |
|
17 |
class WP_Sitemaps_Stylesheet { |
|
18 |
/** |
|
19 |
* Renders the XSL stylesheet depending on whether it's the sitemap index or not. |
|
20 |
* |
|
21 |
* @param string $type Stylesheet type. Either 'sitemap' or 'index'. |
|
22 |
*/ |
|
23 |
public function render_stylesheet( $type ) { |
|
24 |
header( 'Content-type: application/xml; charset=UTF-8' ); |
|
25 |
|
|
26 |
if ( 'sitemap' === $type ) { |
|
27 |
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- All content escaped below. |
|
28 |
echo $this->get_sitemap_stylesheet(); |
|
29 |
} |
|
30 |
|
|
31 |
if ( 'index' === $type ) { |
|
32 |
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- All content escaped below. |
|
33 |
echo $this->get_sitemap_index_stylesheet(); |
|
34 |
} |
|
35 |
|
|
36 |
exit; |
|
37 |
} |
|
38 |
|
|
39 |
/** |
|
40 |
* Returns the escaped XSL for all sitemaps, except index. |
|
41 |
* |
|
42 |
* @since 5.5.0 |
|
43 |
*/ |
|
44 |
public function get_sitemap_stylesheet() { |
|
45 |
$css = $this->get_stylesheet_css(); |
|
46 |
$title = esc_xml( __( 'XML Sitemap' ) ); |
|
47 |
$description = esc_xml( __( 'This XML Sitemap is generated by WordPress to make your content more visible for search engines.' ) ); |
|
48 |
$learn_more = sprintf( |
|
49 |
'<a href="%s">%s</a>', |
|
50 |
esc_url( __( 'https://www.sitemaps.org/' ) ), |
|
51 |
esc_xml( __( 'Learn more about XML sitemaps.' ) ) |
|
52 |
); |
|
53 |
|
|
54 |
$text = sprintf( |
|
55 |
/* translators: %s: Number of URLs. */ |
|
56 |
esc_xml( __( 'Number of URLs in this XML Sitemap: %s.' ) ), |
|
57 |
'<xsl:value-of select="count( sitemap:urlset/sitemap:url )" />' |
|
58 |
); |
|
59 |
|
|
60 |
$lang = get_language_attributes( 'html' ); |
|
61 |
$url = esc_xml( __( 'URL' ) ); |
|
62 |
$lastmod = esc_xml( __( 'Last Modified' ) ); |
|
63 |
$changefreq = esc_xml( __( 'Change Frequency' ) ); |
|
64 |
$priority = esc_xml( __( 'Priority' ) ); |
|
65 |
|
|
66 |
$xsl_content = <<<XSL |
|
67 |
<?xml version="1.0" encoding="UTF-8"?> |
|
68 |
<xsl:stylesheet |
|
69 |
version="1.0" |
|
70 |
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" |
|
71 |
xmlns:sitemap="http://www.sitemaps.org/schemas/sitemap/0.9" |
|
72 |
exclude-result-prefixes="sitemap" |
|
73 |
> |
|
74 |
|
|
75 |
<xsl:output method="html" encoding="UTF-8" indent="yes"/> |
|
76 |
|
|
77 |
<!-- |
|
78 |
Set variables for whether lastmod, changefreq or priority occur for any url in the sitemap. |
|
79 |
We do this up front because it can be expensive in a large sitemap. |
|
80 |
--> |
|
81 |
<xsl:variable name="has-lastmod" select="count( /sitemap:urlset/sitemap:url/sitemap:lastmod )" /> |
|
82 |
<xsl:variable name="has-changefreq" select="count( /sitemap:urlset/sitemap:url/sitemap:changefreq )" /> |
|
83 |
<xsl:variable name="has-priority" select="count( /sitemap:urlset/sitemap:url/sitemap:priority )" /> |
|
84 |
|
|
85 |
<xsl:template match="/"> |
|
86 |
<html {$lang}> |
|
87 |
<head> |
|
88 |
<title>{$title}</title> |
|
89 |
<style> |
|
90 |
{$css} |
|
91 |
</style> |
|
92 |
</head> |
|
93 |
<body> |
|
94 |
<div id="sitemap"> |
|
95 |
<div id="sitemap__header"> |
|
96 |
<h1>{$title}</h1> |
|
97 |
<p>{$description}</p> |
|
98 |
<p>{$learn_more}</p> |
|
99 |
</div> |
|
100 |
<div id="sitemap__content"> |
|
101 |
<p class="text">{$text}</p> |
|
102 |
<table id="sitemap__table"> |
|
103 |
<thead> |
|
104 |
<tr> |
|
105 |
<th class="loc">{$url}</th> |
|
106 |
<xsl:if test="\$has-lastmod"> |
|
107 |
<th class="lastmod">{$lastmod}</th> |
|
108 |
</xsl:if> |
|
109 |
<xsl:if test="\$has-changefreq"> |
|
110 |
<th class="changefreq">{$changefreq}</th> |
|
111 |
</xsl:if> |
|
112 |
<xsl:if test="\$has-priority"> |
|
113 |
<th class="priority">{$priority}</th> |
|
114 |
</xsl:if> |
|
115 |
</tr> |
|
116 |
</thead> |
|
117 |
<tbody> |
|
118 |
<xsl:for-each select="sitemap:urlset/sitemap:url"> |
|
119 |
<tr> |
|
120 |
<td class="loc"><a href="{sitemap:loc}"><xsl:value-of select="sitemap:loc" /></a></td> |
|
121 |
<xsl:if test="\$has-lastmod"> |
|
122 |
<td class="lastmod"><xsl:value-of select="sitemap:lastmod" /></td> |
|
123 |
</xsl:if> |
|
124 |
<xsl:if test="\$has-changefreq"> |
|
125 |
<td class="changefreq"><xsl:value-of select="sitemap:changefreq" /></td> |
|
126 |
</xsl:if> |
|
127 |
<xsl:if test="\$has-priority"> |
|
128 |
<td class="priority"><xsl:value-of select="sitemap:priority" /></td> |
|
129 |
</xsl:if> |
|
130 |
</tr> |
|
131 |
</xsl:for-each> |
|
132 |
</tbody> |
|
133 |
</table> |
|
134 |
</div> |
|
135 |
</div> |
|
136 |
</body> |
|
137 |
</html> |
|
138 |
</xsl:template> |
|
139 |
</xsl:stylesheet> |
|
140 |
|
|
141 |
XSL; |
|
142 |
|
|
143 |
/** |
|
144 |
* Filters the content of the sitemap stylesheet. |
|
145 |
* |
|
146 |
* @since 5.5.0 |
|
147 |
* |
|
148 |
* @param string $xsl_content Full content for the XML stylesheet. |
|
149 |
*/ |
|
150 |
return apply_filters( 'wp_sitemaps_stylesheet_content', $xsl_content ); |
|
151 |
} |
|
152 |
|
|
153 |
/** |
|
154 |
* Returns the escaped XSL for the index sitemaps. |
|
155 |
* |
|
156 |
* @since 5.5.0 |
|
157 |
*/ |
|
158 |
public function get_sitemap_index_stylesheet() { |
|
159 |
$css = $this->get_stylesheet_css(); |
|
160 |
$title = esc_xml( __( 'XML Sitemap' ) ); |
|
161 |
$description = esc_xml( __( 'This XML Sitemap is generated by WordPress to make your content more visible for search engines.' ) ); |
|
162 |
$learn_more = sprintf( |
|
163 |
'<a href="%s">%s</a>', |
|
164 |
esc_url( __( 'https://www.sitemaps.org/' ) ), |
|
165 |
esc_xml( __( 'Learn more about XML sitemaps.' ) ) |
|
166 |
); |
|
167 |
|
|
168 |
$text = sprintf( |
|
169 |
/* translators: %s: Number of URLs. */ |
|
170 |
esc_xml( __( 'Number of URLs in this XML Sitemap: %s.' ) ), |
|
171 |
'<xsl:value-of select="count( sitemap:sitemapindex/sitemap:sitemap )" />' |
|
172 |
); |
|
173 |
|
|
174 |
$lang = get_language_attributes( 'html' ); |
|
175 |
$url = esc_xml( __( 'URL' ) ); |
|
176 |
$lastmod = esc_xml( __( 'Last Modified' ) ); |
|
177 |
|
|
178 |
$xsl_content = <<<XSL |
|
179 |
<?xml version="1.0" encoding="UTF-8"?> |
|
180 |
<xsl:stylesheet |
|
181 |
version="1.0" |
|
182 |
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" |
|
183 |
xmlns:sitemap="http://www.sitemaps.org/schemas/sitemap/0.9" |
|
184 |
exclude-result-prefixes="sitemap" |
|
185 |
> |
|
186 |
|
|
187 |
<xsl:output method="html" encoding="UTF-8" indent="yes" /> |
|
188 |
|
|
189 |
<!-- |
|
190 |
Set variables for whether lastmod occurs for any sitemap in the index. |
|
191 |
We do this up front because it can be expensive in a large sitemap. |
|
192 |
--> |
|
193 |
<xsl:variable name="has-lastmod" select="count( /sitemap:sitemapindex/sitemap:sitemap/sitemap:lastmod )" /> |
|
194 |
|
|
195 |
<xsl:template match="/"> |
|
196 |
<html {$lang}> |
|
197 |
<head> |
|
198 |
<title>{$title}</title> |
|
199 |
<style> |
|
200 |
{$css} |
|
201 |
</style> |
|
202 |
</head> |
|
203 |
<body> |
|
204 |
<div id="sitemap"> |
|
205 |
<div id="sitemap__header"> |
|
206 |
<h1>{$title}</h1> |
|
207 |
<p>{$description}</p> |
|
208 |
<p>{$learn_more}</p> |
|
209 |
</div> |
|
210 |
<div id="sitemap__content"> |
|
211 |
<p class="text">{$text}</p> |
|
212 |
<table id="sitemap__table"> |
|
213 |
<thead> |
|
214 |
<tr> |
|
215 |
<th class="loc">{$url}</th> |
|
216 |
<xsl:if test="\$has-lastmod"> |
|
217 |
<th class="lastmod">{$lastmod}</th> |
|
218 |
</xsl:if> |
|
219 |
</tr> |
|
220 |
</thead> |
|
221 |
<tbody> |
|
222 |
<xsl:for-each select="sitemap:sitemapindex/sitemap:sitemap"> |
|
223 |
<tr> |
|
224 |
<td class="loc"><a href="{sitemap:loc}"><xsl:value-of select="sitemap:loc" /></a></td> |
|
225 |
<xsl:if test="\$has-lastmod"> |
|
226 |
<td class="lastmod"><xsl:value-of select="sitemap:lastmod" /></td> |
|
227 |
</xsl:if> |
|
228 |
</tr> |
|
229 |
</xsl:for-each> |
|
230 |
</tbody> |
|
231 |
</table> |
|
232 |
</div> |
|
233 |
</div> |
|
234 |
</body> |
|
235 |
</html> |
|
236 |
</xsl:template> |
|
237 |
</xsl:stylesheet> |
|
238 |
|
|
239 |
XSL; |
|
240 |
|
|
241 |
/** |
|
242 |
* Filters the content of the sitemap index stylesheet. |
|
243 |
* |
|
244 |
* @since 5.5.0 |
|
245 |
* |
|
246 |
* @param string $xsl_content Full content for the XML stylesheet. |
|
247 |
*/ |
|
248 |
return apply_filters( 'wp_sitemaps_stylesheet_index_content', $xsl_content ); |
|
249 |
} |
|
250 |
|
|
251 |
/** |
|
252 |
* Gets the CSS to be included in sitemap XSL stylesheets. |
|
253 |
* |
|
254 |
* @since 5.5.0 |
|
255 |
* |
|
256 |
* @return string The CSS. |
|
257 |
*/ |
|
258 |
public function get_stylesheet_css() { |
|
259 |
$text_align = is_rtl() ? 'right' : 'left'; |
|
260 |
|
|
261 |
$css = <<<EOF |
|
262 |
|
|
263 |
body { |
|
264 |
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; |
|
265 |
color: #444; |
|
266 |
} |
|
267 |
|
|
268 |
#sitemap__table { |
|
269 |
border: solid 1px #ccc; |
|
270 |
border-collapse: collapse; |
|
271 |
} |
|
272 |
|
|
273 |
#sitemap__table tr td.loc { |
|
274 |
/* |
|
275 |
* URLs should always be LTR. |
|
276 |
* See https://core.trac.wordpress.org/ticket/16834 |
|
277 |
* and https://core.trac.wordpress.org/ticket/49949 |
|
278 |
*/ |
|
279 |
direction: ltr; |
|
280 |
} |
|
281 |
|
|
282 |
#sitemap__table tr th { |
|
283 |
text-align: {$text_align}; |
|
284 |
} |
|
285 |
|
|
286 |
#sitemap__table tr td, |
|
287 |
#sitemap__table tr th { |
|
288 |
padding: 10px; |
|
289 |
} |
|
290 |
|
|
291 |
#sitemap__table tr:nth-child(odd) td { |
|
292 |
background-color: #eee; |
|
293 |
} |
|
294 |
|
|
295 |
a:hover { |
|
296 |
text-decoration: none; |
|
297 |
} |
|
298 |
|
|
299 |
EOF; |
|
300 |
|
|
301 |
/** |
|
302 |
* Filters the CSS only for the sitemap stylesheet. |
|
303 |
* |
|
304 |
* @since 5.5.0 |
|
305 |
* |
|
306 |
* @param string $css CSS to be applied to default XSL file. |
|
307 |
*/ |
|
308 |
return apply_filters( 'wp_sitemaps_stylesheet_css', $css ); |
|
309 |
} |
|
310 |
} |