Completed
Push — try/empty-sitemap-instead-of-4... ( 99f0a9 )
by
unknown
07:27
created

Jetpack_Sitemap_Buffer_Empty   A

Complexity

Total Complexity 3

Size/Duplication

Total Lines 28
Duplicated Lines 35.71 %

Coupling/Cohesion

Components 1
Dependencies 2

Importance

Changes 0
Metric Value
dl 10
loc 28
rs 10
c 0
b 0
f 0
wmc 3
lcom 1
cbo 2

2 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 14 1
A get_root_element() 10 10 2

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
/**
3
 * Build the sitemap tree.
4
 *
5
 * @package Jetpack
6
 * @since 4.8.0
7
 * @author Automattic
8
 */
9
10
/* Include sitemap subclasses, if not already, and include proper buffer based on phpxml's availability. */
11
require_once dirname( __FILE__ ) . '/sitemap-constants.php';
12
require_once dirname( __FILE__ ) . '/sitemap-buffer.php';
13
14
if ( ! class_exists( 'DOMDocument' ) ) {
15
	require_once dirname( __FILE__ ) . '/sitemap-buffer-fallback.php';
16
	require_once dirname( __FILE__ ) . '/sitemap-buffer-image-fallback.php';
17
	require_once dirname( __FILE__ ) . '/sitemap-buffer-master-fallback.php';
18
	require_once dirname( __FILE__ ) . '/sitemap-buffer-news-fallback.php';
19
	require_once dirname( __FILE__ ) . '/sitemap-buffer-page-fallback.php';
20
	require_once dirname( __FILE__ ) . '/sitemap-buffer-video-fallback.php';
21
} else {
22
	require_once dirname( __FILE__ ) . '/sitemap-buffer-image.php';
23
	require_once dirname( __FILE__ ) . '/sitemap-buffer-master.php';
24
	require_once dirname( __FILE__ ) . '/sitemap-buffer-news.php';
25
	require_once dirname( __FILE__ ) . '/sitemap-buffer-page.php';
26
	require_once dirname( __FILE__ ) . '/sitemap-buffer-video.php';
27
}
28
29
require_once dirname( __FILE__ ) . '/sitemap-librarian.php';
30
require_once dirname( __FILE__ ) . '/sitemap-finder.php';
31
require_once dirname( __FILE__ ) . '/sitemap-state.php';
32
33
if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
34
	require_once dirname( __FILE__ ) . '/sitemap-logger.php';
35
}
36
37
/**
38
 * Simple class for rendering an empty sitemap with a short TTL
39
 */
40
class Jetpack_Sitemap_Buffer_Empty extends Jetpack_Sitemap_Buffer {
41
42
	public function __construct() {
43
		parent::__construct( JP_SITEMAP_MAX_ITEMS, JP_SITEMAP_MAX_BYTES, '1970-01-01 00:00:00' );
44
45
		$this->doc->appendChild(
46
			$this->doc->createComment( "generator='jetpack-" . JETPACK__VERSION . "'" )
47
		);
48
49
		$this->doc->appendChild(
50
			$this->doc->createProcessingInstruction(
51
				'xml-stylesheet',
52
				'type="text/xsl" href="' . $this->finder->construct_sitemap_url( 'sitemap-index.xsl' ) . '"'
53
			)
54
		);
55
	}
56
57 View Code Duplication
	protected function get_root_element() {
58
		if ( ! isset( $this->root ) ) {
59
			$this->root = $this->doc->createElement( 'sitemapindex' );
60
			$this->root->setAttribute( 'xmlns', 'http://www.sitemaps.org/schemas/sitemap/0.9' );
61
			$this->doc->appendChild( $this->root );
62
			$this->byte_capacity -= strlen( $this->doc->saveXML( $this->root ) );
63
		}
64
65
		return $this->root;
66
	}
67
}
68
69
/**
70
 * The Jetpack_Sitemap_Builder object handles the construction of
71
 * all sitemap files (except the XSL files, which are handled by
72
 * Jetpack_Sitemap_Stylist.) Other than the constructor, there are
73
 * only two public functions: build_all_sitemaps and news_sitemap_xml.
74
 *
75
 * @since 4.8.0
76
 */
77
class Jetpack_Sitemap_Builder {
78
79
	/**
80
	 * Librarian object for storing and retrieving sitemap data.
81
	 *
82
	 * @access private
83
	 * @since 4.8.0
84
	 * @var $librarian Jetpack_Sitemap_Librarian
85
	 */
86
	private $librarian;
87
88
	/**
89
	 * Logger object for reporting debug messages.
90
	 *
91
	 * @access private
92
	 * @since 4.8.0
93
	 * @var $logger Jetpack_Sitemap_Logger
94
	 */
95
	private $logger = false;
96
97
	/**
98
	 * Finder object for dealing with sitemap URIs.
99
	 *
100
	 * @access private
101
	 * @since 4.8.0
102
	 * @var $finder Jetpack_Sitemap_Finder
103
	 */
104
	private $finder;
105
106
	/**
107
	 * Construct a new Jetpack_Sitemap_Builder object.
108
	 *
109
	 * @access public
110
	 * @since 4.8.0
111
	 */
112
	public function __construct() {
113
		$this->librarian = new Jetpack_Sitemap_Librarian();
114
		$this->finder    = new Jetpack_Sitemap_Finder();
115
116
		if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
117
			$this->logger = new Jetpack_Sitemap_Logger();
0 ignored issues
show
Documentation Bug introduced by
It seems like new \Jetpack_Sitemap_Logger() of type object<Jetpack_Sitemap_Logger> is incompatible with the declared type boolean of property $logger.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
118
		}
119
120
		update_option(
121
			'jetpack_sitemap_post_types',
122
			/**
123
			 * The array of post types to be included in the sitemap.
124
			 *
125
			 * Add your custom post type name to the array to have posts of
126
			 * that type included in the sitemap. The default array includes
127
			 * 'page' and 'post'.
128
			 *
129
			 * The result of this filter is cached in an option, 'jetpack_sitemap_post_types',
130
			 * so this filter only has to be applied once per generation.
131
			 *
132
			 * @since 4.8.0
133
			 */
134
			apply_filters(
135
				'jetpack_sitemap_post_types',
136
				array( 'post', 'page' )
137
			)
138
		);
139
	}
140
141
	/**
142
	 * Update the sitemap.
143
	 *
144
	 * All we do here is call build_next_sitemap_file a bunch of times.
145
	 *
146
	 * @since 4.8.0
147
	 */
148
	public function update_sitemap() {
149
		if ( $this->logger ) {
150
			$this->logger->report( '-- Updating...' );
0 ignored issues
show
Bug introduced by
The method report cannot be called on $this->logger (of type boolean).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
151
			if ( ! class_exists( 'DOMDocument' ) ) {
152
				$this->logger->report(
0 ignored issues
show
Bug introduced by
The method report cannot be called on $this->logger (of type boolean).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
153
					__(
154
						'-- 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.',
155
						'jetpack'
156
					),
157
					true
158
				);
159
			}
160
		}
161
162
		for ( $i = 1; $i <= JP_SITEMAP_UPDATE_SIZE; $i++ ) {
163
			if ( true === $this->build_next_sitemap_file() ) {
164
				break; // All finished!
165
			}
166
		}
167
168
		if ( $this->logger ) {
169
			$this->logger->report( '-- ...done for now.' );
0 ignored issues
show
Bug introduced by
The method report cannot be called on $this->logger (of type boolean).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
170
			$this->logger->time();
0 ignored issues
show
Bug introduced by
The method time cannot be called on $this->logger (of type boolean).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
171
		}
172
	}
