wordpress-activitypub/includes/model/class-follow-request.php

264 lines
6.6 KiB
PHP
Raw Permalink Normal View History

<?php
namespace Activitypub\Model;
use WP_Error;
use Activitypub\Activity\Base_Object;
use Activitypub\Collection\Followers;
use Activitypub\Collection\Users;
use Activitypub\Model\Follower;
/**
* ActivityPub Follow Class
*
* This Object represents a Follow object.
* There is no direct reference to a WordPress User here.
*
* @author André Menrath
*
* @see https://www.w3.org/TR/activitypub/#follow-activity-inbox
*/
class Follow_Request extends Base_Object {
const FOLLOW_REQUEST_POST_TYPE = 'ap_follow_request';
const FOLLOW_REQUEST_STATUS_APPROVED = 'approved';
const FOLLOW_REQUEST_STATUS_REJECTED = 'rejected';
/**
* Stores theinternal WordPress post id of the post of type ap_follow_request
2023-12-26 13:50:54 +01:00
*
* @var string
*/
protected $_id;
/**
* The id/URI of the follower
* @var string
*/
protected $actor;
/**
* The internal WordPress post id of the follower
* @var string
*/
protected $_actor;
/**
* The status: 'approved', 'pending', 'rejected'<div class=""></div>
* @var string
*/
protected $_status;
/**
* @param int $id
* @return Follow_Request $follow_request
*/
public static function get_from_array( $array ) {
$follow_request = self::init_from_array( $array );
if ( ! self::is_valid( $follow_request ) ) {
return;
}
if ( ! $follow_request->get__id() ) {
$follow_request->set__id( self::get_follow_request_id_by_uri( $follow_request->get_id() ) );
}
return $follow_request;
}
/**
* Retrieve the WordPress post id of the follow request by its id (URI)
*/
public static function get_follow_request_id_by_uri( $uri ) {
global $wpdb;
2023-12-26 13:50:54 +01:00
return $wpdb->get_var( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE guid=%s", esc_sql( $uri ) ) );
}
/**
* Check if the follow request is valid which means it fits to the already stored data.
2023-12-26 13:50:54 +01:00
*
* @param Follow_Request $follow_request The follow request to be checked.
* @return bool Whether the follow request is valid.
*/
public static function is_valid( $follow_request ) {
if ( self::class != get_class( $follow_request ) ) {
return false;
}
if ( 'Follow' != $follow_request->get_type() ) {
return false;
}
2023-12-26 13:50:54 +01:00
$id = self::get_follow_request_id_by_uri( $follow_request->get_id() );
if ( ! $id || is_wp_error( $id ) ) {
return false;
}
2023-12-26 13:50:54 +01:00
if ( self::FOLLOW_REQUEST_POST_TYPE != get_post_type( $id ) ) {
return false;
}
$post = get_post( $id );
$follower = get_post_parent( $id );
if ( $follower->guid != $follow_request->get_actor() ) {
return false;
}
return true;
}
/**
* @param int $id
* @return Follow_Request $follow_request
*/
public static function from_wp_id( $id ) {
2023-12-26 13:50:54 +01:00
if ( self::FOLLOW_REQUEST_POST_TYPE != get_post_type( $id ) ) {
return;
}
$post = get_post( $id );
2023-12-26 13:50:54 +01:00
$follow_request = new static();
$follow_request->set_id( $post->guid );
$follow_request->set__id( $post->ID );
$follow_request->set__status( $post->post_status );
$follow_request->set_type( 'Follow' );
return $follow_request;
}
/**
* Get the internal ID of the follower who issues the follow request.
*/
private function get_follower_id() {
return wp_get_post_parent_id( $this->get__id() );
}
/**
* Save the current Follower-Object.
*
* @param Follower $follower
*
* @return Follow_Request|WP_Error The Follow_Request or an WP_Error.
*/
public static function save( $follower_id, $user_id, $activity_id ) {
$meta_input = array(
'activitypub_user_id' => $user_id,
);
$args = array(
'guid' => $activity_id,
'post_author' => 0,
'post_type' => self::FOLLOW_REQUEST_POST_TYPE,
'post_status' => 'pending',
'post_parent' => $follower_id,
'meta_input' => $meta_input,
2023-12-26 13:50:54 +01:00
'mime_type' => 'text/plain',
);
$post_id = wp_insert_post( $args );
return self::from_wp_id( $post_id );
}
/**
* Check if the user is allowed to handle this follow request.
2023-12-26 13:50:54 +01:00
*
* Usually needed for the ajax functions.
* @return bool Whether the user is allowed.
*/
public function can_handle_follow_request() {
2023-12-26 13:50:54 +01:00
$target_actor = get_post_meta( $this->get__id(), 'activitypub_user_id' );
if ( get_current_user_id() == $target_actor || current_user_can( 'manage_options' ) ) {
return true;
}
}
/**
* Get the URL/URI of the Follower that issued the follow request.
*
* @return string The url/uri of the follower.
*/
private function get_follower_actor() {
$follower_id = wp_get_post_parent_id( $this->get__id() );
$follower = Follower::init_from_cpt( get_post( $follower_id ) );
return $follower->get_id();
}
/**
* Save the status of the follow request.
*
* @param string $status The new status of the follow request.
*/
private function save_follow_request_status( $status ) {
2023-12-26 13:50:54 +01:00
wp_update_post(
array(
'ID' => $this->get__id(),
'post_status' => $status,
)
);
}
/**
* Reject the follow request.
*/
public function reject() {
$user_id = get_post_meta( $this->get__id(), 'activitypub_user_id', true );
$actor = $this->get_follower_actor();
Followers::remove_follow_relationship( $user_id, $actor );
$this->save_follow_request_status( self::FOLLOW_REQUEST_STATUS_REJECTED );
2023-12-27 22:41:32 +01:00
$this->send_response( 'Reject', $user_id );
$this->delete();
}
/**
* Approve the follow request.
*/
public function approve() {
$user_id = get_post_meta( $this->get__id(), 'activitypub_user_id', true );
$follower_id = $this->get_follower_id();
Followers::add_follow_relationship( $user_id, $follower_id );
$this->save_follow_request_status( self::FOLLOW_REQUEST_STATUS_APPROVED );
2023-12-27 22:41:32 +01:00
$this->send_response( 'Accept', $user_id, $follower_id );
}
/**
* Delete the follow request.
2023-12-26 13:50:54 +01:00
*
* This should only be called after it has been rejected.
*/
public function delete() {
wp_delete_post( $this->get__id() );
}
/**
* Prepere the sending of the follow request response and hand it over to the sending handler.
2023-12-27 22:41:32 +01:00
*
* @param string $type The Activity type of the response: 'Accept', or 'Reject'.
* @param int|string $user_id The user id of who gets followed.
* @param int $follwer_id The internal follower id.
*/
2023-12-27 22:41:32 +01:00
public function send_response( $type, $user_id = null, $follower_id = null ) {
if ( ! $user_id ) {
$user_id = get_post_meta( $this->get__id(), 'activitypub_user_id', true );
}
2023-12-27 22:41:32 +01:00
if ( ! $follower_id ) {
$follower_id = $this->get_follower_id();
}
2023-12-26 13:50:54 +01:00
$follower_inbox = get_post_field( 'post_content_filtered', $follower_id );
// Reconstruct the follow_object.
$follow_object = array(
'id' => $this->get_id(),
'type' => $this->get_type(),
'actor' => get_post_field( 'guid', $follower_id ),
);
2023-12-27 22:41:32 +01:00
do_action( 'activitypub_send_follow_response', $user_id, $follower_inbox, $follow_object, $type );
}
}