summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnthony G. Basile <blueness@gentoo.org>2017-09-20 09:54:07 -0400
committerAnthony G. Basile <blueness@gentoo.org>2017-09-20 09:54:07 -0400
commitbb31fa2d44dbbe425fa9ce92d4e7be61a1146dfb (patch)
tree33456f5889d315ad2a520fcd33fe491e612588b4 /plugins/jetpack/modules/sitemaps
parentakismet 4.0 (diff)
downloadblogs-gentoo-bb31fa2d44dbbe425fa9ce92d4e7be61a1146dfb.tar.gz
blogs-gentoo-bb31fa2d44dbbe425fa9ce92d4e7be61a1146dfb.tar.bz2
blogs-gentoo-bb31fa2d44dbbe425fa9ce92d4e7be61a1146dfb.zip
jetpack 5.3
Signed-off-by: Anthony G. Basile <blueness@gentoo.org>
Diffstat (limited to 'plugins/jetpack/modules/sitemaps')
-rw-r--r--plugins/jetpack/modules/sitemaps/sitemap-buffer-fallback.php146
-rw-r--r--plugins/jetpack/modules/sitemaps/sitemap-buffer-image-fallback.php56
-rw-r--r--plugins/jetpack/modules/sitemaps/sitemap-buffer-image.php68
-rw-r--r--plugins/jetpack/modules/sitemaps/sitemap-buffer-master-fallback.php38
-rw-r--r--plugins/jetpack/modules/sitemaps/sitemap-buffer-master.php44
-rw-r--r--plugins/jetpack/modules/sitemaps/sitemap-buffer-news-fallback.php56
-rw-r--r--plugins/jetpack/modules/sitemaps/sitemap-buffer-news.php68
-rw-r--r--plugins/jetpack/modules/sitemaps/sitemap-buffer-page-fallback.php55
-rw-r--r--plugins/jetpack/modules/sitemaps/sitemap-buffer-page.php67
-rw-r--r--plugins/jetpack/modules/sitemaps/sitemap-buffer-video-fallback.php56
-rw-r--r--plugins/jetpack/modules/sitemaps/sitemap-buffer-video.php68
-rw-r--r--plugins/jetpack/modules/sitemaps/sitemap-buffer.php242
-rw-r--r--plugins/jetpack/modules/sitemaps/sitemap-builder.php317
-rw-r--r--plugins/jetpack/modules/sitemaps/sitemap-librarian.php85
-rw-r--r--plugins/jetpack/modules/sitemaps/sitemaps.php17
15 files changed, 996 insertions, 387 deletions
diff --git a/plugins/jetpack/modules/sitemaps/sitemap-buffer-fallback.php b/plugins/jetpack/modules/sitemaps/sitemap-buffer-fallback.php
new file mode 100644
index 00000000..1cf73c09
--- /dev/null
+++ b/plugins/jetpack/modules/sitemaps/sitemap-buffer-fallback.php
@@ -0,0 +1,146 @@
+<?php
+/**
+ * The fallback buffer for users with no XML support.
+ *
+ * @since 5.3.0
+ * @package Jetpack
+ */
+
+/**
+ * A buffer for constructing master sitemap xml files.
+ *
+ * @since 5.1.0
+ */
+abstract class Jetpack_Sitemap_Buffer_Fallback extends Jetpack_Sitemap_Buffer {
+
+ /**
+ * The buffer contents.
+ *
+ * @access protected
+ * @since 5.3.0
+ * @var string The buffer contents.
+ */
+ protected $buffer;
+
+ public function __construct( $item_limit, $byte_limit, $time = '1970-01-01 00:00:00' ) {
+ $this->is_full_flag = false;
+ $this->is_empty_flag = true;
+ $this->timestamp = $time;
+
+ $this->finder = new Jetpack_Sitemap_Finder();
+
+ $this->item_capacity = max( 1, intval( $item_limit ) );
+ $this->byte_capacity = max( 1, intval( $byte_limit ) ) - strlen( $this->contents() );
+ }
+
+ /**
+ * Append an item to the buffer, if there is room for it,
+ * and set is_empty_flag to false. If there is no room,
+ * we set is_full_flag to true. If $item is null,
+ * don't do anything and report success.
+ *
+ * @since 5.3.0
+ *
+ * @param array $array The item to be added.
+ *
+ * @return bool True if the append succeeded, False if not.
+ */
+ public function append( $array ) {
+ if ( is_null( $array ) ) {
+ return true;
+ }
+
+ if ( $this->is_full_flag ) {
+ return false;
+ }
+
+ if ( 0 >= $this->item_capacity || 0 >= $this->byte_capacity ) {
+ $this->is_full_flag = true;
+ return false;
+ } else {
+ $this->item_capacity -= 1;
+ $added_string = $this->array_to_xml_string( $array );
+ $this->buffer .= $added_string;
+ $this->is_empty_flag = false;
+
+ mbstring_binary_safe_encoding(); // So we can safely use strlen().
+ $this->byte_capacity -= strlen( $added_string );
+ reset_mbstring_encoding();
+
+ return true;
+ }
+ }
+
+ /**
+ * Detect whether the buffer is empty.
+ *
+ * @since 5.3.0
+ *
+ * @return bool True if the buffer is empty, false otherwise.
+ */
+ public function is_empty() {
+ return $this->is_empty_flag;
+ }
+
+ /**
+ * Retrieve the contents of the buffer.
+ *
+ * @since 5.3.0
+ *
+ * @return string The contents of the buffer (with the footer included).
+ */
+ public function contents() {
+ $root = $this->get_root_element();
+
+ return '<?xml version="1.0" encoding="UTF-8"?>' . PHP_EOL . $root[0] . $this->buffer . $root[1] . PHP_EOL;
+ }
+
+ /**
+ * Legacy implementation of array to XML conversion without using DOMDocument.
+ *
+ * @param Array $array
+ * @return String $result
+ */
+ public function array_to_xml_string( $array, $parent = null, $root = null ) {
+ $string = '';
+
+ foreach ( $array as $key => $value ) {
+ // Only allow a-z, A-Z, colon, underscore, and hyphen.
+ $tag = preg_replace( '/[^a-zA-Z:_-]/', '_', $key );
+
+ if ( is_array( $value ) ) {
+ $string .= "<$tag>";
+ $string .= $this->array_to_xml_string( $value );
+ $string .= "</$tag>";
+ } elseif ( is_null( $value ) ) {
+ $string .= "<$tag />";
+ } else {
+ $string .= "<$tag>" . htmlspecialchars( $value ) . "</$tag>";
+ }
+ }
+
+ return $string;
+ }
+
+ /**
+ * Render an associative array of XML attribute key/value pairs.
+ *
+ * @access public
+ * @since 5.3.0
+ *
+ * @param array $array Key/value array of attributes.
+ *
+ * @return string The rendered attribute string.
+ */
+ public static function array_to_xml_attr_string( $array ) {
+ $string = '';
+
+ foreach ( $array as $key => $value ) {
+ $key = preg_replace( '/[^a-zA-Z:_-]/', '_', $key );
+ $string .= ' ' . $key . '="' . esc_attr( $value ) . '"';
+ }
+
+ return $string;
+ }
+
+}
diff --git a/plugins/jetpack/modules/sitemaps/sitemap-buffer-image-fallback.php b/plugins/jetpack/modules/sitemaps/sitemap-buffer-image-fallback.php
new file mode 100644
index 00000000..1616574f
--- /dev/null
+++ b/plugins/jetpack/modules/sitemaps/sitemap-buffer-image-fallback.php
@@ -0,0 +1,56 @@
+<?php
+/**
+ * Sitemaps (per the protocol) are essentially lists of XML fragments;
+ * lists which are subject to size constraints. The Jetpack_Sitemap_Buffer_Image
+ * extends the Jetpack_Sitemap_Buffer class to represent the single image sitemap
+ * buffer.
+ *
+ * @since 5.3.0
+ * @package Jetpack
+ */
+
+/**
+ * A buffer for constructing sitemap image xml files for users that have no libxml support.
+ *
+ * @since 5.3.0
+ */
+class Jetpack_Sitemap_Buffer_Image extends Jetpack_Sitemap_Buffer_Fallback {
+
+ protected function get_root_element() {
+ if ( ! isset( $this->root ) ) {
+
+ /**
+ * Filter the XML namespaces included in image sitemaps.
+ *
+ * @module sitemaps
+ *
+ * @since 4.8.0
+ *
+ * @param array $namespaces Associative array with namespaces and namespace URIs.
+ */
+ $namespaces = apply_filters(
+ 'jetpack_sitemap_image_ns',
+ array(
+ 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
+ 'xsi:schemaLocation' => 'http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd',
+ 'xmlns' => 'http://www.sitemaps.org/schemas/sitemap/0.9',
+ 'xmlns:image' => 'http://www.google.com/schemas/sitemap-image/1.1',
+ )
+ );
+
+ $sitemap_xsl_url = $this->finder->construct_sitemap_url( 'sitemap.xsl' );
+ $jetpack_version = JETPACK__VERSION;
+
+ $this->root = array(
+ "<!-- generator='jetpack-{$jetpack_version}' -->" . PHP_EOL
+ . "<?xml-stylesheet type='text/xsl' href='{$sitemap_xsl_url}'?>" . PHP_EOL
+ . '<urlset ' . $this->array_to_xml_attr_string( $namespaces ) . '>' . PHP_EOL,
+ '</urlset>'
+ );
+
+ $this->byte_capacity -= strlen( join( '', $this->root ) );
+ }
+
+ return $this->root;
+ }
+}
diff --git a/plugins/jetpack/modules/sitemaps/sitemap-buffer-image.php b/plugins/jetpack/modules/sitemaps/sitemap-buffer-image.php
new file mode 100644
index 00000000..e452fcbf
--- /dev/null
+++ b/plugins/jetpack/modules/sitemaps/sitemap-buffer-image.php
@@ -0,0 +1,68 @@
+<?php
+/**
+ * Sitemaps (per the protocol) are essentially lists of XML fragments;
+ * lists which are subject to size constraints. The Jetpack_Sitemap_Buffer_Image
+ * extends the Jetpack_Sitemap_Buffer class to represent the single image sitemap
+ * buffer.
+ *
+ * @since 5.3.0
+ * @package Jetpack
+ */
+
+/**
+ * A buffer for constructing sitemap image xml files.
+ *
+ * @since 5.3.0
+ */
+class Jetpack_Sitemap_Buffer_Image extends Jetpack_Sitemap_Buffer {
+
+ public function __construct( $item_limit, $byte_limit, $time = '1970-01-01 00:00:00' ) {
+ parent::__construct( $item_limit, $byte_limit, $time );
+
+ $this->doc->appendChild(
+ $this->doc->createComment( "generator='jetpack-" . JETPACK__VERSION . "'" )
+ );
+
+ $this->doc->appendChild(
+ $this->doc->createProcessingInstruction(
+ 'xml-stylesheet',
+ 'type="text/xsl" href="' . $this->finder->construct_sitemap_url( 'image-sitemap.xsl' ) . '"'
+ )
+ );
+ }
+
+ protected function get_root_element() {
+ if ( ! isset( $this->root ) ) {
+
+ /**
+ * Filter the XML namespaces included in image sitemaps.
+ *
+ * @module sitemaps
+ *
+ * @since 4.8.0
+ *
+ * @param array $namespaces Associative array with namespaces and namespace URIs.
+ */
+ $namespaces = apply_filters(
+ 'jetpack_sitemap_image_ns',
+ array(
+ 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
+ 'xsi:schemaLocation' => 'http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd',
+ 'xmlns' => 'http://www.sitemaps.org/schemas/sitemap/0.9',
+ 'xmlns:image' => 'http://www.google.com/schemas/sitemap-image/1.1',
+ )
+ );
+
+ $this->root = $this->doc->createElement( 'urlset' );
+
+ foreach ( $namespaces as $name => $value ) {
+ $this->root->setAttribute( $name, $value );
+ }
+
+ $this->doc->appendChild( $this->root );
+ $this->byte_capacity -= strlen( $this->doc->saveXML( $this->root ) );
+ }
+
+ return $this->root;
+ }
+}
diff --git a/plugins/jetpack/modules/sitemaps/sitemap-buffer-master-fallback.php b/plugins/jetpack/modules/sitemaps/sitemap-buffer-master-fallback.php
new file mode 100644
index 00000000..af665547
--- /dev/null
+++ b/plugins/jetpack/modules/sitemaps/sitemap-buffer-master-fallback.php
@@ -0,0 +1,38 @@
+<?php
+/**
+ * Sitemaps (per the protocol) are essentially lists of XML fragments;
+ * lists which are subject to size constraints. The Jetpack_Sitemap_Buffer_Master
+ * extends the Jetpack_Sitemap_Buffer class to represent the master sitemap
+ * buffer.
+ *
+ * @since 5.3.0
+ * @package Jetpack
+ */
+
+/**
+ * A buffer for constructing master sitemap xml files for users without libxml support.
+ *
+ * @since 5.3.0
+ */
+class Jetpack_Sitemap_Buffer_Master extends Jetpack_Sitemap_Buffer_Fallback {
+
+ protected function get_root_element() {
+
+ if ( ! isset( $this->root ) ) {
+
+ $sitemap_index_xsl_url = $this->finder->construct_sitemap_url( 'sitemap-index.xsl' );
+ $jetpack_version = JETPACK__VERSION;
+
+ $this->root = array(
+ "<!-- generator='jetpack-{$jetpack_version}' -->" . PHP_EOL
+ . "<?xml-stylesheet type='text/xsl' href='{$sitemap_index_xsl_url}'?>" . PHP_EOL
+ . "<sitemapindex xmlns='http://www.sitemaps.org/schemas/sitemap/0.9'>" . PHP_EOL,
+ '</sitemapindex>'
+ );
+
+ $this->byte_capacity -= strlen( join( '', $this->root ) );
+ }
+
+ return $this->root;
+ }
+}
diff --git a/plugins/jetpack/modules/sitemaps/sitemap-buffer-master.php b/plugins/jetpack/modules/sitemaps/sitemap-buffer-master.php
new file mode 100644
index 00000000..fc6be602
--- /dev/null
+++ b/plugins/jetpack/modules/sitemaps/sitemap-buffer-master.php
@@ -0,0 +1,44 @@
+<?php
+/**
+ * Sitemaps (per the protocol) are essentially lists of XML fragments;
+ * lists which are subject to size constraints. The Jetpack_Sitemap_Buffer_Master
+ * extends the Jetpack_Sitemap_Buffer class to represent the master sitemap
+ * buffer.
+ *
+ * @since 5.3.0
+ * @package Jetpack
+ */
+
+/**
+ * A buffer for constructing master sitemap xml files.
+ *
+ * @since 5.3.0
+ */
+class Jetpack_Sitemap_Buffer_Master extends Jetpack_Sitemap_Buffer {
+
+ public function __construct( $item_limit, $byte_limit, $time = '1970-01-01 00:00:00' ) {
+ parent::__construct( $item_limit, $byte_limit, $time );
+
+ $this->doc->appendChild(
+ $this->doc->createComment( "generator='jetpack-" . JETPACK__VERSION . "'" )
+ );
+
+ $this->doc->appendChild(
+ $this->doc->createProcessingInstruction(
+ 'xml-stylesheet',
+ 'type="text/xsl" href="' . $this->finder->construct_sitemap_url( 'sitemap-index.xsl' ) . '"'
+ )
+ );
+ }
+
+ protected function get_root_element() {
+ if ( ! isset( $this->root ) ) {
+ $this->root = $this->doc->createElement( 'sitemapindex' );
+ $this->root->setAttribute( 'xmlns', 'http://www.sitemaps.org/schemas/sitemap/0.9' );
+ $this->doc->appendChild( $this->root );
+ $this->byte_capacity -= strlen( $this->doc->saveXML( $this->root ) );
+ }
+
+ return $this->root;
+ }
+}
diff --git a/plugins/jetpack/modules/sitemaps/sitemap-buffer-news-fallback.php b/plugins/jetpack/modules/sitemaps/sitemap-buffer-news-fallback.php
new file mode 100644
index 00000000..cca2c644
--- /dev/null
+++ b/plugins/jetpack/modules/sitemaps/sitemap-buffer-news-fallback.php
@@ -0,0 +1,56 @@
+<?php
+/**
+ * Sitemaps (per the protocol) are essentially lists of XML fragments;
+ * lists which are subject to size constraints. The Jetpack_Sitemap_Buffer_News
+ * extends the Jetpack_Sitemap_Buffer class to represent the single news sitemap
+ * buffer.
+ *
+ * @since 5.3.0
+ * @package Jetpack
+ */
+
+/**
+ * A buffer for constructing sitemap image xml files for users without libxml support.
+ *
+ * @since 5.3.0
+ */
+class Jetpack_Sitemap_Buffer_News extends Jetpack_Sitemap_Buffer_Fallback {
+
+ protected function get_root_element() {
+ if ( ! isset( $this->root ) ) {
+
+ /**
+ * Filter the attribute value pairs used for namespace and namespace URI mappings.
+ *
+ * @module sitemaps
+ *
+ * @since 4.8.0
+ *
+ * @param array $namespaces Associative array with namespaces and namespace URIs.
+ */
+ $namespaces = apply_filters(
+ 'jetpack_sitemap_news_ns',
+ array(
+ 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
+ 'xsi:schemaLocation' => 'http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd',
+ 'xmlns' => 'http://www.sitemaps.org/schemas/sitemap/0.9',
+ 'xmlns:news' => 'http://www.google.com/schemas/sitemap-news/0.9',
+ )
+ );
+
+ $jetpack_version = JETPACK__VERSION;
+ $news_sitemap_xsl_url = $this->finder->construct_sitemap_url( 'news-sitemap.xsl' );
+
+ $this->root = array(
+ "<!-- generator='jetpack-{$jetpack_version}' -->" . PHP_EOL
+ . "<?xml-stylesheet type='text/xsl' href='{$news_sitemap_xsl_url}'?>" . PHP_EOL
+ . '<urlset ' . $this->array_to_xml_attr_string( $namespaces ) . '>',
+ '</urlset>'
+ );
+
+ $this->byte_capacity -= strlen( join( '', $this->root ) );
+ }
+
+ return $this->root;
+ }
+}
diff --git a/plugins/jetpack/modules/sitemaps/sitemap-buffer-news.php b/plugins/jetpack/modules/sitemaps/sitemap-buffer-news.php
new file mode 100644
index 00000000..0e5b0327
--- /dev/null
+++ b/plugins/jetpack/modules/sitemaps/sitemap-buffer-news.php
@@ -0,0 +1,68 @@
+<?php
+/**
+ * Sitemaps (per the protocol) are essentially lists of XML fragments;
+ * lists which are subject to size constraints. The Jetpack_Sitemap_Buffer_News
+ * extends the Jetpack_Sitemap_Buffer class to represent the single news sitemap
+ * buffer.
+ *
+ * @since 5.3.0
+ * @package Jetpack
+ */
+
+/**
+ * A buffer for constructing sitemap image xml files.
+ *
+ * @since 5.3.0
+ */
+class Jetpack_Sitemap_Buffer_News extends Jetpack_Sitemap_Buffer {
+
+ public function __construct( $item_limit, $byte_limit, $time = '1970-01-01 00:00:00' ) {
+ parent::__construct( $item_limit, $byte_limit, $time );
+
+ $this->doc->appendChild(
+ $this->doc->createComment( "generator='jetpack-" . JETPACK__VERSION . "'" )
+ );
+
+ $this->doc->appendChild(
+ $this->doc->createProcessingInstruction(
+ 'xml-stylesheet',
+ 'type="text/xsl" href="' . $this->finder->construct_sitemap_url( 'news-sitemap.xsl' ) . '"'
+ )
+ );
+ }
+
+ protected function get_root_element() {
+ if ( ! isset( $this->root ) ) {
+
+ /**
+ * Filter the attribute value pairs used for namespace and namespace URI mappings.
+ *
+ * @module sitemaps
+ *
+ * @since 4.8.0
+ *
+ * @param array $namespaces Associative array with namespaces and namespace URIs.
+ */
+ $namespaces = apply_filters(
+ 'jetpack_sitemap_news_ns',
+ array(
+ 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
+ 'xsi:schemaLocation' => 'http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd',
+ 'xmlns' => 'http://www.sitemaps.org/schemas/sitemap/0.9',
+ 'xmlns:news' => 'http://www.google.com/schemas/sitemap-news/0.9',
+ )
+ );
+
+ $this->root = $this->doc->createElement( 'urlset' );
+
+ foreach ( $namespaces as $name => $value ) {
+ $this->root->setAttribute( $name, $value );
+ }
+
+ $this->doc->appendChild( $this->root );
+ $this->byte_capacity -= strlen( $this->doc->saveXML( $this->root ) );
+ }
+
+ return $this->root;
+ }
+}
diff --git a/plugins/jetpack/modules/sitemaps/sitemap-buffer-page-fallback.php b/plugins/jetpack/modules/sitemaps/sitemap-buffer-page-fallback.php
new file mode 100644
index 00000000..e64f31bc
--- /dev/null
+++ b/plugins/jetpack/modules/sitemaps/sitemap-buffer-page-fallback.php
@@ -0,0 +1,55 @@
+<?php
+/**
+ * Sitemaps (per the protocol) are essentially lists of XML fragments;
+ * lists which are subject to size constraints. The Jetpack_Sitemap_Buffer_Page
+ * extends the Jetpack_Sitemap_Buffer class to represent the single page sitemap
+ * buffer.
+ *
+ * @since 5.3.0
+ * @package Jetpack
+ */
+
+/**
+ * A buffer for constructing sitemap page xml files for users with no libxml support.
+ *
+ * @since 5.3.0
+ */
+class Jetpack_Sitemap_Buffer_Page extends Jetpack_Sitemap_Buffer_Fallback {
+
+ protected function get_root_element() {
+ if ( ! isset( $this->root ) ) {
+
+ /**
+ * Filter the attribute value pairs used for namespace and namespace URI mappings.
+ *
+ * @module sitemaps
+ *
+ * @since 3.9.0
+ *
+ * @param array $namespaces Associative array with namespaces and namespace URIs.
+ */
+ $namespaces = apply_filters(
+ 'jetpack_sitemap_ns',
+ array(
+ 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
+ 'xsi:schemaLocation' => 'http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd',
+ 'xmlns' => 'http://www.sitemaps.org/schemas/sitemap/0.9',
+ )
+ );
+
+ $jetpack_version = JETPACK__VERSION;
+ $sitemap_xsl_url = $this->finder->construct_sitemap_url( 'sitemap.xsl' );
+
+ $this->root = array(
+ "<!-- generator='jetpack-{$jetpack_version}' -->" . PHP_EOL
+ . "<?xml-stylesheet type='text/xsl' href='{$sitemap_xsl_url}'?>" . PHP_EOL
+ . '<urlset ' . $this->array_to_xml_attr_string( $namespaces ) . '>',
+ '</urlset>'
+ );
+
+ $this->byte_capacity -= strlen( join( '', $this->root ) );
+ }
+
+ return $this->root;
+ }
+}
diff --git a/plugins/jetpack/modules/sitemaps/sitemap-buffer-page.php b/plugins/jetpack/modules/sitemaps/sitemap-buffer-page.php
new file mode 100644
index 00000000..d6885900
--- /dev/null
+++ b/plugins/jetpack/modules/sitemaps/sitemap-buffer-page.php
@@ -0,0 +1,67 @@
+<?php
+/**
+ * Sitemaps (per the protocol) are essentially lists of XML fragments;
+ * lists which are subject to size constraints. The Jetpack_Sitemap_Buffer_Page
+ * extends the Jetpack_Sitemap_Buffer class to represent the single page sitemap
+ * buffer.
+ *
+ * @since 5.3.0
+ * @package Jetpack
+ */
+
+/**
+ * A buffer for constructing sitemap page xml files.
+ *
+ * @since 5.3.0
+ */
+class Jetpack_Sitemap_Buffer_Page extends Jetpack_Sitemap_Buffer {
+
+ public function __construct( $item_limit, $byte_limit, $time = '1970-01-01 00:00:00' ) {
+ parent::__construct( $item_limit, $byte_limit, $time );
+
+ $this->doc->appendChild(
+ $this->doc->createComment( "generator='jetpack-" . JETPACK__VERSION . "'" )
+ );
+
+ $this->doc->appendChild(
+ $this->doc->createProcessingInstruction(
+ 'xml-stylesheet',
+ 'type="text/xsl" href="' . $this->finder->construct_sitemap_url( 'sitemap.xsl' ) . '"'
+ )
+ );
+ }
+
+ protected function get_root_element() {
+ if ( ! isset( $this->root ) ) {
+
+ /**
+ * Filter the attribute value pairs used for namespace and namespace URI mappings.
+ *
+ * @module sitemaps
+ *
+ * @since 3.9.0
+ *
+ * @param array $namespaces Associative array with namespaces and namespace URIs.
+ */
+ $namespaces = apply_filters(
+ 'jetpack_sitemap_ns',
+ array(
+ 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
+ 'xsi:schemaLocation' => 'http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd',
+ 'xmlns' => 'http://www.sitemaps.org/schemas/sitemap/0.9',
+ )
+ );
+
+ $this->root = $this->doc->createElement( 'urlset' );
+
+ foreach ( $namespaces as $name => $value ) {
+ $this->root->setAttribute( $name, $value );
+ }
+
+ $this->doc->appendChild( $this->root );
+ $this->byte_capacity -= strlen( $this->doc->saveXML( $this->root ) );
+ }
+
+ return $this->root;
+ }
+}
diff --git a/plugins/jetpack/modules/sitemaps/sitemap-buffer-video-fallback.php b/plugins/jetpack/modules/sitemaps/sitemap-buffer-video-fallback.php
new file mode 100644
index 00000000..d211877d
--- /dev/null
+++ b/plugins/jetpack/modules/sitemaps/sitemap-buffer-video-fallback.php
@@ -0,0 +1,56 @@
+<?php
+/**
+ * Sitemaps (per the protocol) are essentially lists of XML fragments;
+ * lists which are subject to size constraints. The Jetpack_Sitemap_Buffer_Video
+ * extends the Jetpack_Sitemap_Buffer class to represent the single video sitemap
+ * buffer.
+ *
+ * @since 5.3.0
+ * @package Jetpack
+ */
+
+/**
+ * A buffer for constructing sitemap video xml files for users without libxml support.
+ *
+ * @since 5.3.0
+ */
+class Jetpack_Sitemap_Buffer_Video extends Jetpack_Sitemap_Buffer_Fallback {
+
+ protected function get_root_element() {
+ if ( ! isset( $this->root ) ) {
+
+ /**
+ * Filter the XML namespaces included in video sitemaps.
+ *
+ * @module sitemaps
+ *
+ * @since 4.8.0
+ *
+ * @param array $namespaces Associative array with namespaces and namespace URIs.
+ */
+ $namespaces = apply_filters(
+ 'jetpack_sitemap_video_ns',
+ array(
+ 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
+ 'xsi:schemaLocation' => 'http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd',
+ 'xmlns' => 'http://www.sitemaps.org/schemas/sitemap/0.9',
+ 'xmlns:video' => 'http://www.google.com/schemas/sitemap-video/1.1',
+ )
+ );
+
+ $video_sitemap_xsl_url = $this->finder->construct_sitemap_url( 'video-sitemap.xsl' );
+ $jetpack_version = JETPACK__VERSION;
+
+ $this->root = array(
+ "<!-- generator='jetpack-{$jetpack_version}' -->" . PHP_EOL
+ . "<?xml-stylesheet type='text/xsl' href='{$video_sitemap_xsl_url}'?>" . PHP_EOL
+ . '<urlset ' . $this->array_to_xml_attr_string( $namespaces ) . '>',
+ '</urlset>'
+ );
+
+ $this->byte_capacity -= strlen( join( '', $this->root ) );
+ }
+
+ return $this->root;
+ }
+}
diff --git a/plugins/jetpack/modules/sitemaps/sitemap-buffer-video.php b/plugins/jetpack/modules/sitemaps/sitemap-buffer-video.php
new file mode 100644
index 00000000..c6faff36
--- /dev/null
+++ b/plugins/jetpack/modules/sitemaps/sitemap-buffer-video.php
@@ -0,0 +1,68 @@
+<?php
+/**
+ * Sitemaps (per the protocol) are essentially lists of XML fragments;
+ * lists which are subject to size constraints. The Jetpack_Sitemap_Buffer_Video
+ * extends the Jetpack_Sitemap_Buffer class to represent the single video sitemap
+ * buffer.
+ *
+ * @since 5.3.0
+ * @package Jetpack
+ */
+
+/**
+ * A buffer for constructing sitemap video xml files.
+ *
+ * @since 5.3.0
+ */
+class Jetpack_Sitemap_Buffer_Video extends Jetpack_Sitemap_Buffer {
+
+ public function __construct( $item_limit, $byte_limit, $time = '1970-01-01 00:00:00' ) {
+ parent::__construct( $item_limit, $byte_limit, $time );
+
+ $this->doc->appendChild(
+ $this->doc->createComment( "generator='jetpack-" . JETPACK__VERSION . "'" )
+ );
+
+ $this->doc->appendChild(
+ $this->doc->createProcessingInstruction(
+ 'xml-stylesheet',
+ 'type="text/xsl" href="' . $this->finder->construct_sitemap_url( 'video-sitemap.xsl' ) . '"'
+ )
+ );
+ }
+
+ protected function get_root_element() {
+ if ( ! isset( $this->root ) ) {
+
+ /**
+ * Filter the XML namespaces included in video sitemaps.
+ *
+ * @module sitemaps
+ *
+ * @since 4.8.0
+ *
+ * @param array $namespaces Associative array with namespaces and namespace URIs.
+ */
+ $namespaces = apply_filters(
+ 'jetpack_sitemap_video_ns',
+ array(
+ 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
+ 'xsi:schemaLocation' => 'http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd',
+ 'xmlns' => 'http://www.sitemaps.org/schemas/sitemap/0.9',
+ 'xmlns:video' => 'http://www.google.com/schemas/sitemap-video/1.1',
+ )
+ );
+
+ $this->root = $this->doc->createElement( 'urlset' );
+
+ foreach ( $namespaces as $name => $value ) {
+ $this->root->setAttribute( $name, $value );
+ }
+
+ $this->doc->appendChild( $this->root );
+ $this->byte_capacity -= strlen( $this->doc->saveXML( $this->root ) );
+ }
+
+ return $this->root;
+ }
+}
diff --git a/plugins/jetpack/modules/sitemaps/sitemap-buffer.php b/plugins/jetpack/modules/sitemaps/sitemap-buffer.php
index f1a8d9b1..0853a49a 100644
--- a/plugins/jetpack/modules/sitemaps/sitemap-buffer.php
+++ b/plugins/jetpack/modules/sitemaps/sitemap-buffer.php
@@ -22,70 +22,80 @@
*
* @since 4.8.0
*/
-class Jetpack_Sitemap_Buffer {
+abstract class Jetpack_Sitemap_Buffer {
/**
* Largest number of items the buffer can hold.
*
- * @access private
+ * @access protected
* @since 4.8.0
* @var int $item_capacity The item capacity.
*/
- private $item_capacity;
+ protected $item_capacity;
/**
* Largest number of bytes the buffer can hold.
*
- * @access private
+ * @access protected
* @since 4.8.0
* @var int $byte_capacity The byte capacity.
*/
- private $byte_capacity;
+ protected $byte_capacity;
/**
- * Footer text of the buffer; stored here so it can be appended when the buffer is full.
+ * Flag which detects when the buffer is full.
*
- * @access private
+ * @access protected
* @since 4.8.0
- * @var string $footer_text The footer text.
+ * @var bool $is_full_flag The flag value. This flag is set to false on construction and only flipped to true if we've tried to add something and failed.
*/
- private $footer_text;
+ protected $is_full_flag;
/**
- * The buffer contents.
+ * Flag which detects when the buffer is empty.
*
- * @access private
+ * @access protected
* @since 4.8.0
- * @var string The buffer contents.
+ * @var bool $is_empty_flag The flag value. This flag is set to true on construction and only flipped to false if we've tried to add something and succeeded.
*/
- private $buffer;
+ protected $is_empty_flag;
/**
- * Flag which detects when the buffer is full.
+ * The most recent timestamp seen by the buffer.
*
- * @access private
+ * @access protected
* @since 4.8.0
- * @var bool $is_full_flag The flag value. This flag is set to false on construction and only flipped to true if we've tried to add something and failed.
+ * @var string $timestamp Must be in 'YYYY-MM-DD hh:mm:ss' format.
*/
- private $is_full_flag;
+ protected $timestamp;
/**
- * Flag which detects when the buffer is empty.
+ * The DOM document object that is currently being used to construct the XML doc.
*
- * @access private
- * @since 4.8.0
- * @var bool $is_empty_flag The flag value. This flag is set to true on construction and only flipped to false if we've tried to add something and succeeded.
+ * @access protected
+ * @since 5.3.0
+ * @var DOMDocument $doc
*/
- private $is_empty_flag;
+ protected $doc = null;
/**
- * The most recent timestamp seen by the buffer.
+ * The root DOM element object that holds everything inside. Do not use directly, call
+ * the get_root_element getter method instead.
*
- * @access private
- * @since 4.8.0
- * @var string $timestamp Must be in 'YYYY-MM-DD hh:mm:ss' format.
+ * @access protected
+ * @since 5.3.0
+ * @var DOMElement $doc
+ */
+ protected $root = null;
+
+ /**
+ * Helper class to construct sitemap paths.
+ *
+ * @since 5.3.0
+ * @protected
+ * @var Jetpack_Sitemap_Finder
*/
- private $timestamp;
+ protected $finder;
/**
* Construct a new Jetpack_Sitemap_Buffer.
@@ -94,32 +104,29 @@ class Jetpack_Sitemap_Buffer {
*
* @param int $item_limit The maximum size of the buffer in items.
* @param int $byte_limit The maximum size of the buffer in bytes.
- * @param string $header The string to prepend to the entire buffer.
- * @param string $footer The string to append to the entire buffer.
* @param string $time The initial datetime of the buffer. Must be in 'YYYY-MM-DD hh:mm:ss' format.
*/
- public function __construct(
- $item_limit,
- $byte_limit,
- $header = '',
- $footer = '',
- $time
- ) {
- $this->item_capacity = max( 1, intval( $item_limit ) );
-
- mbstring_binary_safe_encoding(); // So we can safely use strlen().
- $this->byte_capacity = max( 1, intval( $byte_limit ) ) - strlen( $header ) - strlen( $footer );
- reset_mbstring_encoding();
-
- $this->footer_text = $footer;
- $this->buffer = $header;
+ public function __construct( $item_limit, $byte_limit, $time ) {
$this->is_full_flag = false;
- $this->is_empty_flag = true;
$this->timestamp = $time;
- return;
+
+ $this->finder = new Jetpack_Sitemap_Finder();
+ $this->doc = new DOMDocument( '1.0', 'UTF-8' );
+
+ $this->item_capacity = max( 1, intval( $item_limit ) );
+ $this->byte_capacity = max( 1, intval( $byte_limit ) ) - strlen( $this->doc->saveXML() );
}
/**
+ * Returns a DOM element that contains all sitemap elements.
+ *
+ * @access protected
+ * @since 5.3.0
+ * @return DOMElement $root
+ */
+ abstract protected function get_root_element();
+
+ /**
* Append an item to the buffer, if there is room for it,
* and set is_empty_flag to false. If there is no room,
* we set is_full_flag to true. If $item is null,
@@ -132,24 +139,45 @@ class Jetpack_Sitemap_Buffer {
* @return bool True if the append succeeded, False if not.
*/
public function try_to_add_item( $item ) {
- if ( is_null( $item ) ) {
+ _deprecated_function(
+ 'Jetpack_Sitemap_Buffer::try_to_add_item',
+ '5.3.0',
+ 'Jetpack_Sitemap_Buffer::append'
+ );
+ $this->append( $item );
+ }
+
+ /**
+ * Append an item to the buffer, if there is room for it,
+ * and set is_empty_flag to false. If there is no room,
+ * we set is_full_flag to true. If $item is null,
+ * don't do anything and report success.
+ *
+ * @since 5.3.0
+ *
+ * @param array $array The item to be added.
+ *
+ * @return bool True if the append succeeded, False if not.
+ */
+ public function append( $array ) {
+ if ( is_null( $array ) ) {
return true;
+ }
+
+ if ( $this->is_full_flag ) {
+ return false;
+ }
+
+ if ( 0 >= $this->item_capacity || 0 >= $this->byte_capacity ) {
+ $this->is_full_flag = true;
+ return false;
} else {
+ $this->item_capacity -= 1;
+ $added_element = $this->array_to_xml_string( $array, $this->get_root_element(), $this->doc );
- mbstring_binary_safe_encoding(); // So we can safely use strlen().
- $item_size = strlen( $item ); // Size in bytes.
- reset_mbstring_encoding();
+ $this->byte_capacity -= strlen( $this->doc->saveXML( $added_element ) );
- if ( 0 >= $this->item_capacity || 0 > $this->byte_capacity - $item_size ) {
- $this->is_full_flag = true;
- return false;
- } else {
- $this->is_empty_flag = false;
- $this->item_capacity -= 1;
- $this->byte_capacity -= $item_size;
- $this->buffer .= $item;
- return true;
- }
+ return true;
}
}
@@ -161,7 +189,21 @@ class Jetpack_Sitemap_Buffer {
* @return string The contents of the buffer (with the footer included).
*/
public function contents() {
- return $this->buffer . $this->footer_text;
+ if( $this->is_empty() ) {
+ // The sitemap should have at least the root element added to the DOM
+ $this->get_root_element();
+ }
+ return $this->doc->saveXML();
+ }
+
+ /**
+ * Retrieve the document object.
+ *
+ * @since 5.3.0
+ * @return DOMDocument $doc
+ */
+ public function get_document() {
+ return $this->doc;
}
/**
@@ -183,7 +225,10 @@ class Jetpack_Sitemap_Buffer {
* @return bool True if the buffer is empty, false otherwise.
*/
public function is_empty() {
- return $this->is_empty_flag;
+ return (
+ ! isset( $this->root )
+ || ! $this->root->hasChildNodes()
+ );
}
/**
@@ -195,7 +240,6 @@ class Jetpack_Sitemap_Buffer {
*/
public function view_time( $new_time ) {
$this->timestamp = max( $this->timestamp, $new_time );
- return;
}
/**
@@ -231,56 +275,52 @@ class Jetpack_Sitemap_Buffer {
* ), |</html>
* )
*
- * @access public
+ * @access protected
* @since 3.9.0
* @since 4.8.0 Rename, add $depth parameter, and change return type.
+ * @since 5.3.0 Refactor, remove $depth parameter, add $parent and $root, make access protected.
*
* @param array $array A recursive associative array of tag/child relationships.
- * @param string $depth String to prepend to each line. For internal use only.
+ * @param DOMElement $parent (optional) an element to which new children should be added.
+ * @param DOMDocument $root (optional) the parent document.
*
- * @return string The rendered XML string.
+ * @return string|DOMDocument The rendered XML string or an object if root element is specified.
*/
- public static function array_to_xml_string( $array, $depth = '' ) {
- $string = '';
-
- foreach ( $array as $key => $value ) {
+ protected function array_to_xml_string( $array, $parent = null, $root = null ) {
+ $return_string = false;
- // Only allow a-z, A-Z, colon, underscore, and hyphen.
- $tag = preg_replace( '/[^a-zA-Z:_-]/', '_', $key );
-
- if ( is_array( $value ) ) {
- $string .= $depth . "<$tag>\n";
- $string .= self::array_to_xml_string( $value, $depth . ' ' );
- $string .= $depth . "</$tag>\n";
- } elseif ( is_null( $value ) ) {
- $string .= $depth . "<$tag />\n";
- } else {
- $string .= $depth . "<$tag>" . ent2ncr( $value ) . "</$tag>\n";
- }
+ if ( null === $parent ) {
+ $return_string = true;
+ $parent = $root = new DOMDocument();
}
- return $string;
- }
+ if ( is_array( $array ) ) {
- /**
- * Render an associative array of XML attribute key/value pairs.
- *
- * @access public
- * @since 4.8.0
- *
- * @param array $array Key/value array of attributes.
- *
- * @return string The rendered attribute string.
- */
- public static function array_to_xml_attr_string( $array ) {
- $string = '';
+ foreach ( $array as $key => $value ) {
+ $element = $root->createElement( $key );
+ $parent->appendChild( $element );
- foreach ( $array as $key => $value ) {
- $key = preg_replace( '/[^a-zA-Z:_-]/', '_', $key );
- $string .= ' ' . $key . '="' . esc_attr( $value ) . '"';
+ if ( is_array( $value ) ) {
+ foreach ( $value as $child_key => $child_value ) {
+ $child = $root->createElement( $child_key );
+ $element->appendChild( $child );
+ $child->appendChild( self::array_to_xml_string( $child_value, $child, $root ) );
+ }
+ } else {
+ $element->appendChild(
+ $root->createTextNode( $value )
+ );
+ }
+ }
+ } else {
+ $element = $root->createTextNode( $array );
+ $parent->appendChild( $element );
}
- return $string;
+ if ( $return_string ) {
+ return $root->saveHTML();
+ } else {
+ return $element;
+ }
}
-
}
diff --git a/plugins/jetpack/modules/sitemaps/sitemap-builder.php b/plugins/jetpack/modules/sitemaps/sitemap-builder.php
index cfd7b9a1..9cf91c24 100644
--- a/plugins/jetpack/modules/sitemaps/sitemap-builder.php
+++ b/plugins/jetpack/modules/sitemaps/sitemap-builder.php
@@ -9,6 +9,22 @@
require_once dirname( __FILE__ ) . '/sitemap-constants.php';
require_once dirname( __FILE__ ) . '/sitemap-buffer.php';
+
+if ( ! class_exists( 'DOMDocument' ) ) {
+ require_once dirname( __FILE__ ) . '/sitemap-buffer-fallback.php';
+ require_once dirname( __FILE__ ) . '/sitemap-buffer-image-fallback.php';
+ require_once dirname( __FILE__ ) . '/sitemap-buffer-master-fallback.php';
+ require_once dirname( __FILE__ ) . '/sitemap-buffer-news-fallback.php';
+ require_once dirname( __FILE__ ) . '/sitemap-buffer-page-fallback.php';
+ require_once dirname( __FILE__ ) . '/sitemap-buffer-video-fallback.php';
+} else {
+ require_once dirname( __FILE__ ) . '/sitemap-buffer-image.php';
+ require_once dirname( __FILE__ ) . '/sitemap-buffer-master.php';
+ require_once dirname( __FILE__ ) . '/sitemap-buffer-news.php';
+ require_once dirname( __FILE__ ) . '/sitemap-buffer-page.php';
+ require_once dirname( __FILE__ ) . '/sitemap-buffer-video.php';
+}
+
require_once dirname( __FILE__ ) . '/sitemap-librarian.php';
require_once dirname( __FILE__ ) . '/sitemap-finder.php';
require_once dirname( __FILE__ ) . '/sitemap-state.php';
@@ -87,8 +103,6 @@ class Jetpack_Sitemap_Builder {
array( 'post', 'page' )
)
);
-
- return;
}
/**
@@ -101,6 +115,17 @@ class Jetpack_Sitemap_Builder {
public function update_sitemap() {
if ( $this->logger ) {
$this->logger->report( '-- Updating...' );
+ if ( ! class_exists( 'DOMDocument' ) ) {
+ $this->logger->report(
+ __(
+ '-- WARNING: Jetpack can not load necessary XML manipulation libraries. '
+ . 'This can happen if XML support in PHP is not enabled on your server. '
+ . 'XML support is highly recommended for WordPress and Jetpack, please enable '
+ . 'it or contact your hosting provider about it.',
+ 'jetpack'
+ )
+ );
+ }
}
for ( $i = 1; $i <= JP_SITEMAP_UPDATE_SIZE; $i++ ) {
@@ -201,12 +226,10 @@ class Jetpack_Sitemap_Builder {
JP_PAGE_SITEMAP_TYPE
);
die();
- }
+ } // End switch().
// Unlock the state.
Jetpack_Sitemap_State::unlock();
-
- return;
}
/**
@@ -280,8 +303,6 @@ class Jetpack_Sitemap_Builder {
$this->librarian->delete_numbered_sitemap_rows_after(
$state['number'] + 1, $sitemap_type
);
-
- return;
}
/**
@@ -387,29 +408,13 @@ class Jetpack_Sitemap_Builder {
* @since 4.8.0
*/
private function build_master_sitemap( $max ) {
- $sitemap_index_xsl_url = $this->finder->construct_sitemap_url( 'sitemap-index.xsl' );
- $jetpack_version = JETPACK__VERSION;
-
if ( $this->logger ) {
$this->logger->report( '-- Building Master Sitemap.' );
}
- $buffer = new Jetpack_Sitemap_Buffer(
+ $buffer = new Jetpack_Sitemap_Buffer_Master(
JP_SITEMAP_MAX_ITEMS,
- JP_SITEMAP_MAX_BYTES,
- <<<HEADER
-<?xml version='1.0' encoding='UTF-8'?>
-<!-- generator='jetpack-{$jetpack_version}' -->
-<?xml-stylesheet type='text/xsl' href='{$sitemap_index_xsl_url}'?>
-<sitemapindex xmlns='http://www.sitemaps.org/schemas/sitemap/0.9'>
-HEADER
- ,
- <<<FOOTER
-</sitemapindex>\n
-FOOTER
- ,
- /* epoch */
- '1970-01-01 00:00:00'
+ JP_SITEMAP_MAX_BYTES
);
if ( 0 < $max[ JP_PAGE_SITEMAP_TYPE ]['number'] ) {
@@ -424,14 +429,14 @@ FOOTER
$page['last_modified'] = jp_sitemap_datetime( $max[ JP_PAGE_SITEMAP_INDEX_TYPE ]['lastmod'] );
}
- $buffer->try_to_add_item( Jetpack_Sitemap_Buffer::array_to_xml_string(
+ $buffer->append(
array(
'sitemap' => array(
'loc' => $this->finder->construct_sitemap_url( $page['filename'] ),
'lastmod' => $page['last_modified'],
),
)
- ) );
+ );
}
if ( 0 < $max[ JP_IMAGE_SITEMAP_TYPE ]['number'] ) {
@@ -446,14 +451,14 @@ FOOTER
$image['last_modified'] = jp_sitemap_datetime( $max[ JP_IMAGE_SITEMAP_INDEX_TYPE ]['lastmod'] );
}
- $buffer->try_to_add_item( Jetpack_Sitemap_Buffer::array_to_xml_string(
+ $buffer->append(
array(
'sitemap' => array(
'loc' => $this->finder->construct_sitemap_url( $image['filename'] ),
'lastmod' => $image['last_modified'],
),
)
- ) );
+ );
}
if ( 0 < $max[ JP_VIDEO_SITEMAP_TYPE ]['number'] ) {
@@ -468,14 +473,14 @@ FOOTER
$video['last_modified'] = $max[ JP_VIDEO_SITEMAP_INDEX_TYPE ]['lastmod'];
}
- $buffer->try_to_add_item( Jetpack_Sitemap_Buffer::array_to_xml_string(
+ $buffer->append(
array(
'sitemap' => array(
'loc' => $this->finder->construct_sitemap_url( $video['filename'] ),
'lastmod' => $video['last_modified'],
),
)
- ) );
+ );
}
$this->librarian->store_sitemap_data(
@@ -484,8 +489,6 @@ FOOTER
$buffer->contents(),
''
);
-
- return;
}
/**
@@ -514,46 +517,9 @@ FOOTER
$this->logger->report( "-- Building $debug_name" );
}
- $sitemap_xsl_url = $this->finder->construct_sitemap_url( 'sitemap.xsl' );
-
- $jetpack_version = JETPACK__VERSION;
-
- $namespaces = Jetpack_Sitemap_Buffer::array_to_xml_attr_string(
- /**
- * Filter the attribute value pairs used for namespace and namespace URI mappings.
- *
- * @module sitemaps
- *
- * @since 3.9.0
- *
- * @param array $namespaces Associative array with namespaces and namespace URIs.
- */
- apply_filters(
- 'jetpack_sitemap_ns',
- array(
- 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
- 'xsi:schemaLocation' => 'http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd',
- 'xmlns' => 'http://www.sitemaps.org/schemas/sitemap/0.9',
- )
- )
- );
-
- $buffer = new Jetpack_Sitemap_Buffer(
+ $buffer = new Jetpack_Sitemap_Buffer_Page(
JP_SITEMAP_MAX_ITEMS,
- JP_SITEMAP_MAX_BYTES,
- <<<HEADER
-<?xml version='1.0' encoding='UTF-8'?>
-<!-- generator='jetpack-{$jetpack_version}' -->
-<?xml-stylesheet type='text/xsl' href='{$sitemap_xsl_url}'?>
-<urlset{$namespaces}>\n
-HEADER
- ,
- <<<FOOTER
-</urlset>\n
-FOOTER
- ,
- /* epoch */
- '1970-01-01 00:00:00'
+ JP_SITEMAP_MAX_BYTES
);
// Add entry for the main page (only if we're at the first one).
@@ -576,7 +542,7 @@ FOOTER
*/
$item_array = apply_filters( 'jetpack_sitemap_url_home', $item_array );
- $buffer->try_to_add_item( Jetpack_Sitemap_Buffer::array_to_xml_string( $item_array ) );
+ $buffer->append( $item_array );
}
// Add as many items to the buffer as possible.
@@ -593,7 +559,7 @@ FOOTER
foreach ( $posts as $post ) {
$current_item = $this->post_to_sitemap_item( $post );
- if ( true === $buffer->try_to_add_item( $current_item['xml'] ) ) {
+ if ( true === $buffer->append( $current_item['xml'] ) ) {
$last_post_id = $post->ID;
$buffer->view_time( $current_item['last_modified'] );
} else {
@@ -613,13 +579,14 @@ FOOTER
* @module sitemaps
*
* @since 3.9.0
+ * @since 5.3.0 returns an element of DOMDocument type instead of SimpleXMLElement
*
- * @param SimpleXMLElement $tree Data tree for sitemap.
+ * @param DOMDocument $doc Data tree for sitemap.
* @param string $last_modified Date of last modification.
*/
$tree = apply_filters(
'jetpack_print_sitemap',
- simplexml_load_string( $buffer->contents() ),
+ $buffer->get_document(),
$buffer->last_modified()
);
@@ -627,7 +594,7 @@ FOOTER
$this->librarian->store_sitemap_data(
$number,
JP_PAGE_SITEMAP_TYPE,
- $tree->asXML(),
+ $buffer->contents(),
$buffer->last_modified()
);
@@ -668,47 +635,9 @@ FOOTER
$this->logger->report( "-- Building $debug_name" );
}
- $image_sitemap_xsl_url = $this->finder->construct_sitemap_url( 'image-sitemap.xsl' );
-
- $jetpack_version = JETPACK__VERSION;
-
- $namespaces = Jetpack_Sitemap_Buffer::array_to_xml_attr_string(
- /**
- * Filter the XML namespaces included in image sitemaps.
- *
- * @module sitemaps
- *
- * @since 4.8.0
- *
- * @param array $namespaces Associative array with namespaces and namespace URIs.
- */
- apply_filters(
- 'jetpack_sitemap_image_ns',
- array(
- 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
- 'xsi:schemaLocation' => 'http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd',
- 'xmlns' => 'http://www.sitemaps.org/schemas/sitemap/0.9',
- 'xmlns:image' => 'http://www.google.com/schemas/sitemap-image/1.1',
- )
- )
- );
-
- $buffer = new Jetpack_Sitemap_Buffer(
+ $buffer = new Jetpack_Sitemap_Buffer_Image(
JP_SITEMAP_MAX_ITEMS,
- JP_SITEMAP_MAX_BYTES,
- <<<HEADER
-<?xml version='1.0' encoding='UTF-8'?>
-<!-- generator='jetpack-{$jetpack_version}' -->
-<?xml-stylesheet type='text/xsl' href='{$image_sitemap_xsl_url}'?>
-<urlset{$namespaces}>\n
-HEADER
- ,
- <<<FOOTER
-</urlset>\n
-FOOTER
- ,
- /* epoch */
- '1970-01-01 00:00:00'
+ JP_SITEMAP_MAX_BYTES
);
// Add as many items to the buffer as possible.
@@ -725,7 +654,7 @@ FOOTER
foreach ( $posts as $post ) {
$current_item = $this->image_post_to_sitemap_item( $post );
- if ( true === $buffer->try_to_add_item( $current_item['xml'] ) ) {
+ if ( true === $buffer->append( $current_item['xml'] ) ) {
$last_post_id = $post->ID;
$buffer->view_time( $current_item['last_modified'] );
} else {
@@ -784,47 +713,9 @@ FOOTER
$this->logger->report( "-- Building $debug_name" );
}
- $video_sitemap_xsl_url = $this->finder->construct_sitemap_url( 'video-sitemap.xsl' );
-
- $jetpack_version = JETPACK__VERSION;
-
- $namespaces = Jetpack_Sitemap_Buffer::array_to_xml_attr_string(
- /**
- * Filter the XML namespaces included in video sitemaps.
- *
- * @module sitemaps
- *
- * @since 4.8.0
- *
- * @param array $namespaces Associative array with namespaces and namespace URIs.
- */
- apply_filters(
- 'jetpack_sitemap_video_ns',
- array(
- 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
- 'xsi:schemaLocation' => 'http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd',
- 'xmlns' => 'http://www.sitemaps.org/schemas/sitemap/0.9',
- 'xmlns:video' => 'http://www.google.com/schemas/sitemap-video/1.1',
- )
- )
- );
-
- $buffer = new Jetpack_Sitemap_Buffer(
+ $buffer = new Jetpack_Sitemap_Buffer_Video(
JP_SITEMAP_MAX_ITEMS,
- JP_SITEMAP_MAX_BYTES,
- <<<HEADER
-<?xml version='1.0' encoding='UTF-8'?>
-<!-- generator='jetpack-{$jetpack_version}' -->
-<?xml-stylesheet type='text/xsl' href='{$video_sitemap_xsl_url}'?>
-<urlset{$namespaces}>\n
-HEADER
- ,
- <<<FOOTER
-</urlset>\n
-FOOTER
- ,
- /* epoch */
- '1970-01-01 00:00:00'
+ JP_SITEMAP_MAX_BYTES
);
// Add as many items to the buffer as possible.
@@ -841,7 +732,7 @@ FOOTER
foreach ( $posts as $post ) {
$current_item = $this->video_post_to_sitemap_item( $post );
- if ( true === $buffer->try_to_add_item( $current_item['xml'] ) ) {
+ if ( true === $buffer->append( $current_item['xml'] ) ) {
$last_post_id = $post->ID;
$buffer->view_time( $current_item['last_modified'] );
} else {
@@ -908,25 +799,9 @@ FOOTER
$this->logger->report( "-- Building $index_debug_name" );
}
- $sitemap_index_xsl_url = $this->finder->construct_sitemap_url( 'sitemap-index.xsl' );
-
- $jetpack_version = JETPACK__VERSION;
-
- $buffer = new Jetpack_Sitemap_Buffer(
+ $buffer = new Jetpack_Sitemap_Buffer_Master(
JP_SITEMAP_MAX_ITEMS,
JP_SITEMAP_MAX_BYTES,
- <<<HEADER
-<?xml version='1.0' encoding='UTF-8'?>
-<!-- generator='jetpack-{$jetpack_version}' -->
-<?xml-stylesheet type='text/xsl' href='{$sitemap_index_xsl_url}'?>
-<sitemapindex xmlns='http://www.sitemaps.org/schemas/sitemap/0.9'>\n
-HEADER
- ,
- <<<FOOTER
-</sitemapindex>\n
-FOOTER
- ,
- /* initial last_modified value */
$datetime
);
@@ -944,7 +819,7 @@ FOOTER
),
);
- $buffer->try_to_add_item( Jetpack_Sitemap_Buffer::array_to_xml_string( $item_array ) );
+ $buffer->append( $item_array );
}
// Add as many items to the buffer as possible.
@@ -966,7 +841,7 @@ FOOTER
$current_item = $this->sitemap_row_to_index_item( (array) $post );
// Try adding this item to the buffer.
- if ( true === $buffer->try_to_add_item( $current_item['xml'] ) ) {
+ if ( true === $buffer->append( $current_item['xml'] ) ) {
$last_sitemap_id = $post['ID'];
$buffer->view_time( $current_item['last_modified'] );
} else {
@@ -1023,7 +898,7 @@ FOOTER
);
return array(
- 'xml' => Jetpack_Sitemap_Buffer::array_to_xml_string( $item_array ),
+ 'xml' => $item_array,
'last_modified' => $row['post_date'],
);
}
@@ -1046,10 +921,6 @@ FOOTER
$this->logger->report( 'Beginning news sitemap generation.' );
}
- $news_sitemap_xsl_url = $this->finder->construct_sitemap_url( 'news-sitemap.xsl' );
-
- $jetpack_version = JETPACK__VERSION;
-
/**
* Filter limit of entries to include in news sitemap.
*
@@ -1064,43 +935,9 @@ FOOTER
JP_NEWS_SITEMAP_MAX_ITEMS
);
- $namespaces = Jetpack_Sitemap_Buffer::array_to_xml_attr_string(
- /**
- * Filter the attribute value pairs used for namespace and namespace URI mappings.
- *
- * @module sitemaps
- *
- * @since 4.8.0
- *
- * @param array $namespaces Associative array with namespaces and namespace URIs.
- */
- apply_filters(
- 'jetpack_sitemap_news_ns',
- array(
- 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
- 'xsi:schemaLocation' => 'http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd',
- 'xmlns' => 'http://www.sitemaps.org/schemas/sitemap/0.9',
- 'xmlns:news' => 'http://www.google.com/schemas/sitemap-news/0.9',
- )
- )
- );
-
- $buffer = new Jetpack_Sitemap_Buffer(
+ $buffer = new Jetpack_Sitemap_Buffer_News(
min( $item_limit, JP_NEWS_SITEMAP_MAX_ITEMS ),
- JP_SITEMAP_MAX_BYTES,
- <<<HEADER
-<?xml version='1.0' encoding='UTF-8'?>
-<!-- generator='jetpack-{$jetpack_version}' -->
-<?xml-stylesheet type='text/xsl' href='{$news_sitemap_xsl_url}'?>
-<urlset{$namespaces}>\n
-HEADER
- ,
- <<<FOOTER
-</urlset>\n
-FOOTER
- ,
- /* epoch */
- '1970-01-01 00:00:00'
+ JP_SITEMAP_MAX_BYTES
);
$posts = $this->librarian->query_most_recent_posts( JP_NEWS_SITEMAP_MAX_ITEMS );
@@ -1108,7 +945,7 @@ FOOTER
foreach ( $posts as $post ) {
$current_item = $this->post_to_news_sitemap_item( $post );
- if ( false === $buffer->try_to_add_item( $current_item['xml'] ) ) {
+ if ( false === $buffer->append( $current_item['xml'] ) ) {
break;
}
}
@@ -1124,7 +961,7 @@ FOOTER
$the_stored_news_sitemap,
JP_NEWS_SITEMAP_INTERVAL
);
- }
+ } // End if().
return $the_stored_news_sitemap;
}
@@ -1138,7 +975,7 @@ FOOTER
*
* @param WP_Post $post The post to be processed.
*
- * @return string An XML fragment representing the post URL.
+ * @return array An array representing the post URL.
*/
private function post_to_sitemap_item( $post ) {
@@ -1200,7 +1037,7 @@ FOOTER
$item_array = apply_filters( 'jetpack_sitemap_url', $item_array, $post->ID );
return array(
- 'xml' => Jetpack_Sitemap_Buffer::array_to_xml_string( $item_array ),
+ 'xml' => $item_array,
'last_modified' => $last_modified,
);
}
@@ -1236,11 +1073,11 @@ FOOTER
);
}
- $url = esc_url( wp_get_attachment_url( $post->ID ) );
+ $url = wp_get_attachment_url( $post->ID );
- $parent_url = esc_url( get_permalink( get_post( $post->post_parent ) ) );
+ $parent_url = get_permalink( get_post( $post->post_parent ) );
if ( '' == $parent_url ) { // WPCS: loose comparison ok.
- $parent_url = esc_url( get_permalink( $post ) );
+ $parent_url = get_permalink( $post );
}
$item_array = array(
@@ -1252,16 +1089,9 @@ FOOTER
),
),
);
- /** This filter is already documented in core/wp-includes/feed.php */
- $title = apply_filters( 'the_title_rss', $post->post_title );
- if ( '' !== $title ) {
- $item_array['url']['image:image']['image:title'] = htmlentities( $title );
- }
- /** This filter is already documented in core/wp-includes/feed.php */
- $caption = apply_filters( 'the_excerpt_rss', $post->post_excerpt );
- if ( '' !== $caption ) {
- $item_array['url']['image:image']['image:caption'] = "<![CDATA[" . $caption . "]]>";
- }
+
+ $item_array['url']['image:image']['image:title'] = $post->post_title;
+ $item_array['url']['image:image']['image:caption'] = $post->post_excerpt;
/**
* Filter associative array with data to build <url> node
@@ -1281,7 +1111,7 @@ FOOTER
);
return array(
- 'xml' => Jetpack_Sitemap_Buffer::array_to_xml_string( $item_array ),
+ 'xml' => $item_array,
'last_modified' => $post->post_modified_gmt,
);
}
@@ -1323,11 +1153,11 @@ FOOTER
$parent_url = esc_url( get_permalink( $post ) );
}
- // Prepare the content like get_the_content_feed()
+ // Prepare the content like get_the_content_feed().
$content = $post->post_content;
/** This filter is already documented in core/wp-includes/post-template.php */
$content = apply_filters( 'the_content', $content );
- $content = str_replace(']]>', ']]&gt;', $content);
+
/** This filter is already documented in core/wp-includes/feed.php */
$content = apply_filters( 'the_content_feed', $content, 'rss2' );
@@ -1339,7 +1169,7 @@ FOOTER
/** This filter is already documented in core/wp-includes/feed.php */
'video:title' => apply_filters( 'the_title_rss', $post->post_title ),
'video:thumbnail_loc' => '',
- 'video:description' => '<![CDATA[' . $content . ']]>',
+ 'video:description' => $content,
'video:content_loc' => esc_url( wp_get_attachment_url( $post->ID ) ),
),
),
@@ -1366,7 +1196,7 @@ FOOTER
);
return array(
- 'xml' => Jetpack_Sitemap_Buffer::array_to_xml_string( $item_array ),
+ 'xml' => $item_array,
'last_modified' => $post->post_modified_gmt,
);
}
@@ -1430,7 +1260,7 @@ FOOTER
'lastmod' => jp_sitemap_datetime( $post->post_modified_gmt ),
'news:news' => array(
'news:publication' => array(
- 'news:name' => esc_html( get_bloginfo( 'name' ) ),
+ 'news:name' => get_bloginfo( 'name' ),
'news:language' => $language,
),
/** This filter is already documented in core/wp-includes/feed.php */
@@ -1459,8 +1289,7 @@ FOOTER
);
return array(
- 'xml' => Jetpack_Sitemap_Buffer::array_to_xml_string( $item_array ),
+ 'xml' => $item_array,
);
}
-
}
diff --git a/plugins/jetpack/modules/sitemaps/sitemap-librarian.php b/plugins/jetpack/modules/sitemaps/sitemap-librarian.php
index ac895749..89a86830 100644
--- a/plugins/jetpack/modules/sitemaps/sitemap-librarian.php
+++ b/plugins/jetpack/modules/sitemaps/sitemap-librarian.php
@@ -39,7 +39,14 @@ class Jetpack_Sitemap_Librarian {
* }
*/
public function read_sitemap_data( $name, $type ) {
- $the_post = get_page_by_title( $name, 'OBJECT', $type );
+ $post_array = get_posts( array(
+ 'numberposts' => 1,
+ 'title' => $name,
+ 'post_type' => $type,
+ 'post_status' => 'draft'
+ ) );
+
+ $the_post = array_shift( $post_array );
if ( null === $the_post ) {
return null;
@@ -49,15 +56,14 @@ class Jetpack_Sitemap_Librarian {
'timestamp' => $the_post->post_date,
'name' => $the_post->post_title,
'type' => $the_post->post_type,
- 'text' => $the_post->post_content,
+ 'text' => base64_decode( $the_post->post_content ),
);
}
}
/**
* Store a sitemap of given type and index in the database.
- * Note that the sitemap contents are run through esc_html before
- * being stored, and the timestamp reencoded as 'Y-m-d H:i:s'.
+ * Note that the timestamp is reencoded as 'Y-m-d H:i:s'.
*
* If a sitemap with that type and name does not exist, create it.
* If a sitemap with that type and name does exist, update it.
@@ -73,27 +79,26 @@ class Jetpack_Sitemap_Librarian {
public function store_sitemap_data( $index, $type, $contents, $timestamp ) {
$name = jp_sitemap_filename( $type, $index );
- $the_post = get_page_by_title( $name, 'OBJECT', $type );
+ $the_post = $this->read_sitemap_data( $name, $type );
if ( null === $the_post ) {
// Post does not exist.
wp_insert_post(array(
'post_title' => $name,
- 'post_content' => esc_html( $contents ),
+ 'post_content' => base64_encode( $contents ),
'post_type' => $type,
'post_date' => date( 'Y-m-d H:i:s', strtotime( $timestamp ) ),
));
} else {
// Post does exist.
wp_insert_post(array(
- 'ID' => $the_post->ID,
+ 'ID' => $the_post['id'],
'post_title' => $name,
- 'post_content' => esc_html( $contents ),
+ 'post_content' => base64_encode( $contents ),
'post_type' => $type,
'post_date' => date( 'Y-m-d H:i:s', strtotime( $timestamp ) ),
));
}
- return;
}
/**
@@ -108,12 +113,12 @@ class Jetpack_Sitemap_Librarian {
* @return bool 'true' if a row was deleted, 'false' otherwise.
*/
public function delete_sitemap_data( $name, $type ) {
- $the_post = get_page_by_title( $name, 'OBJECT', $type );
+ $the_post = $this->read_sitemap_data( $name, $type );
if ( null === $the_post ) {
return false;
} else {
- wp_delete_post( $the_post->ID );
+ wp_delete_post( $the_post['id'] );
return true;
}
}
@@ -137,7 +142,7 @@ class Jetpack_Sitemap_Librarian {
if ( null === $row ) {
return '';
} else {
- return wp_specialchars_decode( $row['text'], ENT_QUOTES );
+ return $row['text'];
}
}
@@ -159,8 +164,6 @@ class Jetpack_Sitemap_Librarian {
$name = jp_sitemap_filename( $type, $position );
$any_left = $this->delete_sitemap_data( $name, $type );
}
-
- return;
}
/**
@@ -170,35 +173,33 @@ class Jetpack_Sitemap_Librarian {
* @since 4.8.0
*/
public function delete_all_stored_sitemap_data() {
- $this->delete_sitemap_data(
- jp_sitemap_filename( JP_MASTER_SITEMAP_TYPE ),
- JP_MASTER_SITEMAP_TYPE
- );
-
- $this->delete_numbered_sitemap_rows_after(
- 0, JP_PAGE_SITEMAP_TYPE
- );
-
- $this->delete_numbered_sitemap_rows_after(
- 0, JP_PAGE_SITEMAP_INDEX_TYPE
- );
-
- $this->delete_numbered_sitemap_rows_after(
- 0, JP_IMAGE_SITEMAP_TYPE
- );
-
- $this->delete_numbered_sitemap_rows_after(
- 0, JP_IMAGE_SITEMAP_INDEX_TYPE
- );
-
- $this->delete_numbered_sitemap_rows_after(
- 0, JP_VIDEO_SITEMAP_TYPE
- );
+ $this->delete_sitemap_type_data( JP_MASTER_SITEMAP_TYPE );
+ $this->delete_sitemap_type_data( JP_PAGE_SITEMAP_TYPE );
+ $this->delete_sitemap_type_data( JP_PAGE_SITEMAP_INDEX_TYPE );
+ $this->delete_sitemap_type_data( JP_IMAGE_SITEMAP_TYPE );
+ $this->delete_sitemap_type_data( JP_IMAGE_SITEMAP_INDEX_TYPE );
+ $this->delete_sitemap_type_data( JP_VIDEO_SITEMAP_TYPE );
+ $this->delete_sitemap_type_data( JP_VIDEO_SITEMAP_INDEX_TYPE );
+ }
- $this->delete_numbered_sitemap_rows_after(
- 0, JP_VIDEO_SITEMAP_INDEX_TYPE
- );
- return;
+ /**
+ * Deletes all sitemap data of specific type
+ *
+ * @access protected
+ * @since 5.3.0
+ *
+ * @param String $type
+ */
+ protected function delete_sitemap_type_data( $type ) {
+ $ids = get_posts( array(
+ 'post_type' => $type,
+ 'post_status' => 'draft',
+ 'fields' => 'ids'
+ ) );
+
+ foreach( $ids as $id ) {
+ wp_trash_post( $id );
+ }
}
/**
diff --git a/plugins/jetpack/modules/sitemaps/sitemaps.php b/plugins/jetpack/modules/sitemaps/sitemaps.php
index 3620957c..2c433a1d 100644
--- a/plugins/jetpack/modules/sitemaps/sitemaps.php
+++ b/plugins/jetpack/modules/sitemaps/sitemaps.php
@@ -108,6 +108,12 @@ class Jetpack_Sitemap_Manager {
10
);
+ // In case we need to purge all sitemaps, we do this.
+ add_action(
+ 'jetpack_sitemaps_purge_data',
+ array( $this, 'callback_action_purge_data' )
+ );
+
/*
* Module parameters are stored as options in the database.
* This allows us to avoid having to process all of init
@@ -434,6 +440,17 @@ class Jetpack_Sitemap_Manager {
}
/**
+ * Callback for resetting stored sitemap data.
+ *
+ * @access public
+ * @since 5.3.0
+ */
+ public function callback_action_purge_data() {
+ $this->callback_action_flush_news_sitemap_cache();
+ $this->librarian->delete_all_stored_sitemap_data();
+ }
+
+ /**
* Callback to set the sitemap location.
*
* @access public