173
174
	/**
175
	 * Generate the next sitemap file.
176
	 *
177
	 * Reads the most recent state of the sitemap generation phase,
178
	 * constructs the next file, and updates the state.
179
	 *
180
	 * @since 4.8.0
181
	 *
182
	 * @return bool True when finished.
183
	 */
184
	private function build_next_sitemap_file() {
185
		$finished = false; // Initialize finished flag.
186
187
		// Get the most recent state, and lock the state.
188
		$state = Jetpack_Sitemap_State::check_out();
189
190
		// Do nothing if the state was locked.
191
		if ( false === $state ) {
192
			return false;
193
		}
194
195
		// Otherwise, branch on the sitemap-type key of $state.
196
		switch ( $state['sitemap-type'] ) {
197
			case JP_PAGE_SITEMAP_TYPE:
198
				$this->build_next_sitemap_of_type(
199
					JP_PAGE_SITEMAP_TYPE,
200
					array( $this, 'build_one_page_sitemap' ),
201
					$state
0 ignored issues
show
Bug introduced by
It seems like $state defined by \Jetpack_Sitemap_State::check_out() on line 188 can also be of type boolean; however, Jetpack_Sitemap_Builder:..._next_sitemap_of_type() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
202
				);
203
				break;
204
205
			case JP_PAGE_SITEMAP_INDEX_TYPE:
206
				$this->build_next_sitemap_index_of_type(
207
					JP_PAGE_SITEMAP_INDEX_TYPE,
208
					JP_IMAGE_SITEMAP_TYPE,
209
					$state
0 ignored issues
show
Bug introduced by
It seems like $state defined by \Jetpack_Sitemap_State::check_out() on line 188 can also be of type boolean; however, Jetpack_Sitemap_Builder:...sitemap_index_of_type() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
210
				);
211
				break;
212
213
			case JP_IMAGE_SITEMAP_TYPE:
214
				$this->build_next_sitemap_of_type(
215
					JP_IMAGE_SITEMAP_TYPE,
216
					array( $this, 'build_one_image_sitemap' ),
217
					$state
0 ignored issues
show
Bug introduced by
It seems like $state defined by \Jetpack_Sitemap_State::check_out() on line 188 can also be of type boolean; however, Jetpack_Sitemap_Builder:..._next_sitemap_of_type() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
218
				);
219
				break;
220
221
			case JP_IMAGE_SITEMAP_INDEX_TYPE:
222
				$this->build_next_sitemap_index_of_type(
223
					JP_IMAGE_SITEMAP_INDEX_TYPE,
224
					JP_VIDEO_SITEMAP_TYPE,
225
					$state
0 ignored issues
show
Bug introduced by
It seems like $state defined by \Jetpack_Sitemap_State::check_out() on line 188 can also be of type boolean; however, Jetpack_Sitemap_Builder:...sitemap_index_of_type() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
226
				);
227
				break;
228
229
			case JP_VIDEO_SITEMAP_TYPE:
230
				$this->build_next_sitemap_of_type(
231
					JP_VIDEO_SITEMAP_TYPE,
232
					array( $this, 'build_one_video_sitemap' ),
233
					$state
0 ignored issues
show
Bug introduced by
It seems like $state defined by \Jetpack_Sitemap_State::check_out() on line 188 can also be of type boolean; however, Jetpack_Sitemap_Builder:..._next_sitemap_of_type() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
234
				);
235
				break;
236
237
			case JP_VIDEO_SITEMAP_INDEX_TYPE:
238
				$this->build_next_sitemap_index_of_type(
239
					JP_VIDEO_SITEMAP_INDEX_TYPE,
240
					JP_MASTER_SITEMAP_TYPE,
241
					$state
0 ignored issues
show
Bug introduced by
It seems like $state defined by \Jetpack_Sitemap_State::check_out() on line 188 can also be of type boolean; however, Jetpack_Sitemap_Builder:...sitemap_index_of_type() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
242
				);
243
				break;
244
245
			case JP_MASTER_SITEMAP_TYPE:
246
				$this->build_master_sitemap( $state['max'] );
247
248
				// Reset the state and quit.
249
				Jetpack_Sitemap_State::reset(
250
					JP_PAGE_SITEMAP_TYPE
251
				);
252
253
				if ( $this->logger ) {
254
					$this->logger->report( '-- Finished.' );
0 ignored issues
show
Bug introduced by
The method report cannot be called on $this->logger (of type boolean).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
255
					$this->logger->time();
0 ignored issues
show
Bug introduced by
The method time cannot be called on $this->logger (of type boolean).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
256
				}
257
				$finished = true;
258
259
				break;
260
261
			default:
262
				Jetpack_Sitemap_State::reset(
263
					JP_PAGE_SITEMAP_TYPE
264
				);
265
				$finished = true;
266
267
				break;
268
		} // End switch.
269
270
		// Unlock the state.
271
		Jetpack_Sitemap_State::unlock();
272
273
		return $finished;
274
	}
275
276
	/**
277
	 * Build the next sitemap of a given type and update the sitemap state.
278
	 *
279
	 * @since 4.8.0
280
	 *
281
	 * @param string   $sitemap_type The type of the sitemap being generated.
282
	 * @param callback $build_one    A callback which builds a single sitemap file.
283
	 * @param array    $state        A sitemap state.
284
	 */
285
	private function build_next_sitemap_of_type( $sitemap_type, $build_one, $state ) {
286
		$index_type = jp_sitemap_index_type_of( $sitemap_type );
287
288
		// Try to build a sitemap.
289
		$result = call_user_func_array(
290
			$build_one,
291
			array(
292
				$state['number'] + 1,
293
				$state['last-added'],
294
			)
295
		);
296
297 View Code Duplication
		if ( false === $result ) {
298
			// If no sitemap was generated, advance to the next type.
299
			Jetpack_Sitemap_State::check_in(
300
				array(
301
					'sitemap-type'  => $index_type,
302
					'last-added'    => 0,
303
					'number'        => 0,
304
					'last-modified' => '1970-01-01 00:00:00',
305
				)
306
			);
307
308
			if ( $this->logger ) {
309
				$this->logger->report( "-- Cleaning Up $sitemap_type" );
0 ignored issues
show
Bug introduced by
The method report cannot be called on $this->logger (of type boolean).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
310
			}
311
312
			// Clean up old files.
313
			$this->librarian->delete_numbered_sitemap_rows_after(
314
				$state['number'],
315
				$sitemap_type
316
			);
317
318
			return;
319
		}
320
321
		// Otherwise, update the state.
322
		Jetpack_Sitemap_State::check_in(
323
			array(
324
				'sitemap-type'  => $state['sitemap-type'],
325
				'last-added'    => $result['last_id'],
326
				'number'        => $state['number'] + 1,
327
				'last-modified' => $result['last_modified'],
328
			)
329
		);
330
331
		if ( true === $result['any_left'] ) {
332
			// If there's more work to be done with this type, return.
333
			return;
334
		}
335
336
		// Otherwise, advance state to the next sitemap type.
337
		Jetpack_Sitemap_State::check_in(
338
			array(
339
				'sitemap-type'  => $index_type,
340
				'last-added'    => 0,
341
				'number'        => 0,
342
				'last-modified' => '1970-01-01 00:00:00',
343
			)
344
		);
345
346
		if ( $this->logger ) {
347
			$this->logger->report( "-- Cleaning Up $sitemap_type" );
0 ignored issues
show
Bug introduced by
The method report cannot be called on $this->logger (of type boolean).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
348
		}
349
350
		// Clean up old files.
351
		$this->librarian->delete_numbered_sitemap_rows_after(
352
			$state['number'] + 1,
353
			$sitemap_type
354
		);
355
	}
