Edit File by line
/home/zeestwma/richards.../wp-conte.../plugins/jetpack/modules/sitemaps
File: sitemap-buffer-xmlwriter.php
<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
[0] Fix | Delete
/**
[1] Fix | Delete
* XMLWriter implementation of the sitemap buffer.
[2] Fix | Delete
*
[3] Fix | Delete
* @since 14.6
[4] Fix | Delete
* @package automattic/jetpack
[5] Fix | Delete
*/
[6] Fix | Delete
[7] Fix | Delete
if ( ! defined( 'ABSPATH' ) ) {
[8] Fix | Delete
exit( 0 );
[9] Fix | Delete
}
[10] Fix | Delete
[11] Fix | Delete
/**
[12] Fix | Delete
* A buffer for constructing sitemap xml files using XMLWriter.
[13] Fix | Delete
*
[14] Fix | Delete
* @since 14.6
[15] Fix | Delete
*/
[16] Fix | Delete
abstract class Jetpack_Sitemap_Buffer_XMLWriter {
[17] Fix | Delete
[18] Fix | Delete
/**
[19] Fix | Delete
* Largest number of items the buffer can hold.
[20] Fix | Delete
*
[21] Fix | Delete
* @access protected
[22] Fix | Delete
* @since 14.6
[23] Fix | Delete
* @var int $item_capacity The item capacity.
[24] Fix | Delete
*/
[25] Fix | Delete
protected $item_capacity;
[26] Fix | Delete
[27] Fix | Delete
/**
[28] Fix | Delete
* Largest number of bytes the buffer can hold.
[29] Fix | Delete
*
[30] Fix | Delete
* @access protected
[31] Fix | Delete
* @since 14.6
[32] Fix | Delete
* @var int $byte_capacity The byte capacity.
[33] Fix | Delete
*/
[34] Fix | Delete
protected $byte_capacity;
[35] Fix | Delete
[36] Fix | Delete
/**
[37] Fix | Delete
* Flag which detects when the buffer is full.
[38] Fix | Delete
*
[39] Fix | Delete
* @access protected
[40] Fix | Delete
* @since 14.6
[41] Fix | Delete
* @var bool $is_full_flag The flag value.
[42] Fix | Delete
*/
[43] Fix | Delete
protected $is_full_flag;
[44] Fix | Delete
[45] Fix | Delete
/**
[46] Fix | Delete
* Flag which detects when the buffer is empty.
[47] Fix | Delete
* Set true on construction and flipped to false only after a successful append.
[48] Fix | Delete
*
[49] Fix | Delete
* @since 15.0
[50] Fix | Delete
* @var bool
[51] Fix | Delete
*/
[52] Fix | Delete
protected $is_empty_flag = true;
[53] Fix | Delete
[54] Fix | Delete
/**
[55] Fix | Delete
* The most recent timestamp seen by the buffer.
[56] Fix | Delete
*
[57] Fix | Delete
* @access protected
[58] Fix | Delete
* @since 14.6
[59] Fix | Delete
* @var string $timestamp Must be in 'YYYY-MM-DD hh:mm:ss' format.
[60] Fix | Delete
*/
[61] Fix | Delete
protected $timestamp;
[62] Fix | Delete
[63] Fix | Delete
/**
[64] Fix | Delete
* The XMLWriter instance used to construct the XML.
[65] Fix | Delete
*
[66] Fix | Delete
* @access protected
[67] Fix | Delete
* @since 14.6
[68] Fix | Delete
* @var XMLWriter $writer
[69] Fix | Delete
*/
[70] Fix | Delete
protected $writer;
[71] Fix | Delete
[72] Fix | Delete
/**
[73] Fix | Delete
* Helper class to construct sitemap paths.
[74] Fix | Delete
*
[75] Fix | Delete
* @since 14.6
[76] Fix | Delete
* @protected
[77] Fix | Delete
* @var Jetpack_Sitemap_Finder
[78] Fix | Delete
*/
[79] Fix | Delete
protected $finder;
[80] Fix | Delete
[81] Fix | Delete
/**
[82] Fix | Delete
* The XML content chunks collected from XMLWriter.
[83] Fix | Delete
*
[84] Fix | Delete
* Collect chunks and join once at the end to reduce string reallocations
[85] Fix | Delete
* and improve performance on large sitemaps.
[86] Fix | Delete
*
[87] Fix | Delete
* @access protected
[88] Fix | Delete
* @since 15.0
[89] Fix | Delete
* @var array $chunks
[90] Fix | Delete
*/
[91] Fix | Delete
protected $chunks = array();
[92] Fix | Delete
[93] Fix | Delete
/**
[94] Fix | Delete
* Tracks whether the root element has been started.
[95] Fix | Delete
*
[96] Fix | Delete
* @since 15.0
[97] Fix | Delete
* @var bool
[98] Fix | Delete
*/
[99] Fix | Delete
protected $root_started = false;
[100] Fix | Delete
[101] Fix | Delete
/**
[102] Fix | Delete
* Mirror DOMDocument built on-demand for jetpack_print_sitemap compatibility.
[103] Fix | Delete
*
[104] Fix | Delete
* @since 15.0
[105] Fix | Delete
* @var DOMDocument|null
[106] Fix | Delete
*/
[107] Fix | Delete
protected $dom_document = null;
[108] Fix | Delete
[109] Fix | Delete
/**
[110] Fix | Delete
* Tracks whether XMLWriter document has been finalized (closed and flushed).
[111] Fix | Delete
*
[112] Fix | Delete
* @since 15.0
[113] Fix | Delete
* @var bool
[114] Fix | Delete
*/
[115] Fix | Delete
protected $is_finalized = false;
[116] Fix | Delete
[117] Fix | Delete
/**
[118] Fix | Delete
* Construct a new Jetpack_Sitemap_Buffer_XMLWriter.
[119] Fix | Delete
*
[120] Fix | Delete
* @since 14.6
[121] Fix | Delete
*
[122] Fix | Delete
* @param int $item_limit The maximum size of the buffer in items.
[123] Fix | Delete
* @param int $byte_limit The maximum size of the buffer in bytes.
[124] Fix | Delete
* @param string $time The initial datetime of the buffer. Must be in 'YYYY-MM-DD hh:mm:ss' format.
[125] Fix | Delete
*/
[126] Fix | Delete
public function __construct( $item_limit, $byte_limit, $time ) {
[127] Fix | Delete
$this->is_full_flag = false;
[128] Fix | Delete
$this->is_empty_flag = true;
[129] Fix | Delete
$this->timestamp = $time;
[130] Fix | Delete
$this->finder = new Jetpack_Sitemap_Finder();
[131] Fix | Delete
[132] Fix | Delete
$this->writer = new XMLWriter();
[133] Fix | Delete
$this->writer->openMemory();
[134] Fix | Delete
$this->writer->setIndent( true );
[135] Fix | Delete
$this->writer->startDocument( '1.0', 'UTF-8' );
[136] Fix | Delete
[137] Fix | Delete
$this->item_capacity = max( 1, (int) $item_limit );
[138] Fix | Delete
$this->byte_capacity = max( 1, (int) $byte_limit );
[139] Fix | Delete
[140] Fix | Delete
// Capture and account the XML declaration bytes to mirror DOM behavior.
[141] Fix | Delete
$declaration = $this->writer->outputMemory( true );
[142] Fix | Delete
$this->chunks[] = $declaration;
[143] Fix | Delete
$this->byte_capacity -= strlen( $declaration );
[144] Fix | Delete
[145] Fix | Delete
// Allow subclasses to write comments and processing instructions only.
[146] Fix | Delete
$this->initialize_buffer();
[147] Fix | Delete
[148] Fix | Delete
// Capture pre-root bytes (comments/PI). Do not subtract from capacity.
[149] Fix | Delete
$pre_root_output = $this->writer->outputMemory( true );
[150] Fix | Delete
$this->chunks[] = $pre_root_output;
[151] Fix | Delete
}
[152] Fix | Delete
[153] Fix | Delete
/**
[154] Fix | Delete
* Initialize the buffer with any required headers or setup.
[155] Fix | Delete
* This should be implemented by child classes.
[156] Fix | Delete
*
[157] Fix | Delete
* @access protected
[158] Fix | Delete
* @since 14.6
[159] Fix | Delete
*/
[160] Fix | Delete
abstract protected function initialize_buffer();
[161] Fix | Delete
[162] Fix | Delete
/**
[163] Fix | Delete
* Start the root element (e.g., urlset or sitemapindex) and write its attributes.
[164] Fix | Delete
* Implemented by subclasses.
[165] Fix | Delete
*
[166] Fix | Delete
* @since 15.0
[167] Fix | Delete
* @access protected
[168] Fix | Delete
* @return void
[169] Fix | Delete
*/
[170] Fix | Delete
abstract protected function start_root();
[171] Fix | Delete
[172] Fix | Delete
/**
[173] Fix | Delete
* Ensure the root element has been started and account its bytes once.
[174] Fix | Delete
*
[175] Fix | Delete
* @since 15.0
[176] Fix | Delete
* @access protected
[177] Fix | Delete
* @return void
[178] Fix | Delete
*/
[179] Fix | Delete
protected function ensure_root_started() {
[180] Fix | Delete
if ( $this->root_started ) {
[181] Fix | Delete
return;
[182] Fix | Delete
}
[183] Fix | Delete
$this->start_root();
[184] Fix | Delete
$root_chunk = $this->writer->outputMemory( true );
[185] Fix | Delete
$this->chunks[] = $root_chunk;
[186] Fix | Delete
$this->byte_capacity -= strlen( $root_chunk );
[187] Fix | Delete
$this->root_started = true;
[188] Fix | Delete
}
[189] Fix | Delete
[190] Fix | Delete
/**
[191] Fix | Delete
* Finalize writer output once by closing the root and document and flushing.
[192] Fix | Delete
*
[193] Fix | Delete
* @since 15.0
[194] Fix | Delete
* @access protected
[195] Fix | Delete
* @return void
[196] Fix | Delete
*/
[197] Fix | Delete
protected function finalize_writer_output() {
[198] Fix | Delete
if ( $this->is_finalized ) {
[199] Fix | Delete
return;
[200] Fix | Delete
}
[201] Fix | Delete
$this->ensure_root_started();
[202] Fix | Delete
$this->writer->endElement(); // End root element (urlset/sitemapindex)
[203] Fix | Delete
$this->writer->endDocument();
[204] Fix | Delete
$final_content = $this->writer->outputMemory( true );
[205] Fix | Delete
$this->chunks[] = $final_content;
[206] Fix | Delete
$this->is_finalized = true;
[207] Fix | Delete
}
[208] Fix | Delete
[209] Fix | Delete
/**
[210] Fix | Delete
* Append an item to the buffer.
[211] Fix | Delete
*
[212] Fix | Delete
* @since 14.6
[213] Fix | Delete
*
[214] Fix | Delete
* @param array $array The item to be added.
[215] Fix | Delete
* @return bool True if the append succeeded, False if not.
[216] Fix | Delete
*/
[217] Fix | Delete
public function append( $array ) {
[218] Fix | Delete
if ( $array === null ) {
[219] Fix | Delete
return true;
[220] Fix | Delete
}
[221] Fix | Delete
[222] Fix | Delete
if ( $this->is_full_flag ) {
[223] Fix | Delete
return false;
[224] Fix | Delete
}
[225] Fix | Delete
[226] Fix | Delete
if ( 0 >= $this->item_capacity || 0 >= $this->byte_capacity ) {
[227] Fix | Delete
$this->is_full_flag = true;
[228] Fix | Delete
return false;
[229] Fix | Delete
}
[230] Fix | Delete
[231] Fix | Delete
// Ensure root is started on first append and account its bytes.
[232] Fix | Delete
$this->ensure_root_started();
[233] Fix | Delete
[234] Fix | Delete
// Attempt to render the item. Subclasses may decide to skip writing
[235] Fix | Delete
// if the input structure is invalid for that sitemap type.
[236] Fix | Delete
$this->append_item( $array );
[237] Fix | Delete
[238] Fix | Delete
// Capture only the bytes produced by this item.
[239] Fix | Delete
$new_content = $this->writer->outputMemory( true );
[240] Fix | Delete
[241] Fix | Delete
// If nothing was written, treat as a no-op: keep the buffer "empty"
[242] Fix | Delete
// and do not consume item/byte capacities.
[243] Fix | Delete
if ( '' === $new_content ) {
[244] Fix | Delete
return true;
[245] Fix | Delete
}
[246] Fix | Delete
[247] Fix | Delete
// Persist newly written bytes and update capacities.
[248] Fix | Delete
$this->chunks[] = $new_content;
[249] Fix | Delete
$this->item_capacity -= 1;
[250] Fix | Delete
$this->byte_capacity -= strlen( $new_content );
[251] Fix | Delete
$this->is_empty_flag = false;
[252] Fix | Delete
[253] Fix | Delete
// Check both capacity limits.
[254] Fix | Delete
if ( 0 >= $this->item_capacity || $this->byte_capacity <= 0 ) {
[255] Fix | Delete
$this->is_full_flag = true;
[256] Fix | Delete
}
[257] Fix | Delete
[258] Fix | Delete
return true;
[259] Fix | Delete
}
[260] Fix | Delete
[261] Fix | Delete
/**
[262] Fix | Delete
* Append a specific item to the buffer.
[263] Fix | Delete
* This should be implemented by child classes.
[264] Fix | Delete
*
[265] Fix | Delete
* @access protected
[266] Fix | Delete
* @since 14.6
[267] Fix | Delete
* @param array $array The item to be added.
[268] Fix | Delete
*/
[269] Fix | Delete
abstract protected function append_item( $array );
[270] Fix | Delete
[271] Fix | Delete
/**
[272] Fix | Delete
* Recursively writes XML elements from an associative array.
[273] Fix | Delete
*
[274] Fix | Delete
* This method iterates through an array and writes XML elements using the XMLWriter instance.
[275] Fix | Delete
* If a value in the array is itself an array, it calls itself recursively.
[276] Fix | Delete
*
[277] Fix | Delete
* @access protected
[278] Fix | Delete
* @since 15.0
[279] Fix | Delete
*
[280] Fix | Delete
* @param array $data The array to convert to XML.
[281] Fix | Delete
*/
[282] Fix | Delete
protected function array_to_xml( $data ) {
[283] Fix | Delete
foreach ( (array) $data as $tag => $value ) {
[284] Fix | Delete
if ( is_array( $value ) ) {
[285] Fix | Delete
$this->writer->startElement( $tag );
[286] Fix | Delete
$this->array_to_xml( $value );
[287] Fix | Delete
$this->writer->endElement();
[288] Fix | Delete
} else {
[289] Fix | Delete
// Write raw text; XMLWriter will escape XML-reserved chars, matching DOMDocument behavior.
[290] Fix | Delete
$this->writer->writeElement( $tag, (string) $value );
[291] Fix | Delete
}
[292] Fix | Delete
}
[293] Fix | Delete
}
[294] Fix | Delete
[295] Fix | Delete
/**
[296] Fix | Delete
* Retrieve the contents of the buffer.
[297] Fix | Delete
*
[298] Fix | Delete
* @since 14.6
[299] Fix | Delete
* @return string The contents of the buffer.
[300] Fix | Delete
*/
[301] Fix | Delete
public function contents() {
[302] Fix | Delete
$this->finalize_writer_output();
[303] Fix | Delete
if ( $this->dom_document instanceof DOMDocument ) {
[304] Fix | Delete
return $this->dom_document->saveXML();
[305] Fix | Delete
}
[306] Fix | Delete
if ( empty( $this->chunks ) ) {
[307] Fix | Delete
// If buffer is empty, return a minimal valid XML structure
[308] Fix | Delete
return "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\"></urlset>";
[309] Fix | Delete
}
[310] Fix | Delete
return implode( '', $this->chunks );
[311] Fix | Delete
}
[312] Fix | Delete
[313] Fix | Delete
/**
[314] Fix | Delete
* Detect whether the buffer is full.
[315] Fix | Delete
*
[316] Fix | Delete
* @since 14.6
[317] Fix | Delete
* @return bool True if the buffer is full, false otherwise.
[318] Fix | Delete
*/
[319] Fix | Delete
public function is_full() {
[320] Fix | Delete
return $this->is_full_flag;
[321] Fix | Delete
}
[322] Fix | Delete
[323] Fix | Delete
/**
[324] Fix | Delete
* Detect whether the buffer is empty.
[325] Fix | Delete
*
[326] Fix | Delete
* @since 14.6
[327] Fix | Delete
* @return bool True if the buffer is empty, false otherwise.
[328] Fix | Delete
*/
[329] Fix | Delete
public function is_empty() {
[330] Fix | Delete
return $this->is_empty_flag;
[331] Fix | Delete
}
[332] Fix | Delete
[333] Fix | Delete
/**
[334] Fix | Delete
* Update the timestamp of the buffer.
[335] Fix | Delete
*
[336] Fix | Delete
* @since 14.6
[337] Fix | Delete
* @param string $new_time A datetime string in 'YYYY-MM-DD hh:mm:ss' format.
[338] Fix | Delete
*/
[339] Fix | Delete
public function view_time( $new_time ) {
[340] Fix | Delete
$this->timestamp = max( $this->timestamp, $new_time );
[341] Fix | Delete
}
[342] Fix | Delete
[343] Fix | Delete
/**
[344] Fix | Delete
* Retrieve the timestamp of the buffer.
[345] Fix | Delete
*
[346] Fix | Delete
* @since 14.6
[347] Fix | Delete
* @return string A datetime string in 'YYYY-MM-DD hh:mm:ss' format.
[348] Fix | Delete
*/
[349] Fix | Delete
public function last_modified() {
[350] Fix | Delete
return $this->timestamp;
[351] Fix | Delete
}
[352] Fix | Delete
[353] Fix | Delete
/**
[354] Fix | Delete
* Compatibility method for the old DOMDocument implementation.
[355] Fix | Delete
* This is only here to satisfy the jetpack_print_sitemap filter.
[356] Fix | Delete
*
[357] Fix | Delete
* @since 14.6
[358] Fix | Delete
* @return DOMDocument DOM representation of the current sitemap contents.
[359] Fix | Delete
*/
[360] Fix | Delete
public function get_document() {
[361] Fix | Delete
if ( $this->dom_document instanceof DOMDocument ) {
[362] Fix | Delete
return $this->dom_document;
[363] Fix | Delete
}
[364] Fix | Delete
[365] Fix | Delete
$this->finalize_writer_output();
[366] Fix | Delete
[367] Fix | Delete
$dom = new DOMDocument( '1.0', 'UTF-8' );
[368] Fix | Delete
$dom->formatOutput = true; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
[369] Fix | Delete
$dom->preserveWhiteSpace = false; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
[370] Fix | Delete
// Load current XML content into DOM for compatibility with filters.
[371] Fix | Delete
@$dom->loadXML( implode( '', $this->chunks ) ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged -- Avoid fatal on unexpected content
[372] Fix | Delete
[373] Fix | Delete
$this->dom_document = $dom;
[374] Fix | Delete
return $this->dom_document;
[375] Fix | Delete
}
[376] Fix | Delete
}
[377] Fix | Delete
[378] Fix | Delete
It is recommended that you Edit text format, this type of Fix handles quite a lot in one request
Function