2023-04-24 20:46:51 +02:00
|
|
|
<?php
|
|
|
|
namespace Activitypub\Model;
|
|
|
|
|
|
|
|
use Activitypub\Collection\Followers;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* ActivityPub Follower Class
|
|
|
|
*
|
2023-04-25 09:09:07 +02:00
|
|
|
* This Object represents a single Follower.
|
|
|
|
* There is no direct reference to a WordPress User here.
|
|
|
|
*
|
2023-04-24 20:46:51 +02:00
|
|
|
* @author Matthias Pfefferle
|
|
|
|
*
|
|
|
|
* @see https://www.w3.org/TR/activitypub/#follow-activity-inbox
|
|
|
|
*/
|
|
|
|
class Follower {
|
2023-04-25 09:09:07 +02:00
|
|
|
/**
|
|
|
|
* The Object ID
|
|
|
|
*
|
|
|
|
* @var int
|
|
|
|
*/
|
2023-04-24 20:46:51 +02:00
|
|
|
private $id;
|
|
|
|
|
2023-04-25 09:09:07 +02:00
|
|
|
/**
|
|
|
|
* The Actor-URL of the Follower
|
|
|
|
*
|
|
|
|
* @var string
|
|
|
|
*/
|
2023-04-24 20:46:51 +02:00
|
|
|
private $actor;
|
|
|
|
|
2023-04-25 09:09:07 +02:00
|
|
|
/**
|
|
|
|
* The Object slug
|
|
|
|
*
|
|
|
|
* This is a requirement of the Term-Meta but will not
|
|
|
|
* be actively used in the ActivityPub context.
|
|
|
|
*
|
|
|
|
* @var string
|
|
|
|
*/
|
2023-04-24 20:46:51 +02:00
|
|
|
private $slug;
|
|
|
|
|
2023-04-25 09:09:07 +02:00
|
|
|
/**
|
|
|
|
* The Object Name
|
|
|
|
*
|
|
|
|
* This is the same as the Actor-URL
|
|
|
|
*
|
|
|
|
* @var string
|
|
|
|
*/
|
2023-04-24 20:46:51 +02:00
|
|
|
private $name;
|
|
|
|
|
2023-04-25 09:09:07 +02:00
|
|
|
/**
|
|
|
|
* The Username
|
|
|
|
*
|
|
|
|
* @var string
|
|
|
|
*/
|
2023-04-24 20:46:51 +02:00
|
|
|
private $username;
|
|
|
|
|
2023-04-25 09:09:07 +02:00
|
|
|
/**
|
|
|
|
* The Avatar URL
|
|
|
|
*
|
|
|
|
* @var string
|
|
|
|
*/
|
2023-04-24 20:46:51 +02:00
|
|
|
private $avatar;
|
|
|
|
|
2023-04-25 09:09:07 +02:00
|
|
|
/**
|
|
|
|
* The URL to the Followers Inbox
|
|
|
|
*
|
|
|
|
* @var string
|
|
|
|
*/
|
2023-04-24 20:46:51 +02:00
|
|
|
private $inbox;
|
|
|
|
|
2023-04-25 09:09:07 +02:00
|
|
|
/**
|
|
|
|
* The URL to the Servers Shared-Inbox
|
|
|
|
*
|
|
|
|
* If the Server does not support Shared-Inboxes,
|
|
|
|
* the Inbox will be stored.
|
|
|
|
*
|
|
|
|
* @var string
|
|
|
|
*/
|
2023-04-24 20:46:51 +02:00
|
|
|
private $shared_inbox;
|
|
|
|
|
2023-04-25 09:09:07 +02:00
|
|
|
/**
|
|
|
|
* The date, the Follower was updated
|
|
|
|
*
|
|
|
|
* @var string untixtimestamp
|
|
|
|
*/
|
2023-04-24 20:46:51 +02:00
|
|
|
private $updated_at;
|
|
|
|
|
2023-04-25 09:09:07 +02:00
|
|
|
/**
|
|
|
|
* The complete Remote-Profile of the Follower
|
|
|
|
*
|
|
|
|
* @var array
|
|
|
|
*/
|
2023-04-24 20:46:51 +02:00
|
|
|
private $meta;
|
|
|
|
|
2023-05-02 14:39:25 +02:00
|
|
|
/**
|
|
|
|
* The latest received error.
|
|
|
|
*
|
|
|
|
* This will only temporary and will saved to $this->errors
|
|
|
|
*
|
|
|
|
* @var string
|
|
|
|
*/
|
|
|
|
private $error;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* A list of errors
|
|
|
|
*
|
|
|
|
* @var array
|
|
|
|
*/
|
|
|
|
private $errors;
|
|
|
|
|
2023-04-25 09:09:07 +02:00
|
|
|
/**
|
|
|
|
* Maps the meta fields to the local db fields
|
|
|
|
*
|
|
|
|
* @var array
|
|
|
|
*/
|
2023-04-24 20:46:51 +02:00
|
|
|
private $map_meta = array(
|
|
|
|
'name' => 'name',
|
|
|
|
'preferredUsername' => 'username',
|
|
|
|
'inbox' => 'inbox',
|
|
|
|
);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Constructor
|
|
|
|
*
|
|
|
|
* @param WP_Post $post
|
|
|
|
*/
|
|
|
|
public function __construct( $actor ) {
|
|
|
|
$this->actor = $actor;
|
|
|
|
|
2023-04-27 09:57:50 +02:00
|
|
|
$term = get_term_by( 'name', $actor, Followers::TAXONOMY );
|
|
|
|
|
2023-04-24 20:46:51 +02:00
|
|
|
if ( $term ) {
|
|
|
|
$this->id = $term->term_id;
|
|
|
|
$this->slug = $term->slug;
|
|
|
|
$this->meta = json_decode( $term->meta );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Magic function to implement getter and setter
|
|
|
|
*
|
2023-05-10 15:02:01 +02:00
|
|
|
* @param string $method The method name.
|
|
|
|
* @param string $params The method params.
|
2023-04-24 20:46:51 +02:00
|
|
|
*
|
|
|
|
* @return void
|
|
|
|
*/
|
|
|
|
public function __call( $method, $params ) {
|
|
|
|
$var = \strtolower( \substr( $method, 4 ) );
|
|
|
|
|
|
|
|
if ( \strncasecmp( $method, 'get', 3 ) === 0 ) {
|
|
|
|
if ( empty( $this->$var ) ) {
|
|
|
|
return $this->get( $var );
|
|
|
|
}
|
|
|
|
return $this->$var;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( \strncasecmp( $method, 'set', 3 ) === 0 ) {
|
|
|
|
$this->$var = $params[0];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-05-10 15:02:01 +02:00
|
|
|
/**
|
|
|
|
* Prefill the Object with the meta data.
|
|
|
|
*
|
|
|
|
* @param array $meta The meta data.
|
|
|
|
*
|
|
|
|
* @return void
|
|
|
|
*/
|
2023-04-27 09:57:50 +02:00
|
|
|
public function from_meta( $meta ) {
|
|
|
|
$this->meta = $meta;
|
|
|
|
|
|
|
|
foreach ( $this->map_meta as $remote => $internal ) {
|
|
|
|
if ( ! empty( $meta[ $remote ] ) ) {
|
|
|
|
$this->$internal = $meta[ $remote ];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( ! empty( $meta['icon']['url'] ) ) {
|
|
|
|
$this->avatar = $meta['icon']['url'];
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( ! empty( $meta['endpoints']['sharedInbox'] ) ) {
|
|
|
|
$this->shared_inbox = $meta['endpoints']['sharedInbox'];
|
|
|
|
} elseif ( ! empty( $meta['inbox'] ) ) {
|
|
|
|
$this->shared_inbox = $meta['inbox'];
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->updated_at = \strtotime( 'now' );
|
|
|
|
}
|
|
|
|
|
2023-05-10 15:02:01 +02:00
|
|
|
/**
|
|
|
|
* Get the data by the given attribute
|
|
|
|
*
|
|
|
|
* @param string $attribute The attribute name.
|
|
|
|
*
|
|
|
|
* @return mixed The attribute value.
|
|
|
|
*/
|
2023-04-24 20:46:51 +02:00
|
|
|
public function get( $attribute ) {
|
|
|
|
if ( $this->$attribute ) {
|
|
|
|
return $this->$attribute;
|
|
|
|
}
|
|
|
|
|
2023-04-27 09:57:50 +02:00
|
|
|
$attribute = get_term_meta( $this->id, $attribute, true );
|
|
|
|
if ( $attribute ) {
|
|
|
|
$this->$attribute = $attribute;
|
|
|
|
return $attribute;
|
2023-04-24 20:46:51 +02:00
|
|
|
}
|
|
|
|
|
2023-04-27 09:57:50 +02:00
|
|
|
$attribute = $this->get_meta_by( $attribute );
|
|
|
|
if ( $attribute ) {
|
|
|
|
$this->$attribute = $attribute;
|
|
|
|
return $attribute;
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
2023-04-24 20:46:51 +02:00
|
|
|
}
|
|
|
|
|
2023-05-10 15:02:01 +02:00
|
|
|
/**
|
|
|
|
* Get the errors.
|
|
|
|
*
|
|
|
|
* @return mixed
|
|
|
|
*/
|
2023-05-02 14:39:25 +02:00
|
|
|
public function get_errors() {
|
|
|
|
if ( $this->errors ) {
|
|
|
|
return $this->errors;
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->errors = get_term_meta( $this->id, 'errors' );
|
|
|
|
return $this->errors;
|
|
|
|
}
|
|
|
|
|
2023-05-10 15:02:01 +02:00
|
|
|
/**
|
|
|
|
* Reset (delete) all errors.
|
|
|
|
*
|
|
|
|
* @return void
|
|
|
|
*/
|
2023-05-10 14:18:56 +02:00
|
|
|
public function reset_errors() {
|
|
|
|
delete_term_meta( $this->id, 'errors' );
|
|
|
|
}
|
|
|
|
|
2023-05-10 15:02:01 +02:00
|
|
|
/**
|
|
|
|
* Count the errors.
|
|
|
|
*
|
|
|
|
* @return int The number of errors.
|
|
|
|
*/
|
2023-05-02 14:39:25 +02:00
|
|
|
public function count_errors() {
|
|
|
|
$errors = $this->get_errors();
|
|
|
|
|
|
|
|
if ( is_array( $errors ) && ! empty( $errors ) ) {
|
|
|
|
return count( $errors );
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2023-05-10 15:02:01 +02:00
|
|
|
/**
|
|
|
|
* Return the latest error message.
|
|
|
|
*
|
|
|
|
* @return string The error message.
|
|
|
|
*/
|
2023-05-02 14:39:25 +02:00
|
|
|
public function get_latest_error_message() {
|
|
|
|
$errors = $this->get_errors();
|
|
|
|
|
|
|
|
if ( is_array( $errors ) && ! empty( $errors ) ) {
|
|
|
|
return reset( $errors );
|
|
|
|
}
|
|
|
|
|
|
|
|
return '';
|
|
|
|
}
|
|
|
|
|
2023-05-10 15:02:01 +02:00
|
|
|
/**
|
|
|
|
* Get the meta data by the given attribute.
|
|
|
|
*
|
|
|
|
* @param string $attribute The attribute name.
|
|
|
|
*
|
|
|
|
* @return mixed $attribute The attribute value.
|
|
|
|
*/
|
2023-04-27 09:57:50 +02:00
|
|
|
public function get_meta_by( $attribute ) {
|
|
|
|
$meta = $this->get_meta();
|
2023-04-24 20:46:51 +02:00
|
|
|
|
2023-05-02 14:39:25 +02:00
|
|
|
// try mapped data (see $this->map_meta)
|
2023-04-24 20:46:51 +02:00
|
|
|
foreach ( $this->map_meta as $remote => $local ) {
|
|
|
|
if ( $attribute === $local && isset( $meta[ $remote ] ) ) {
|
|
|
|
return $meta[ $remote ];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-04-27 09:57:50 +02:00
|
|
|
// try ActivityPub attribtes
|
|
|
|
if ( ! empty( $this->map_meta[ $attribute ] ) ) {
|
|
|
|
return $this->map_meta[ $attribute ];
|
|
|
|
}
|
|
|
|
|
2023-04-24 20:46:51 +02:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2023-05-10 15:02:01 +02:00
|
|
|
/**
|
|
|
|
* Get the meta data.
|
|
|
|
*
|
|
|
|
* @return array $meta The meta data.
|
|
|
|
*/
|
2023-04-27 09:57:50 +02:00
|
|
|
public function get_meta() {
|
|
|
|
if ( $this->meta ) {
|
2023-04-24 20:46:51 +02:00
|
|
|
return $this->meta;
|
|
|
|
}
|
|
|
|
|
2023-04-27 09:57:50 +02:00
|
|
|
return null;
|
2023-04-24 20:46:51 +02:00
|
|
|
}
|
|
|
|
|
2023-05-10 15:02:01 +02:00
|
|
|
/**
|
|
|
|
* Update the current Follower-Object.
|
|
|
|
*
|
|
|
|
* @return void
|
|
|
|
*/
|
2023-04-24 20:46:51 +02:00
|
|
|
public function update() {
|
|
|
|
$term = wp_update_term(
|
|
|
|
$this->id,
|
|
|
|
Followers::TAXONOMY,
|
|
|
|
array(
|
|
|
|
'description' => wp_json_encode( $this->get_meta( true ) ),
|
|
|
|
)
|
|
|
|
);
|
|
|
|
|
2023-05-03 15:11:20 +02:00
|
|
|
$this->updated_at = \strtotime( 'now' );
|
2023-04-24 20:46:51 +02:00
|
|
|
$this->update_term_meta();
|
|
|
|
}
|
|
|
|
|
2023-05-10 15:02:01 +02:00
|
|
|
/**
|
|
|
|
* Save the current Follower-Object.
|
|
|
|
*
|
|
|
|
* @return void
|
|
|
|
*/
|
2023-04-24 20:46:51 +02:00
|
|
|
public function save() {
|
|
|
|
$term = wp_insert_term(
|
|
|
|
$this->actor,
|
|
|
|
Followers::TAXONOMY,
|
|
|
|
array(
|
|
|
|
'slug' => sanitize_title( $this->get_actor() ),
|
|
|
|
'description' => wp_json_encode( $this->get_meta() ),
|
|
|
|
)
|
|
|
|
);
|
|
|
|
|
|
|
|
$this->id = $term['term_id'];
|
|
|
|
|
|
|
|
$this->update_term_meta();
|
|
|
|
}
|
|
|
|
|
2023-05-10 15:02:01 +02:00
|
|
|
/**
|
|
|
|
* Upsert the current Follower-Object.
|
|
|
|
*
|
|
|
|
* @return void
|
|
|
|
*/
|
2023-04-24 20:46:51 +02:00
|
|
|
public function upsert() {
|
|
|
|
if ( $this->id ) {
|
|
|
|
$this->update();
|
|
|
|
} else {
|
|
|
|
$this->save();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-05-10 15:02:01 +02:00
|
|
|
/**
|
|
|
|
* Delete the current Follower-Object.
|
|
|
|
*
|
|
|
|
* @return void
|
|
|
|
*/
|
2023-05-10 14:18:56 +02:00
|
|
|
public function delete() {
|
|
|
|
wp_delete_term( $this->id, Followers::TAXONOMY );
|
|
|
|
}
|
|
|
|
|
2023-05-10 15:02:01 +02:00
|
|
|
/**
|
|
|
|
* Update the term meta.
|
|
|
|
*
|
|
|
|
* @return void
|
|
|
|
*/
|
2023-04-24 20:46:51 +02:00
|
|
|
protected function update_term_meta() {
|
2023-04-27 09:57:50 +02:00
|
|
|
$attributes = array( 'inbox', 'shared_inbox', 'avatar', 'updated_at', 'name', 'username' );
|
2023-04-24 20:46:51 +02:00
|
|
|
|
2023-04-27 09:57:50 +02:00
|
|
|
foreach ( $attributes as $attribute ) {
|
|
|
|
if ( $this->get( $attribute ) ) {
|
2023-05-02 14:39:25 +02:00
|
|
|
update_term_meta( $this->id, $attribute, $this->get( $attribute ) );
|
2023-04-24 20:46:51 +02:00
|
|
|
}
|
|
|
|
}
|
2023-05-02 14:39:25 +02:00
|
|
|
|
|
|
|
if ( $this->error ) {
|
|
|
|
if ( is_string( $this->error ) ) {
|
|
|
|
$error = $this->error;
|
|
|
|
} elseif ( is_wp_error( $this->error ) ) {
|
|
|
|
$error = $this->error->get_error_message();
|
|
|
|
} else {
|
|
|
|
$error = __( 'Unknown Error or misconfigured Error-Message', 'activitypub' );
|
|
|
|
}
|
|
|
|
|
|
|
|
add_term_meta( $this->id, 'errors', $error );
|
|
|
|
}
|
2023-04-24 20:46:51 +02:00
|
|
|
}
|
|
|
|
}
|