356
357
	/**
358
	 * Build the next sitemap index of a given type and update the state.
359
	 *
360
	 * @since 4.8.0
361
	 *
362
	 * @param string $index_type The type of index being generated.
363
	 * @param string $next_type  The next type to generate after this one.
364
	 * @param array  $state      A sitemap state.
365
	 */
366
	private function build_next_sitemap_index_of_type( $index_type, $next_type, $state ) {
367
		$sitemap_type = jp_sitemap_child_type_of( $index_type );
368
369
		// If only 0 or 1 sitemaps were built, advance to the next type and return.
370
		if ( 1 >= $state['max'][ $sitemap_type ]['number'] ) {
371
			Jetpack_Sitemap_State::check_in(
372
				array(
373
					'sitemap-type'  => $next_type,
374
					'last-added'    => 0,
375
					'number'        => 0,
376
					'last-modified' => '1970-01-01 00:00:00',
377
				)
378
			);
379
380
			if ( $this->logger ) {
381
				$this->logger->report( "-- Cleaning Up $index_type" );
0 ignored issues
show
Bug introduced by
The method report cannot be called on $this->logger (of type boolean).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
382
			}
383
384
			// There are no indices of this type.
385
			$this->librarian->delete_numbered_sitemap_rows_after(
386
				0,
387
				$index_type
388
			);
389
390
			return;
391
		}
392
393
		// Otherwise, try to build a sitemap index.
394
		$result = $this->build_one_sitemap_index(
395
			$state['number'] + 1,
396
			$state['last-added'],
397
			$state['last-modified'],
398
			$index_type
399
		);
400
401
		// If no index was built, advance to the next type and return.
402 View Code Duplication
		if ( false === $result ) {
403
			Jetpack_Sitemap_State::check_in(
404
				array(
405
					'sitemap-type'  => $next_type,
406
					'last-added'    => 0,
407
					'number'        => 0,
408
					'last-modified' => '1970-01-01 00:00:00',
409
				)
410
			);
411
412
			if ( $this->logger ) {
413
				$this->logger->report( "-- Cleaning Up $index_type" );
0 ignored issues
show
Bug introduced by
The method report cannot be called on $this->logger (of type boolean).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
414
			}
415
416
			// Clean up old files.
417
			$this->librarian->delete_numbered_sitemap_rows_after(
418
				$state['number'],
419
				$index_type
420
			);
421
422
			return;
423
		}
424
425
		// Otherwise, check in the state.
426
		Jetpack_Sitemap_State::check_in(
427
			array(
428
				'sitemap-type'  => $index_type,
429
				'last-added'    => $result['last_id'],
430
				'number'        => $state['number'] + 1,
431
				'last-modified' => $result['last_modified'],
432
			)
433
		);
434
435
		// If there are still sitemaps left to index, return.
436
		if ( true === $result['any_left'] ) {
437
			return;
438
		}
439
440
		// Otherwise, advance to the next type.
441
		Jetpack_Sitemap_State::check_in(
442
			array(
443
				'sitemap-type'  => $next_type,
444
				'last-added'    => 0,
445
				'number'        => 0,
446
				'last-modified' => '1970-01-01 00:00:00',
447
			)
448
		);
449
450
		if ( $this->logger ) {
451
			$this->logger->report( "-- Cleaning Up $index_type" );
0 ignored issues
show
Bug introduced by
The method report cannot be called on $this->logger (of type boolean).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
452
		}
453
454
		// We're done generating indices of this type.
455
		$this->librarian->delete_numbered_sitemap_rows_after(
456
			$state['number'] + 1,
457
			$index_type
458
		);
459
	}
460
461
	/**
462
	 * Builds the master sitemap index.
463
	 *
464
	 * @param array $max Array of sitemap types with max index and datetime.
465
	 *
466
	 * @since 4.8.0
467
	 */
468
	private function build_master_sitemap( $max ) {
469
		$page  = array();
470
		$image = array();
471
		$video = array();
472
		if ( $this->logger ) {
473
			$this->logger->report( '-- Building Master Sitemap.' );
0 ignored issues
show
Bug introduced by
The method report cannot be called on $this->logger (of type boolean).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
474
		}
475
476
		$buffer = new Jetpack_Sitemap_Buffer_Master(
477
			JP_SITEMAP_MAX_ITEMS,
478
			JP_SITEMAP_MAX_BYTES
479
		);
480
481 View Code Duplication
		if ( 0 < $max[ JP_PAGE_SITEMAP_TYPE ]['number'] ) {
482
			if ( 1 === $max[ JP_PAGE_SITEMAP_TYPE ]['number'] ) {
483
				$page['filename']      = jp_sitemap_filename( JP_PAGE_SITEMAP_TYPE, 1 );
484
				$page['last_modified'] = jp_sitemap_datetime( $max[ JP_PAGE_SITEMAP_TYPE ]['lastmod'] );
485
			} else {
486
				$page['filename']      = jp_sitemap_filename(
487
					JP_PAGE_SITEMAP_INDEX_TYPE,
488
					$max[ JP_PAGE_SITEMAP_INDEX_TYPE ]['number']
489
				);
490
				$page['last_modified'] = jp_sitemap_datetime( $max[ JP_PAGE_SITEMAP_INDEX_TYPE ]['lastmod'] );
491
			}
492
493
			$buffer->append(
494
				array(
495
					'sitemap' => array(
496
						'loc'     => $this->finder->construct_sitemap_url( $page['filename'] ),
497
						'lastmod' => $page['last_modified'],
498
					),
499
				)
500
			);
501
		}
502
503 View Code Duplication
		if ( 0 < $max[ JP_IMAGE_SITEMAP_TYPE ]['number'] ) {
504
			if ( 1 === $max[ JP_IMAGE_SITEMAP_TYPE ]['number'] ) {
505
				$image['filename']      = jp_sitemap_filename( JP_IMAGE_SITEMAP_TYPE, 1 );
506
				$image['last_modified'] = jp_sitemap_datetime( $max[ JP_IMAGE_SITEMAP_TYPE ]['lastmod'] );
507
			} else {
508
				$image['filename']      = jp_sitemap_filename(
509
					JP_IMAGE_SITEMAP_INDEX_TYPE,
510
					$max[ JP_IMAGE_SITEMAP_INDEX_TYPE ]['number']
511
				);
512
				$image['last_modified'] = jp_sitemap_datetime( $max[ JP_IMAGE_SITEMAP_INDEX_TYPE ]['lastmod'] );
513
			}
514
515
			$buffer->append(
516
				array(
517
					'sitemap' => array(
518
						'loc'     => $this->finder->construct_sitemap_url( $image['filename'] ),
519
						'lastmod' => $image['last_modified'],
520
					),
521
				)
522
			);
523
		}
524
525 View Code Duplication
		if ( 0 < $max[ JP_VIDEO_SITEMAP_TYPE ]['number'] ) {
526
			if ( 1 === $max[ JP_VIDEO_SITEMAP_TYPE ]['number'] ) {
527
				$video['filename']      = jp_sitemap_filename( JP_VIDEO_SITEMAP_TYPE, 1 );
528
				$video['last_modified'] = jp_sitemap_datetime( $max[ JP_VIDEO_SITEMAP_TYPE ]['lastmod'] );
529
			} else {
530
				$video['filename']      = jp_sitemap_filename(
531
					JP_VIDEO_SITEMAP_INDEX_TYPE,
532
					$max[ JP_VIDEO_SITEMAP_INDEX_TYPE ]['number']
533
				);
534
				$video['last_modified'] = jp_sitemap_datetime( $max[ JP_VIDEO_SITEMAP_INDEX_TYPE ]['lastmod'] );
535
			}
536
537
			$buffer->append(
538
				array(
539
					'sitemap' => array(
540
						'loc'     => $this->finder->construct_sitemap_url( $video['filename'] ),
541
						'lastmod' => $video['last_modified'],
542
					),
543
				)
544
			);
545
		}
546
547
		$this->librarian->store_sitemap_data(
548
			0,
549
			JP_MASTER_SITEMAP_TYPE,
550
			$buffer->contents(),
551
			''
552
		);
553
	}
