PluginProbe
ActivityPub / 8.1.1
ActivityPub v8.1.1
9.3.1 9.3.0 9.2.2 9.2.1 9.2.0 9.1.0 9.0.2 9.0.1 9.0.0 8.3.0 8.2.1 8.2.0 8.1.1 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.2.0 1.3.0 2.0.0 2.0.1 2.1.0 2.1.1 All 160 releases
activitypub / includes / model / class-follower.php

class-follower.php in ActivityPub 8.1.1, at includes/model/class-follower.php

360 lines 7.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Follower class file.
4 *
5 * @package Activitypub
6 */
7
8 namespace Activitypub\Model;
9
10 use Activitypub\Activity\Actor;
11 use Activitypub\Collection\Followers;
12 use Activitypub\Collection\Remote_Actors;
13
14 use function Activitypub\extract_name_from_uri;
15
16 /**
17 * ActivityPub Follower Class.
18 *
19 * This Object represents a single Follower.
20 * There is no direct reference to a WordPress User here.
21 *
22 * @author Matt Wiebe
23 * @author Matthias Pfefferle
24 *
25 * @deprecated 7.0.0
26 * @see https://www.w3.org/TR/activitypub/#follow-activity-inbox
27 *
28 * @method int get__id() Gets the post ID of the follower record.
29 * @method string[]|null get_image() Gets the follower's profile image data.
30 * @method string|null get_inbox() Gets the follower's ActivityPub inbox URL.
31 * @method string[]|null get_endpoints() Gets the follower's ActivityPub endpoints.
32 *
33 * @method Follower set__id( int $id ) Sets the post ID of the follower record.
34 * @method Follower set_id( string $guid ) Sets the follower's GUID.
35 * @method Follower set_name( string $name ) Sets the follower's display name.
36 * @method Follower set_summary( string $summary ) Sets the follower's bio/summary.
37 * @method Follower set_published( string $datetime ) Sets the follower's published datetime in ISO 8601 format.
38 * @method Follower set_updated( string $datetime ) Sets the follower's last updated datetime in ISO 8601 format.
39 */
40 class Follower extends Actor {
41 /**
42 * The complete Remote-Profile of the Follower.
43 *
44 * @var int
45 */
46 protected $_id; // phpcs:ignore PSR2.Classes.PropertyDeclaration.Underscore
47
48 /**
49 * Constructor.
50 *
51 * @deprecated Use Actor instead.
52 */
53 public function __construct() {
54 \_deprecated_class( __CLASS__, '7.0.0', Actor::class );
55 }
56
57 /**
58 * Get the errors.
59 *
60 * @return mixed
61 */
62 public function get_errors() {
63 return Remote_Actors::get_errors( $this->_id );
64 }
65
66 /**
67 * Clear the errors for the current Follower.
68 *
69 * @return bool True on success, false on failure.
70 */
71 public function clear_errors() {
72 return Remote_Actors::clear_errors( $this->_id );
73 }
74
75 /**
76 * Get the Summary.
77 *
78 * @return string The Summary.
79 */
80 public function get_summary() {
81 if ( isset( $this->summary ) ) {
82 return $this->summary;
83 }
84
85 return '';
86 }
87
88 /**
89 * Getter for URL attribute.
90 *
91 * Falls back to ID, if no URL is set. This is relevant for
92 * Platforms like Lemmy, where the ID is the URL.
93 *
94 * @return string The URL.
95 */
96 public function get_url() {
97 if ( $this->url ) {
98 return $this->url;
99 }
100
101 return $this->id;
102 }
103
104 /**
105 * Reset (delete) all errors.
106 *
107 * @return bool True on success, false on failure.
108 */
109 public function reset_errors() {
110 return Remote_Actors::clear_errors( $this->_id );
111 }
112
113 /**
114 * Count the errors.
115 *
116 * @return int The number of errors.
117 */
118 public function count_errors() {
119 return Remote_Actors::count_errors( $this->_id );
120 }
121
122 /**
123 * Return the latest error message.
124 *
125 * @return string The error message.
126 */
127 public function get_latest_error_message() {
128 $errors = $this->get_errors();
129
130 if ( \is_array( $errors ) && ! empty( $errors ) ) {
131 return \reset( $errors );
132 }
133
134 return '';
135 }
136
137 /**
138 * Update the current Follower object.
139 */
140 public function update() {
141 $this->save();
142 }
143
144 /**
145 * Validate the current Follower object.
146 *
147 * @return boolean True if the verification was successful.
148 */
149 public function is_valid() {
150 // The minimum required attributes.
151 $required_attributes = array(
152 'id',
153 'preferredUsername',
154 'inbox',
155 'publicKey',
156 'publicKeyPem',
157 );
158
159 foreach ( $required_attributes as $attribute ) {
160 if ( ! $this->get( $attribute ) ) {
161 return false;
162 }
163 }
164
165 return true;
166 }
167
168 /**
169 * Save the current Follower object.
170 *
171 * @return int|\WP_Error The post ID or an WP_Error.
172 */
173 public function save() {
174 if ( ! $this->is_valid() ) {
175 return new \WP_Error( 'activitypub_invalid_follower', __( 'Invalid Follower', 'activitypub' ), array( 'status' => 400 ) );
176 }
177
178 $id = Remote_Actors::upsert( $this );
179 if ( \is_wp_error( $id ) ) {
180 return $id;
181 }
182
183 $this->set__id( $id );
184 return $id;
185 }
186
187 /**
188 * Upsert the current Follower object.
189 *
190 * @return int|\WP_Error The post ID or an WP_Error.
191 */
192 public function upsert() {
193 return $this->save();
194 }
195
196 /**
197 * Delete the current Follower object.
198 *
199 * Beware that this os deleting a Follower for ALL users!!!
200 *
201 * To delete only the User connection (unfollow)
202 *
203 * @see \Activitypub\Rest\Followers::remove_follower()
204 */
205 public function delete() {
206 Followers::remove_follower( $this->_id, $this->get_id() );
207 }
208
209 /**
210 * Get the icon.
211 *
212 * Sets a fallback to better handle API and HTML outputs.
213 *
214 * @return string[] The icon.
215 */
216 public function get_icon() {
217 if ( isset( $this->icon['url'] ) ) {
218 return $this->icon;
219 }
220
221 return array(
222 'type' => 'Image',
223 'mediaType' => 'image/jpeg',
224 'url' => ACTIVITYPUB_PLUGIN_URL . 'assets/img/mp.jpg',
225 );
226 }
227
228 /**
229 * Get Name.
230 *
231 * Tries to extract a name from the URL or ID if not set.
232 *
233 * @return string The name.
234 */
235 public function get_name() {
236 if ( $this->name ) {
237 return $this->name;
238 } elseif ( $this->preferred_username ) {
239 return $this->preferred_username;
240 }
241
242 return $this->extract_name_from_uri();
243 }
244
245 /**
246 * The preferred Username.
247 *
248 * Tries to extract a name from the URL or ID if not set.
249 *
250 * @return string The preferred Username.
251 */
252 public function get_preferred_username() {
253 if ( $this->preferred_username ) {
254 return $this->preferred_username;
255 }
256
257 return $this->extract_name_from_uri();
258 }
259
260 /**
261 * Get the Icon URL (Avatar).
262 *
263 * @return string The URL to the Avatar.
264 */
265 public function get_icon_url() {
266 $icon = $this->get_icon();
267
268 if ( ! $icon ) {
269 return '';
270 }
271
272 if ( \is_array( $icon ) ) {
273 return $icon['url'];
274 }
275
276 return $icon;
277 }
278
279 /**
280 * Get the Icon URL (Avatar).
281 *
282 * @return string The URL to the Avatar.
283 */
284 public function get_image_url() {
285 $image = $this->get_image();
286
287 if ( ! $image ) {
288 return '';
289 }
290
291 if ( \is_array( $image ) ) {
292 return $image['url'];
293 }
294
295 return $image;
296 }
297
298 /**
299 * Get the shared inbox, with a fallback to the inbox.
300 *
301 * @return string|null The URL to the shared inbox, the inbox or null.
302 */
303 public function get_shared_inbox() {
304 if ( ! empty( $this->get_endpoints()['sharedInbox'] ) ) {
305 return $this->get_endpoints()['sharedInbox'];
306 } elseif ( ! empty( $this->get_inbox() ) ) {
307 return $this->get_inbox();
308 }
309
310 return null;
311 }
312
313 /**
314 * Convert a Custom-Post-Type input to an Activitypub\Model\Follower.
315 *
316 * @param \WP_Post $post The post object.
317 * @return Follower|false The Follower object or false on failure.
318 */
319 public static function init_from_cpt( $post ) {
320 if ( empty( $post->post_content ) ) {
321 $json = \get_post_meta( $post->ID, '_activitypub_actor_json', true );
322 } else {
323 $json = $post->post_content;
324 }
325
326 /* @var Follower $object Follower object. */
327 $object = self::init_from_json( $json );
328
329 if ( \is_wp_error( $object ) ) {
330 return false;
331 }
332
333 $object->set__id( $post->ID );
334 $object->set_id( $post->guid );
335 $object->set_name( $post->post_title );
336 $object->set_summary( $post->post_excerpt );
337 $object->set_published( gmdate( 'Y-m-d H:i:s', strtotime( $post->post_date ) ) );
338 $object->set_updated( gmdate( 'Y-m-d H:i:s', strtotime( $post->post_modified ) ) );
339
340 return $object;
341 }
342
343 /**
344 * Infer a shortname from the Actor ID or URL. Used only for fallbacks,
345 * we will try to use what's supplied.
346 *
347 * @return string Hopefully the name of the Follower.
348 */
349 protected function extract_name_from_uri() {
350 // prefer the URL, but fall back to the ID.
351 if ( $this->url ) {
352 $uri = $this->url;
353 } else {
354 $uri = $this->id;
355 }
356
357 return extract_name_from_uri( $uri );
358 }
359 }
360