Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 42
0.00% covered (danger)
0.00%
0 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
Jetpack_Sitemap_Buffer_Fallback
0.00% covered (danger)
0.00%
0 / 40
0.00% covered (danger)
0.00%
0 / 6
210
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
2
 append
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 1
30
 is_empty
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 contents
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 array_to_xml_string
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
20
 array_to_xml_attr_string
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
6
1<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
2/**
3 * The fallback buffer for users with no XML support.
4 *
5 * @since 5.3.0
6 * @package automattic/jetpack
7 */
8
9if ( ! defined( 'ABSPATH' ) ) {
10    exit( 0 );
11}
12
13/**
14 * A buffer for constructing master sitemap xml files.
15 *
16 * @since 5.1.0
17 */
18abstract class Jetpack_Sitemap_Buffer_Fallback extends Jetpack_Sitemap_Buffer {
19
20    /**
21     * The buffer contents.
22     *
23     * @access protected
24     * @since 5.3.0
25     * @var string The buffer contents.
26     */
27    protected $buffer;
28
29    /**
30     * Jetpack_Sitemap_Buffer_Fallback constructor.
31     *
32     * @param int    $item_limit The maximum size of the buffer in items.
33     * @param int    $byte_limit The maximum size of the buffer in bytes.
34     * @param string $time The initial datetime of the buffer. Must be in 'YYYY-MM-DD hh:mm:ss' format.
35     */
36    public function __construct( $item_limit, $byte_limit, $time = '1970-01-01 00:00:00' ) {
37        $this->is_full_flag  = false;
38        $this->is_empty_flag = true;
39        $this->timestamp     = $time;
40
41        $this->finder = new Jetpack_Sitemap_Finder();
42
43        $this->item_capacity = max( 1, (int) $item_limit );
44        $this->byte_capacity = max( 1, (int) $byte_limit ) - strlen( $this->contents() );
45    }
46
47    /**
48     * Append an item to the buffer, if there is room for it,
49     * and set is_empty_flag to false. If there is no room,
50     * we set is_full_flag to true. If $item is null,
51     * don't do anything and report success.
52     *
53     * @since 5.3.0
54     *
55     * @param array $array The item to be added.
56     *
57     * @return bool True if the append succeeded, False if not.
58     */
59    public function append( $array ) {
60        if ( $array === null ) {
61            return true;
62        }
63
64        if ( $this->is_full_flag ) {
65            return false;
66        }
67
68        if ( 0 >= $this->item_capacity || 0 >= $this->byte_capacity ) {
69            $this->is_full_flag = true;
70            return false;
71        } else {
72            $this->item_capacity -= 1;
73            $added_string         = $this->array_to_xml_string( $array );
74            $this->buffer        .= $added_string;
75            $this->is_empty_flag  = false;
76
77            mbstring_binary_safe_encoding(); // So we can safely use strlen().
78            $this->byte_capacity -= strlen( $added_string );
79            reset_mbstring_encoding();
80
81            return true;
82        }
83    }
84
85    /**
86     * Detect whether the buffer is empty.
87     *
88     * @since 5.3.0
89     *
90     * @return bool True if the buffer is empty, false otherwise.
91     */
92    public function is_empty() {
93        return $this->is_empty_flag;
94    }
95
96    /**
97     * Retrieve the contents of the buffer.
98     *
99     * @since 5.3.0
100     *
101     * @return string The contents of the buffer (with the footer included).
102     */
103    public function contents() {
104        $root = $this->get_root_element();
105
106        return '<?xml version="1.0" encoding="UTF-8"?>' . PHP_EOL . $root[0] . $this->buffer . $root[1] . PHP_EOL;
107    }
108
109    /**
110     * Legacy implementation of array to XML conversion without using DOMDocument.
111     *
112     * @param array       $array Item to append to buffer.
113     * @param DOMElement  $parent (optional) an element to which new children should be added.
114     * @param DOMDocument $root (optional) the parent document.
115     * @return String $result
116     */
117    public function array_to_xml_string( $array, $parent = null, $root = null ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
118        $string = '';
119
120        foreach ( $array as $key => $value ) {
121            // Only allow a-z, A-Z, colon, underscore, and hyphen.
122            $tag = preg_replace( '/[^a-zA-Z:_-]/', '_', $key );
123
124            if ( is_array( $value ) ) {
125                $string .= "<$tag>";
126                $string .= $this->array_to_xml_string( $value );
127                $string .= "</$tag>";
128            } elseif ( $value === null ) {
129                $string .= "<$tag />";
130            } else {
131                $string .= "<$tag>" . htmlspecialchars( $value, ENT_COMPAT ) . "</$tag>";
132            }
133        }
134
135        return $string;
136    }
137
138    /**
139     * Render an associative array of XML attribute key/value pairs.
140     *
141     * @access public
142     * @since 5.3.0
143     *
144     * @param array $array Key/value array of attributes.
145     *
146     * @return string The rendered attribute string.
147     */
148    public static function array_to_xml_attr_string( $array ) {
149        $string = '';
150
151        foreach ( $array as $key => $value ) {
152            $key     = preg_replace( '/[^a-zA-Z:_-]/', '_', $key );
153            $string .= ' ' . $key . '="' . esc_attr( $value ) . '"';
154        }
155
156        return $string;
157    }
158}