554
555
	/**
556
	 * Build and store a single page sitemap. Returns false if no sitemap is built.
557
	 *
558
	 * Side effect: Create/update a sitemap row.
559
	 *
560
	 * @access private
561
	 * @since 4.8.0
562
	 *
563
	 * @param int $number The number of the current sitemap.
564
	 * @param int $from_id The greatest lower bound of the IDs of the posts to be included.
565
	 *
566
	 * @return bool|array @args {
567
	 *   @type int    $last_id       The ID of the last item to be successfully added to the buffer.
568
	 *   @type bool   $any_left      'true' if there are items which haven't been saved to a sitemap, 'false' otherwise.
569
	 *   @type string $last_modified The most recent timestamp to appear on the sitemap.
570
	 * }
571
	 */
572
	public function build_one_page_sitemap( $number, $from_id ) {
573
		$last_post_id   = $from_id;
574
		$any_posts_left = true;
575
576
		if ( $this->logger ) {
577
			$debug_name = jp_sitemap_filename( JP_PAGE_SITEMAP_TYPE, $number );
578
			$this->logger->report( "-- Building $debug_name" );
0 ignored issues
show
Bug introduced by
The method report cannot be called on $this->logger (of type boolean).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
579
		}
580
581
		$buffer = new Jetpack_Sitemap_Buffer_Page(
582
			JP_SITEMAP_MAX_ITEMS,
583
			JP_SITEMAP_MAX_BYTES
584
		);
585
586
		// Add entry for the main page (only if we're at the first one) and it isn't already going to be included as a page.
587
		if ( 1 === $number && 'page' !== get_option( 'show_on_front' ) ) {
588
			$item_array = array(
589
				'url' => array(
590
					'loc' => home_url(),
591
				),
592
			);
593
594
			/**
595
			 * Filter associative array with data to build <url> node
596
			 * and its descendants for site home.
597
			 *
598
			 * @module sitemaps
599
			 *
600
			 * @since 3.9.0
601
			 *
602
			 * @param array $blog_home Data to build parent and children nodes for site home.
603
			 */
604
			$item_array = apply_filters( 'jetpack_sitemap_url_home', $item_array );
605
606
			$buffer->append( $item_array );
607
		}
608
609
		// Add as many items to the buffer as possible.
610
		while ( $last_post_id >= 0 && false === $buffer->is_full() ) {
611
			$posts = $this->librarian->query_posts_after_id(
612
				$last_post_id,
613
				JP_SITEMAP_BATCH_SIZE
614
			);
615
616
			if ( null == $posts ) { // WPCS: loose comparison ok.
617
				$any_posts_left = false;
618
				break;
619
			}
620
621
			foreach ( $posts as $post ) {
622
				$current_item = $this->post_to_sitemap_item( $post );
623
624
				if ( true === $buffer->append( $current_item['xml'] ) ) {
0 ignored issues
show
Documentation introduced by
$current_item['xml'] is of type null, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
625
					$last_post_id = $post->ID;
626
					$buffer->view_time( $current_item['last_modified'] );
627
				} else {
628
					break;
629
				}
630
			}
631
		}
632
633
		// Handle other page sitemap URLs.
634
		if ( false === $any_posts_left || $last_post_id < 0 ) {
635
			// Negative IDs are used to track URL indexes.
636
			$last_post_id   = min( 0, $last_post_id );
637
			$any_posts_left = true; // Reinitialize.
638
639
			/**
640
			 * Filter other page sitemap URLs.
641
			 *
642
			 * @module sitemaps
643
			 *
644
			 * @since 6.1.0
645
			 *
646
			 * @param array $urls An array of other URLs.
647
			 */
648
			$other_urls = apply_filters( 'jetpack_page_sitemap_other_urls', array() );
649
650
			if ( $other_urls ) { // Start with index [1].
651
				$other_urls = array_values( $other_urls );
652
				array_unshift( $other_urls, $other_urls[0] );
653
				unset( $other_urls[0] );
654
			}
655
656
			// Add as many items to the buffer as possible.
657
			while ( false === $buffer->is_full() ) {
658
				$last_post_id_index       = abs( $last_post_id );
659
				$start_from_post_id_index = $last_post_id_index ? $last_post_id_index + 1 : 0;
660
				$urls                     = array_slice(
661
					$other_urls,
662
					$start_from_post_id_index,
663
					JP_SITEMAP_BATCH_SIZE,
664
					true
665
				);
666
667
				if ( ! $urls ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $urls of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
668
					$any_posts_left = false;
669
					break;
670
				}
671
672
				foreach ( $urls as $index => $url ) {
673
					if ( ! is_array( $url ) ) {
674
						$url = array( 'loc' => $url );
675
					}
676
					$item = array( 'xml' => compact( 'url' ) );
677
678
					if ( true === $buffer->append( $item['xml'] ) ) {
679
						$last_post_id = -$index;
680
					} else {
681
						break;
682
					}
683
				}
684
			}
685
		}
686
687
		// If no items were added, return false.
688
		if ( true === $buffer->is_empty() ) {
689
			return false;
690
		}
691
692
		/**
693
		 * Filter sitemap before rendering it as XML.
694
		 *
695
		 * @module sitemaps
696
		 *
697
		 * @since 3.9.0
698
		 * @since 5.3.0 returns an element of DOMDocument type instead of SimpleXMLElement
699
		 *
700
		 * @param DOMDocument      $doc Data tree for sitemap.
701
		 * @param string           $last_modified Date of last modification.
702
		 */
703
		$tree = apply_filters(
0 ignored issues
show
Unused Code introduced by
$tree is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
704
			'jetpack_print_sitemap',
705
			$buffer->get_document(),
706
			$buffer->last_modified()
707
		);
708
709
		// Store the buffer as the content of a sitemap row.
710
		$this->librarian->store_sitemap_data(
711
			$number,
712
			JP_PAGE_SITEMAP_TYPE,
713
			$buffer->contents(),
714
			$buffer->last_modified()
715
		);
716
717
		/*
718
		 * Now report back with the ID of the last post ID to be
719
		 * successfully added and whether there are any posts left.
720
		 */
721
		return array(
722
			'last_id'       => $last_post_id,
723
			'any_left'      => $any_posts_left,
724
			'last_modified' => $buffer->last_modified(),
725
		);
726
	}
