updated plugin ActivityPub
version 1.3.0
This commit is contained in:
@ -2,9 +2,11 @@
|
||||
namespace Activitypub;
|
||||
|
||||
use WP_Error;
|
||||
use WP_Comment_Query;
|
||||
use Activitypub\Http;
|
||||
use Activitypub\Activity\Activity;
|
||||
use Activitypub\Collection\Followers;
|
||||
use Activitypub\Collection\Users;
|
||||
|
||||
/**
|
||||
* Returns the ActivityPub default JSON-context
|
||||
@ -42,7 +44,7 @@ function get_webfinger_resource( $user_id ) {
|
||||
* @param string $actor The Actor URL.
|
||||
* @param bool $cached If the result should be cached.
|
||||
*
|
||||
* @return array The Actor profile as array
|
||||
* @return array|WP_Error The Actor profile as array or WP_Error on failure.
|
||||
*/
|
||||
function get_remote_metadata_by_actor( $actor, $cached = true ) {
|
||||
$pre = apply_filters( 'pre_get_remote_metadata_by_actor', false, $actor );
|
||||
@ -74,32 +76,25 @@ function get_remote_metadata_by_actor( $actor, $cached = true ) {
|
||||
|
||||
if ( ! \wp_http_validate_url( $actor ) ) {
|
||||
$metadata = new WP_Error( 'activitypub_no_valid_actor_url', \__( 'The "actor" is no valid URL', 'activitypub' ), array( 'status' => 400, 'actor' => $actor ) );
|
||||
\set_transient( $transient_key, $metadata, HOUR_IN_SECONDS ); // Cache the error for a shorter period.
|
||||
return $metadata;
|
||||
}
|
||||
|
||||
$short_timeout = function() {
|
||||
return 3;
|
||||
};
|
||||
add_filter( 'activitypub_remote_get_timeout', $short_timeout );
|
||||
$response = Http::get( $actor );
|
||||
remove_filter( 'activitypub_remote_get_timeout', $short_timeout );
|
||||
|
||||
if ( \is_wp_error( $response ) ) {
|
||||
\set_transient( $transient_key, $response, HOUR_IN_SECONDS ); // Cache the error for a shorter period.
|
||||
return $response;
|
||||
}
|
||||
|
||||
$metadata = \wp_remote_retrieve_body( $response );
|
||||
$metadata = \json_decode( $metadata, true );
|
||||
|
||||
\set_transient( $transient_key, $metadata, WEEK_IN_SECONDS );
|
||||
|
||||
if ( ! $metadata ) {
|
||||
$metadata = new WP_Error( 'activitypub_invalid_json', \__( 'No valid JSON data', 'activitypub' ), array( 'status' => 400, 'actor' => $actor ) );
|
||||
\set_transient( $transient_key, $metadata, HOUR_IN_SECONDS ); // Cache the error for a shorter period.
|
||||
return $metadata;
|
||||
}
|
||||
|
||||
\set_transient( $transient_key, $metadata, WEEK_IN_SECONDS );
|
||||
|
||||
return $metadata;
|
||||
}
|
||||
|
||||
@ -285,6 +280,16 @@ function is_activitypub_request() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if the current post type supports ActivityPub.
|
||||
if ( \is_singular() ) {
|
||||
$queried_object = \get_queried_object();
|
||||
$post_type = \get_post_type( $queried_object );
|
||||
|
||||
if ( ! \post_type_supports( $post_type, 'activitypub' ) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// One can trigger an ActivityPub request by adding ?activitypub to the URL.
|
||||
// phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.VariableRedeclaration
|
||||
global $wp_query;
|
||||
@ -481,3 +486,215 @@ function is_json( $data ) {
|
||||
function is_blog_public() {
|
||||
return (bool) apply_filters( 'activitypub_is_blog_public', \get_option( 'blog_public', 1 ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitize a URL
|
||||
*
|
||||
* @param string $value The URL to sanitize
|
||||
*
|
||||
* @return string|null The sanitized URL or null if invalid
|
||||
*/
|
||||
function sanitize_url( $value ) {
|
||||
if ( filter_var( $value, FILTER_VALIDATE_URL ) === false ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return esc_url_raw( $value );
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract recipient URLs from Activity object
|
||||
*
|
||||
* @param array $data
|
||||
*
|
||||
* @return array The list of user URLs
|
||||
*/
|
||||
function extract_recipients_from_activity( $data ) {
|
||||
$recipient_items = array();
|
||||
|
||||
foreach ( array( 'to', 'bto', 'cc', 'bcc', 'audience' ) as $i ) {
|
||||
if ( array_key_exists( $i, $data ) ) {
|
||||
if ( is_array( $data[ $i ] ) ) {
|
||||
$recipient = $data[ $i ];
|
||||
} else {
|
||||
$recipient = array( $data[ $i ] );
|
||||
}
|
||||
$recipient_items = array_merge( $recipient_items, $recipient );
|
||||
}
|
||||
|
||||
if ( is_array( $data['object'] ) && array_key_exists( $i, $data['object'] ) ) {
|
||||
if ( is_array( $data['object'][ $i ] ) ) {
|
||||
$recipient = $data['object'][ $i ];
|
||||
} else {
|
||||
$recipient = array( $data['object'][ $i ] );
|
||||
}
|
||||
$recipient_items = array_merge( $recipient_items, $recipient );
|
||||
}
|
||||
}
|
||||
|
||||
$recipients = array();
|
||||
|
||||
// flatten array
|
||||
foreach ( $recipient_items as $recipient ) {
|
||||
if ( is_array( $recipient ) ) {
|
||||
// check if recipient is an object
|
||||
if ( array_key_exists( 'id', $recipient ) ) {
|
||||
$recipients[] = $recipient['id'];
|
||||
}
|
||||
} else {
|
||||
$recipients[] = $recipient;
|
||||
}
|
||||
}
|
||||
|
||||
return array_unique( $recipients );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if passed Activity is Public
|
||||
*
|
||||
* @param array $data The Activity object as array
|
||||
*
|
||||
* @return boolean True if public, false if not
|
||||
*/
|
||||
function is_activity_public( $data ) {
|
||||
$recipients = extract_recipients_from_activity( $data );
|
||||
|
||||
return in_array( 'https://www.w3.org/ns/activitystreams#Public', $recipients, true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get active users based on a given duration
|
||||
*
|
||||
* @param int $duration The duration to check in month(s)
|
||||
*
|
||||
* @return int The number of active users
|
||||
*/
|
||||
function get_active_users( $duration = 1 ) {
|
||||
|
||||
$duration = intval( $duration );
|
||||
$transient_key = sprintf( 'monthly_active_users_%d', $duration );
|
||||
$count = get_transient( $transient_key );
|
||||
|
||||
if ( false === $count ) {
|
||||
global $wpdb;
|
||||
$query = "SELECT COUNT( DISTINCT post_author ) FROM {$wpdb->posts} WHERE post_type = 'post' AND post_status = 'publish' AND post_date <= DATE_SUB( NOW(), INTERVAL %d MONTH )";
|
||||
$query = $wpdb->prepare( $query, $duration );
|
||||
$count = $wpdb->get_var( $query ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
|
||||
|
||||
set_transient( $transient_key, $count, DAY_IN_SECONDS );
|
||||
}
|
||||
|
||||
// if 0 authors where active
|
||||
if ( 0 === $count ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// if single user mode
|
||||
if ( is_single_user() ) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// if blog user is disabled
|
||||
if ( is_user_disabled( Users::BLOG_USER_ID ) ) {
|
||||
return $count;
|
||||
}
|
||||
|
||||
// also count blog user
|
||||
return $count + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the total number of users
|
||||
*
|
||||
* @return int The total number of users
|
||||
*/
|
||||
function get_total_users() {
|
||||
// if single user mode
|
||||
if ( is_single_user() ) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
$users = \get_users(
|
||||
array(
|
||||
'capability__in' => array( 'publish_posts' ),
|
||||
)
|
||||
);
|
||||
|
||||
if ( is_array( $users ) ) {
|
||||
$users = count( $users );
|
||||
} else {
|
||||
$users = 1;
|
||||
}
|
||||
|
||||
// if blog user is disabled
|
||||
if ( is_user_disabled( Users::BLOG_USER_ID ) ) {
|
||||
return $users;
|
||||
}
|
||||
|
||||
return $users + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Examine a comment ID and look up an existing comment it represents.
|
||||
*
|
||||
* @param string $id ActivityPub object ID (usually a URL) to check.
|
||||
*
|
||||
* @return int|boolean Comment ID, or false on failure.
|
||||
*/
|
||||
function object_id_to_comment( $id ) {
|
||||
$comment_query = new WP_Comment_Query(
|
||||
array(
|
||||
'meta_key' => 'source_id', // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
|
||||
'meta_value' => $id, // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
|
||||
)
|
||||
);
|
||||
|
||||
if ( ! $comment_query->comments ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( count( $comment_query->comments ) > 1 ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $comment_query->comments[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify if URL is a local comment,
|
||||
* Or if it is a previously received remote comment
|
||||
* (For threading comments locally)
|
||||
*
|
||||
* @param string $url The URL to check.
|
||||
*
|
||||
* @return int comment_ID or null if not found
|
||||
*/
|
||||
function url_to_commentid( $url ) {
|
||||
if ( ! $url || ! filter_var( $url, FILTER_VALIDATE_URL ) ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$args = array(
|
||||
// phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
|
||||
'meta_query' => array(
|
||||
'relation' => 'OR',
|
||||
array(
|
||||
'key' => 'source_url',
|
||||
'value' => $url,
|
||||
),
|
||||
array(
|
||||
'key' => 'source_id',
|
||||
'value' => $url,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
$query = new \WP_Comment_Query();
|
||||
$comments = $query->query( $args );
|
||||
|
||||
if ( $comments && is_array( $comments ) ) {
|
||||
return $comments[0]->comment_ID;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
Reference in New Issue
Block a user