forked from Automattic/wordpress-activitypub
-
Notifications
You must be signed in to change notification settings - Fork 0
/
class-replies.php
176 lines (148 loc) · 4.96 KB
/
class-replies.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
<?php
namespace Activitypub\Collection;
use WP_Post;
use WP_Comment;
use WP_Error;
use Activitypub\Comment;
use function Activitypub\is_local_comment;
use function Activitypub\get_rest_url_by_path;
/**
* Class containing code for getting replies Collections and CollectionPages of posts and comments.
*/
class Replies {
/**
* Build base arguments for fetching the comments of either a WordPress post or comment.
*
* @param WP_Post|WP_Comment $wp_object
*/
private static function build_args( $wp_object ) {
$args = array(
'status' => 'approve',
'orderby' => 'comment_date_gmt',
'order' => 'ASC',
);
if ( $wp_object instanceof WP_Post ) {
$args['parent'] = 0; // TODO: maybe this is unnecessary.
$args['post_id'] = $wp_object->ID;
} elseif ( $wp_object instanceof WP_Comment ) {
$args['parent'] = $wp_object->comment_ID;
} else {
return new WP_Error();
}
return $args;
}
/**
* Adds pagination args comments query.
*
* @param array $args Query args built by self::build_args.
* @param int $page The current pagination page.
* @param int $comments_per_page The number of comments per page.
*/
private static function add_pagination_args( $args, $page, $comments_per_page ) {
$args['number'] = $comments_per_page;
$offset = intval( $page ) * $comments_per_page;
$args['offset'] = $offset;
return $args;
}
/**
* Get the replies collections ID.
*
* @param WP_Post|WP_Comment $wp_object
*
* @return string The rest URL of the replies collection.
*/
private static function get_id( $wp_object ) {
if ( $wp_object instanceof WP_Post ) {
return get_rest_url_by_path( sprintf( 'posts/%d/replies', $wp_object->ID ) );
} elseif ( $wp_object instanceof WP_Comment ) {
return get_rest_url_by_path( sprintf( 'comments/%d/replies', $wp_object->comment_ID ) );
} else {
return new WP_Error();
}
}
/**
* Get the replies collection.
*
* @param WP_Post|WP_Comment $wp_object
* @param int $page
*
* @return array An associative array containing the replies collection without JSON-LD context.
*/
public static function get_collection( $wp_object ) {
$id = self::get_id( $wp_object );
if ( ! $id ) {
return null;
}
$replies = array(
'id' => $id,
'type' => 'Collection',
);
$replies['first'] = self::get_collection_page( $wp_object, 0, $replies['id'] );
return $replies;
}
/**
* Get the ActivityPub ID's from a list of comments.
*
* It takes only federated/non-local comments into account, others also do not have an
* ActivityPub ID available.
*
* @param WP_Comment[] $comments The comments to retrieve the ActivityPub ids from.
*
* @return string[] A list of the ActivityPub ID's.
*/
private static function get_reply_ids( $comments ) {
$comment_ids = array();
// Only add external comments from the fediverse.
// Maybe use the Comment class more and the function is_local_comment etc.
foreach ( $comments as $comment ) {
if ( is_local_comment( $comment ) ) {
continue;
}
$public_comment_id = Comment::get_source_id( $comment->comment_ID );
if ( $public_comment_id ) {
$comment_ids[] = $public_comment_id;
}
}
return $comment_ids;
}
/**
* Returns a replies collection page as an associative array.
*
* @link https://www.w3.org/TR/activitystreams-vocabulary/#dfn-collectionpage
*
* @param WP_Post|WP_Comment $wp_object The post of comment the replies are for.
* @param int $page The current pagination page.
* @param string $part_of The collection id/url the returned CollectionPage belongs to.
*
* @return array A CollectionPage as an associative array.
*/
public static function get_collection_page( $wp_object, $page, $part_of = null ) {
// Build initial arguments for fetching approved comments.
$args = self::build_args( $wp_object );
// Retrieve the partOf if not already given.
$part_of = $part_of ?? self::get_id( $wp_object );
// If the collection page does not exist.
if ( is_wp_error( $args ) || is_wp_error( $part_of ) ) {
return null;
}
// Get to total replies count.
$total_replies = \get_comments( array_merge( $args, array( 'count' => true ) ) );
// Modify query args to retrieve paginated results.
$comments_per_page = \get_option( 'comments_per_page' );
// Fetch internal and external comments for current page.
$comments = get_comments( self::add_pagination_args( $args, $page, $comments_per_page ) );
// Get the ActivityPub ID's of the comments, without out local-only comments.
$comment_ids = self::get_reply_ids( $comments );
// Build the associative CollectionPage array.
$collection_page = array(
'id' => \add_query_arg( 'page', $page, $part_of ),
'type' => 'CollectionPage',
'partOf' => $part_of,
'items' => $comment_ids,
);
if ( $total_replies / $comments_per_page > $page + 1 ) {
$collection_page['next'] = \add_query_arg( 'page', $page + 1, $part_of );
}
return $collection_page;
}
}