727
728
	/**
729
	 * Build and store a single image sitemap. Returns false if no sitemap is built.
730
	 *
731
	 * Side effect: Create/update an image sitemap row.
732
	 *
733
	 * @access private
734
	 * @since 4.8.0
735
	 *
736
	 * @param int $number The number of the current sitemap.
737
	 * @param int $from_id The greatest lower bound of the IDs of the posts to be included.
738
	 *
739
	 * @return bool|array @args {
740
	 *   @type int    $last_id       The ID of the last item to be successfully added to the buffer.
741
	 *   @type bool   $any_left      'true' if there are items which haven't been saved to a sitemap, 'false' otherwise.
742
	 *   @type string $last_modified The most recent timestamp to appear on the sitemap.
743
	 * }
744
	 */
745 View Code Duplication
	public function build_one_image_sitemap( $number, $from_id ) {
746
		$last_post_id   = $from_id;
747
		$any_posts_left = true;
748
749
		if ( $this->logger ) {
750
			$debug_name = jp_sitemap_filename( JP_IMAGE_SITEMAP_TYPE, $number );
751
			$this->logger->report( "-- Building $debug_name" );
0 ignored issues
show
Bug introduced by
The method report cannot be called on $this->logger (of type boolean).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
752
		}
753
754
		$buffer = new Jetpack_Sitemap_Buffer_Image(
755
			JP_SITEMAP_MAX_ITEMS,
756
			JP_SITEMAP_MAX_BYTES
757
		);
758
759
		// Add as many items to the buffer as possible.
760
		while ( false === $buffer->is_full() ) {
761
			$posts = $this->librarian->query_images_after_id(
762
				$last_post_id,
763
				JP_SITEMAP_BATCH_SIZE
764
			);
765
766
			if ( null == $posts ) { // WPCS: loose comparison ok.
767
				$any_posts_left = false;
768
				break;
769
			}
770
771
			foreach ( $posts as $post ) {
772
				$current_item = $this->image_post_to_sitemap_item( $post );
773
774
				if ( true === $buffer->append( $current_item['xml'] ) ) {
0 ignored issues
show
Documentation introduced by
$current_item['xml'] is of type null, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
775
					$last_post_id = $post->ID;
776
					$buffer->view_time( $current_item['last_modified'] );
777
				} else {
778
					break;
779
				}
780
			}
781
		}
782
783
		// If no items were added, return false.
784
		if ( true === $buffer->is_empty() ) {
785
			return false;
786
		}
787
788
		// Store the buffer as the content of a jp_sitemap post.
789
		$this->librarian->store_sitemap_data(
790
			$number,
791
			JP_IMAGE_SITEMAP_TYPE,
792
			$buffer->contents(),
793
			$buffer->last_modified()
794
		);
795
796
		/*
797
		 * Now report back with the ID of the last post to be
798
		 * successfully added and whether there are any posts left.
799
		 */
800
		return array(
801
			'last_id'       => $last_post_id,
802
			'any_left'      => $any_posts_left,
803
			'last_modified' => $buffer->last_modified(),
804
		);
805
	}
806
807
	/**
808
	 * Build and store a single video sitemap. Returns false if no sitemap is built.
809
	 *
810
	 * Side effect: Create/update an video sitemap row.
811
	 *
812
	 * @access private
813
	 * @since 4.8.0
814
	 *
815
	 * @param int $number The number of the current sitemap.
816
	 * @param int $from_id The greatest lower bound of the IDs of the posts to be included.
817
	 *
818
	 * @return bool|array @args {
819
	 *   @type int    $last_id       The ID of the last item to be successfully added to the buffer.
820
	 *   @type bool   $any_left      'true' if there are items which haven't been saved to a sitemap, 'false' otherwise.
821
	 *   @type string $last_modified The most recent timestamp to appear on the sitemap.
822
	 * }
823
	 */
824 View Code Duplication
	public function build_one_video_sitemap( $number, $from_id ) {
825
		$last_post_id   = $from_id;
826
		$any_posts_left = true;
827
828
		if ( $this->logger ) {
829
			$debug_name = jp_sitemap_filename( JP_VIDEO_SITEMAP_TYPE, $number );
830
			$this->logger->report( "-- Building $debug_name" );
0 ignored issues
show
Bug introduced by
The method report cannot be called on $this->logger (of type boolean).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
831
		}
832
833
		$buffer = new Jetpack_Sitemap_Buffer_Video(
834
			JP_SITEMAP_MAX_ITEMS,
835
			JP_SITEMAP_MAX_BYTES
836
		);
837
838
		// Add as many items to the buffer as possible.
839
		while ( false === $buffer->is_full() ) {
840
			$posts = $this->librarian->query_videos_after_id(
841
				$last_post_id,
842
				JP_SITEMAP_BATCH_SIZE
843
			);
844
845
			if ( null == $posts ) { // WPCS: loose comparison ok.
846
				$any_posts_left = false;
847
				break;
848
			}
849
850
			foreach ( $posts as $post ) {
851
				$current_item = $this->video_post_to_sitemap_item( $post );
852
853
				if ( true === $buffer->append( $current_item['xml'] ) ) {
0 ignored issues
show
Documentation introduced by
$current_item['xml'] is of type null, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
854
					$last_post_id = $post->ID;
855
					$buffer->view_time( $current_item['last_modified'] );
856
				} else {
857
					break;
858
				}
859
			}
860
		}
861
862
		// If no items were added, return false.
863
		if ( true === $buffer->is_empty() ) {
864
			return false;
865
		}
866
867
		if ( false === $buffer->is_empty() ) {
868
			$this->librarian->store_sitemap_data(
869
				$number,
870
				JP_VIDEO_SITEMAP_TYPE,
871
				$buffer->contents(),
872
				$buffer->last_modified()
873
			);
874
		}
875
876
		/*
877
		 * Now report back with the ID of the last post to be
878
		 * successfully added and whether there are any posts left.
879
		 */
880
		return array(
881
			'last_id'       => $last_post_id,
882
			'any_left'      => $any_posts_left,
883
			'last_modified' => $buffer->last_modified(),
884
		);
885
	}
