2024-11-18 16:07:09 +01:00
|
|
|
<?php
|
|
|
|
/**
|
|
|
|
* Class for handling and saving the ActivityPub event sources (i.e. follows).
|
|
|
|
*
|
2024-12-05 17:50:17 +01:00
|
|
|
* @package Event_Bridge_For_ActivityPub
|
2024-12-08 21:57:53 +01:00
|
|
|
* @since 1.0.0
|
|
|
|
* @license AGPL-3.0-or-later
|
2024-11-18 16:07:09 +01:00
|
|
|
*/
|
|
|
|
|
2024-12-05 17:50:17 +01:00
|
|
|
namespace Event_Bridge_For_ActivityPub;
|
2024-11-18 16:07:09 +01:00
|
|
|
|
2024-12-15 13:42:57 +01:00
|
|
|
use Activitypub\Model\Blog;
|
2024-12-14 14:46:00 +01:00
|
|
|
use Event_Bridge_For_ActivityPub\ActivityPub\Collection\Event_Sources as Event_Sources_Collection;
|
2024-12-15 09:52:20 +01:00
|
|
|
use Event_Bridge_For_ActivityPub\Activitypub\Transmogrifier\GatherPress;
|
2024-11-18 16:07:09 +01:00
|
|
|
|
2024-12-08 17:38:05 +01:00
|
|
|
use function Activitypub\get_remote_metadata_by_actor;
|
2024-12-11 23:32:19 +01:00
|
|
|
use function Activitypub\is_activitypub_request;
|
2024-11-18 16:07:09 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Class for handling and saving the ActivityPub event sources (i.e. follows).
|
|
|
|
*
|
2024-12-05 17:50:17 +01:00
|
|
|
* @package Event_Bridge_For_ActivityPub
|
2024-11-18 16:07:09 +01:00
|
|
|
*/
|
|
|
|
class Event_Sources {
|
2024-12-08 17:38:05 +01:00
|
|
|
/**
|
|
|
|
* Get metadata of ActivityPub Actor by ID/URL.
|
|
|
|
*
|
|
|
|
* @param string $url The URL or ID of the ActivityPub actor.
|
|
|
|
*/
|
|
|
|
public static function get_metadata( $url ) {
|
|
|
|
if ( ! is_string( $url ) ) {
|
|
|
|
return array();
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( false !== strpos( $url, '@' ) ) {
|
|
|
|
if ( false === strpos( $url, '/' ) && preg_match( '#^https?://#', $url, $m ) ) {
|
|
|
|
$url = substr( $url, strlen( $m[0] ) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return get_remote_metadata_by_actor( $url );
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the Application actor via FEP-2677.
|
|
|
|
*
|
|
|
|
* @param string $domain The domain without scheme.
|
|
|
|
* @return bool|string The URL/ID of the application actor, false if not found.
|
|
|
|
*/
|
|
|
|
public static function get_application_actor( $domain ) {
|
|
|
|
$result = wp_remote_get( 'https://' . $domain . '/.well-known/nodeinfo' );
|
|
|
|
|
|
|
|
if ( is_wp_error( $result ) ) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
$body = wp_remote_retrieve_body( $result );
|
|
|
|
|
|
|
|
$nodeinfo = json_decode( $body, true );
|
|
|
|
|
|
|
|
// Check if 'links' exists and is an array.
|
|
|
|
if ( isset( $nodeinfo['links'] ) && is_array( $nodeinfo['links'] ) ) {
|
|
|
|
foreach ( $nodeinfo['links'] as $link ) {
|
|
|
|
// Check if this link matches the application actor rel.
|
|
|
|
if ( isset( $link['rel'] ) && 'https://www.w3.org/ns/activitystreams#Application' === $link['rel'] ) {
|
|
|
|
if ( is_string( $link['href'] ) ) {
|
|
|
|
return $link['href'];
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Return false if no application actor is found.
|
|
|
|
return false;
|
|
|
|
}
|
2024-12-11 23:27:32 +01:00
|
|
|
|
2024-12-14 14:46:00 +01:00
|
|
|
/**
|
|
|
|
* Filter that cached external posts are not scheduled via the ActivityPub plugin.
|
|
|
|
*
|
|
|
|
* Posts that are actually just external events are treated as cache. They are displayed in
|
|
|
|
* the frontend HTML view and redirected via ActivityPub request, but we do not own them.
|
|
|
|
*
|
|
|
|
* @param bool $disabled If it is disabled already by others (the upstream ActivityPub plugin).
|
|
|
|
* @param WP_Post $post The WordPress post object.
|
|
|
|
* @return bool True if the post can be federated via ActivityPub.
|
|
|
|
*/
|
|
|
|
public static function is_cached_external_post( $disabled, $post = null ): bool {
|
|
|
|
if ( $disabled || ! $post ) {
|
|
|
|
return $disabled;
|
|
|
|
}
|
|
|
|
if ( ! str_starts_with( \get_site_url(), $post->guid ) ) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Determine whether a WP post is a cached external event.
|
|
|
|
*
|
|
|
|
* @param WP_Post $post The WordPress post object.
|
|
|
|
* @return bool
|
|
|
|
*/
|
2024-12-15 12:17:32 +01:00
|
|
|
public static function is_cached_external_event_post( $post ): bool {
|
|
|
|
if ( 'gatherpress_event' !== $post->post_type ) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2024-12-14 14:46:00 +01:00
|
|
|
if ( ! str_starts_with( \get_site_url(), $post->guid ) ) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2024-12-11 23:27:32 +01:00
|
|
|
/**
|
|
|
|
* Add the ActivityPub template for EventPrime.
|
|
|
|
*
|
|
|
|
* @param string $template The path to the template object.
|
|
|
|
* @return string The new path to the JSON template.
|
|
|
|
*/
|
|
|
|
public static function redirect_activitypub_requests_for_cached_external_events( $template ) {
|
|
|
|
if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) {
|
|
|
|
return $template;
|
|
|
|
}
|
|
|
|
|
2024-12-11 23:32:19 +01:00
|
|
|
if ( ! is_activitypub_request() ) {
|
|
|
|
return $template;
|
|
|
|
}
|
|
|
|
|
2024-12-11 23:27:32 +01:00
|
|
|
if ( ! \is_singular() ) {
|
|
|
|
return $template;
|
|
|
|
}
|
|
|
|
|
|
|
|
global $post;
|
|
|
|
|
2024-12-15 12:17:32 +01:00
|
|
|
if ( self::is_cached_external_event_post( $post ) ) {
|
2024-12-14 14:46:00 +01:00
|
|
|
\wp_safe_redirect( $post->guid, 301 );
|
2024-12-11 23:32:19 +01:00
|
|
|
exit;
|
2024-12-11 23:27:32 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return $template;
|
|
|
|
}
|
2024-12-15 09:52:20 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Delete old cached events that took place in the past.
|
|
|
|
*/
|
|
|
|
public static function clear_cache() {
|
|
|
|
$cache_retention_period = get_option( 'event_bridge_for_activitypub_event_source_cache_retention', WEEK_IN_SECONDS );
|
|
|
|
|
|
|
|
$past_event_ids = GatherPress::get_past_events( $cache_retention_period );
|
|
|
|
|
|
|
|
foreach ( $past_event_ids as $post_id ) {
|
|
|
|
if ( has_post_thumbnail( $post_id ) ) {
|
|
|
|
$attachment_id = get_post_thumbnail_id( $post_id );
|
|
|
|
wp_delete_attachment( $attachment_id, true );
|
|
|
|
}
|
|
|
|
wp_delete_post( $post_id, true );
|
|
|
|
}
|
|
|
|
}
|
2024-12-15 13:42:57 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Add the Blog Authors to the following list of the Blog Actor
|
|
|
|
* if Blog not in single mode.
|
|
|
|
*
|
|
|
|
* @param array $follow_list The array of following urls.
|
|
|
|
* @param \Activitypub\Model\User $user The user object.
|
|
|
|
*
|
|
|
|
* @return array The array of following urls.
|
|
|
|
*/
|
|
|
|
public static function add_event_sources_to_following_collection( $follow_list, $user ) {
|
|
|
|
if ( ! $user instanceof Blog ) {
|
|
|
|
return $follow_list;
|
|
|
|
}
|
|
|
|
|
|
|
|
$event_sources = Event_Sources_Collection::get_event_sources_ids();
|
|
|
|
|
|
|
|
if ( ! is_array( $event_sources ) ) {
|
|
|
|
return $follow_list;
|
|
|
|
}
|
|
|
|
|
|
|
|
return array_merge( $follow_list, $event_sources );
|
|
|
|
}
|
2024-11-18 16:07:09 +01:00
|
|
|
}
|