Completed
Push — add/comments-tree-endpoint-pin... ( 31a20b...dab30a )
by Kirk
10:26
created

y_map_all_as_ints()   A

Complexity

Conditions 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
class WPCOM_JSON_API_Get_Comments_Tree_Endpoint extends WPCOM_JSON_API_Endpoint {
4
	/**
5
	 * Retrieves a list of comment data for a given site.
6
	 *
7
	 * @param string $status Filter by status: all, approved, pending, spam or trash.
8
	 * @param int $start_at first comment to search from going back in time
9
	 *
10
	 * @return array
11
	 */
12
	function get_site_tree( $status, $start_at = PHP_INT_MAX ) {
13
		global $wpdb;
14
		$max_comment_count = 50000;
15
		$db_status = $this->get_comment_db_status( $status );
16
17
		$db_comment_rows = $wpdb->get_results(
18
			$wpdb->prepare(
19
				"SELECT comment_ID, comment_post_ID, comment_parent, comment_type " .
20
				"FROM $wpdb->comments AS comments " .
21
				"INNER JOIN $wpdb->posts AS posts ON comments.comment_post_ID = posts.ID " .
22
				"WHERE comment_ID <= %d AND ( %s = 'all' OR comment_approved = %s ) " .
23
				"ORDER BY comment_ID DESC " .
24
				"LIMIT %d",
25
				(int) $start_at, $db_status, $db_status, $max_comment_count
26
			),
27
			ARRAY_N
28
		);
29
30
		$comments = array();
31
		$trackbacks = array();
32
		$pingbacks = array();
33
		foreach ( $db_comment_rows as $row ) {
34
			list( $comment_id, $comment_post_id, $comment_parent, $comment_type ) = $row;
35
			switch ( $comment_type ) {
36
				case 'trackback':
37
					$trackbacks[] = array( $comment_id, $comment_post_id, $comment_parent );
38
					break;
39
				case 'pingback':
40
					$pingbacks[] = array( $comment_id, $comment_post_id, $comment_parent );
41
					break;
42
				default:
43
					$comments[] = array( $comment_id, $comment_post_id, $comment_parent );
44
			}
45
		}
46
47
		return array(
48
			'comments_count' => $this->get_site_tree_total_count( $status, 'comment' ),
49
			'comments_tree' => array_map( array( $this, 'array_map_all_as_ints' ), $comments ),
50
			'trackbacks_count' => $this->get_site_tree_total_count( $status, 'trackback' ),
51
			'trackbacks_tree' => array_map( array( $this, 'array_map_all_as_ints' ), $trackbacks ),
52
			'pingbacks_count' => $this->get_site_tree_total_count( $status, 'pingback' ),
53
			'pingbacks_tree' => array_map( array( $this, 'array_map_all_as_ints' ), $pingbacks ),
54
		);
55
	}
56
57
	/**
58
	 * Ensure all values are integers.
59
	 *
60
	 * @param array $comments Collection of comments.
61
	 *
62
	 * @return array Comments with values as integers.
63
	 */
64
	function array_map_all_as_ints( $comments ) {
65
		return array_map( 'intval', $comments );
66
	}
67
68
	/**
69
	 * Retrieves a total count of comments by type for the given site.
70
	 *
71
	 * @param string $status Filter by status: all, approved, pending, spam or trash.
72
	 * @param string $type Comment type: 'trackback', 'pingback', or 'comment'.
73
	 *
74
	 * @return int Total count of comments for a site.
75
	 */
76
	function get_site_tree_total_count( $status, $type ) {
77
		global $wpdb;
78
		$db_status = $this->get_comment_db_status( $status );
79
		$type = $this->get_sanitized_comment_type( $type );
80
		// An empty value in the comments_type column denotes a regular comment.
81
		$type = ( 'comment' === $type ) ? '' : $type;
82
83
		$result = $wpdb->get_var(
84
			$wpdb->prepare(
85
				"SELECT COUNT(1) " .
86
				"FROM $wpdb->comments AS comments " .
87
				"INNER JOIN $wpdb->posts AS posts ON comments.comment_post_ID = posts.ID " .
88
				"WHERE comment_type = %s AND ( %s = 'all' OR comment_approved = %s )",
89
				$type, $db_status, $db_status
90
			)
91
		);
92
		return intval( $result );
93
	}
94
95
	/**
96
	 * Ensure a valid status is converted to a database-supported value if necessary.
97
	 *
98
	 * @param string $status Should be one of: all, approved, pending, spam or trash.
99
	 *
100
	 * @return string Corresponding value that exists in database.
101
	 */
102
	function get_comment_db_status( $status ) {
103
		if ( 'approved' === $status ) {
104
			return '1';
105
		}
106
		if ( 'pending' === $status ) {
107
			return '0';
108
		}
109
		return $status;
110
	}
111
112
	/**
113
	 * Determine if the passed comment status is valid or not.
114
	 *
115
	 * @param string $status
116
	 *
117
	 * @return boolean
118
	 */
119
	function validate_status_param( $status ) {
120
		return in_array( $status, array( 'all', 'approved', 'pending', 'spam', 'trash' ) );
121
	}
122
123
	/**
124
	 * Sanitize a given comment type.
125
	 *
126
	 * @param string Comment type: can be 'trackback', 'pingback', or 'comment'.
127
	 *
128
	 * @return string Sanitized comment type.
129
	 */
130
	function get_sanitized_comment_type( $type = 'comment' ) {
131
		if ( in_array( $type, array( 'trackback', 'pingback', 'comment' ) ) ) {
132
			return $type;
133
		}
134
		return 'comment';
135
	}
136
137
	/**
138
	 * Endpoint callback for /sites/%s/comments-tree
139
	 *
140
	 * @param string $path
141
	 * @param int    $blog_id
142
	 *
143
	 * @return array Site tree results by status.
144
	 */
145
	function callback( $path = '', $blog_id = 0 ) {
146
		$blog_id = $this->api->switch_to_blog_and_validate_user( $this->api->get_blog_id( $blog_id ) );
147
		if ( is_wp_error( $blog_id ) ) {
148
			return $blog_id;
149
		}
150
151
		$args = $this->query_args();
152
		$comment_status = empty( $args['status'] ) ? 'all' : $args['status'];
153
154
		if ( ! $this->validate_status_param( $comment_status ) ) {
155
			return new WP_Error( 'invalid_status', "Invalid comment status value provided: '$comment_status'.", 400 );
156
		}
157
158
		return $this->get_site_tree( $comment_status );
159
	}
160
}
161