Completed
Push — kraftbj-patch-2 ( 82c983...ae9d16 )
by
unknown
513:58 queued 503:20
created

Jetpack_Sitemap_Librarian::delete_sitemap_data()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 7
nc 2
nop 2
dl 0
loc 10
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/**
3
 * Sitemaps are stored in the database using a custom table. This class
4
 * provides a small API for storing and retrieving sitemap data so we can
5
 * avoid lots of explicit SQL juggling while building sitemaps. This file
6
 * also includes the SQL used to retrieve posts and images to be included
7
 * in the sitemaps.
8
 *
9
 * @since 4.7.0
10
 * @package Jetpack
11
 */
12
13
require_once dirname( __FILE__ ) . '/sitemap-constants.php';
14
15
/**
16
 * This object handles any database interaction required
17
 * for sitemap generation.
18
 *
19
 * @since 4.7.0
20
 */
21
class Jetpack_Sitemap_Librarian {
22
23
	/**
24
	 * Retrieve a single sitemap with given name and type.
25
	 * Returns null if no such sitemap exists.
26
	 *
27
	 * @access public
28
	 * @since 4.7.0
29
	 *
30
	 * @param string $name Name of the sitemap to be retrieved.
31
	 * @param string $type Type of the sitemap to be retrieved.
32
	 *
33
	 * @return array $args {
34
	 *   @type int    $id        ID number of the sitemap in the database.
35
	 *   @type string $timestamp Most recent timestamp of the resources pointed to.
36
	 *   @type string $name      Name of the sitemap in the database.
37
	 *   @type string $type      Type of the sitemap in the database.
38
	 *   @type string $text      The content of the sitemap.
39
	 * }
40
	 */
41
	public function read_sitemap_data( $name, $type ) {
42
		$the_post = get_page_by_title( $name, 'OBJECT', $type );
43
44
		if ( null === $the_post ) {
45
			return null;
46
		} else {
47
			return array(
48
				'id'        => $the_post->ID,
49
				'timestamp' => $the_post->post_date,
50
				'name'      => $the_post->post_title,
51
				'type'      => $the_post->post_type,
52
				'text'      => $the_post->post_content,
53
			);
54
		}
55
	}
56
57
	/**
58
	 * Store a sitemap of given type and index in the database.
59
	 * Note that the sitemap contents are run through esc_html before
60
	 * being stored, and the timestamp reencoded as 'Y-m-d H:i:s'.
61
	 *
62
	 * If a sitemap with that type and name does not exist, create it.
63
	 * If a sitemap with that type and name does exist, update it.
64
	 *
65
	 * @access public
66
	 * @since 4.7.0
67
	 *
68
	 * @param string $index     Index of the sitemap to be stored.
69
	 * @param string $type      Type of the sitemap to be stored.
70
	 * @param string $contents  Contents of the sitemap to be stored.
71
	 * @param string $timestamp Timestamp of the sitemap to be stored, in 'YYYY-MM-DD hh:mm:ss' format.
72
	 */
73
	public function store_sitemap_data( $index, $type, $contents, $timestamp ) {
74
		$name = jp_sitemap_filename( $type, $index );
75
76
		$the_post = get_page_by_title( $name, 'OBJECT', $type );
77
78
		if ( null === $the_post ) {
79
			// Post does not exist.
80
			wp_insert_post(array(
81
				'post_title'   => $name,
82
				'post_content' => esc_html( $contents ),
83
				'post_type'    => $type,
84
				'post_date'    => date( 'Y-m-d H:i:s', strtotime( $timestamp ) ),
85
			));
86
		} else {
87
			// Post does exist.
88
			wp_insert_post(array(
89
				'ID'           => $the_post->ID,
90
				'post_title'   => $name,
91
				'post_content' => esc_html( $contents ),
92
				'post_type'    => $type,
93
				'post_date'    => date( 'Y-m-d H:i:s', strtotime( $timestamp ) ),
94
			));
95
		}
96
		return;
97
	}
98
99
	/**
100
	 * Delete a sitemap by name and type.
101
	 *
102
	 * @access public
103
	 * @since 4.7.0
104
	 *
105
	 * @param string $name Row name.
106
	 * @param string $type Row type.
107
	 *
108
	 * @return bool 'true' if a row was deleted, 'false' otherwise.
109
	 */
110
	public function delete_sitemap_data( $name, $type ) {
111
		$the_post = get_page_by_title( $name, 'OBJECT', $type );
112
113
		if ( null === $the_post ) {
114
			return false;
115
		} else {
116
			wp_delete_post( $the_post->ID );
117
			return true;
118
		}
119
	}
120
121
	/**
122
	 * Retrieve the contents of a sitemap with given name and type.
123
	 * If no such sitemap exists, return the empty string. Note that the
124
	 * returned string is run through wp_specialchars_decode.
125
	 *
126
	 * @access public
127
	 * @since 4.7.0
128
	 *
129
	 * @param string $name Row name.
130
	 * @param string $type Row type.
131
	 *
132
	 * @return string Text of the specified sitemap, or the empty string.
133
	 */
134
	public function get_sitemap_text( $name, $type ) {
135
		$row = $this->read_sitemap_data( $name, $type );
136
137
		if ( null === $row ) {
138
			return '';
139
		} else {
140
			return wp_specialchars_decode( $row['text'], ENT_QUOTES );
141
		}
142
	}
143
144
	/**
145
	 * Delete numbered sitemaps named prefix-(p+1), prefix-(p+2), ...
146
	 * until the first nonexistent sitemap is found.
147
	 *
148
	 * @access public
149
	 * @since 4.7.0
150
	 *
151
	 * @param int    $position Number before the first sitemap to be deleted.
152
	 * @param string $type Sitemap type.
153
	 */
154
	public function delete_numbered_sitemap_rows_after( $position, $type ) {
155
		$any_left = true;
156
157
		while ( true === $any_left ) {
158
			$position += 1;
159
			$name = jp_sitemap_filename( $type, $position );
160
			$any_left = $this->delete_sitemap_data( $name, $type );
161
		}
162
163
		return;
164
	}
165
166
	/**
167
	 * Deletes all stored sitemap data.
168
	 *
169
	 * @access public
170
	 * @since 4.7.0
171
	 */
172
	public function delete_all_stored_sitemap_data() {
173
		$this->delete_sitemap_data(
174
			jp_sitemap_filename( MASTER_SITEMAP_TYPE ),
0 ignored issues
show
Bug introduced by
The call to jp_sitemap_filename() misses a required argument $number.

This check looks for function calls that miss required arguments.

Loading history...
175
			JP_MASTER_SITEMAP_TYPE
176
		);
177
178
		$this->delete_numbered_sitemap_rows_after(
179
			0, JP_PAGE_SITEMAP_TYPE
180
		);
181
182
		$this->delete_numbered_sitemap_rows_after(
183
			0, JP_PAGE_SITEMAP_INDEX_TYPE
184
		);
185
186
		$this->delete_numbered_sitemap_rows_after(
187
			0, JP_IMAGE_SITEMAP_TYPE
188
		);
189
190
		$this->delete_numbered_sitemap_rows_after(
191
			0, JP_IMAGE_SITEMAP_INDEX_TYPE
192
		);
193
194
		$this->delete_numbered_sitemap_rows_after(
195
			0, JP_VIDEO_SITEMAP_TYPE
196
		);
197
198
		$this->delete_numbered_sitemap_rows_after(
199
			0, JP_VIDEO_SITEMAP_INDEX_TYPE
200
		);
201
		return;
202
	}
203
204
	/**
205
	 * Retrieve an array of sitemap rows (of a given type) sorted by ID.
206
	 *
207
	 * Returns the smallest $num_posts sitemap rows (measured by ID)
208
	 * of the given type which are larger than $from_id.
209
	 *
210
	 * @access public
211
	 * @since 4.7.0
212
	 *
213
	 * @param string $type Type of the sitemap rows to retrieve.
214
	 * @param int    $from_id Greatest lower bound of retrieved sitemap post IDs.
215
	 * @param int    $num_posts Largest number of sitemap posts to retrieve.
216
	 *
217
	 * @return array The sitemaps, as an array of associative arrays.
218
	 */
219
	public function query_sitemaps_after_id( $type, $from_id, $num_posts ) {
220
		global $wpdb;
221
222
		return $wpdb->get_results(
223
			$wpdb->prepare(
224
				"SELECT *
225
					FROM $wpdb->posts
226
					WHERE post_type=%s
227
						AND ID>%d
228
					ORDER BY ID ASC
229
					LIMIT %d;",
230
				$type,
231
				$from_id,
232
				$num_posts
233
			),
234
			ARRAY_A
235
		); // WPCS: db call ok; no-cache ok.
236
	}
237
238
	/**
239
	 * Retrieve an array of posts sorted by ID.
240
	 *
241
	 * More precisely, returns the smallest $num_posts posts
242
	 * (measured by ID) which are larger than $from_id.
243
	 *
244
	 * @access public
245
	 * @since 4.7.0
246
	 *
247
	 * @param int $from_id Greatest lower bound of retrieved post IDs.
248
	 * @param int $num_posts Largest number of posts to retrieve.
249
	 *
250
	 * @return array The posts.
251
	 */
252
	public function query_posts_after_id( $from_id, $num_posts ) {
253
		global $wpdb;
254
255
		// Get the list of post types to include and prepare for query.
256
		$post_types = Jetpack_Options::get_option_and_ensure_autoload(
257
			'jetpack_sitemap_post_types',
258
			array( 'page', 'post' )
259
		);
260
		foreach ( (array) $post_types as $i => $post_type ) {
261
			$post_types[ $i ] = $wpdb->prepare( '%s', $post_type );
262
		}
263
		$post_types_list = join( ',', $post_types );
264
265
		return $wpdb->get_results(
266
			$wpdb->prepare(
267
				"SELECT *
268
					FROM $wpdb->posts
269
					WHERE post_status='publish'
270
						AND post_type IN ($post_types_list)
271
						AND ID>%d
272
					ORDER BY ID ASC
273
					LIMIT %d;",
274
				$from_id,
275
				$num_posts
276
			)
277
		); // WPCS: db call ok; no-cache ok.
278
	}
279
280
	/**
281
	 * Get the most recent timestamp among approved comments for the given post_id.
282
	 *
283
	 * @access public
284
	 * @since 4.7.0
285
	 *
286
	 * @param int $post_id Post identifier.
287
	 *
288
	 * @return int Timestamp in 'Y-m-d h:i:s' format (UTC) of the most recent comment on the given post, or null if no such comments exist.
289
	 */
290
	public function query_latest_approved_comment_time_on_post( $post_id ) {
291
		global $wpdb;
292
293
		return $wpdb->get_var(
294
			$wpdb->prepare(
295
				"SELECT MAX(comment_date_gmt)
296
					FROM $wpdb->comments
297
					WHERE comment_post_ID = %d AND comment_approved = '1' AND comment_type=''",
298
				$post_id
299
			)
300
		);
301
	}
302
303
	/**
304
	 * Retrieve an array of image posts sorted by ID.
305
	 *
306
	 * More precisely, returns the smallest $num_posts image posts
307
	 * (measured by ID) which are larger than $from_id.
308
	 *
309
	 * @access public
310
	 * @since 4.7.0
311
	 *
312
	 * @param int $from_id Greatest lower bound of retrieved image post IDs.
313
	 * @param int $num_posts Largest number of image posts to retrieve.
314
	 *
315
	 * @return array The posts.
316
	 */
317
	public function query_images_after_id( $from_id, $num_posts ) {
318
		global $wpdb;
319
320
		return $wpdb->get_results(
321
			$wpdb->prepare(
322
				"SELECT *
323
					FROM $wpdb->posts
324
					WHERE post_type='attachment'
325
						AND post_mime_type IN ('image/jpeg','image/png','image/gif')
326
						AND ID>%d
327
					ORDER BY ID ASC
328
					LIMIT %d;",
329
				$from_id,
330
				$num_posts
331
			)
332
		); // WPCS: db call ok; no-cache ok.
333
	}
334
335
	/**
336
	 * Retrieve an array of video posts sorted by ID.
337
	 *
338
	 * More precisely, returns the smallest $num_posts video posts
339
	 * (measured by ID) which are larger than $from_id.
340
	 *
341
	 * @access public
342
	 * @since 4.7.0
343
	 *
344
	 * @param int $from_id Greatest lower bound of retrieved video post IDs.
345
	 * @param int $num_posts Largest number of video posts to retrieve.
346
	 *
347
	 * @return array The posts.
348
	 */
349
	public function query_videos_after_id( $from_id, $num_posts ) {
350
		global $wpdb;
351
352
		return $wpdb->get_results(
353
			$wpdb->prepare(
354
				"SELECT *
355
					FROM $wpdb->posts
356
					WHERE post_type='attachment'
357
						AND post_mime_type IN ('video/mpeg','video/wmv','video/mov','video/avi','video/ogg')
358
						AND ID>%d
359
					ORDER BY ID ASC
360
					LIMIT %d;",
361
				$from_id,
362
				$num_posts
363
			)
364
		); // WPCS: db call ok; no-cache ok.
365
	}
366
367
	/**
368
	 * Retrieve an array of published posts from the last 2 days.
369
	 *
370
	 * @access public
371
	 * @since 4.7.0
372
	 *
373
	 * @param int $num_posts Largest number of posts to retrieve.
374
	 *
375
	 * @return array The posts.
376
	 */
377
	public function query_most_recent_posts( $num_posts ) {
378
		global $wpdb;
379
380
		$two_days_ago = date( 'Y-m-d', strtotime( '-2 days' ) );
381
382
		/**
383
		 * Filter post types to be included in news sitemap.
384
		 *
385
		 * @module sitemaps
386
		 *
387
		 * @since 3.9.0
388
		 *
389
		 * @param array $post_types Array with post types to include in news sitemap.
390
		 */
391
		$post_types = apply_filters(
392
			'jetpack_sitemap_news_sitemap_post_types',
393
			array( 'page', 'post' )
394
		);
395
396
		foreach ( (array) $post_types as $i => $post_type ) {
397
			$post_types[ $i ] = $wpdb->prepare( '%s', $post_type );
398
		}
399
400
		$post_types_list = join( ',', $post_types );
401
402
		return $wpdb->get_results(
403
			$wpdb->prepare(
404
				"SELECT *
405
					FROM $wpdb->posts
406
					WHERE post_status='publish'
407
						AND post_date >= '%s'
408
						AND post_type IN ($post_types_list)
409
					ORDER BY post_date DESC
410
					LIMIT %d;",
411
				$two_days_ago,
412
				$num_posts
413
			)
414
		); // WPCS: db call ok; no-cache ok.
415
	}
416
417
}
418