886
887
	/**
888
	 * Build and store a single page sitemap index. Return false if no index is built.
889
	 *
890
	 * Side effect: Create/update a sitemap index row.
891
	 *
892
	 * @access private
893
	 * @since 4.8.0
894
	 *
895
	 * @param int    $number     The number of the current sitemap index.
896
	 * @param int    $from_id    The greatest lower bound of the IDs of the sitemaps to be included.
897
	 * @param string $datetime   Datetime of previous sitemap in 'YYYY-MM-DD hh:mm:ss' format.
898
	 * @param string $index_type Sitemap index type.
899
	 *
900
	 * @return bool|array @args {
901
	 *   @type int    $last_id       The ID of the last item to be successfully added to the buffer.
902
	 *   @type bool   $any_left      'true' if there are items which haven't been saved to a sitemap, 'false' otherwise.
903
	 *   @type string $last_modified The most recent timestamp to appear on the sitemap.
904
	 * }
905
	 */
906
	private function build_one_sitemap_index( $number, $from_id, $datetime, $index_type ) {
907
		$last_sitemap_id   = $from_id;
908
		$any_sitemaps_left = true;
909
910
		// Check the datetime format.
911
		$datetime = jp_sitemap_datetime( $datetime );
912
913
		$sitemap_type = jp_sitemap_child_type_of( $index_type );
914
915
		if ( $this->logger ) {
916
			$index_debug_name = jp_sitemap_filename( $index_type, $number );
917
			$this->logger->report( "-- Building $index_debug_name" );
0 ignored issues
show
Bug introduced by
The method report cannot be called on $this->logger (of type boolean).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
918
		}
919
920
		$buffer = new Jetpack_Sitemap_Buffer_Master(
921
			JP_SITEMAP_MAX_ITEMS,
922
			JP_SITEMAP_MAX_BYTES,
923
			$datetime
924
		);
925
926
		// Add pointer to the previous sitemap index (unless we're at the first one).
927
		if ( 1 !== $number ) {
928
			$i              = $number - 1;
929
			$prev_index_url = $this->finder->construct_sitemap_url(
930
				jp_sitemap_filename( $index_type, $i )
931
			);
932
933
			$item_array = array(
934
				'sitemap' => array(
935
					'loc'     => $prev_index_url,
936
					'lastmod' => $datetime,
937
				),
938
			);
939
940
			$buffer->append( $item_array );
941
		}
942
943
		// Add as many items to the buffer as possible.
944
		while ( false === $buffer->is_full() ) {
945
			// Retrieve a batch of posts (in order).
946
			$posts = $this->librarian->query_sitemaps_after_id(
947
				$sitemap_type,
948
				$last_sitemap_id,
949
				JP_SITEMAP_BATCH_SIZE
950
			);
951
952
			// If there were no posts to get, make a note.
953
			if ( null == $posts ) { // WPCS: loose comparison ok.
954
				$any_sitemaps_left = false;
955
				break;
956
			}
957
958
			// Otherwise, loop through each post in the batch.
959
			foreach ( $posts as $post ) {
960
				// Generate the sitemap XML for the post.
961
				$current_item = $this->sitemap_row_to_index_item( (array) $post );
962
963
				// Try adding this item to the buffer.
964
				if ( true === $buffer->append( $current_item['xml'] ) ) {
965
					$last_sitemap_id = $post['ID'];
966
					$buffer->view_time( $current_item['last_modified'] );
967
				} else {
968
					// Otherwise stop looping through posts.
969
					break;
970
				}
971
			}
972
		}
973
974
		// If no items were added, return false.
975
		if ( true === $buffer->is_empty() ) {
976
			return false;
977
		}
978
979
		$this->librarian->store_sitemap_data(
980
			$number,
981
			$index_type,
982
			$buffer->contents(),
983
			$buffer->last_modified()
984
		);
985
986
		/*
987
		 * Now report back with the ID of the last sitemap post ID to
988
		 * be successfully added, whether there are any sitemap posts
989
		 * left, and the most recent modification time seen.
990
		 */
991
		return array(
992
			'last_id'       => $last_sitemap_id,
993
			'any_left'      => $any_sitemaps_left,
994
			'last_modified' => $buffer->last_modified(),
995
		);
996
	}
997
998
	/**
999
	 * Construct the sitemap index url entry for a sitemap row.
1000
	 *
1001
	 * @link http://www.sitemaps.org/protocol.html#sitemapIndex_sitemap
1002
	 *
1003
	 * @access private
1004
	 * @since 4.8.0
1005
	 *
1006
	 * @param array $row The sitemap data to be processed.
1007
	 *
1008
	 * @return string An XML fragment representing the post URL.
1009
	 */
1010
	private function sitemap_row_to_index_item( $row ) {
1011
		$url = $this->finder->construct_sitemap_url( $row['post_title'] );
1012
1013
		$item_array = array(
1014
			'sitemap' => array(
1015
				'loc'     => $url,
1016
				'lastmod' => jp_sitemap_datetime( $row['post_date'] ),
1017
			),
1018
		);
1019
1020
		return array(
1021
			'xml'           => $item_array,
1022
			'last_modified' => $row['post_date'],
1023
		);
1024
	}
1025
1026
1027
	/**
1028
	 * This is served instead of a 404 when the master sitemap is requested
1029
	 * but not yet generated.
1030
	 */
1031
	public function empty_sitemap_xml() {
1032
		$empty_sitemap = new Jetpack_Sitemap_Buffer_Empty();
1033
		return $empty_sitemap->contents();
1034
	}
1035
1036
	/**
1037
	 * Build and return the news sitemap xml. Note that the result of this
1038
	 * function is cached in the transient 'jetpack_news_sitemap_xml'.
1039
	 *
1040
	 * @access public
1041
	 * @since 4.8.0
1042
	 *
1043
	 * @return string The news sitemap xml.
1044
	 */
1045
	public function news_sitemap_xml() {
1046
		$the_stored_news_sitemap = get_transient( 'jetpack_news_sitemap_xml' );
1047
1048
		if ( false === $the_stored_news_sitemap ) {
1049
1050
			if ( $this->logger ) {
1051
				$this->logger->report( 'Beginning news sitemap generation.' );
0 ignored issues
show
Bug introduced by
The method report cannot be called on $this->logger (of type boolean).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
1052
			}
1053
1054
			/**
1055
			 * Filter limit of entries to include in news sitemap.
1056
			 *
1057
			 * @module sitemaps
1058
			 *
1059
			 * @since 3.9.0
1060
			 *
1061
			 * @param int $count Number of entries to include in news sitemap.
1062
			 */
1063
			$item_limit = apply_filters(
1064
				'jetpack_sitemap_news_sitemap_count',
1065
				JP_NEWS_SITEMAP_MAX_ITEMS
1066
			);
1067
1068
			$buffer = new Jetpack_Sitemap_Buffer_News(
1069
				min( $item_limit, JP_NEWS_SITEMAP_MAX_ITEMS ),
1070
				JP_SITEMAP_MAX_BYTES
1071
			);
1072
1073
			$posts = $this->librarian->query_most_recent_posts( JP_NEWS_SITEMAP_MAX_ITEMS );
1074
1075
			foreach ( $posts as $post ) {
1076
				$current_item = $this->post_to_news_sitemap_item( $post );
1077
1078
				if ( false === $buffer->append( $current_item['xml'] ) ) {
0 ignored issues
show
Documentation introduced by
$current_item['xml'] is of type null, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1079
					break;
1080
				}
1081
			}
1082
1083
			if ( $this->logger ) {
1084
				$this->logger->time( 'End news sitemap generation.' );
0 ignored issues
show
Bug introduced by
The method time cannot be called on $this->logger (of type boolean).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
1085
			}
1086
1087
			$the_stored_news_sitemap = $buffer->contents();
1088
1089
			set_transient(
1090
				'jetpack_news_sitemap_xml',
1091
				$the_stored_news_sitemap,
1092
				JP_NEWS_SITEMAP_INTERVAL
1093
			);
1094
		} // End if.
1095
1096
		return $the_stored_news_sitemap;
1097
	}
1098
1099
	/**
1100
	 * Construct the sitemap url entry for a WP_Post.
1101
	 *
1102
	 * @link http://www.sitemaps.org/protocol.html#urldef
1103
	 * @access private
1104
	 * @since 4.8.0
1105
	 *
1106
	 * @param WP_Post $post The post to be processed.
1107
	 *
1108
	 * @return array
1109
	 *              @type array  $xml An XML fragment representing the post URL.
1110
	 *              @type string $last_modified Date post was last modified.
1111
	 */
1112
	private function post_to_sitemap_item( $post ) {
1113
1114
		/**
1115
		 * Filter condition to allow skipping specific posts in sitemap.
1116
		 *
1117
		 * @module sitemaps
1118
		 *
1119
		 * @since 3.9.0
1120
		 *
1121
		 * @param bool    $skip Current boolean. False by default, so no post is skipped.
1122
		 * @param WP_POST $post Current post object.
1123
		 */
1124
		if ( true === apply_filters( 'jetpack_sitemap_skip_post', false, $post ) ) {
1125
			return array(
1126
				'xml'           => null,
1127
				'last_modified' => null,
1128
			);
1129
		}
1130
1131
		$url = esc_url( get_permalink( $post ) );
1132
1133
		/*
1134
		 * Spec requires the URL to be <=2048 bytes.
1135
		 * In practice this constraint is unlikely to be violated.
1136
		 */
1137
		if ( 2048 < strlen( $url ) ) {
1138
			$url = home_url() . '/?p=' . $post->ID;
1139
		}
1140
1141
		$last_modified = $post->post_modified_gmt;
1142
1143
		// Check for more recent comments.
1144
		// Note that 'Y-m-d h:i:s' strings sort lexicographically.
1145
		if ( 0 < $post->comment_count ) {
1146
			$last_modified = max(
1147
				$last_modified,
1148
				$this->librarian->query_latest_approved_comment_time_on_post( $post->ID )
1149
			);
1150
		}
1151
1152
		$item_array = array(
1153
			'url' => array(
1154
				'loc'     => $url,
1155
				'lastmod' => jp_sitemap_datetime( $last_modified ),
1156
			),
1157
		);
1158
1159
		/**
1160
		 * Filter sitemap URL item before rendering it as XML.
1161
		 *
1162
		 * @module sitemaps
1163
		 *
1164
		 * @since 3.9.0
1165
		 *
1166
		 * @param array $tree Associative array representing sitemap URL element.
1167
		 * @param int   $post_id ID of the post being processed.
1168
		 */
1169
		$item_array = apply_filters( 'jetpack_sitemap_url', $item_array, $post->ID );
1170
1171
		return array(
1172
			'xml'           => $item_array,
1173
			'last_modified' => $last_modified,
1174
		);
1175
	}
1176
1177
	/**
1178
	 * Construct the image sitemap url entry for a WP_Post of image type.
1179
	 *
1180
	 * @link http://www.sitemaps.org/protocol.html#urldef
1181
	 *
1182
	 * @access private
1183
	 * @since 4.8.0
1184
	 *
1185
	 * @param WP_Post $post The image post to be processed.
1186
	 *
1187
	 * @return array
1188
	 *              @type array  $xml An XML fragment representing the post URL.
1189
	 *              @type string $last_modified Date post was last modified.
1190
	 */
1191
	private function image_post_to_sitemap_item( $post ) {
1192
1193
		/**
1194
		 * Filter condition to allow skipping specific image posts in the sitemap.
1195
		 *
1196
		 * @module sitemaps
1197
		 *
1198
		 * @since 4.8.0
1199
		 *
1200
		 * @param bool    $skip Current boolean. False by default, so no post is skipped.
1201
		 * @param WP_POST $post Current post object.
1202
		 */
1203
		if ( apply_filters( 'jetpack_sitemap_image_skip_post', false, $post ) ) {
1204
			return array(
1205
				'xml'           => null,
1206
				'last_modified' => null,
1207
			);
1208
		}
1209
1210
		$url = wp_get_attachment_url( $post->ID );
1211
1212
		// Do not include the image if the attached parent is not published.
1213
		// Unattached will be published. Otherwise, will inherit parent status.
1214 View Code Duplication
		if ( 'publish' !== get_post_status( $post ) ) {
1215
			return array(
1216
				'xml'           => null,
1217
				'last_modified' => null,
1218
			);
1219
		}
1220
1221
		$parent_url = get_permalink( get_post( $post->post_parent ) );
1222
		if ( '' == $parent_url ) { // WPCS: loose comparison ok.
1223
			$parent_url = get_permalink( $post );
1224
		}
1225
1226
		$item_array = array(
1227
			'url' => array(
1228
				'loc'         => $parent_url,
1229
				'lastmod'     => jp_sitemap_datetime( $post->post_modified_gmt ),
1230
				'image:image' => array(
1231
					'image:loc' => $url,
1232
				),
1233
			),
1234
		);
1235
1236
		$item_array['url']['image:image']['image:title']   = $post->post_title;
1237
		$item_array['url']['image:image']['image:caption'] = $post->post_excerpt;
1238
1239
		/**
1240
		 * Filter associative array with data to build <url> node
1241
		 * and its descendants for current post in image sitemap.
1242
		 *
1243
		 * @module sitemaps
1244
		 *
1245
		 * @since 4.8.0
1246
		 *
1247
		 * @param array $item_array Data to build parent and children nodes for current post.
1248
		 * @param int   $post_id Current image post ID.
1249
		 */
1250
		$item_array = apply_filters(
1251
			'jetpack_sitemap_image_sitemap_item',
1252
			$item_array,
1253
			$post->ID
1254
		);
1255
1256
		return array(
1257
			'xml'           => $item_array,
1258
			'last_modified' => $post->post_modified_gmt,
1259
		);
1260
	}
1261
1262
	/**
1263
	 * Construct the video sitemap url entry for a WP_Post of video type.
1264
	 *
1265
	 * @link http://www.sitemaps.org/protocol.html#urldef
1266
	 * @link https://developers.google.com/webmasters/videosearch/sitemaps
1267
	 *
1268
	 * @access private
1269
	 * @since 4.8.0
1270
	 *
1271
	 * @param WP_Post $post The video post to be processed.
1272
	 *
1273
	 * @return array
1274
	 *              @type array  $xml An XML fragment representing the post URL.
1275
	 *              @type string $last_modified Date post was last modified.
1276
	 */
1277
	private function video_post_to_sitemap_item( $post ) {
1278
1279
		/**
1280
		 * Filter condition to allow skipping specific image posts in the sitemap.
1281
		 *
1282
		 * @module sitemaps
1283
		 *
1284
		 * @since 4.8.0
1285
		 *
1286
		 * @param bool    $skip Current boolean. False by default, so no post is skipped.
1287
		 * @param WP_POST $post Current post object.
1288
		 */
1289
		if ( apply_filters( 'jetpack_sitemap_video_skip_post', false, $post ) ) {
1290
			return array(
1291
				'xml'           => null,
1292
				'last_modified' => null,
1293
			);
1294
		}
1295
1296
		// Do not include the video if the attached parent is not published.
1297
		// Unattached will be published. Otherwise, will inherit parent status.
1298 View Code Duplication
		if ( 'publish' !== get_post_status( $post ) ) {
1299
			return array(
1300
				'xml'           => null,
1301
				'last_modified' => null,
1302
			);
1303
		}
1304
1305
		$parent_url = esc_url( get_permalink( get_post( $post->post_parent ) ) );
1306
		if ( '' == $parent_url ) { // WPCS: loose comparison ok.
1307
			$parent_url = esc_url( get_permalink( $post ) );
1308
		}
1309
1310
		// Prepare the content like get_the_content_feed().
1311
		$content = $post->post_content;
1312
		/** This filter is already documented in core/wp-includes/post-template.php */
1313
		$content = apply_filters( 'the_content', $content );
1314
1315
		/** This filter is already documented in core/wp-includes/feed.php */
1316
		$content = apply_filters( 'the_content_feed', $content, 'rss2' );
1317
1318
		$item_array = array(
1319
			'url' => array(
1320
				'loc'         => $parent_url,
1321
				'lastmod'     => jp_sitemap_datetime( $post->post_modified_gmt ),
1322
				'video:video' => array(
1323
					/** This filter is already documented in core/wp-includes/feed.php */
1324
					'video:title'         => apply_filters( 'the_title_rss', $post->post_title ),
1325
					'video:thumbnail_loc' => '',
1326
					'video:description'   => $content,
1327
					'video:content_loc'   => esc_url( wp_get_attachment_url( $post->ID ) ),
1328
				),
1329
			),
1330
		);
1331
1332
		// TODO: Integrate with VideoPress here.
1333
		// cf. video:player_loc tag in video sitemap spec.
1334
1335
		/**
1336
		 * Filter associative array with data to build <url> node
1337
		 * and its descendants for current post in video sitemap.
1338
		 *
1339
		 * @module sitemaps
1340
		 *
1341
		 * @since 4.8.0
1342
		 *
1343
		 * @param array $item_array Data to build parent and children nodes for current post.
1344
		 * @param int   $post_id Current video post ID.
1345
		 */
1346
		$item_array = apply_filters(
1347
			'jetpack_sitemap_video_sitemap_item',
1348
			$item_array,
1349
			$post->ID
1350
		);
1351
1352
		return array(
1353
			'xml'           => $item_array,
1354
			'last_modified' => $post->post_modified_gmt,
1355
		);
1356
	}
1357
1358
	/**
1359
	 * Construct the news sitemap url entry for a WP_Post.
1360
	 *
1361
	 * @link http://www.sitemaps.org/protocol.html#urldef
1362
	 *
1363
	 * @access private
1364
	 * @since 4.8.0
1365
	 *
1366
	 * @param WP_Post $post The post to be processed.
1367
	 *
1368
	 * @return string An XML fragment representing the post URL.
1369
	 */
1370
	private function post_to_news_sitemap_item( $post ) {
1371
1372
		/**
1373
		 * Filter condition to allow skipping specific posts in news sitemap.
1374
		 *
1375
		 * @module sitemaps
1376
		 *
1377
		 * @since 3.9.0
1378
		 *
1379
		 * @param bool    $skip Current boolean. False by default, so no post is skipped.
1380
		 * @param WP_POST $post Current post object.
1381
		 */
1382
		if ( apply_filters( 'jetpack_sitemap_news_skip_post', false, $post ) ) {
1383
			return array(
1384
				'xml' => null,
1385
			);
1386
		}
1387
1388
		$url = get_permalink( $post );
1389
1390
		/*
1391
		 * Spec requires the URL to be <=2048 bytes.
1392
		 * In practice this constraint is unlikely to be violated.
1393
		 */
1394
		if ( 2048 < strlen( $url ) ) {
1395
			$url = home_url() . '/?p=' . $post->ID;
1396
		}
1397
1398
		/*
1399
		 * Trim the locale to an ISO 639 language code as required by Google.
1400
		 * Special cases are zh-cn (Simplified Chinese) and zh-tw (Traditional Chinese).
1401
		 * @link http://www.loc.gov/standards/iso639-2/php/code_list.php
1402
		 */
1403
		$language = strtolower( get_locale() );
1404
1405
		if ( in_array( $language, array( 'zh_tw', 'zh_cn' ), true ) ) {
1406
			$language = str_replace( '_', '-', $language );
1407
		} else {
1408
			$language = preg_replace( '/(_.*)$/i', '', $language );
1409
		}
1410
1411
		$item_array = array(
1412
			'url' => array(
1413
				'loc'       => $url,
1414
				'lastmod'   => jp_sitemap_datetime( $post->post_modified_gmt ),
1415
				'news:news' => array(
1416
					'news:publication'      => array(
1417
						'news:name'     => html_entity_decode( get_bloginfo( 'name' ) ),
1418
						'news:language' => $language,
1419
					),
1420
					/** This filter is already documented in core/wp-includes/feed.php */
1421
					'news:title'            => apply_filters( 'the_title_rss', $post->post_title ),
1422
					'news:publication_date' => jp_sitemap_datetime( $post->post_date_gmt ),
1423
					'news:genres'           => 'Blog',
1424
				),
1425
			),
1426
		);
1427
1428
		/**
1429
		 * Filter associative array with data to build <url> node
1430
		 * and its descendants for current post in news sitemap.
1431
		 *
1432
		 * @module sitemaps
1433
		 *
1434
		 * @since 3.9.0
1435
		 *
1436
		 * @param array $item_array Data to build parent and children nodes for current post.
1437
		 * @param int   $post_id Current post ID.
1438
		 */
1439
		$item_array = apply_filters(
1440
			'jetpack_sitemap_news_sitemap_item',
1441
			$item_array,
1442
			$post->ID
1443
		);
1444
1445
		return array(
1446
			'xml' => $item_array,
1447
		);
1448
	}
1449
}
1450