updated plugin Event Bridge for ActivityPub version 1.3.0
This commit is contained in:
@ -10,7 +10,7 @@
|
||||
namespace Event_Bridge_For_ActivityPub\ActivityPub;
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
use Event_Bridge_For_ActivityPub\ActivityPub\Handler\Accept;
|
||||
use Event_Bridge_For_ActivityPub\ActivityPub\Handler\Update;
|
||||
|
||||
@ -21,14 +21,15 @@
|
||||
namespace Event_Bridge_For_ActivityPub\ActivityPub\Collection;
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
use Activitypub\Model\Blog;
|
||||
use Activitypub\Tombstone;
|
||||
use Event_Bridge_For_ActivityPub\ActivityPub\Model\Event_Source;
|
||||
use WP_Error;
|
||||
use WP_Post;
|
||||
use WP_Query;
|
||||
|
||||
use function Activitypub\is_tombstone;
|
||||
use function Activitypub\get_remote_metadata_by_actor;
|
||||
|
||||
/**
|
||||
@ -49,7 +50,7 @@ class Event_Sources {
|
||||
/**
|
||||
* The custom post type.
|
||||
*/
|
||||
const POST_TYPE = 'ap_event_source';
|
||||
public const POST_TYPE = 'ap_event_source';
|
||||
|
||||
/**
|
||||
* Init.
|
||||
@ -173,10 +174,10 @@ class Event_Sources {
|
||||
*
|
||||
* @return Event_Source|WP_Error|null The Followed (WP_Post array) or an WP_Error.
|
||||
*/
|
||||
public static function add_event_source( $actor ) {
|
||||
public static function add_event_source( string $actor ) {
|
||||
$meta = get_remote_metadata_by_actor( $actor );
|
||||
|
||||
if ( is_tombstone( $meta ) ) {
|
||||
if ( Tombstone::exists_in_error( $meta ) ) {
|
||||
return $meta;
|
||||
}
|
||||
|
||||
@ -211,7 +212,7 @@ class Event_Sources {
|
||||
* @param string $followed_id The ActivityPub ID of the followed actor.
|
||||
* @return string The `Follow` ID.
|
||||
*/
|
||||
public static function compose_follow_id( $follower_id, $followed_id ) {
|
||||
public static function compose_follow_id( string $follower_id, string $followed_id ) {
|
||||
return $follower_id . '#follow-' . \preg_replace( '~^https?://~', '', $followed_id );
|
||||
}
|
||||
|
||||
@ -231,14 +232,14 @@ class Event_Sources {
|
||||
* @param string|int $attachment_id The numeric post ID of the attachment.
|
||||
* @return bool
|
||||
*/
|
||||
public static function is_attachment_featured_image( $attachment_id ): bool {
|
||||
public static function is_attachment_featured_image( string|int $attachment_id ): bool {
|
||||
if ( ! is_numeric( $attachment_id ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Query posts with the given attachment ID as their featured image.
|
||||
$args = array(
|
||||
'post_type' => 'any',
|
||||
// phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
|
||||
'meta_query' => array(
|
||||
array(
|
||||
'key' => '_thumbnail_id',
|
||||
@ -261,8 +262,10 @@ class Event_Sources {
|
||||
* @param int $event_source_post_id The WordPress Post ID of the event source.
|
||||
* @return void
|
||||
*/
|
||||
public static function delete_events_by_event_source( $event_source_post_id ): void {
|
||||
public static function delete_events_by_event_source( int $event_source_post_id ): void {
|
||||
global $wpdb;
|
||||
|
||||
// phpcs:disable WordPress.DB.DirectDatabaseQuery
|
||||
$results = $wpdb->get_results(
|
||||
$wpdb->prepare(
|
||||
"SELECT post_id FROM $wpdb->postmeta WHERE meta_key = %s AND meta_value = %s",
|
||||
@ -305,7 +308,7 @@ class Event_Sources {
|
||||
*
|
||||
* @return void Post data on success, false or null on failure.
|
||||
*/
|
||||
public static function remove_event_source( $event_source_post_id ): void {
|
||||
public static function remove_event_source( int|string $event_source_post_id ): void {
|
||||
$event_source = Event_Source::get_by_id( $event_source_post_id );
|
||||
|
||||
if ( ! $event_source ) {
|
||||
@ -320,7 +323,7 @@ class Event_Sources {
|
||||
$post = \get_post( $event_source->get__id() );
|
||||
$post->post_status = 'draft';
|
||||
|
||||
if ( $post instanceof \WP_Post ) {
|
||||
if ( $post instanceof WP_Post ) {
|
||||
$post = \get_object_vars( $post );
|
||||
$post = \wp_slash( $post );
|
||||
$post = \wp_update_post( $post );
|
||||
@ -358,9 +361,9 @@ class Event_Sources {
|
||||
/**
|
||||
* Get the Event Sources along with a total count for pagination purposes.
|
||||
*
|
||||
* @param int $number Maximum number of results to return.
|
||||
* @param int $page Page number.
|
||||
* @param array $args The WP_Query arguments.
|
||||
* @param int $number Maximum number of results to return.
|
||||
* @param int|null $page Page number.
|
||||
* @param array $args The WP_Query arguments.
|
||||
*
|
||||
* @return array {
|
||||
* Data about the event sources.
|
||||
@ -369,7 +372,7 @@ class Event_Sources {
|
||||
* @type int $total Total number of followers.
|
||||
* }
|
||||
*/
|
||||
public static function get_event_sources_with_count( $number = -1, $page = null, $args = array() ): array {
|
||||
public static function get_event_sources_with_count( int $number = -1, int|null $page = null, array $args = array() ): array {
|
||||
$defaults = array(
|
||||
'post_type' => self::POST_TYPE,
|
||||
'posts_per_page' => $number,
|
||||
@ -396,12 +399,12 @@ class Event_Sources {
|
||||
/**
|
||||
* Queue a hook to run async.
|
||||
*
|
||||
* @param string $hook The hook name.
|
||||
* @param array $args The arguments to pass to the hook.
|
||||
* @param string $unqueue_hook Optional a hook to unschedule before queuing.
|
||||
* @return void|bool|WP_Error Whether the hook was queued.
|
||||
* @param string $hook The hook name.
|
||||
* @param array $args The arguments to pass to the hook.
|
||||
* @param string $unqueue_hook Optional a hook to unschedule before queuing.
|
||||
* @return bool|WP_Error Whether the hook was queued.
|
||||
*/
|
||||
public static function queue( $hook, $args, $unqueue_hook = null ) {
|
||||
public static function queue( string $hook, array $args, $unqueue_hook = null ): bool|WP_Error {
|
||||
if ( $unqueue_hook ) {
|
||||
$hook_timestamp = \wp_next_scheduled( $unqueue_hook, $args );
|
||||
if ( $hook_timestamp ) {
|
||||
@ -410,7 +413,7 @@ class Event_Sources {
|
||||
}
|
||||
|
||||
if ( \wp_next_scheduled( $hook, $args ) ) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
return \wp_schedule_single_event( \time(), $hook, $args );
|
||||
@ -419,11 +422,11 @@ class Event_Sources {
|
||||
/**
|
||||
* Prepare to follow an ActivityPub actor via a scheduled event.
|
||||
*
|
||||
* @param string $actor The ActivityPub actor.
|
||||
* @param string $actor The ActivityPub actor.
|
||||
*
|
||||
* @return bool Whether the event was queued.
|
||||
* @return bool Whether the event was queued.
|
||||
*/
|
||||
public static function queue_follow_actor( $actor ): bool {
|
||||
public static function queue_follow_actor( string $actor ): bool {
|
||||
$queued = self::queue(
|
||||
'event_bridge_for_activitypub_follow',
|
||||
array( $actor ),
|
||||
@ -435,7 +438,7 @@ class Event_Sources {
|
||||
}
|
||||
|
||||
// Following this actor has already been queued.
|
||||
if ( null === $queued ) {
|
||||
if ( false === $queued ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -447,11 +450,11 @@ class Event_Sources {
|
||||
*
|
||||
* @param string $actor_id The ID/URL of the Actor.
|
||||
*/
|
||||
public static function activitypub_follow_actor( $actor_id ) {
|
||||
public static function activitypub_follow_actor( string $actor_id ): void {
|
||||
$actor = Event_Source::get_by_id( $actor_id );
|
||||
|
||||
if ( ! $actor ) {
|
||||
return $actor;
|
||||
return;
|
||||
}
|
||||
|
||||
$inbox = $actor->get_shared_inbox();
|
||||
@ -461,8 +464,7 @@ class Event_Sources {
|
||||
|
||||
$activity = new \Activitypub\Activity\Activity();
|
||||
$activity->set_type( 'Follow' );
|
||||
$activity->set_to( null );
|
||||
$activity->set_cc( null );
|
||||
$activity->set_to( array( $to ) );
|
||||
$activity->set_actor( $from_actor->get_id() );
|
||||
$activity->set_object( $to );
|
||||
$activity->set_id( self::compose_follow_id( $from_actor->get_id(), $to ) );
|
||||
@ -475,9 +477,9 @@ class Event_Sources {
|
||||
*
|
||||
* @param string $actor The ActivityPub actor ID.
|
||||
*
|
||||
* @return bool|void|WP_Error Whether the event was queued.
|
||||
* @return bool|WP_Error Whether the event was queued.
|
||||
*/
|
||||
public static function queue_unfollow_actor( $actor ) {
|
||||
public static function queue_unfollow_actor( string $actor ): bool|WP_Error {
|
||||
$queued = self::queue(
|
||||
'event_bridge_for_activitypub_unfollow',
|
||||
array( $actor ),
|
||||
@ -489,7 +491,7 @@ class Event_Sources {
|
||||
}
|
||||
|
||||
// Following this actor has already been queued.
|
||||
if ( null === $queued ) {
|
||||
if ( false === $queued ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -502,7 +504,7 @@ class Event_Sources {
|
||||
* @param string $actor The ActivityPub ID of the actor to unfollow.
|
||||
* @return void
|
||||
*/
|
||||
public static function activitypub_unfollow_actor( $actor ): void {
|
||||
public static function activitypub_unfollow_actor( string $actor ): void {
|
||||
$actor = Event_Source::get_by_id( $actor );
|
||||
|
||||
if ( ! $actor ) {
|
||||
@ -520,8 +522,7 @@ class Event_Sources {
|
||||
|
||||
$activity = new \Activitypub\Activity\Activity();
|
||||
$activity->set_type( 'Undo' );
|
||||
$activity->set_to( null );
|
||||
$activity->set_cc( null );
|
||||
$activity->set_to( array( $to ) );
|
||||
$activity->set_actor( $from_actor->get_id() );
|
||||
$activity->set_object(
|
||||
array(
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
namespace Event_Bridge_For_ActivityPub\ActivityPub\Handler;
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
use Activitypub\Collection\Actors;
|
||||
use Activitypub\Model\Blog;
|
||||
@ -37,10 +37,10 @@ class Accept {
|
||||
/**
|
||||
* Handle incoming "Accept" activities.
|
||||
*
|
||||
* @param array $activity The activity-object.
|
||||
* @param int $user_id The id of the local blog-user.
|
||||
* @param array $activity The activity-object.
|
||||
* @param int|int[] $user_id The id of the local blog-user.
|
||||
*/
|
||||
public static function handle_accept( $activity, $user_id ): void {
|
||||
public static function handle_accept( array $activity, int|array $user_id ): void {
|
||||
// We only process activities that are target to the blog actor.
|
||||
if ( Actors::BLOG_USER_ID !== $user_id ) {
|
||||
return;
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
namespace Event_Bridge_For_ActivityPub\ActivityPub\Handler;
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
use Activitypub\Collection\Actors;
|
||||
use Event_Bridge_For_ActivityPub\ActivityPub\Model\Event_Source;
|
||||
@ -36,10 +36,10 @@ class Create {
|
||||
/**
|
||||
* Handle incoming "Create" activities.
|
||||
*
|
||||
* @param array $activity The activity-object.
|
||||
* @param int $user_id The id of the local blog-user.
|
||||
* @param array $activity The activity-object.
|
||||
* @param int|int[] $user_id The id of the local blog-user.
|
||||
*/
|
||||
public static function handle_create( $activity, $user_id ): void {
|
||||
public static function handle_create( array $activity, int|array $user_id ): void {
|
||||
// We only process activities that are target to the blog actor.
|
||||
if ( Actors::BLOG_USER_ID !== $user_id ) {
|
||||
return;
|
||||
@ -56,7 +56,7 @@ class Create {
|
||||
}
|
||||
|
||||
// Check that we are actually following/or have a pending follow request this actor.
|
||||
$event_source_post_id = Event_Source::get_post_id_by_activitypub_id( $activity['actor'] );
|
||||
$event_source_post_id = self::determine_event_source( $activity );
|
||||
if ( ! $event_source_post_id ) {
|
||||
return;
|
||||
}
|
||||
@ -65,6 +65,11 @@ class Create {
|
||||
return;
|
||||
}
|
||||
|
||||
// Apply custom filters whether an Event should be ignored.
|
||||
if ( \apply_filters( 'event_bridge_for_activitypub_ignore_incoming_event', false, $activity['object'], $event_source_post_id ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$transmogrifier = Setup::get_transmogrifier();
|
||||
|
||||
if ( ! $transmogrifier ) {
|
||||
@ -73,4 +78,36 @@ class Create {
|
||||
|
||||
$transmogrifier::save( $activity['object'], $event_source_post_id );
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup the post ID of the event source for a given ActivityPub activity.
|
||||
*
|
||||
* First tries the actor of the activity. For Mobilizon-like groups, falls back
|
||||
* to the attributedTo field if it has the same host as the actor.
|
||||
*
|
||||
* @param array $activity The ActivityPub activity as associative array.
|
||||
* @return int|false Post ID of the event source, or false if none found.
|
||||
*/
|
||||
public static function determine_event_source( $activity ): int|false {
|
||||
$event_source_post_id = Event_Source::get_post_id_by_activitypub_id( $activity['actor'] );
|
||||
|
||||
if ( $event_source_post_id ) {
|
||||
return $event_source_post_id;
|
||||
}
|
||||
|
||||
// Fallback for Mobilizon groups, where a member of the group sends them.
|
||||
if ( ! isset( $activity['object']['attributedTo'] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We only trust this, when the attributedTo of the event object and the actor of the activity have the same hostname.
|
||||
$actor_host = \wp_parse_url( $activity['actor'], PHP_URL_HOST );
|
||||
$attributed_to_host = \wp_parse_url( $activity['object']['attributedTo'], PHP_URL_HOST );
|
||||
|
||||
if ( $actor_host === $attributed_to_host ) {
|
||||
return Event_Source::get_post_id_by_activitypub_id( $activity['object']['attributedTo'] );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
namespace Event_Bridge_For_ActivityPub\ActivityPub\Handler;
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
use Activitypub\Collection\Actors;
|
||||
use Event_Bridge_For_ActivityPub\Event_Sources;
|
||||
@ -35,10 +35,10 @@ class Delete {
|
||||
/**
|
||||
* Handle "Follow" requests.
|
||||
*
|
||||
* @param array $activity The activity-object.
|
||||
* @param int $user_id The id of the local blog-user.
|
||||
* @param array $activity The activity-object.
|
||||
* @param int|int[] $user_id The id of the local blog-user.
|
||||
*/
|
||||
public static function handle_delete( $activity, $user_id ): void {
|
||||
public static function handle_delete( array $activity, int|array $user_id ): void {
|
||||
// We only process activities that are target to the application user.
|
||||
if ( Actors::BLOG_USER_ID !== $user_id ) {
|
||||
return;
|
||||
|
||||
@ -1,159 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Join handler file.
|
||||
*
|
||||
* @package Event_Bridge_For_ActivityPub
|
||||
* @license AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
namespace Event_Bridge_For_ActivityPub\ActivityPub\Handler;
|
||||
|
||||
use Activitypub\Activity\Activity;
|
||||
use Activitypub\Collection\Actors;
|
||||
use Activitypub\Activity\Actor;
|
||||
use Activitypub\Http;
|
||||
use Activitypub\Transformer\Factory;
|
||||
use Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Event\Event as Event_Transformer;
|
||||
|
||||
use function Activitypub\get_remote_metadata_by_actor;
|
||||
use function Activitypub\object_to_uri;
|
||||
|
||||
/**
|
||||
* Handle Join requests.
|
||||
*/
|
||||
class Join {
|
||||
/**
|
||||
* Initialize the class, registering WordPress hooks.
|
||||
*/
|
||||
public static function init() {
|
||||
\add_action(
|
||||
'activitypub_register_handlers',
|
||||
array( self::class, 'register_join_handler' )
|
||||
);
|
||||
|
||||
\add_action(
|
||||
'event_bridge_for_activitypub_ignore_join',
|
||||
array( self::class, 'send_ignore_response' ),
|
||||
10,
|
||||
3
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the join handler to the ActivityPub plugin.
|
||||
*/
|
||||
public static function register_join_handler() {
|
||||
\add_action(
|
||||
'activitypub_inbox_join',
|
||||
array( self::class, 'handle_join' )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle ActivityPub "Join" requests.
|
||||
*
|
||||
* @param array $activity The activity object.
|
||||
*/
|
||||
public static function handle_join( $activity ) {
|
||||
$actor = get_remote_metadata_by_actor( object_to_uri( $activity['actor'] ) );
|
||||
|
||||
// If we cannot fetch the actor, we cannot continue.
|
||||
if ( \is_wp_error( $actor ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// This should be already validated, but just to be sure.
|
||||
if ( ! array_key_exists( 'object', $activity ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the WordPress Post ID, via the ActivityPub ID.
|
||||
$post_id = self::get_post_id_by_activitypub_id( \sanitize_url( object_to_uri( $activity['object'] ) ) );
|
||||
|
||||
if ( ! $post_id ) {
|
||||
// No post is found for this URL/ID.
|
||||
return;
|
||||
}
|
||||
|
||||
// Check whether the target object/post is an event post.
|
||||
|
||||
$transformer = Factory::get_transformer( get_post( $post_id ) );
|
||||
|
||||
if ( ! $transformer instanceof Event_Transformer ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Pass over to Event plugin specific handler if implemented here. Until then just send an ignore.
|
||||
do_action(
|
||||
'event_bridge_for_activitypub_ignore_join',
|
||||
$transformer->get_actor_object()->get_id(), // Gets the WordPress user that "owns" the object by ActivityPub means.
|
||||
$activity['id'],
|
||||
Actor::init_from_array( $actor )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send "Ignore" response.
|
||||
*
|
||||
* @param string $actor The actors ActivityPub ID which sends the response.
|
||||
* @param string $ignored The ID of the Activity that gets ignored.
|
||||
* @param Actor|mixed $to The target actor.
|
||||
*/
|
||||
public static function send_ignore_response( $actor, $ignored, $to ) {
|
||||
// Get actor object that owns the object that was targeted by the ignored activity.
|
||||
$actor = Actors::get_by_resource( $actor );
|
||||
|
||||
if ( \is_wp_error( $to ) || \is_wp_error( $actor ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get inbox.
|
||||
$inbox = $to->get_inbox();
|
||||
|
||||
if ( ! $inbox ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Send "Ignore" activity.
|
||||
$activity = new Activity();
|
||||
$activity->set_type( 'Ignore' );
|
||||
$activity->set_object( \esc_url_raw( $ignored ) );
|
||||
$activity->set_actor( $actor->get_id() );
|
||||
$activity->set_to( $to->get_id() );
|
||||
$activity->set_id( $actor->get_id() . '#ignore-' . \preg_replace( '~^https?://~', '', $ignored ) );
|
||||
$activity->set_sensitive( null );
|
||||
|
||||
// @phpstan-ignore-next-line
|
||||
Http::post( $inbox, $activity->to_json(), $actor->get__id() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the WordPress Post ID by the ActivityPub ID.
|
||||
*
|
||||
* @param string $activitypub_id The ActivityPub objects ID.
|
||||
* @return int The WordPress post ID.
|
||||
*/
|
||||
private static function get_post_id_by_activitypub_id( $activitypub_id ) {
|
||||
// Parse the URL and extract its components.
|
||||
$parsed_url = wp_parse_url( $activitypub_id );
|
||||
$home_url = \trailingslashit( \home_url() );
|
||||
|
||||
// Ensure the base URL matches the home URL.
|
||||
if ( \trailingslashit( "{$parsed_url['scheme']}://{$parsed_url['host']}" ) !== $home_url ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Check for a valid query string and parse it.
|
||||
if ( isset( $parsed_url['query'] ) ) {
|
||||
parse_str( $parsed_url['query'], $query_vars );
|
||||
|
||||
// Ensure the only parameter is 'p'.
|
||||
if ( count( $query_vars ) === 1 && isset( $query_vars['p'] ) ) {
|
||||
return intval( $query_vars['p'] ); // Return the post ID.
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback: legacy ActivityPub plugin (before version 3.0.0) used pretty permalinks as `id`.
|
||||
return \url_to_postid( $activitypub_id );
|
||||
}
|
||||
}
|
||||
@ -9,7 +9,7 @@
|
||||
namespace Event_Bridge_For_ActivityPub\ActivityPub\Handler;
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
use Activitypub\Collection\Actors;
|
||||
use Event_Bridge_For_ActivityPub\Event_Sources;
|
||||
@ -35,10 +35,10 @@ class Undo {
|
||||
/**
|
||||
* Handle incoming "Undo" activities.
|
||||
*
|
||||
* @param array $activity The activity-object.
|
||||
* @param int $user_id The id of the local blog-user.
|
||||
* @param array $activity The activity-object.
|
||||
* @param int|int[] $user_id The id of the local blog-user.
|
||||
*/
|
||||
public static function handle_undo( $activity, $user_id ): void {
|
||||
public static function handle_undo( array $activity, int|array $user_id ): void {
|
||||
// We only process activities that are target to the blog actor.
|
||||
if ( Actors::BLOG_USER_ID !== $user_id ) {
|
||||
return;
|
||||
@ -53,6 +53,7 @@ class Undo {
|
||||
|
||||
global $wpdb;
|
||||
|
||||
// phpcs:disable WordPress.DB.DirectDatabaseQuery
|
||||
$results = $wpdb->get_results(
|
||||
$wpdb->prepare(
|
||||
"SELECT post_id FROM $wpdb->postmeta WHERE meta_key = %s AND meta_value = %s",
|
||||
|
||||
@ -8,14 +8,7 @@
|
||||
namespace Event_Bridge_For_ActivityPub\ActivityPub\Handler;
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
use Activitypub\Collection\Actors;
|
||||
use Event_Bridge_For_ActivityPub\ActivityPub\Model\Event_Source;
|
||||
use Event_Bridge_For_ActivityPub\Event_Sources;
|
||||
use Event_Bridge_For_ActivityPub\Setup;
|
||||
|
||||
use function Activitypub\is_activity_public;
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
/**
|
||||
* Handle Update requests.
|
||||
@ -36,41 +29,11 @@ class Update {
|
||||
/**
|
||||
* Handle incoming "Update" activities..
|
||||
*
|
||||
* @param array $activity The activity-object.
|
||||
* @param int $user_id The id of the local blog-user.
|
||||
* @param array $activity The activity-object.
|
||||
* @param int|int[] $user_id The id of the local blog-user.
|
||||
*/
|
||||
public static function handle_update( $activity, $user_id ): void {
|
||||
// We only process activities that are target to the application user.
|
||||
if ( Actors::BLOG_USER_ID !== $user_id ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if Activity is public or not.
|
||||
if ( ! is_activity_public( $activity ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if an object is set and it is an object of type `Event`.
|
||||
if ( ! isset( $activity['object']['type'] ) || 'Event' !== $activity['object']['type'] ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check that we are actually following/or have a pending follow request this actor.
|
||||
$event_source_post_id = Event_Source::get_post_id_by_activitypub_id( $activity['actor'] );
|
||||
if ( ! $event_source_post_id ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( Event_Sources::is_time_passed( $activity['object']['startTime'] ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$transmogrifier = Setup::get_transmogrifier();
|
||||
|
||||
if ( ! $transmogrifier ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$transmogrifier::save( $activity['object'], $event_source_post_id );
|
||||
public static function handle_update( array $activity, int|array $user_id ): void {
|
||||
// We handle updates the same as we handle creates for now (specification though says we should ignore it).
|
||||
Create::handle_create( $activity, $user_id );
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
namespace Event_Bridge_For_ActivityPub\ActivityPub\Model;
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
use Activitypub\Activity\Actor;
|
||||
use Event_Bridge_For_ActivityPub\ActivityPub\Collection\Event_Sources;
|
||||
@ -46,7 +46,7 @@ use WP_Post;
|
||||
* @method array get_endpoints()
|
||||
*/
|
||||
class Event_Source extends Actor {
|
||||
const ACTIVITYPUB_USER_HANDLE_REGEXP = '(?:([A-Za-z0-9_.-]+)@((?:[A-Za-z0-9_-]+\.)+[A-Za-z]+))';
|
||||
public const ACTIVITYPUB_USER_HANDLE_REGEXP = '(?:([A-Za-z0-9_.-]+)@((?:[A-Za-z0-9_-]+\.)+[A-Za-z]+))';
|
||||
|
||||
/**
|
||||
* The WordPress Post ID which stores the event source.
|
||||
@ -133,7 +133,7 @@ class Event_Source extends Actor {
|
||||
* @param string $activitypub_actor_id The ActivityPub actor ID.
|
||||
* @return int|false The Event Sources Post ID, if a WordPress Post representing it is found, false otherwise.
|
||||
*/
|
||||
public static function get_post_id_by_activitypub_id( $activitypub_actor_id ) {
|
||||
public static function get_post_id_by_activitypub_id( string $activitypub_actor_id ) {
|
||||
$event_sources = Event_Sources::get_event_sources();
|
||||
|
||||
return array_search( $activitypub_actor_id, $event_sources, true );
|
||||
@ -145,7 +145,7 @@ class Event_Source extends Actor {
|
||||
* @param int|string $event_source_id The ActivityPub actor ID as string or the Post ID as int of the Event Source.
|
||||
* @return ?Event_Source The Event Sources if it exists, false otherwise.
|
||||
*/
|
||||
public static function get_by_id( $event_source_id ): ?Event_Source {
|
||||
public static function get_by_id( int|string $event_source_id ): ?Event_Source {
|
||||
$post_id = is_integer( $event_source_id ) ? $event_source_id : self::get_post_id_by_activitypub_id( $event_source_id );
|
||||
|
||||
if ( ! $post_id ) {
|
||||
@ -172,15 +172,21 @@ class Event_Source extends Actor {
|
||||
/**
|
||||
* Convert a Custom-Post-Type input to an \Event_Bridge_For_ActivityPub\ActivityPub\Model\Event_Source.
|
||||
*
|
||||
* @param \WP_Post $post The post object.
|
||||
* @param WP_Post $post The post object.
|
||||
* @return ?Event_Source
|
||||
*/
|
||||
public static function init_from_cpt( $post ): ?Event_Source {
|
||||
public static function init_from_cpt( WP_Post $post ): ?Event_Source {
|
||||
if ( Event_Sources::POST_TYPE !== $post->post_type ) {
|
||||
return null;
|
||||
}
|
||||
$actor_json = \get_post_meta( $post->ID, '_activitypub_actor_json', true );
|
||||
$object = static::init_from_json( $actor_json );
|
||||
|
||||
if ( empty( $post->post_content ) ) {
|
||||
$actor_json = \get_post_meta( $post->ID, '_activitypub_actor_json', true );
|
||||
} else {
|
||||
$actor_json = $post->post_content;
|
||||
}
|
||||
|
||||
$object = static::init_from_json( $actor_json );
|
||||
|
||||
if ( \is_wp_error( $object ) ) {
|
||||
return null;
|
||||
@ -202,10 +208,6 @@ class Event_Source extends Actor {
|
||||
);
|
||||
}
|
||||
|
||||
if ( ! $object instanceof Event_Source ) { // To make phpstan happy.
|
||||
return null;
|
||||
}
|
||||
|
||||
return $object;
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,101 @@
|
||||
<?php
|
||||
/**
|
||||
* FEP-8a8e compatible representation of an Event in ActivityStreams.
|
||||
*
|
||||
* See: https://codeberg.org/Event-Federation/gatherpress-activitypub/src/branch/main/includes/classes/class-event-fep-8a8e.php
|
||||
*
|
||||
* @package Event_Bridge_For_ActivityPub
|
||||
* @since 1.3.0
|
||||
* @license AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
namespace Event_Bridge_For_ActivityPub\ActivityPub\Object;
|
||||
|
||||
use Activitypub\Activity\Base_Object;
|
||||
|
||||
/**
|
||||
* Event is an implementation of Activity Streams Event object type.
|
||||
*
|
||||
* This class contains extensions from FEP-8a8e: A common approach to using the Event object type.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-event
|
||||
* @see https://w3id.org/fep/8a8ae
|
||||
*
|
||||
* @method int|null get_maximum_attendee_capacity() Gets how many places there can be for an event.
|
||||
* @method string|null get_name() Gets the title of the event.
|
||||
* @method string|null get_event_status() Gets the event's status.
|
||||
* @method string|null get_timezone() Gets the timezone of the event.
|
||||
*
|
||||
* @method Event_FEP_8a8e set_maximum_attendee_capacity( int $capacity ) Sets how many places there can be for an event.
|
||||
* @method Event_FEP_8a8e set_name( string $name ) Sets the title of the event.
|
||||
* @method Event_FEP_8a8e set_event_status( string $status ) Sets the event's status.
|
||||
* @method Event_FEP_8a8e set_timezone( string $timezone ) Sets the timezone of the event.
|
||||
*/
|
||||
class Event_FEP_8a8e extends Base_Object {
|
||||
/**
|
||||
* The JSON-LD Context.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
const JSON_LD_CONTEXT = array(
|
||||
'https://schema.org/', // The base context is schema.org, because it is used a lot.
|
||||
'https://w3id.org/fep/8a8e', // FEP-8a8e context.
|
||||
'https://www.w3.org/ns/activitystreams', // The ActivityStreams context overrides everything also defined in schema.org.
|
||||
);
|
||||
|
||||
/**
|
||||
* Event is an implementation of one of the Activity Streams.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $type = 'Event';
|
||||
|
||||
/**
|
||||
* The title of the event.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $name;
|
||||
|
||||
/**
|
||||
* Timezone of the event.
|
||||
*
|
||||
* @context https://w3id.org/fep/8a8e/timezone
|
||||
* @var string
|
||||
*/
|
||||
protected $timezone;
|
||||
|
||||
/**
|
||||
* The event's status.
|
||||
*
|
||||
* @context https://w3id.org/fep/8a8e/eventStatus
|
||||
* @var string
|
||||
*/
|
||||
protected $event_status = 'EventScheduled';
|
||||
|
||||
/**
|
||||
* How many places there can be for an event.
|
||||
*
|
||||
* @context https://schema.org/maximumAttendeeCapacity
|
||||
* @var int
|
||||
*/
|
||||
protected $maximum_attendee_capacity;
|
||||
|
||||
/**
|
||||
* Attendees collection
|
||||
*
|
||||
* @context https://w3id.org/fep/8a8e/attendees
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $attendees;
|
||||
|
||||
/**
|
||||
* URL to an iCal file.
|
||||
*
|
||||
* @context https://w3id.org/fep/8a8e/ical
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $ical;
|
||||
}
|
||||
@ -0,0 +1,119 @@
|
||||
<?php
|
||||
/**
|
||||
* Event is an implementation of one of the Activity Streams Event object type
|
||||
*
|
||||
* See https://codeberg.org/Event-Federation/gatherpress-activitypub/src/branch/main/includes/classes/class-place.php
|
||||
*
|
||||
* @package GatherPress_ActivityPUb
|
||||
*/
|
||||
|
||||
namespace Event_Bridge_For_ActivityPub\ActivityPub\Object;
|
||||
|
||||
use Activitypub\Activity\Base_Object;
|
||||
|
||||
/**
|
||||
* Place is an implementation of the Activity Streams Place object type.
|
||||
*
|
||||
* The Place object represents a logical or physical location.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-place
|
||||
*
|
||||
* @method float|null get_accuracy() Gets the accuracy of position coordinates.
|
||||
* @method array|string|null get_address() Gets the address of the place.
|
||||
* @method float|null get_altitude() Gets the altitude of the place.
|
||||
* @method float|null get_latitude() Gets the latitude of the place.
|
||||
* @method float|null get_longitude() Gets the longitude of the place.
|
||||
* @method float|null get_radius() Gets the radius from the given latitude and longitude.
|
||||
* @method string|null get_units() Gets the measurement units for radius and altitude.
|
||||
*
|
||||
* @method Place set_accuracy( float $accuracy ) Sets the accuracy of position coordinates.
|
||||
* @method Place set_address( array|string $address ) Sets the address of the place.
|
||||
* @method Place set_altitude( float $altitude ) Sets the altitude of the place.
|
||||
* @method Place set_latitude( float $latitude ) Sets the latitude of the place.
|
||||
* @method Place set_longitude( float $longitude ) Sets the longitude of the place.
|
||||
* @method Place set_radius( float $radius ) Sets the radius from the given latitude and longitude.
|
||||
* @method Place set_units( string $units ) Sets the measurement units for radius and altitude.
|
||||
*/
|
||||
class Place extends Base_Object {
|
||||
/**
|
||||
* Place is an implementation of one of the
|
||||
* Activity Streams
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $type = 'Place';
|
||||
|
||||
/**
|
||||
* Indicates the accuracy of position coordinates on a Place objects.
|
||||
* Expressed in properties of percentage. e.g. "94.0" means "94.0% accurate".
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-accuracy
|
||||
* @var float xsd:float [>= 0.0f, <= 100.0f]
|
||||
*/
|
||||
protected $accuracy;
|
||||
|
||||
/**
|
||||
* Indicates the altitude of a place. The measurement unit is indicated using the unit's property.
|
||||
* If unit is not specified, the default is assumed to be "m" indicating meters.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-altitude
|
||||
* @var float xsd:float
|
||||
*/
|
||||
protected $altitude;
|
||||
|
||||
/**
|
||||
* The latitude of a place.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-latitude
|
||||
* @var float xsd:float
|
||||
*/
|
||||
protected $latitude;
|
||||
|
||||
/**
|
||||
* The longitude of a place.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-longitude
|
||||
* @var float xsd:float
|
||||
*/
|
||||
protected $longitude;
|
||||
|
||||
/**
|
||||
* The radius from the given latitude and longitude for a Place.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-radius
|
||||
* @var float
|
||||
*/
|
||||
protected $radius;
|
||||
|
||||
/**
|
||||
* Specifies the measurement units for the `radius` and `altitude` properties.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-units
|
||||
* @var string
|
||||
*/
|
||||
protected $units;
|
||||
|
||||
/**
|
||||
* The address of the place.
|
||||
*
|
||||
* @see https://schema.org/PostalAddress
|
||||
* @var array|string
|
||||
*/
|
||||
protected $address;
|
||||
|
||||
/**
|
||||
* External URL/Website of the place/venue.
|
||||
*
|
||||
* @see https://schema.org/sameAs
|
||||
* @var string
|
||||
*/
|
||||
protected $same_as;
|
||||
|
||||
/**
|
||||
* Telephone number of the place.
|
||||
*
|
||||
* @see https://schema.org/telephone
|
||||
* @var string
|
||||
*/
|
||||
protected $telephone;
|
||||
}
|
||||
@ -19,7 +19,7 @@ class Event {
|
||||
* Initialize the class, registering WordPress hooks.
|
||||
*/
|
||||
public static function init() {
|
||||
\add_action( 'transition_post_status', array( self::class, 'maybe_schedule_event_post_activity' ), 50, 3 );
|
||||
\add_action( 'wp_after_insert_post', array( self::class, 'maybe_schedule_event_post_activity' ), 50, 4 );
|
||||
\add_action( 'event_bridge_for_activitypub_add_event_post_to_outbox', array( self::class, 'add_event_post_to_outbox' ), 10, 3 );
|
||||
\add_filter( 'activitypub_is_post_disabled', array( self::class, 'is_post_disabled_for_the_activitypub_plugin' ), 50, 2 );
|
||||
}
|
||||
@ -44,13 +44,14 @@ class Event {
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedule Activities.
|
||||
* Handle post updates and determine the appropriate Activity type.
|
||||
*
|
||||
* @param string $new_status New post status.
|
||||
* @param string $old_status Old post status.
|
||||
* @param \WP_Post $post Post object.
|
||||
* @param int $post_id Post ID.
|
||||
* @param \WP_Post $post Post object.
|
||||
* @param bool $update Whether this is an existing post being updated.
|
||||
* @param null|\WP_Post $post_before Post object before the update.
|
||||
*/
|
||||
public static function maybe_schedule_event_post_activity( $new_status, $old_status, $post ): void {
|
||||
public static function maybe_schedule_event_post_activity( $post_id, $post, $update, $post_before ) {
|
||||
if ( defined( 'WP_IMPORTING' ) && WP_IMPORTING ) {
|
||||
return;
|
||||
}
|
||||
@ -63,9 +64,17 @@ class Event {
|
||||
return;
|
||||
}
|
||||
|
||||
// Bail on bulk edits, unless post author or post status changed.
|
||||
if ( isset( $_REQUEST['bulk_edit'] ) && -1 === (int) $_REQUEST['post_author'] && -1 === (int) $_REQUEST['_status'] ) { // phpcs:ignore WordPress
|
||||
return;
|
||||
}
|
||||
|
||||
$new_status = get_post_status( $post );
|
||||
$old_status = $post_before ? get_post_status( $post_before ) : null;
|
||||
|
||||
switch ( $new_status ) {
|
||||
case 'publish':
|
||||
$type = ( 'publish' === $old_status ) ? 'Update' : 'Create';
|
||||
$type = $update ? 'Update' : 'Create';
|
||||
break;
|
||||
|
||||
case 'draft':
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
namespace Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Event;
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
use Activitypub\Activity\Extended_Object\Place;
|
||||
use Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Event\Event as Base_Event_Transformer;
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
namespace Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Event;
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
use Activitypub\Activity\Extended_Object\Event as Event_Object;
|
||||
use Activitypub\Activity\Extended_Object\Place;
|
||||
@ -38,6 +38,20 @@ abstract class Event extends Post {
|
||||
*/
|
||||
protected $wp_taxonomy;
|
||||
|
||||
/**
|
||||
* A valid timezone string.
|
||||
*
|
||||
* @var ?string
|
||||
*/
|
||||
protected $timezone_string = null;
|
||||
|
||||
/**
|
||||
* Bool that stores whether timezone is indeed not known = null.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $no_valid_timezone_known = false;
|
||||
|
||||
/**
|
||||
* Returns the ActivityStreams 2.0 Object-Type for an Event.
|
||||
*
|
||||
@ -188,7 +202,7 @@ abstract class Event extends Post {
|
||||
* @param ?string $time The time which needs to be formatted.
|
||||
*/
|
||||
protected static function format_time( $time ) {
|
||||
if ( is_null( $time ) ) {
|
||||
if ( null === $time ) {
|
||||
return '';
|
||||
}
|
||||
$start_datetime = new DateTime( $time );
|
||||
@ -433,7 +447,6 @@ abstract class Event extends Post {
|
||||
|
||||
// Fill in the shortcodes.
|
||||
\setup_postdata( $this->item );
|
||||
Shortcodes::register();
|
||||
$summary = \do_shortcode( $summary );
|
||||
\wp_reset_postdata();
|
||||
|
||||
@ -491,19 +504,20 @@ abstract class Event extends Post {
|
||||
*/
|
||||
public function get_formatted_address( $include_location_name = false, $args = array() ) {
|
||||
$location = $this->get_location();
|
||||
Shortcodes::register();
|
||||
|
||||
if ( $location instanceof Place ) {
|
||||
$location_name = $location->get_name();
|
||||
$foramted_address = self::format_address( $location->get_address(), $args );
|
||||
$location_name = $location->get_name();
|
||||
$formatted_address = self::format_address( $location->get_address(), $args );
|
||||
|
||||
$loaction_parts = array();
|
||||
$location_parts = array();
|
||||
|
||||
if ( $location_name ) {
|
||||
$location_parts[] = $location_name;
|
||||
}
|
||||
|
||||
if ( $foramted_address ) {
|
||||
$location_parts[] = $foramted_address;
|
||||
if ( $formatted_address ) {
|
||||
$location_parts[] = $formatted_address;
|
||||
}
|
||||
|
||||
if ( ! empty( $location_parts ) ) {
|
||||
@ -531,16 +545,76 @@ abstract class Event extends Post {
|
||||
}
|
||||
|
||||
/**
|
||||
* By default set the timezone of the WordPress site.
|
||||
* Get the timezone of the event if known.
|
||||
*
|
||||
* By default gets the timezone of the WordPress site.
|
||||
* This is not to be overwritten by the event transformers. Instead override get_timezone_string.
|
||||
* This function does also cache and sanitize the timezone string.
|
||||
*
|
||||
* @return string|null The timezone string of the event. Or no null if timezone information.
|
||||
*/
|
||||
final public function get_timezone(): ?string {
|
||||
// Return cached timezone, if a valid one is known.
|
||||
if ( $this->timezone_string ) {
|
||||
return $this->timezone_string;
|
||||
}
|
||||
|
||||
// Return cached failure.
|
||||
if ( $this->no_valid_timezone_known ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Step 1: Get timezone string.
|
||||
$timezone_string = $this->get_timezone_string();
|
||||
|
||||
// Step 2: Fallback to site default if child class override returned null or empty string.
|
||||
if ( ! $timezone_string ) {
|
||||
$timezone_string = $this->get_site_timezone_string();
|
||||
}
|
||||
|
||||
// Step 3: Reject non-strings early.
|
||||
if ( ! \is_string( $timezone_string ) ) {
|
||||
$this->no_valid_timezone_known = true;
|
||||
return null;
|
||||
}
|
||||
|
||||
// Step 4: Validate against known timezone identifiers.
|
||||
$valid_timezone_strings = \DateTimeZone::listIdentifiers();
|
||||
|
||||
if ( \in_array( $timezone_string, $valid_timezone_strings, true ) ) {
|
||||
// Cache and return valid timezone identifier string.
|
||||
$this->timezone_string = $timezone_string;
|
||||
return $this->timezone_string;
|
||||
}
|
||||
|
||||
// Cache failure.
|
||||
$this->no_valid_timezone_known = true;
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the timezone string of the event. Will be validated later.
|
||||
*
|
||||
* This is likely to be overwritten by the actual transformer.
|
||||
*
|
||||
* @return string The timezone string of the site.
|
||||
* @return mixed
|
||||
*/
|
||||
public function get_timezone(): string {
|
||||
protected function get_timezone_string(): mixed {
|
||||
return $this->get_site_timezone_string();
|
||||
}
|
||||
|
||||
/**
|
||||
* Non-overridable fallback method for timezone.
|
||||
*
|
||||
* Often in WordPress timezone string might be a UTC offset like "+01:00". But this will be sanitized be later in get_timezone().
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
final protected function get_site_timezone_string(): string {
|
||||
return \wp_timezone_string();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove the permalink shortcode from a WordPress template.
|
||||
*
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
namespace Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Event;
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
use Activitypub\Activity\Extended_Object\Place;
|
||||
use Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Event\Event;
|
||||
@ -51,20 +51,20 @@ final class Eventin extends Event {
|
||||
* Get the end time from the event object.
|
||||
*/
|
||||
public function get_start_time(): string {
|
||||
return \gmdate( 'Y-m-d\TH:i:s\Z', strtotime( $this->event_model->get_start_datetime() ) );
|
||||
return $this->event_model->get_start_datetime( 'Y-m-d\TH:i:sP' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the end time from the event object.
|
||||
*/
|
||||
public function get_end_time(): string {
|
||||
return \gmdate( 'Y-m-d\TH:i:s\Z', strtotime( $this->event_model->get_end_datetime() ) );
|
||||
return $this->event_model->get_end_datetime( 'Y-m-d\TH:i:sP' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the timezone of the event.
|
||||
*/
|
||||
public function get_timezone(): string {
|
||||
public function get_timezone_string(): string {
|
||||
return $this->event_model->get_timezone();
|
||||
}
|
||||
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
namespace Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Event;
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
use Activitypub\Activity\Extended_Object\Place;
|
||||
use Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Event\Event as Event_Transformer;
|
||||
@ -20,6 +20,8 @@ use Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Place\EventOn as EventO
|
||||
*
|
||||
* This transformer tries a different principle: The setters are chainable.
|
||||
*
|
||||
* @link https://docs.myeventon.com/documentations/event-post-meta-variables/
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
final class EventOn extends Event_Transformer {
|
||||
@ -102,8 +104,8 @@ final class EventOn extends Event_Transformer {
|
||||
* Get the end time from the events metadata.
|
||||
*/
|
||||
public function get_end_time(): ?string {
|
||||
$end_time = \get_post_meta( $this->item->ID, '_unix_end_ev', true );
|
||||
$timezone = \get_post_meta( $this->item->ID, '_evo_tz', true );
|
||||
$end_time = \get_post_meta( $this->item->ID, 'evcal_erow', true );
|
||||
$timezone = \get_post_meta( $this->item->ID, 'evo_event_timezone', true );
|
||||
$timezone = $timezone ? new \DateTimeZone( $timezone ) : null;
|
||||
|
||||
if ( is_null( $end_time ) || empty( $end_time ) ) {
|
||||
@ -117,18 +119,16 @@ final class EventOn extends Event_Transformer {
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_timezone(): string {
|
||||
$timezone = \get_post_meta( $this->item->ID, '_evo_tz', true );
|
||||
|
||||
return $timezone ?? \wp_timezone_string();
|
||||
public function get_timezone_string(): string {
|
||||
return \get_post_meta( $this->item->ID, 'evo_event_timezone', true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the end time from the events metadata.
|
||||
*/
|
||||
public function get_start_time(): string {
|
||||
$start_time = \get_post_meta( $this->item->ID, '_unix_start_ev', true );
|
||||
$timezone = \get_post_meta( $this->item->ID, '_evo_tz', true );
|
||||
$start_time = \get_post_meta( $this->item->ID, 'evcal_srow', true );
|
||||
$timezone = \get_post_meta( $this->item->ID, 'evo_event_timezone', true );
|
||||
$timezone = $timezone ? new \DateTimeZone( $timezone ) : null;
|
||||
|
||||
return \wp_date( 'Y-m-d\TH:i:sP', (int) $start_time, $timezone );
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
namespace Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Event;
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
use Activitypub\Activity\Extended_Object\Place;
|
||||
use Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Event\Event as Base_Event_Transformer;
|
||||
@ -27,7 +27,7 @@ final class EventPrime extends Base_Event_Transformer {
|
||||
public function get_end_time(): ?string {
|
||||
$timestamp = \get_post_meta( $this->wp_object->ID, 'em_end_date', true );
|
||||
if ( $timestamp ) {
|
||||
return \gmdate( 'Y-m-d\TH:i:s\Z', $timestamp );
|
||||
return \wp_date( 'Y-m-d\TH:i:sP', $timestamp );
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
@ -39,7 +39,7 @@ final class EventPrime extends Base_Event_Transformer {
|
||||
public function get_start_time(): string {
|
||||
$timestamp = \get_post_meta( $this->wp_object->ID, 'em_start_date', true );
|
||||
if ( $timestamp ) {
|
||||
return \gmdate( 'Y-m-d\TH:i:s\Z', $timestamp );
|
||||
return \wp_date( 'Y-m-d\TH:i:sP', $timestamp );
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
namespace Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Event;
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
use Activitypub\Activity\Extended_Object\Place;
|
||||
use Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Event\Event as Event_Transformer;
|
||||
@ -66,11 +66,7 @@ final class Events_Manager extends Event_Transformer {
|
||||
*/
|
||||
public function get_location() {
|
||||
if ( $this->is_online() ) {
|
||||
if ( property_exists( $this->em_event->event_location, 'data' ) ) {
|
||||
$event_location = $this->em_event->event_location->data;
|
||||
} else {
|
||||
$event_location = array();
|
||||
}
|
||||
$event_location = $this->em_event->event_location->data;
|
||||
|
||||
$event_link_url = isset( $event_location['url'] ) ? $event_location['url'] : null;
|
||||
$event_link_text = isset( $event_location['text'] ) ? $event_location['text'] : esc_html__( 'Link', 'event-bridge-for-activitypub' );
|
||||
@ -103,29 +99,26 @@ final class Events_Manager extends Event_Transformer {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the end time from the events metadata.
|
||||
* Get the start time of the event.
|
||||
*/
|
||||
public function get_end_time(): ?string {
|
||||
return null;
|
||||
public function get_start_time(): string {
|
||||
return $this->em_event->start()->format( 'Y-m-d\TH:i:sP' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the end time from the events metadata.
|
||||
* Get the end time of the event.
|
||||
*/
|
||||
public function get_start_time(): string {
|
||||
$date_string = $this->em_event->event_start_date;
|
||||
$time_string = $this->em_event->event_start_time;
|
||||
$timezone_string = $this->em_event->event_timezone;
|
||||
public function get_end_time(): string {
|
||||
return $this->em_event->end()->format( 'Y-m-d\TH:i:sP' );
|
||||
}
|
||||
|
||||
// Create a DateTime object with the given date, time, and timezone.
|
||||
$datetime = new DateTime( $date_string . ' ' . $time_string, new DateTimeZone( $timezone_string ) );
|
||||
|
||||
// Set the timezone for proper formatting.
|
||||
$datetime->setTimezone( new DateTimeZone( 'UTC' ) );
|
||||
|
||||
// Format the DateTime object as 'Y-m-d\TH:i:s\Z'.
|
||||
$formatted_date = $datetime->format( 'Y-m-d\TH:i:s\Z' );
|
||||
return $formatted_date;
|
||||
/**
|
||||
* Get the timezone. Events calendar also supports "UTC-offset timezones", ActivityPub federation does not.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_timezone_string(): string {
|
||||
return $this->em_event->get_timezone()->getName();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -170,12 +163,7 @@ final class Events_Manager extends Event_Transformer {
|
||||
*/
|
||||
private function get_event_link_attachment(): ?array {
|
||||
if ( $this->is_online() ) {
|
||||
if ( property_exists( $this->em_event->event_location, 'data' ) ) {
|
||||
$event_location = $this->em_event->event_location->data;
|
||||
} else {
|
||||
$event_location = array();
|
||||
}
|
||||
|
||||
$event_location = $this->em_event->event_location->data;
|
||||
$event_link_url = isset( $event_location['url'] ) ? $event_location['url'] : null;
|
||||
$event_link_text = isset( $event_location['text'] ) ? $event_location['text'] : __( 'Link', 'event-bridge-for-activitypub' );
|
||||
|
||||
@ -224,16 +212,23 @@ final class Events_Manager extends Event_Transformer {
|
||||
|
||||
$post_tags = \wp_get_post_terms( $this->item->ID, 'event-tags' );
|
||||
|
||||
if ( $post_tags ) {
|
||||
foreach ( $post_tags as $post_tag ) {
|
||||
$tag = array(
|
||||
if ( \is_wp_error( $post_tags ) ) {
|
||||
return $tags;
|
||||
}
|
||||
|
||||
foreach ( $post_tags as $post_tag ) {
|
||||
// @phpstan-ignore-next-line
|
||||
if ( $post_tag instanceof \WP_Term ) {
|
||||
$tag = array(
|
||||
'type' => 'Hashtag',
|
||||
'href' => \esc_url( \get_tag_link( $post_tag->term_id ) ),
|
||||
'name' => esc_hashtag( $post_tag->name ),
|
||||
);
|
||||
|
||||
$tags[] = $tag;
|
||||
}
|
||||
}
|
||||
|
||||
return $tags;
|
||||
}
|
||||
|
||||
|
||||
@ -1,28 +1,34 @@
|
||||
<?php
|
||||
/**
|
||||
* ActivityPub Transformer for the GatherPress event plugin.
|
||||
* ActivityPub Transformer for the GatherPress events.
|
||||
*
|
||||
* @package Event_Bridge_For_ActivityPub
|
||||
* @package GatherPress_ActivityPub
|
||||
* @since 1.0.0
|
||||
* @license AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
namespace Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Event;
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
use Activitypub\Activity\Extended_Object\Event as Event_Object;
|
||||
use Activitypub\Activity\Extended_Object\Place;
|
||||
use Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Event\Event;
|
||||
use Event_Bridge_For_ActivityPub\ActivityPub\Object\Place;
|
||||
use Event_Bridge_For_ActivityPub\ActivityPub\Object\Event_FEP_8a8e;
|
||||
use Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Place\GatherPress as Venue_Transformer;
|
||||
use Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Event\Event as Event_Transformer;
|
||||
use Activitypub\Activity\Base_Object;
|
||||
use GatherPress\Core\Event as GatherPress_Event;
|
||||
use GatherPress\Core\Venue;
|
||||
use WP_Error;
|
||||
|
||||
use function Activitypub\get_content_warning;
|
||||
|
||||
/**
|
||||
* ActivityPub Transformer for VS Event
|
||||
* Class GatherPress Event Transformer.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* Manages the transformation of a GatherPress event post to ActivityStreams.
|
||||
*/
|
||||
final class GatherPress extends Event {
|
||||
|
||||
final class GatherPress extends Event_Transformer {
|
||||
/**
|
||||
* The current GatherPress Event object.
|
||||
*
|
||||
@ -38,12 +44,9 @@ final class GatherPress extends Event {
|
||||
protected $gp_venue;
|
||||
|
||||
/**
|
||||
* Extend the constructor, to also set the GatherPress objects.
|
||||
* Extend the constructor to also set the GatherPress objects.
|
||||
*
|
||||
* This is a special class object form The Events Calendar which
|
||||
* has a lot of useful functions, we make use of our getter functions.
|
||||
*
|
||||
* @param \WP_Post $item The WordPress object.
|
||||
* @param \WP_Post $item The WordPress object.
|
||||
* @param string $wp_taxonomy The taxonomy slug of the event post type.
|
||||
*/
|
||||
public function __construct( $item, $wp_taxonomy ) {
|
||||
@ -52,70 +55,59 @@ final class GatherPress extends Event {
|
||||
$this->gp_venue = $this->gp_event->get_venue_information();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the correct type of an Event.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_type(): string {
|
||||
return 'Event';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the event location.
|
||||
*
|
||||
* @return ?Place The place objector null if not place set.
|
||||
* @return Place|array|null A Place object or VirtualLocation.
|
||||
*/
|
||||
public function get_location(): ?Place {
|
||||
$address = $this->gp_venue['full_address'];
|
||||
if ( $address ) {
|
||||
$place = new Place();
|
||||
$place->set_type( 'Place' );
|
||||
$place->set_name( $address );
|
||||
$place->set_address( $address );
|
||||
return $place;
|
||||
public function get_location(): mixed {
|
||||
$event_link = $this->gp_event->maybe_get_online_event_link();
|
||||
if ( $event_link ) {
|
||||
return array(
|
||||
'type' => 'VirtualLocation',
|
||||
'url' => $event_link,
|
||||
);
|
||||
}
|
||||
|
||||
$term = current( (array) get_the_terms( $this->gp_event->event, Venue::TAXONOMY ) );
|
||||
|
||||
if ( ! empty( $term ) && is_a( $term, 'WP_Term' ) ) {
|
||||
$venue_post = Venue::get_instance()->get_venue_post_from_term_slug( $term->slug );
|
||||
|
||||
if ( ! $venue_post ) {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
$venue_transformer = new Venue_Transformer( $venue_post );
|
||||
$full_location_object = false;
|
||||
$location = $venue_transformer->to_object( $full_location_object );
|
||||
return $location;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the end time from the event object.
|
||||
*/
|
||||
public function get_end_time(): string {
|
||||
return $this->gp_event->get_datetime_end( 'Y-m-d\TH:i:s\Z' );
|
||||
return $this->gp_event->get_datetime_end( 'Y-m-d\TH:i:sP' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the end time from the event object.
|
||||
*/
|
||||
public function get_start_time(): string {
|
||||
return $this->gp_event->get_datetime_start( 'Y-m-d\TH:i:s\Z' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the event link from the events metadata.
|
||||
*/
|
||||
private function get_event_link(): array {
|
||||
|
||||
$event_link = get_post_meta( $this->item->ID, 'event-link', true );
|
||||
if ( $event_link ) {
|
||||
return array(
|
||||
'type' => 'Link',
|
||||
'name' => 'Website',
|
||||
'href' => \esc_url( $event_link ),
|
||||
'mediaType' => 'text/html',
|
||||
);
|
||||
}
|
||||
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides/extends the get_attachments function to also add the event Link.
|
||||
*/
|
||||
protected function get_attachment(): array {
|
||||
$attachments = parent::get_attachment();
|
||||
if ( count( $attachments ) ) {
|
||||
$attachments[0]['type'] = 'Document';
|
||||
$attachments[0]['name'] = 'Banner';
|
||||
}
|
||||
$event_link = $this->get_event_link();
|
||||
if ( $event_link ) {
|
||||
$attachments[] = $this->get_event_link();
|
||||
}
|
||||
return $attachments;
|
||||
return $this->gp_event->get_datetime_start( 'Y-m-d\TH:i:sP' );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -130,27 +122,44 @@ final class GatherPress extends Event {
|
||||
return ''; // Skip rendering this block.
|
||||
}
|
||||
|
||||
return $block_content; // Return the content for other blocks.
|
||||
return str_replace( '<p></p>', '', $block_content ); // Return the content for other blocks.
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the filter for preventing the rendering off gatherpress blocks just in time.
|
||||
* Transform to an the Event object.
|
||||
*
|
||||
* @return Event_Object
|
||||
* @return Base_Object|WP_Error
|
||||
*/
|
||||
public function to_object(): Event_Object {
|
||||
/**
|
||||
* Transform to an the Event object.
|
||||
*
|
||||
* @return Base_Object|WP_Error
|
||||
*/
|
||||
public function to_object(): Base_Object|WP_Error {
|
||||
// Apply the filter for preventing the rendering off gatherpress blocks just in time.
|
||||
add_filter( 'render_block', array( self::class, 'filter_gatherpress_blocks' ), 10, 2 );
|
||||
$activitypub_object = parent::to_object();
|
||||
remove_filter( 'render_block', array( self::class, 'filter_gatherpress_blocks' ) );
|
||||
return $activitypub_object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the event is online.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function get_is_online(): bool {
|
||||
return $this->gp_event->maybe_get_online_event_link() ? true : false;
|
||||
// Transform all properties via getter functions.
|
||||
$object = new Event_FEP_8a8e();
|
||||
$object = $this->transform_object_properties( $object );
|
||||
|
||||
if ( \is_wp_error( $object ) ) {
|
||||
return $object;
|
||||
}
|
||||
|
||||
$this->set_audience( $object );
|
||||
|
||||
remove_filter( 'render_block', array( self::class, 'filter_gatherpress_blocks' ) );
|
||||
|
||||
// Maybe modify object for content warning.
|
||||
$content_warning = get_content_warning( $this->item );
|
||||
if ( ! empty( $content_warning ) ) {
|
||||
$object->set_sensitive( true );
|
||||
$object->set_summary( $content_warning );
|
||||
$object->set_summary_map( null );
|
||||
$object->set_dcterms( array( 'subject' => $content_warning ) );
|
||||
}
|
||||
|
||||
return $object;
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
namespace Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Event;
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
use Activitypub\Activity\Extended_Object\Place;
|
||||
use Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Event\Event;
|
||||
@ -67,7 +67,10 @@ final class Modern_Events_Calendar_Lite extends Event {
|
||||
* @return string
|
||||
*/
|
||||
public function get_start_time(): string {
|
||||
return \gmdate( 'Y-m-d\TH:i:s\Z', $this->mec_event->get_datetime()['start']['timestamp'] );
|
||||
$datetime = $this->mec_event->get_datetime()['start']['datetime'];
|
||||
$timezone = $this->get_timezone() ? new \DateTimeZone( $this->get_timezone() ) : null;
|
||||
$start_time = new \DateTime( $datetime, $timezone );
|
||||
return $start_time->format( 'Y-m-d\TH:i:sP' );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -76,7 +79,10 @@ final class Modern_Events_Calendar_Lite extends Event {
|
||||
* @return string
|
||||
*/
|
||||
public function get_end_time(): string {
|
||||
return \gmdate( 'Y-m-d\TH:i:s\Z', $this->mec_event->get_datetime()['end']['timestamp'] );
|
||||
$datetime = $this->mec_event->get_datetime()['end']['datetime'];
|
||||
$timezone = $this->get_timezone() ? new \DateTimeZone( $this->get_timezone() ) : null;
|
||||
$end_time = new \DateTime( $datetime, $timezone );
|
||||
return $end_time->format( 'Y-m-d\TH:i:sP' );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -113,15 +119,11 @@ final class Modern_Events_Calendar_Lite extends Event {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the location.
|
||||
* Get the timezone string of the current event.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function get_timezone(): string {
|
||||
$timezone = get_post_meta( $this->item->ID, 'mec_timezone', true );
|
||||
|
||||
if ( 'global' === $timezone ) {
|
||||
return parent::get_timezone();
|
||||
}
|
||||
|
||||
return $timezone;
|
||||
public function get_timezone_string(): mixed {
|
||||
return \get_post_meta( $this->item->ID, 'mec_timezone', true );
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,140 @@
|
||||
<?php
|
||||
/**
|
||||
* ActivityPub Transformer for Events managed with Eventin.
|
||||
*
|
||||
* @link https://support.themewinter.com/docs/plugins/docs-category/eventin/
|
||||
*
|
||||
* @package Event_Bridge_For_ActivityPub
|
||||
* @license AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
namespace Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Event;
|
||||
|
||||
use DateTimeImmutable;
|
||||
use DateTimeZone;
|
||||
|
||||
// Exit if accessed directly.
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
use Activitypub\Activity\Extended_Object\Place;
|
||||
use Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Event\Event;
|
||||
|
||||
/**
|
||||
* ActivityPub Transformer for Events managed with Eventin.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
final class Spiffy_Calendar extends Event {
|
||||
/**
|
||||
* Get the end time from the event object.
|
||||
*/
|
||||
public function get_start_time(): string {
|
||||
$start_date = \get_post_meta( $this->item->ID, '_spiffy_event_begin', true );
|
||||
$start_time = \get_post_meta( $this->item->ID, '_spiffy_event_begin_time', true );
|
||||
|
||||
$start_datetime = $this->get_datetime_from_fuzzy_input( $start_date, $start_time );
|
||||
|
||||
return $start_datetime->format( 'Y-m-d\TH:i:sP' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the end time from the event object.
|
||||
*/
|
||||
public function get_end_time(): string {
|
||||
$end_date = \get_post_meta( $this->item->ID, '_spiffy_event_end', true );
|
||||
$end_time = \get_post_meta( $this->item->ID, '_spiffy_event_end_time', true );
|
||||
|
||||
$end_datetime = $this->get_datetime_from_fuzzy_input( $end_date, $end_time );
|
||||
|
||||
return $end_datetime->format( 'Y-m-d\TH:i:sP' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the location.
|
||||
*
|
||||
* @return ?Place
|
||||
*/
|
||||
public function get_location(): ?Place {
|
||||
$location = \get_post_meta( $this->item->ID, '_spiffy_event_location', true );
|
||||
|
||||
if ( ! $location ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$place = new Place();
|
||||
$place->set_address( $location );
|
||||
$place->set_name( $location );
|
||||
return $place;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides/extends the get_attachments function to also add the event Link.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function get_attachment(): array {
|
||||
$attachments = parent::get_attachment();
|
||||
if ( \count( $attachments ) ) {
|
||||
$attachments[0]['type'] = 'Document';
|
||||
$attachments[0]['name'] = 'Banner';
|
||||
}
|
||||
$event_link = $this->get_event_link();
|
||||
if ( $event_link ) {
|
||||
$attachments[] = $event_link;
|
||||
}
|
||||
return $attachments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the event link from the events metadata.
|
||||
*
|
||||
* @return array|null Associated array of an ActivityStreams Link object with the event link.
|
||||
*/
|
||||
private function get_event_link(): ?array {
|
||||
$event_link = \get_post_meta( $this->item->ID, '_spiffy_event_link', true );
|
||||
if ( $event_link ) {
|
||||
return array(
|
||||
'type' => 'Link',
|
||||
'name' => __( 'Event Link', 'event-bridge-for-activitypub' ),
|
||||
'href' => \esc_url( $event_link ),
|
||||
'mediaType' => 'text/html',
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the best datetime object of the fuzzy human made data Spiffy Calendar provides.
|
||||
*
|
||||
* @param string $date The date as 2026-05-18 string.
|
||||
* @param string $time Fuzzy time like 14:00, 2pm, 2 PM, noon, midnight, etc.
|
||||
* @return DateTimeImmutable
|
||||
*/
|
||||
private function get_datetime_from_fuzzy_input( string $date = '', string $time = '' ): DateTimeImmutable {
|
||||
$timezone = new DateTimeZone( $this->get_timezone_string() );
|
||||
|
||||
// Normalize fuzzy human time.
|
||||
$time = trim( strtolower( $time ) );
|
||||
|
||||
$map = array(
|
||||
__( 'noon', 'event-bridge-for-activitypub' ) => '12:00',
|
||||
__( 'midday', 'event-bridge-for-activitypub' ) => '12:00',
|
||||
__( 'midnight', 'event-bridge-for-activitypub' ) => '00:00',
|
||||
__( 'morning', 'event-bridge-for-activitypub' ) => '09:00',
|
||||
__( 'afternoon', 'event-bridge-for-activitypub' ) => '15:00',
|
||||
__( 'evening', 'event-bridge-for-activitypub' ) => '19:00',
|
||||
);
|
||||
|
||||
$time = $map[ $time ] ?? $time;
|
||||
|
||||
$input = trim( "$date $time" );
|
||||
|
||||
try {
|
||||
$datetime = new DateTimeImmutable( $input, $timezone );
|
||||
} catch ( \Throwable $e ) {
|
||||
$datetime = new DateTimeImmutable( "$date 00:00", $timezone );
|
||||
}
|
||||
|
||||
return $datetime;
|
||||
}
|
||||
}
|
||||
@ -9,7 +9,7 @@
|
||||
namespace Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Event;
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
use Activitypub\Activity\Extended_Object\Event as Event_Object;
|
||||
use Activitypub\Activity\Extended_Object\Place;
|
||||
@ -81,7 +81,7 @@ final class The_Events_Calendar extends Event {
|
||||
*/
|
||||
public function get_end_time(): string {
|
||||
$utc_time = get_post_meta( $this->tribe_event->ID, '_EventEndDateUTC', true );
|
||||
$timezone = new \DateTimeZone( $this->get_timezone() );
|
||||
$timezone = new \DateTimeZone( $this->get_timezone_string() );
|
||||
$time = new \DateTime( $utc_time );
|
||||
$time->setTimezone( $timezone );
|
||||
return $time->format( 'Y-m-d\TH:i:sP' );
|
||||
@ -92,7 +92,7 @@ final class The_Events_Calendar extends Event {
|
||||
*/
|
||||
public function get_start_time(): string {
|
||||
$utc_time = get_post_meta( $this->tribe_event->ID, '_EventStartDateUTC', true );
|
||||
$timezone = new \DateTimeZone( $this->get_timezone() );
|
||||
$timezone = new \DateTimeZone( $this->get_timezone_string() );
|
||||
$time = new \DateTime( $utc_time );
|
||||
$time->setTimezone( $timezone );
|
||||
return $time->format( 'Y-m-d\TH:i:sP' );
|
||||
@ -101,17 +101,11 @@ final class The_Events_Calendar extends Event {
|
||||
/**
|
||||
* Get the timezone of the event.
|
||||
*
|
||||
* @return string The timezone string of the site.
|
||||
* @return string The timezone string of the event.
|
||||
*/
|
||||
public function get_timezone(): string {
|
||||
public function get_timezone_string(): string {
|
||||
// @phpstan-ignore-next-line
|
||||
$timezone = $this->tribe_event->timezone;
|
||||
|
||||
if ( ! $timezone || ! is_string( $timezone ) ) {
|
||||
return parent::get_timezone();
|
||||
}
|
||||
|
||||
return $timezone;
|
||||
return (string) $this->tribe_event->timezone;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -144,8 +138,10 @@ final class The_Events_Calendar extends Event {
|
||||
|
||||
/**
|
||||
* Check if the event is an online event.
|
||||
*
|
||||
* @return false
|
||||
*/
|
||||
public function get_is_online(): bool {
|
||||
public function get_is_online() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
namespace Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Event;
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
use Activitypub\Activity\Extended_Object\Place;
|
||||
use Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Event\Event as Event_Transformer;
|
||||
@ -52,7 +52,7 @@ final class VS_Event_List extends Event_Transformer {
|
||||
if ( is_null( $end_time ) || empty( $end_time ) || 'no' === $end_time ) {
|
||||
return null;
|
||||
}
|
||||
return \gmdate( 'Y-m-d\TH:i:s\Z', (int) $end_time );
|
||||
return \wp_date( 'Y-m-d\TH:i:sP', (int) $end_time );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -60,7 +60,7 @@ final class VS_Event_List extends Event_Transformer {
|
||||
*/
|
||||
public function get_start_time(): string {
|
||||
$start_time = \get_post_meta( $this->item->ID, 'event-start-date', true );
|
||||
return \gmdate( 'Y-m-d\TH:i:s\Z', (int) $start_time );
|
||||
return \wp_date( 'Y-m-d\TH:i:sP', (int) $start_time );
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
namespace Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Event;
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
use Activitypub\Activity\Extended_Object\Place;
|
||||
use Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Event\Event as Event_Transformer;
|
||||
@ -30,7 +30,7 @@ final class WP_Event_Manager extends Event_Transformer {
|
||||
* @return bool
|
||||
*/
|
||||
protected function get_is_online(): bool {
|
||||
$is_online_text = get_post_meta( $this->item->ID, '_event_online', true );
|
||||
$is_online_text = \get_post_meta( $this->item->ID, '_event_online', true );
|
||||
$is_online = false;
|
||||
// Radio buttons.
|
||||
if ( 'yes' === $is_online_text ) {
|
||||
@ -49,7 +49,7 @@ final class WP_Event_Manager extends Event_Transformer {
|
||||
* @return ?Place The Place.
|
||||
*/
|
||||
public function get_location(): ?Place {
|
||||
$location_name = get_post_meta( $this->item->ID, '_event_location', true );
|
||||
$location_name = \get_post_meta( $this->item->ID, '_event_location', true );
|
||||
|
||||
if ( $location_name ) {
|
||||
$location = new Place();
|
||||
@ -68,11 +68,12 @@ final class WP_Event_Manager extends Event_Transformer {
|
||||
* @return ?string The events end-datetime if is set, null otherwise.
|
||||
*/
|
||||
public function get_end_time(): ?string {
|
||||
$end_date = get_post_meta( $this->item->ID, '_event_end_date', true );
|
||||
$end_date = \get_post_meta( $this->item->ID, '_event_end_date', true );
|
||||
if ( ! $end_date ) {
|
||||
return null;
|
||||
}
|
||||
$timezone = new DateTimeZone( $this->get_timezone() );
|
||||
|
||||
$timezone = $this->get_timezone() ? new DateTimeZone( $this->get_timezone() ) : null;
|
||||
|
||||
if ( is_numeric( $end_date ) ) {
|
||||
$end_date = '@' . $end_date;
|
||||
@ -86,22 +87,19 @@ final class WP_Event_Manager extends Event_Transformer {
|
||||
/**
|
||||
* Get timezone.
|
||||
*
|
||||
* @return string
|
||||
* @return mixed
|
||||
*/
|
||||
public function get_timezone(): string {
|
||||
$time_zone = get_post_meta( $this->item->ID, '_event_timezone', true );
|
||||
if ( $time_zone ) {
|
||||
return $time_zone;
|
||||
}
|
||||
return parent::get_timezone();
|
||||
public function get_timezone_string(): mixed {
|
||||
return \get_post_meta( $this->item->ID, '_event_timezone', true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the end time from the events metadata.
|
||||
*/
|
||||
public function get_start_time(): string {
|
||||
$start_date = get_post_meta( $this->item->ID, '_event_start_date', true );
|
||||
$timezone = new DateTimeZone( $this->get_timezone() );
|
||||
$start_date = \get_post_meta( $this->item->ID, '_event_start_date', true );
|
||||
|
||||
$timezone = $this->get_timezone() ? new DateTimeZone( $this->get_timezone() ) : null;
|
||||
|
||||
if ( is_numeric( $start_date ) ) {
|
||||
$start_date = '@' . $start_date;
|
||||
@ -118,7 +116,7 @@ final class WP_Event_Manager extends Event_Transformer {
|
||||
* @return ?array
|
||||
*/
|
||||
private function get_event_link_attachment(): ?array {
|
||||
$event_link_url = get_post_meta( $this->item->ID, '_event_video_url', true );
|
||||
$event_link_url = \get_post_meta( $this->item->ID, '_event_video_url', true );
|
||||
|
||||
if ( str_starts_with( $event_link_url, 'http' ) ) {
|
||||
return array(
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
namespace Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Place;
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
use Activitypub\Activity\Extended_Object\Place as Place_Object;
|
||||
use Activitypub\Transformer\Post;
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
namespace Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Place;
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
use Activitypub\Activity\Extended_Object\Place as Place_Object;
|
||||
use Activitypub\Transformer\Base;
|
||||
@ -128,7 +128,7 @@ abstract class Base_Term_Place extends Base {
|
||||
/**
|
||||
* Don't set sensitive per default.
|
||||
*
|
||||
* @return null
|
||||
* @return null|bool
|
||||
*/
|
||||
public function get_sensitive() {
|
||||
return null;
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
namespace Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Place;
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
/**
|
||||
* Class for the ActivityPub transformer of the venues of The Events Calendar to `as:Place`.
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
namespace Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Place;
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
use Activitypub\Activity\Extended_Object\Place as Place_Object;
|
||||
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
namespace Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Place;
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
/**
|
||||
* Class for the ActivityPub transformer of the venues of The Events Calendar to `as:Place`.
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
namespace Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Place;
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
use Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Place\Base_Post_Place;
|
||||
|
||||
|
||||
@ -0,0 +1,152 @@
|
||||
<?php
|
||||
/**
|
||||
* ActivityPub Transformer for the GatherPress venues.
|
||||
*
|
||||
* See https://codeberg.org/Event-Federation/gatherpress-activitypub/src/branch/main/includes/classes/class-venue-transformer.php
|
||||
*
|
||||
* @package GatherPress_ActivityPub
|
||||
* @since 1.0.0
|
||||
* @license AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
namespace Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Place;
|
||||
|
||||
// Exit if accessed directly.
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
use Event_Bridge_For_ActivityPub\ActivityPub\Object\Place;
|
||||
use Activitypub\Activity\Base_Object;
|
||||
use Activitypub\Transformer\Post;
|
||||
use stdClass;
|
||||
use WP_Error;
|
||||
use WP_Post;
|
||||
|
||||
/**
|
||||
* Class GatherPress Venue Transformer.
|
||||
*
|
||||
* Manages the transformation of a GatherPress event post to ActivityStreams.
|
||||
*/
|
||||
class GatherPress extends Post {
|
||||
/**
|
||||
* The current GatherPress Venue WP_Post.
|
||||
*
|
||||
* @var stdClass
|
||||
*/
|
||||
protected $venue_meta;
|
||||
|
||||
/**
|
||||
* Extend the constructor to also set the GatherPress objects.
|
||||
*
|
||||
* @param WP_Post $item The WordPress object.
|
||||
*/
|
||||
public function __construct( WP_Post $item ) {
|
||||
parent::__construct( $item );
|
||||
$this->venue_meta = json_decode( get_post_meta( $this->item->ID, 'gatherpress_venue_information', true ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the correct type of an Event.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_type(): string {
|
||||
return 'Place';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the event location.
|
||||
*
|
||||
* @return string The name of the venue.
|
||||
*/
|
||||
public function get_name(): string {
|
||||
return $this->item->post_title;
|
||||
}
|
||||
|
||||
/**
|
||||
* The full address of the venue.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function get_address(): ?string {
|
||||
return $this->venue_meta->fullAddress ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Latitude of the venue.
|
||||
*
|
||||
* @return float|null
|
||||
*/
|
||||
public function get_latitude(): ?float {
|
||||
return $this->venue_meta->latitude ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Longitude of the venue.
|
||||
*
|
||||
* @return float|null
|
||||
*/
|
||||
public function get_longitude(): ?float {
|
||||
return $this->venue_meta->longitude ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The telephone number of the venue.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function get_telephone(): ?string {
|
||||
return $this->venue_meta->phone_number ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The website of the venue.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function get_same_as(): ?string {
|
||||
return $this->venue_meta->website ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic function that converts an WordPress location object to an ActivityPub-Place object.
|
||||
*
|
||||
* @param bool $full_object bool Return an object with all properties set, or a minimal one as used within an `as:Event`s location.
|
||||
* @return Place|\WP_Error
|
||||
*/
|
||||
public function to_object( $full_object = true ): Base_Object|WP_Error {
|
||||
$activitypub_object = new Place();
|
||||
$activitypub_object = $this->transform_object_properties( $activitypub_object );
|
||||
|
||||
if ( \is_wp_error( $activitypub_object ) ) {
|
||||
return $activitypub_object;
|
||||
}
|
||||
|
||||
if ( ! empty( $activitypub_object->get_content() ) ) {
|
||||
$activitypub_object->set_content_map(
|
||||
array(
|
||||
$this->get_locale() => $this->get_content(),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
$updated = \strtotime( $this->item->post_modified_gmt );
|
||||
|
||||
$activitypub_object->set_updated( \gmdate( 'Y-m-d\TH:i:s\Z', $updated ) );
|
||||
|
||||
if ( $full_object ) {
|
||||
$published = \strtotime( $this->item->post_date_gmt );
|
||||
|
||||
$activitypub_object->set_published( \gmdate( 'Y-m-d\TH:i:s\Z', $published ) );
|
||||
|
||||
$activitypub_object->set_to(
|
||||
array(
|
||||
'https://www.w3.org/ns/activitystreams#Public',
|
||||
$this->get_actor_object()->get_followers(),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// @phpstan-ignore-next-line
|
||||
return $activitypub_object;
|
||||
}
|
||||
}
|
||||
@ -9,7 +9,7 @@
|
||||
namespace Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Place;
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
use Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Place\Base_Post_Place;
|
||||
|
||||
@ -60,4 +60,22 @@ final class The_Events_Calendar extends Base_Post_Place {
|
||||
|
||||
return $postal_address;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the latitude of the place.
|
||||
*
|
||||
* @return ?float The latitude if it is known.
|
||||
*/
|
||||
public function get_latitude() {
|
||||
return tribe_get_coordinates( $this->item->ID )['lat'] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the longitude of the place.
|
||||
*
|
||||
* @return ?float The longitude if it is known.
|
||||
*/
|
||||
public function get_longitude() {
|
||||
return tribe_get_coordinates( $this->item->ID )['lng'] ?? null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
namespace Event_Bridge_For_ActivityPub\ActivityPub\Transmogrifier;
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
use Activitypub\Activity\Extended_Object\Event;
|
||||
use Event_Bridge_For_ActivityPub\ActivityPub\Collection\Event_Sources;
|
||||
@ -48,9 +48,18 @@ abstract class Base {
|
||||
return;
|
||||
}
|
||||
|
||||
// Add hook to insert post meta to flag post as remote and remember where we received it from.
|
||||
$add_origin_post_meta_callback = function ( $post_id ) use ( $event_source_post_id ): void {
|
||||
self::add_origin_post_meta( $post_id, $event_source_post_id );
|
||||
};
|
||||
\add_action( 'wp_after_insert_post', $add_origin_post_meta_callback, 10, 1 );
|
||||
|
||||
// Pass the saving to the actual Transmogrifier implementation.
|
||||
$post_id = static::save_event( $activitypub_event, $event_source_post_id );
|
||||
|
||||
// Remove hook added above.
|
||||
\remove_action( 'wp_after_insert_post', $add_origin_post_meta_callback, 10 );
|
||||
|
||||
// Post processing: Logging and marking the imported event's origin.
|
||||
$event_activitypub_id = $activitypub_event->get_id();
|
||||
$event_source_activitypub_id = \get_the_guid( $event_source_post_id );
|
||||
@ -60,9 +69,6 @@ abstract class Base {
|
||||
'event_bridge_for_activitypub_write_log',
|
||||
array( "[ACTIVITYPUB] Processed incoming event {$event_activitypub_id} from {$event_source_activitypub_id}" )
|
||||
);
|
||||
// Use post meta to remember who we received this event from.
|
||||
\update_post_meta( $post_id, '_event_bridge_for_activitypub_event_source', absint( $event_source_post_id ) );
|
||||
\update_post_meta( $post_id, 'activitypub_content_visibility', defined( 'ACTIVITYPUB_CONTENT_VISIBILITY_LOCAL' ) ? constant( 'ACTIVITYPUB_CONTENT_VISIBILITY_LOCAL' ) : '' );
|
||||
} else {
|
||||
\do_action(
|
||||
'event_bridge_for_activitypub_write_log',
|
||||
@ -71,6 +77,20 @@ abstract class Base {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert post meta to remember who we received an event from.
|
||||
*
|
||||
* @param int $post_id The WordPress post ID of the event itself.
|
||||
* @param int $event_source_post_id The WordPress post ID of the event source custom post type.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function add_origin_post_meta( $post_id, $event_source_post_id ): void {
|
||||
// Use post meta to remember who we received this event from.
|
||||
\update_post_meta( $post_id, '_event_bridge_for_activitypub_event_source', absint( $event_source_post_id ) );
|
||||
\update_post_meta( $post_id, 'activitypub_content_visibility', defined( 'ACTIVITYPUB_CONTENT_VISIBILITY_LOCAL' ) ? constant( 'ACTIVITYPUB_CONTENT_VISIBILITY_LOCAL' ) : '' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a local event in WordPress that is a cached remote one.
|
||||
*
|
||||
@ -129,6 +149,8 @@ abstract class Base {
|
||||
*/
|
||||
protected static function get_post_id_from_activitypub_id( $activitypub_id ): int {
|
||||
global $wpdb;
|
||||
|
||||
// phpcs:disable WordPress.DB.DirectDatabaseQuery
|
||||
return (int) $wpdb->get_var(
|
||||
$wpdb->prepare(
|
||||
"SELECT ID FROM $wpdb->posts WHERE guid=%s",
|
||||
@ -227,15 +249,13 @@ abstract class Base {
|
||||
|
||||
// Include necessary WordPress file for media handling.
|
||||
if ( ! function_exists( 'media_sideload_image' ) ) {
|
||||
// @phpstan-ignore-next-line
|
||||
require_once ABSPATH . 'wp-admin/includes/media.php';
|
||||
// @phpstan-ignore-next-line
|
||||
require_once ABSPATH . 'wp-admin/includes/file.php';
|
||||
// @phpstan-ignore-next-line
|
||||
require_once ABSPATH . 'wp-admin/includes/image.php';
|
||||
}
|
||||
|
||||
// Check to see if the URL has already been fetched, if so return the attachment ID.
|
||||
// phpcs:disable WordPress.DB.DirectDatabaseQuery
|
||||
$attachment_id = $wpdb->get_var(
|
||||
$wpdb->prepare( "SELECT `post_id` FROM {$wpdb->postmeta} WHERE `meta_key` = '_source_url' AND `meta_value` = %s", $url )
|
||||
);
|
||||
@ -243,6 +263,7 @@ abstract class Base {
|
||||
return $attachment_id;
|
||||
}
|
||||
|
||||
// phpcs:disable WordPress.DB.DirectDatabaseQuery
|
||||
$attachment_id = $wpdb->get_var(
|
||||
$wpdb->prepare( "SELECT `ID` FROM {$wpdb->posts} WHERE guid=%s", $url )
|
||||
);
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
namespace Event_Bridge_For_ActivityPub\ActivityPub\Transmogrifier;
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
use Activitypub\Activity\Extended_Object\Event;
|
||||
use Activitypub\Activity\Extended_Object\Place;
|
||||
@ -40,7 +40,7 @@ class GatherPress extends Base {
|
||||
$tags_array = $event->get_tag();
|
||||
|
||||
// Ensure the input is valid.
|
||||
if ( empty( $tags_array ) || ! is_array( $tags_array ) || ! $post_id ) {
|
||||
if ( empty( $tags_array ) || ! $post_id ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
namespace Event_Bridge_For_ActivityPub\ActivityPub\Transmogrifier;
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
use Activitypub\Activity\Extended_Object\Event;
|
||||
use Activitypub\Activity\Extended_Object\Place;
|
||||
@ -43,19 +43,18 @@ class The_Events_Calendar extends Base {
|
||||
add_filter( 'wp_revisions_to_keep', array( self::class, 'revisions_to_keep' ) );
|
||||
|
||||
$post_id = self::get_post_id_from_activitypub_id( $activitypub_event->get_id() );
|
||||
$duration = self::get_duration( $activitypub_event );
|
||||
$venue_id = self::add_venue( $activitypub_event, $event_source_post_id );
|
||||
$organizer_id = self::add_organizer( $activitypub_event );
|
||||
|
||||
$args = array(
|
||||
'title' => $activitypub_event->get_name(),
|
||||
'content' => $activitypub_event->get_content() ?? '',
|
||||
'start_date' => gmdate( 'Y-m-d H:i:s', strtotime( $activitypub_event->get_start_time() ) ),
|
||||
'duration' => $duration,
|
||||
'status' => 'publish',
|
||||
'guid' => $activitypub_event->get_id(),
|
||||
'title' => $activitypub_event->get_name(),
|
||||
'content' => $activitypub_event->get_content() ?? '',
|
||||
'status' => 'publish',
|
||||
'guid' => $activitypub_event->get_id(),
|
||||
);
|
||||
|
||||
$args = self::enrich_event_args_with_date_info( $args, $activitypub_event );
|
||||
|
||||
if ( $venue_id ) {
|
||||
$args['venue'] = $venue_id;
|
||||
$args['VenueID'] = $venue_id;
|
||||
@ -103,6 +102,33 @@ class The_Events_Calendar extends Base {
|
||||
return $post_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enrich event arguments with normalized start date and timezone.
|
||||
*
|
||||
* @param array $args Existing event arguments.
|
||||
* @param Event $activitypub_event The ActivityPub event as associative array.
|
||||
* @return array Modified $args array including 'start_date' and 'timezone' and 'duration'.
|
||||
*/
|
||||
private static function enrich_event_args_with_date_info( $args, $activitypub_event ): array {
|
||||
$start_time_str = $activitypub_event->get_start_time();
|
||||
$timezone_string = $activitypub_event->get_timezone();
|
||||
|
||||
$start_time = new \DateTime( $start_time_str );
|
||||
|
||||
if ( empty( $timezone_string ) ) {
|
||||
$timezone_string = 'UTC';
|
||||
}
|
||||
|
||||
$start_time->setTimezone( new \DateTimeZone( $timezone_string ) );
|
||||
|
||||
$args['timezone'] = $timezone_string;
|
||||
$args['start_date'] = $start_time->format( 'Y-m-d H:i:s' );
|
||||
$args['duration'] = self::get_duration( $activitypub_event );
|
||||
|
||||
return $args;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Map an ActivityStreams Place to the Events Calendar venue.
|
||||
*
|
||||
@ -148,6 +174,14 @@ class The_Events_Calendar extends Base {
|
||||
$args['guid'] = $location['id'];
|
||||
}
|
||||
|
||||
if ( isset( $location['latitude'] ) ) {
|
||||
$args['latitude'] = $location['latitude'];
|
||||
}
|
||||
|
||||
if ( isset( $location['longitude'] ) ) {
|
||||
$args['longitude'] = $location['longitude'];
|
||||
}
|
||||
|
||||
return $args;
|
||||
}
|
||||
|
||||
@ -210,7 +244,6 @@ class The_Events_Calendar extends Base {
|
||||
$results = $tribe_venue->search( $location['name'] )->all();
|
||||
|
||||
foreach ( $results as $potential_matching_post_id ) {
|
||||
// @phpstan-ignore-next-line
|
||||
if ( $potential_matching_post_id instanceof \WP_Post ) {
|
||||
$potential_matching_post_id = $potential_matching_post_id->ID;
|
||||
}
|
||||
@ -251,6 +284,13 @@ class The_Events_Calendar extends Base {
|
||||
// This might likely change, because of FEP-8a8e.
|
||||
$actor = $activitypub_event->get_attributed_to();
|
||||
|
||||
/**
|
||||
* Allow filtering of incoming organizer.
|
||||
*
|
||||
* @var mixed
|
||||
*/
|
||||
$actor = \apply_filters( 'event_bridge_for_activitypub_remote_organizer', $actor, $activitypub_event );
|
||||
|
||||
if ( is_null( $actor ) ) {
|
||||
return false;
|
||||
}
|
||||
@ -270,6 +310,7 @@ class The_Events_Calendar extends Base {
|
||||
'website' => $event_source->get_url(),
|
||||
'excerpt' => $event_source->get_summary(),
|
||||
'post_parent' => $event_source->get__id(), // Maybe just use post meta too here.
|
||||
'post_status' => 'publish',
|
||||
);
|
||||
|
||||
if ( $event_source->get_published() ) {
|
||||
@ -334,7 +375,7 @@ class The_Events_Calendar extends Base {
|
||||
$tags_array = $activitypub_event->get_tag();
|
||||
|
||||
// Ensure the input is valid.
|
||||
if ( empty( $tags_array ) || ! is_array( $tags_array ) || ! $post_id ) {
|
||||
if ( empty( $tags_array ) || ! $post_id ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
namespace Event_Bridge_For_ActivityPub\ActivityPub\Transmogrifier;
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
use Activitypub\Activity\Extended_Object\Event;
|
||||
use Activitypub\Activity\Extended_Object\Place;
|
||||
@ -77,7 +77,7 @@ class VS_Event_List extends Base {
|
||||
$tags_array = $activitypub_event->get_tag();
|
||||
|
||||
// Ensure the input is valid.
|
||||
if ( empty( $tags_array ) || ! is_array( $tags_array ) || ! $post_id ) {
|
||||
if ( empty( $tags_array ) || ! $post_id ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
namespace Event_Bridge_For_ActivityPub\ActivityPub\Transmogrifier\Helper;
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
use Activitypub\Activity\Extended_Object\Event;
|
||||
use Activitypub\Activity\Extended_Object\Place;
|
||||
@ -67,6 +67,10 @@ class Sanitizer {
|
||||
$event->set_end_time( \sanitize_text_field( $data['endTime'] ) );
|
||||
}
|
||||
|
||||
if ( isset( $data['timezone'] ) && in_array( $data['timezone'], \DateTimeZone::listIdentifiers(), true ) ) {
|
||||
$event->set_timezone( \sanitize_text_field( $data['timezone'] ) );
|
||||
}
|
||||
|
||||
if ( isset( $data['published'] ) ) {
|
||||
$event->set_published( \sanitize_text_field( $data['published'] ) );
|
||||
}
|
||||
@ -177,6 +181,17 @@ class Sanitizer {
|
||||
return array_is_list( $arr );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitize an validate a float.
|
||||
*
|
||||
* @param mixed $value The input value.
|
||||
* @return float|null
|
||||
*/
|
||||
private static function validate_and_sanitize_float( $value ) {
|
||||
$sanitized = filter_var( $value, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION );
|
||||
return is_numeric( $sanitized ) ? (float) $sanitized : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert input array to an Location.
|
||||
*
|
||||
@ -189,9 +204,18 @@ class Sanitizer {
|
||||
return null;
|
||||
}
|
||||
|
||||
// If the array is a list, work with the first item.
|
||||
if ( array_key_exists( 0, $data ) ) {
|
||||
$data = $data[0];
|
||||
// If the array is a list, search for the first item with 'type' === 'Place'.
|
||||
if ( self::array_is_list( $data ) ) {
|
||||
foreach ( $data as $item ) {
|
||||
if ( is_array( $item ) && ( 'Place' === ( $item['type'] ?? null ) ) ) {
|
||||
$data = $item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! isset( $data['type'] ) || 'Place' !== $data['type'] ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$place = new Place();
|
||||
@ -204,6 +228,14 @@ class Sanitizer {
|
||||
$place->set_id( \sanitize_url( $data['id'] ) );
|
||||
}
|
||||
|
||||
if ( isset( $data['latitude'] ) ) {
|
||||
$place->set_latitude( self::validate_and_sanitize_float( $data['latitude'] ) );
|
||||
}
|
||||
|
||||
if ( isset( $data['longitude'] ) ) {
|
||||
$place->set_longitude( self::validate_and_sanitize_float( $data['longitude'] ) );
|
||||
}
|
||||
|
||||
if ( isset( $data['url'] ) ) {
|
||||
$place->set_url( \sanitize_url( $data['url'] ) );
|
||||
}
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
namespace Event_Bridge_For_ActivityPub\ActivityPub\Transmogrifier\Helper;
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
/**
|
||||
* Extending the Tribe Events API to allow setting of the guid.
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
namespace Event_Bridge_For_ActivityPub\ActivityPub\Transmogrifier\Helper;
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
/**
|
||||
* Extending the Organizer Venue API to allow setting of the guid.
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
namespace Event_Bridge_For_ActivityPub\ActivityPub\Transmogrifier\Helper;
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
/**
|
||||
* Extending the Tribe Venue API to allow setting of the guid.
|
||||
@ -29,6 +29,30 @@ class The_Events_Calendar_Venue_Repository extends \Tribe__Events__Repositories_
|
||||
'comment_count',
|
||||
);
|
||||
|
||||
/**
|
||||
* Tribe__Events__Repositories__Venue constructor.
|
||||
*
|
||||
* Add aliases for longitude an latitude.
|
||||
*
|
||||
* @since 4.9
|
||||
* @since 6.10.1 Added `show_map` and `show_map_link` aliases.
|
||||
*/
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
|
||||
// Add venue specific aliases.
|
||||
$this->update_fields_aliases = array_merge(
|
||||
$this->update_fields_aliases,
|
||||
array(
|
||||
'latitude' => '_VenueLat',
|
||||
'longitude' => '_VenueLng',
|
||||
)
|
||||
);
|
||||
|
||||
$this->add_simple_meta_schema_entry( 'latitude', '_VenueLat' );
|
||||
$this->add_simple_meta_schema_entry( 'longitude', '_VenueLng' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the current key can be updated by this repository or not.
|
||||
*
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
namespace Event_Bridge_For_ActivityPub\Admin;
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
use Event_Bridge_For_ActivityPub\Integrations\Event_Plugin_Integration;
|
||||
|
||||
@ -49,7 +49,7 @@ class Event_Plugin_Admin_Notices {
|
||||
* @return bool
|
||||
*/
|
||||
private function event_post_type_is_not_activitypub_enabled(): bool {
|
||||
return ! in_array( $this->event_plugin::get_post_type(), get_option( 'activitypub_support_post_types', array() ), true );
|
||||
return ! \in_array( $this->event_plugin::get_post_type(), get_option( 'activitypub_support_post_types', array() ), true );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -79,7 +79,7 @@ class Event_Plugin_Admin_Notices {
|
||||
return;
|
||||
}
|
||||
$activitypub_plugin_data = get_plugin_data( ACTIVITYPUB_PLUGIN_FILE );
|
||||
$notice = sprintf(
|
||||
$notice = \sprintf(
|
||||
/* translators: 1: the name of the event plugin a admin notice is shown. 2: The name of the ActivityPub plugin. */
|
||||
_x(
|
||||
'You have installed the <i>%1$s</i> plugin, but the event post type of the plugin <i>%2$s</i> is <b>not enabled</b> in the <a href="%3$s">%1$s settings</a>.',
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
namespace Event_Bridge_For_ActivityPub\Admin;
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
/**
|
||||
* Class responsible for general admin notices.
|
||||
@ -52,7 +52,7 @@ class General_Admin_Notices {
|
||||
* @return string
|
||||
*/
|
||||
public static function get_admin_notice_activitypub_plugin_not_enabled(): string {
|
||||
return sprintf(
|
||||
return \sprintf(
|
||||
/* translators: 1: An URL that points to the ActivityPub plugin. */
|
||||
_x(
|
||||
'For the Event Bridge for ActivityPub to work, you will need to install and activate the <a href="%1$s">ActivityPub</a> plugin.',
|
||||
@ -69,7 +69,7 @@ class General_Admin_Notices {
|
||||
* @return string
|
||||
*/
|
||||
public static function get_admin_notice_activitypub_plugin_version_too_old(): string {
|
||||
return sprintf(
|
||||
return \sprintf(
|
||||
/* translators: 1: The name of the ActivityPub plugin. 2: The minimum required version number of the ActivityPub plugin. */
|
||||
_x(
|
||||
'Please upgrade your <a href="%1$s">ActivityPub</a> plugin. At least version %2$s is required for the Event Bridge for ActivityPub to work.',
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
namespace Event_Bridge_For_ActivityPub\Admin;
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
use Activitypub\Transformer\Factory as Transformer_Factory;
|
||||
use Event_Bridge_For_ActivityPub\Integrations\Event_Plugin_Integration;
|
||||
@ -90,10 +90,6 @@ class Health_Check {
|
||||
* @return bool True if the check passed.
|
||||
*/
|
||||
public static function test_if_event_transformer_is_used( $event_plugin ): bool {
|
||||
if ( ! Setup::get_instance()->is_activitypub_plugin_active() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get a (random) event post.
|
||||
$event_posts = self::get_most_recent_event_posts( $event_plugin->get_post_type(), 1 );
|
||||
|
||||
@ -121,10 +117,6 @@ class Health_Check {
|
||||
* @return \WP_Post[] Array of event posts, or false if none are found.
|
||||
*/
|
||||
public static function get_most_recent_event_posts( $event_post_type = null, $number_of_posts = 5 ): array {
|
||||
if ( ! Setup::get_instance()->is_activitypub_plugin_active() ) {
|
||||
return array();
|
||||
}
|
||||
|
||||
if ( ! $event_post_type ) {
|
||||
$active_event_plugins = Setup::get_instance()->get_active_event_plugins();
|
||||
$active_event_plugin = reset( $active_event_plugins );
|
||||
@ -141,6 +133,7 @@ class Health_Check {
|
||||
'order' => 'DESC',
|
||||
'include' => array(),
|
||||
'exclude' => array(),
|
||||
// phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
|
||||
'meta_query' => array(
|
||||
'relation' => 'OR',
|
||||
array(
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
namespace Event_Bridge_For_ActivityPub\Admin;
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
use Activitypub\Webfinger;
|
||||
use Event_Bridge_For_ActivityPub\ActivityPub\Model\Event_Source;
|
||||
@ -69,7 +69,7 @@ class Settings_Page {
|
||||
* @return void
|
||||
*/
|
||||
public static function maybe_add_event_source() {
|
||||
if ( ! isset( $_POST['event_bridge_for_activitypub_add_event_source'] ) ) {
|
||||
if ( ! \array_key_exists( '_wpnonce', $_REQUEST ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -78,11 +78,15 @@ class Settings_Page {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! isset( $_POST['event_bridge_for_activitypub_add_event_source'] ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! \current_user_can( 'manage_options' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$event_source = \sanitize_text_field( $_POST['event_bridge_for_activitypub_add_event_source'] );
|
||||
$event_source = \sanitize_text_field( \wp_unslash( $_POST['event_bridge_for_activitypub_add_event_source'] ) );
|
||||
|
||||
$actor_url = false;
|
||||
$url = \wp_parse_url( $event_source );
|
||||
@ -203,13 +207,13 @@ class Settings_Page {
|
||||
private static function get_event_terms( $event_plugin ): array {
|
||||
$taxonomy = $event_plugin::get_event_category_taxonomy();
|
||||
if ( $taxonomy ) {
|
||||
$event_terms = get_terms(
|
||||
$event_terms = \get_terms(
|
||||
array(
|
||||
'taxonomy' => $taxonomy,
|
||||
'hide_empty' => true,
|
||||
)
|
||||
);
|
||||
return ! is_wp_error( $event_terms ) ? $event_terms : array();
|
||||
return ! \is_wp_error( $event_terms ) ? $event_terms : array();
|
||||
} else {
|
||||
return array();
|
||||
}
|
||||
|
||||
@ -9,10 +9,11 @@
|
||||
|
||||
namespace Event_Bridge_For_ActivityPub\Admin;
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
use WP_Post;
|
||||
|
||||
// Exit if accessed directly.
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
use Event_Bridge_For_ActivityPub\ActivityPub\Model\Event_Source;
|
||||
use Event_Bridge_For_ActivityPub\ActivityPub\Collection\Event_Sources as Event_Sources_Collection;
|
||||
use Event_Bridge_For_ActivityPub\Event_Sources;
|
||||
|
||||
@ -39,7 +40,7 @@ class User_Interface {
|
||||
* @param array $columns The current columns.
|
||||
* @return array
|
||||
*/
|
||||
public static function add_origin_column( $columns ) {
|
||||
public static function add_origin_column( array $columns ) {
|
||||
// Add a new column after the title column.
|
||||
$columns['activitypub_origin'] = __( 'ActivityPub origin', 'event-bridge-for-activitypub' );
|
||||
return $columns;
|
||||
@ -48,12 +49,12 @@ class User_Interface {
|
||||
/**
|
||||
* Add a "⁂ Preview" link to the row actions.
|
||||
*
|
||||
* @param array $actions The existing actions.
|
||||
* @param \WP_Post $post The post object.
|
||||
* @param array $actions The existing actions.
|
||||
* @param WP_Post $post The post object.
|
||||
*
|
||||
* @return array The modified actions.
|
||||
*/
|
||||
public static function row_actions( $actions, $post ): array {
|
||||
public static function row_actions( array $actions, WP_Post $post ): array {
|
||||
// check if the post is enabled for ActivityPub.
|
||||
if ( ! Event_Sources::is_cached_external_post( $post ) ) {
|
||||
return $actions;
|
||||
@ -67,7 +68,7 @@ class User_Interface {
|
||||
$url = \get_post_meta( $parent->ID, '_activitypub_actor_id', true );
|
||||
}
|
||||
|
||||
$actions['view_origin'] = sprintf(
|
||||
$actions['view_origin'] = \sprintf(
|
||||
'<a href="%s" target="_blank">⁂ %s</a>',
|
||||
\esc_url( $url ),
|
||||
\esc_html__( 'Open original page', 'event-bridge-for-activitypub' )
|
||||
@ -79,14 +80,14 @@ class User_Interface {
|
||||
/**
|
||||
* Modify the user capabilities so that nobody can edit external events.
|
||||
*
|
||||
* @param array $caps Concerned user's capabilities.
|
||||
* @param mixed $cap Required primitive capabilities for the requested capability.
|
||||
* @param array $user_id The WordPress user ID.
|
||||
* @param array $args Additional args.
|
||||
* @param string[] $caps Concerned user's capabilities.
|
||||
* @param string $cap Required primitive capabilities for the requested capability.
|
||||
* @param int $user_id The WordPress user ID.
|
||||
* @param array $args Additional args.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function disable_editing_for_external_events( $caps, $cap, $user_id, $args ) {
|
||||
public static function disable_editing_for_external_events( array $caps, string $cap, int $user_id, array $args ) {
|
||||
if ( 'edit_post' === $cap && isset( $args[0] ) ) {
|
||||
$post_id = $args[0];
|
||||
$post = get_post( $post_id );
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
namespace Event_Bridge_For_ActivityPub;
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
/**
|
||||
* Class Autoloader.
|
||||
@ -37,7 +37,7 @@ class Autoloader {
|
||||
$base_dir = EVENT_BRIDGE_FOR_ACTIVITYPUB_PLUGIN_DIR . '/includes/';
|
||||
$base = 'Event_Bridge_For_ActivityPub\\';
|
||||
|
||||
if ( strncmp( $full_class, $base, strlen( $base ) ) === 0 ) {
|
||||
if ( strncmp( $full_class, $base, \strlen( $base ) ) === 0 ) {
|
||||
$maybe_uppercase = str_replace( $base, '', $full_class );
|
||||
$class = strtolower( $maybe_uppercase );
|
||||
// All classes should be capitalized. If this is instead looking for a lowercase method, we ignore that.
|
||||
@ -58,7 +58,7 @@ class Autoloader {
|
||||
if ( file_exists( $file ) && is_readable( $file ) ) {
|
||||
require_once $file;
|
||||
} else {
|
||||
\wp_die( sprintf( esc_html( 'Required class not found or not readable: %s' ), esc_html( $full_class ) ) );
|
||||
\wp_die( \sprintf( esc_html( 'Required class not found or not readable: %s' ), esc_html( $full_class ) ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
namespace Event_Bridge_For_ActivityPub;
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
/**
|
||||
* Debug Class.
|
||||
@ -24,7 +24,7 @@ class Debug {
|
||||
* Initialize the class, registering WordPress hooks.
|
||||
*/
|
||||
public static function init() {
|
||||
if ( defined( 'WP_DEBUG_LOG' ) && constant( 'WP_DEBUG_LOG' ) ) {
|
||||
if ( \defined( 'WP_DEBUG_LOG' ) && constant( 'WP_DEBUG_LOG' ) && ! getenv( 'WP_TESTS_DIR' ) ) {
|
||||
\add_action( 'event_bridge_for_activitypub_write_log', array( self::class, 'write_log' ), 10, 1 );
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
namespace Event_Bridge_For_ActivityPub;
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
use Activitypub\Model\Blog;
|
||||
use DateTime;
|
||||
@ -34,7 +34,7 @@ class Event_Sources {
|
||||
/**
|
||||
* Init.
|
||||
*/
|
||||
public static function init() {
|
||||
public static function init(): void {
|
||||
// Register the Event Sources Collection which takes care of managing the event sources.
|
||||
\add_action( 'init', array( Event_Sources_Collection::class, 'init' ) );
|
||||
|
||||
@ -87,7 +87,7 @@ class Event_Sources {
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function register_post_meta() {
|
||||
public static function register_post_meta(): void {
|
||||
$setup = Setup::get_instance();
|
||||
|
||||
foreach ( $setup->get_active_event_plugins() as $event_plugin_integration ) {
|
||||
@ -116,7 +116,7 @@ class Event_Sources {
|
||||
* @param string $post_type The post type to register the meta for.
|
||||
* @return void
|
||||
*/
|
||||
private static function register_post_meta_event_bridge_for_activitypub_event_source( $post_type ) {
|
||||
private static function register_post_meta_event_bridge_for_activitypub_event_source( string $post_type ): void {
|
||||
\register_post_meta(
|
||||
$post_type,
|
||||
'_event_bridge_for_activitypub_event_source',
|
||||
@ -132,9 +132,9 @@ class Event_Sources {
|
||||
* 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.
|
||||
* @return string|false The URL/ID of the application actor, false if not found.
|
||||
*/
|
||||
public static function get_application_actor( $domain ) {
|
||||
public static function get_application_actor( string $domain ): string|false {
|
||||
$result = wp_remote_get( 'https://' . $domain . '/.well-known/nodeinfo' );
|
||||
|
||||
if ( is_wp_error( $result ) ) {
|
||||
@ -146,11 +146,11 @@ class Event_Sources {
|
||||
$nodeinfo = json_decode( $body, true );
|
||||
|
||||
// Check if 'links' exists and is an array.
|
||||
if ( isset( $nodeinfo['links'] ) && is_array( $nodeinfo['links'] ) ) {
|
||||
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'] ) ) {
|
||||
if ( \is_string( $link['href'] ) ) {
|
||||
return $link['href'];
|
||||
}
|
||||
break;
|
||||
@ -172,7 +172,7 @@ class Event_Sources {
|
||||
* @param WP_Post $post The WordPress post object.
|
||||
* @return bool False if the post is not disabled for federation via ActivityPub.
|
||||
*/
|
||||
public static function is_post_disabled_for_activitypub( $disabled, $post = null ): bool {
|
||||
public static function is_post_disabled_for_activitypub( bool $disabled, WP_Post $post ): bool {
|
||||
if ( $disabled ) {
|
||||
return $disabled;
|
||||
}
|
||||
@ -185,7 +185,7 @@ class Event_Sources {
|
||||
* @param WP_Post|int $post The WordPress post object or post ID.
|
||||
* @return bool
|
||||
*/
|
||||
public static function is_cached_external_post( $post ): bool {
|
||||
public static function is_cached_external_post( WP_Post|int $post ): bool {
|
||||
$post_id = $post instanceof WP_Post ? $post->ID : $post;
|
||||
|
||||
if ( \get_post_meta( $post_id, '_event_bridge_for_activitypub_event_source', true ) ) {
|
||||
@ -196,13 +196,13 @@ class Event_Sources {
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the ActivityPub template for EventPrime.
|
||||
* Maybe redirect cached external events to origin.
|
||||
*
|
||||
* @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 ) {
|
||||
public static function redirect_activitypub_requests_for_cached_external_events( string $template ) {
|
||||
if ( \defined( 'REST_REQUEST' ) && REST_REQUEST ) {
|
||||
return $template;
|
||||
}
|
||||
|
||||
@ -259,7 +259,7 @@ class Event_Sources {
|
||||
*
|
||||
* @return array The array of following urls.
|
||||
*/
|
||||
public static function add_event_sources_to_follow_collection( $follow_list, $user ): array {
|
||||
public static function add_event_sources_to_follow_collection( array $follow_list, mixed $user ): array {
|
||||
if ( ! $user instanceof Blog ) {
|
||||
return $follow_list;
|
||||
}
|
||||
@ -274,7 +274,7 @@ class Event_Sources {
|
||||
*
|
||||
* @return array A list with all unique hosts of all Event Sources' ActivityPub IDs.
|
||||
*/
|
||||
public static function get_event_sources_hosts() {
|
||||
public static function get_event_sources_hosts(): array {
|
||||
$hosts = get_transient( 'event_bridge_for_activitypub_event_sources_hosts' );
|
||||
|
||||
if ( $hosts ) {
|
||||
@ -304,7 +304,7 @@ class Event_Sources {
|
||||
* @param array $hosts The hosts before the filter.
|
||||
* @return array
|
||||
*/
|
||||
public static function add_event_sources_hosts_to_allowed_redirect_hosts( $hosts ) {
|
||||
public static function add_event_sources_hosts_to_allowed_redirect_hosts( array $hosts ): array {
|
||||
$event_sources_hosts = self::get_event_sources_hosts();
|
||||
return array_merge( $hosts, $event_sources_hosts );
|
||||
}
|
||||
@ -313,18 +313,18 @@ class Event_Sources {
|
||||
* Mark incoming accept activities as valid.
|
||||
*
|
||||
* @param bool $valid The validation state.
|
||||
* @param string $param The object parameter.
|
||||
* @param mixed $param The object parameter.
|
||||
* @param WP_REST_Request $request The request object.
|
||||
*
|
||||
* @return bool|WP_Error The validation state: true if valid, false if not.
|
||||
*/
|
||||
public static function validate_activity( $valid, $param, $request ) {
|
||||
public static function validate_activity( bool $valid, mixed $param, WP_REST_Request $request ) {
|
||||
if ( $valid ) {
|
||||
return $valid;
|
||||
}
|
||||
$json_params = $request->get_json_params();
|
||||
|
||||
if ( isset( $json_params['object']['type'] ) && in_array( $json_params['object']['type'], array( 'Accept', 'Undo' ), true ) ) {
|
||||
if ( isset( $json_params['object']['type'] ) && \in_array( $json_params['object']['type'], array( 'Accept', 'Undo' ), true ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -335,12 +335,12 @@ class Event_Sources {
|
||||
* Validate the event object.
|
||||
*
|
||||
* @param bool $valid The validation state.
|
||||
* @param string $param The object parameter.
|
||||
* @param mixed $param The object parameter.
|
||||
* @param WP_REST_Request $request The request object.
|
||||
*
|
||||
* @return bool|WP_Error The validation state: true if valid, false if not.
|
||||
*/
|
||||
public static function validate_event_object( $valid, $param, $request ) {
|
||||
public static function validate_event_object( bool $valid, mixed $param, WP_REST_Request $request ): bool|WP_Error {
|
||||
$json_params = $request->get_json_params();
|
||||
|
||||
// Check if we should continue with the validation.
|
||||
@ -379,7 +379,7 @@ class Event_Sources {
|
||||
* @param string ...$urls List of URLs to compare.
|
||||
* @return bool True if all URLs have the same host, false otherwise.
|
||||
*/
|
||||
public static function same_host( ...$urls ) {
|
||||
public static function same_host( string ...$urls ): bool {
|
||||
if ( empty( $urls ) ) {
|
||||
return false; // No URLs given, can't compare hosts.
|
||||
}
|
||||
@ -412,8 +412,8 @@ class Event_Sources {
|
||||
* @param mixed $event_object The (event) object as an associative array.
|
||||
* @return bool True if the object is an valid ActivityPub Event, false if not.
|
||||
*/
|
||||
public static function is_valid_activitypub_event_object( $event_object ): bool {
|
||||
if ( ! is_array( $event_object ) ) {
|
||||
public static function is_valid_activitypub_event_object( mixed $event_object ): bool {
|
||||
if ( ! \is_array( $event_object ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -446,7 +446,7 @@ class Event_Sources {
|
||||
* @param string $id The ID to validate.
|
||||
* @return bool
|
||||
*/
|
||||
public static function is_valid_activitypub_id( $id ) {
|
||||
public static function is_valid_activitypub_id( string $id ): bool {
|
||||
return \sanitize_url( $id ) ? true : false;
|
||||
}
|
||||
|
||||
@ -469,7 +469,7 @@ class Event_Sources {
|
||||
* @param string|DateTime $time The ActivityPub like time string or DateTime object.
|
||||
* @return bool
|
||||
*/
|
||||
public static function is_time_passed( $time ) {
|
||||
public static function is_time_passed( string|DateTime $time ): bool {
|
||||
if ( ! $time instanceof DateTime ) {
|
||||
// Create a DateTime object from the ActivityPub time string.
|
||||
$time = new DateTime( $time, new DateTimeZone( 'UTC' ) );
|
||||
@ -488,7 +488,7 @@ class Event_Sources {
|
||||
* @param array $event_object The ActivityPub Event as an associative array.
|
||||
* @return bool
|
||||
*/
|
||||
public static function is_ongoing_or_future_event( $event_object ) {
|
||||
public static function is_ongoing_or_future_event( array $event_object ): bool {
|
||||
if ( isset( $event_object['endTime'] ) ) {
|
||||
$time = $event_object['endTime'];
|
||||
} else {
|
||||
@ -504,9 +504,9 @@ class Event_Sources {
|
||||
* @param string $actor_id The actor ID.
|
||||
* @return bool True if the ActivityPub actor ID is followed, false otherwise.
|
||||
*/
|
||||
public static function actor_is_event_source( $actor_id ) {
|
||||
public static function actor_is_event_source( string $actor_id ): bool {
|
||||
$event_sources = Event_Sources_Collection::get_event_sources();
|
||||
if ( in_array( $actor_id, $event_sources, true ) ) {
|
||||
if ( \in_array( $actor_id, $event_sources, true ) ) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
namespace Event_Bridge_For_ActivityPub;
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
use Activitypub\Http;
|
||||
use Event_Bridge_For_ActivityPub\ActivityPub\Model\Event_Source;
|
||||
@ -31,7 +31,7 @@ class Outbox_Parser {
|
||||
/**
|
||||
* Maximum number of events to backfill per actor.
|
||||
*/
|
||||
const MAX_EVENTS_TO_IMPORT = 20;
|
||||
public const MAX_EVENTS_TO_IMPORT = 20;
|
||||
|
||||
/**
|
||||
* Init actions.
|
||||
@ -48,7 +48,7 @@ class Outbox_Parser {
|
||||
* @param int $event_source_post_id The Post ID of Event Source we want to backfill the events for.
|
||||
* @return void
|
||||
*/
|
||||
public static function backfill_events( $event_source_post_id ): void {
|
||||
public static function backfill_events( int $event_source_post_id ): void {
|
||||
$event_source = Event_Source::get_by_id( $event_source_post_id );
|
||||
|
||||
if ( ! $event_source ) {
|
||||
@ -72,12 +72,7 @@ class Outbox_Parser {
|
||||
* @param int $event_source_post_id The Post ID of the Event Source that owns the outbox.
|
||||
* @return void
|
||||
*/
|
||||
public static function import_events_from_outbox( $url, $event_source_post_id ) {
|
||||
$setup = Setup::get_instance();
|
||||
if ( ! $setup->is_activitypub_plugin_active() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
public static function import_events_from_outbox( string $url, int $event_source_post_id ): void {
|
||||
$outbox = self::fetch_outbox( $url );
|
||||
|
||||
if ( ! $outbox ) {
|
||||
@ -91,7 +86,7 @@ class Outbox_Parser {
|
||||
}
|
||||
|
||||
// Process orderedItems if they exist (non-paginated outbox).
|
||||
if ( isset( $outbox['orderedItems'] ) && is_array( $outbox['orderedItems'] ) ) {
|
||||
if ( isset( $outbox['orderedItems'] ) && \is_array( $outbox['orderedItems'] ) ) {
|
||||
$current_count += self::import_events_from_items(
|
||||
$outbox['orderedItems'],
|
||||
$event_source_post_id,
|
||||
@ -120,11 +115,11 @@ class Outbox_Parser {
|
||||
* @param array $activity The Activity as associative array.
|
||||
* @return bool
|
||||
*/
|
||||
private static function is_create_or_update_activity( $activity ) {
|
||||
private static function is_create_or_update_activity( array $activity ): bool {
|
||||
if ( ! isset( $activity['type'] ) ) {
|
||||
return false;
|
||||
}
|
||||
if ( in_array( $activity['type'], array( 'Update', 'Create' ), true ) ) {
|
||||
if ( \in_array( $activity['type'], array( 'Update', 'Create' ), true ) ) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -137,12 +132,12 @@ class Outbox_Parser {
|
||||
* @param int $max_items The maximum number of items to parse.
|
||||
* @return array Parsed events from the collection.
|
||||
*/
|
||||
private static function parse_outbox_items_for_events( $items, $max_items ) {
|
||||
private static function parse_outbox_items_for_events( array $items, int $max_items ): array {
|
||||
$parsed_events = array();
|
||||
|
||||
foreach ( $items as $activity ) {
|
||||
// Abort if we have exceeded the maximal events to return.
|
||||
if ( $max_items > 0 && count( $parsed_events ) >= $max_items ) {
|
||||
if ( $max_items > 0 && \count( $parsed_events ) >= $max_items ) {
|
||||
break;
|
||||
}
|
||||
|
||||
@ -179,7 +174,7 @@ class Outbox_Parser {
|
||||
* @param int $limit The limit of how many events to save locally.
|
||||
* @return int The number of saved events (at least attempted).
|
||||
*/
|
||||
private static function import_events_from_items( $items, $event_source_post_id, $limit = -1 ): int {
|
||||
private static function import_events_from_items( array $items, int $event_source_post_id, int $limit = -1 ): int {
|
||||
$events = self::parse_outbox_items_for_events( $items, $limit );
|
||||
|
||||
$transmogrifier = Setup::get_transmogrifier();
|
||||
@ -209,7 +204,7 @@ class Outbox_Parser {
|
||||
* @param int $delay The delay of the current time in seconds.
|
||||
* @return bool
|
||||
*/
|
||||
private static function queue_importing_from_outbox( $url, $event_source_post_id, $delay = 10 ): bool {
|
||||
private static function queue_importing_from_outbox( string $url, int $event_source_post_id, int $delay = 10 ): bool {
|
||||
$hook = 'event_bridge_for_activitypub_import_events_from_outbox';
|
||||
$args = array( $url, $event_source_post_id );
|
||||
|
||||
@ -237,7 +232,7 @@ class Outbox_Parser {
|
||||
* @param int $count The new count of imported events.
|
||||
* @return void
|
||||
*/
|
||||
private static function update_import_count( $event_source_post_id, $count ) {
|
||||
private static function update_import_count( int $event_source_post_id, int $count ): void {
|
||||
\update_post_meta( $event_source_post_id, '_event_bridge_for_activitypub_event_count', $count );
|
||||
}
|
||||
|
||||
@ -247,7 +242,7 @@ class Outbox_Parser {
|
||||
* @param string $url The URL of the outbox.
|
||||
* @return array|null The decoded outbox data, or null if fetching fails.
|
||||
*/
|
||||
private static function fetch_outbox( $url ) {
|
||||
private static function fetch_outbox( string $url ): ?array {
|
||||
$response = Http::get( $url );
|
||||
|
||||
if ( \is_wp_error( $response ) ) {
|
||||
@ -266,9 +261,9 @@ class Outbox_Parser {
|
||||
* @param array $outbox The outbox data.
|
||||
* @return string|null The pagination URL, or null if not found.
|
||||
*/
|
||||
private static function get_pagination_url( $outbox ) {
|
||||
private static function get_pagination_url( array $outbox ): ?string {
|
||||
// If we are on a collection page simply use the next key.
|
||||
if ( 'OrderedCollectionPage' === $outbox['type'] && ! empty( $outbox['next'] ) && is_string( $outbox['next'] ) ) {
|
||||
if ( 'OrderedCollectionPage' === $outbox['type'] && ! empty( $outbox['next'] ) && \is_string( $outbox['next'] ) ) {
|
||||
return $outbox['next'];
|
||||
}
|
||||
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
namespace Event_Bridge_For_ActivityPub;
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
/**
|
||||
* Class for initializing the custom ActivityPub preview(s).
|
||||
@ -31,7 +31,7 @@ class Preview {
|
||||
public static function maybe_apply_event_preview_template() {
|
||||
$event_post_types = Setup::get_instance()->get_active_event_plugins_post_types();
|
||||
|
||||
if ( in_array( \get_post_type(), $event_post_types, true ) ) {
|
||||
if ( \in_array( \get_post_type(), $event_post_types, true ) ) {
|
||||
return EVENT_BRIDGE_FOR_ACTIVITYPUB_PLUGIN_DIR . '/templates/event-preview.php';
|
||||
}
|
||||
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
namespace Event_Bridge_For_ActivityPub;
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
use Activitypub\Transformer\Factory as Transformer_Factory;
|
||||
use Event_Bridge_For_ActivityPub\Setup;
|
||||
@ -21,7 +21,7 @@ use DateTime;
|
||||
use WP_Post;
|
||||
|
||||
use function ActivityPub\add_to_outbox;
|
||||
use function Activitypub\is_user_disabled;
|
||||
use function Activitypub\user_can_activitypub;
|
||||
|
||||
/**
|
||||
* Adds automatic announcing or sending of reminders before the events start time.
|
||||
@ -71,7 +71,7 @@ class Reminder {
|
||||
// Check for our supported post types.
|
||||
$current_screen = \get_current_screen();
|
||||
$event_post_types = Setup::get_instance()->get_active_event_plugins_post_types();
|
||||
if ( ! $current_screen || ! in_array( $current_screen->post_type, $event_post_types, true ) ) {
|
||||
if ( ! $current_screen || ! \in_array( $current_screen->post_type, $event_post_types, true ) ) {
|
||||
return;
|
||||
}
|
||||
$asset_data = include EVENT_BRIDGE_FOR_ACTIVITYPUB_PLUGIN_DIR . 'build/reminder/plugin.asset.php';
|
||||
@ -91,11 +91,11 @@ class Reminder {
|
||||
/**
|
||||
* Schedule Activities.
|
||||
*
|
||||
* @param string $new_status New post status.
|
||||
* @param string $old_status Old post status.
|
||||
* @param ?WP_Post $post Post object.
|
||||
* @param string $new_status New post status.
|
||||
* @param string $old_status Old post status.
|
||||
* @param WP_Post|null $post Post object.
|
||||
*/
|
||||
public static function maybe_schedule_event_reminder( $new_status, $old_status, $post ): void {
|
||||
public static function maybe_schedule_event_reminder( string $new_status, string $old_status, WP_Post|null $post ): void {
|
||||
if ( ! $post instanceof WP_Post ) {
|
||||
return;
|
||||
}
|
||||
@ -170,7 +170,7 @@ class Reminder {
|
||||
*
|
||||
* @param int $post_id The WordPress post ID of the event post.
|
||||
*/
|
||||
public static function send_event_reminder( $post_id ) {
|
||||
public static function send_event_reminder( int $post_id ): void {
|
||||
$post = \get_post( $post_id );
|
||||
|
||||
$transformer = Transformer_Factory::get_transformer( $post );
|
||||
@ -182,7 +182,7 @@ class Reminder {
|
||||
$actor = $transformer->get_actor_object();
|
||||
$user_id = $actor->get__id();
|
||||
|
||||
if ( $user_id > 0 && is_user_disabled( $user_id ) ) {
|
||||
if ( $user_id > 0 && ! user_can_activitypub( $user_id ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -14,7 +14,7 @@ namespace Event_Bridge_For_ActivityPub;
|
||||
use Event_Bridge_For_ActivityPub\ActivityPub\Collection\Event_Sources;
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
use Event_Bridge_For_ActivityPub\Integrations\Feature_Event_Sources;
|
||||
|
||||
@ -26,14 +26,14 @@ use Event_Bridge_For_ActivityPub\Integrations\Feature_Event_Sources;
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class Settings {
|
||||
const SETTINGS_SLUG = 'event-bridge-for-activitypub';
|
||||
public const SETTINGS_SLUG = 'event-bridge-for-activitypub';
|
||||
|
||||
/**
|
||||
* The default ActivityPub event category.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const DEFAULT_EVENT_CATEGORY = 'MEETING';
|
||||
private const DEFAULT_EVENT_CATEGORY = 'MEETING';
|
||||
|
||||
/**
|
||||
* Register the settings for the Event Bridge for ActivityPub plugin.
|
||||
@ -168,10 +168,11 @@ class Settings {
|
||||
/**
|
||||
* Do not allow the event sources feature to get deactivated, when event sources are still followed.
|
||||
*
|
||||
* @param mixed $value The optios value.
|
||||
* @param mixed $value The options value.
|
||||
* @return bool
|
||||
*/
|
||||
public static function sanitize_event_sources_feature_active( $value ) {
|
||||
$count = count( Event_Sources::get_event_sources() );
|
||||
public static function sanitize_event_sources_feature_active( mixed $value ): bool {
|
||||
$count = \count( Event_Sources::get_event_sources() );
|
||||
|
||||
$value = (bool) $value;
|
||||
|
||||
@ -198,7 +199,7 @@ class Settings {
|
||||
* @return string
|
||||
*/
|
||||
public static function sanitize_event_plugin_integration_used_for_event_sources( $event_plugin_integration ): string {
|
||||
if ( ! is_string( $event_plugin_integration ) ) {
|
||||
if ( ! \is_string( $event_plugin_integration ) ) {
|
||||
return '';
|
||||
}
|
||||
$setup = Setup::get_instance();
|
||||
@ -207,10 +208,10 @@ class Settings {
|
||||
$valid_options = array();
|
||||
foreach ( $active_event_plugins as $active_event_plugin ) {
|
||||
if ( $active_event_plugin instanceof Feature_Event_Sources ) {
|
||||
$valid_options[] = get_class( $active_event_plugin );
|
||||
$valid_options[] = \get_class( $active_event_plugin );
|
||||
}
|
||||
}
|
||||
if ( in_array( $event_plugin_integration, $valid_options, true ) ) {
|
||||
if ( \in_array( $event_plugin_integration, $valid_options, true ) ) {
|
||||
return $event_plugin_integration;
|
||||
}
|
||||
return Setup::get_default_integration_class_name_used_for_event_sources_feature();
|
||||
@ -220,8 +221,9 @@ class Settings {
|
||||
* Sanitize the target ActivityPub Event category.
|
||||
*
|
||||
* @param string $event_category The ActivityPUb event category.
|
||||
* @return string
|
||||
*/
|
||||
public static function sanitize_mapped_event_category( $event_category ): string {
|
||||
public static function sanitize_mapped_event_category( string $event_category ): string {
|
||||
return self::is_allowed_event_category( $event_category ) ? $event_category : self::DEFAULT_EVENT_CATEGORY;
|
||||
}
|
||||
|
||||
@ -231,10 +233,9 @@ class Settings {
|
||||
* Currently only the default event categories are allowed to be target of a mapping.
|
||||
*
|
||||
* @param array $event_category_mappings The settings value.
|
||||
*
|
||||
* @return array An array that contains only valid mapping pairs.
|
||||
*/
|
||||
public static function sanitize_event_category_mappings( $event_category_mappings ): array {
|
||||
public static function sanitize_event_category_mappings( array $event_category_mappings ): array {
|
||||
if ( empty( $event_category_mappings ) ) {
|
||||
return array();
|
||||
}
|
||||
@ -253,9 +254,9 @@ class Settings {
|
||||
*
|
||||
* @return bool True if allowed, false otherwise.
|
||||
*/
|
||||
private static function is_allowed_event_category( $event_category ): bool {
|
||||
private static function is_allowed_event_category( string $event_category ): bool {
|
||||
require_once EVENT_BRIDGE_FOR_ACTIVITYPUB_PLUGIN_DIR . '/includes/event-categories.php';
|
||||
$allowed_event_categories = array_keys( EVENT_BRIDGE_FOR_ACTIVITYPUB_EVENT_CATEGORIES );
|
||||
return in_array( $event_category, $allowed_event_categories, true );
|
||||
return \in_array( $event_category, $allowed_event_categories, true );
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,10 +13,9 @@
|
||||
namespace Event_Bridge_For_ActivityPub;
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
use Event_Bridge_For_ActivityPub\ActivityPub\Collection\Event_Sources as Event_Sources_Collection;
|
||||
use Event_Bridge_For_ActivityPub\ActivityPub\Handler\Join as Join_Handler;
|
||||
use Event_Bridge_For_ActivityPub\ActivityPub\Scheduler\Event as Event_Scheduler;
|
||||
use Event_Bridge_For_ActivityPub\Admin\Event_Plugin_Admin_Notices;
|
||||
use Event_Bridge_For_ActivityPub\Admin\General_Admin_Notices;
|
||||
@ -25,10 +24,14 @@ use Event_Bridge_For_ActivityPub\Admin\Settings_Page;
|
||||
use Event_Bridge_For_ActivityPub\Integrations\Event_Plugin_Integration;
|
||||
use Event_Bridge_For_ActivityPub\Integrations\Feature_Event_Sources;
|
||||
use Event_Bridge_For_ActivityPub\Reminder;
|
||||
use WP_Comment;
|
||||
use WP_Post;
|
||||
use WP_Post_Type;
|
||||
use WP_User;
|
||||
use WP_Term;
|
||||
|
||||
use function Activitypub\is_user_type_disabled;
|
||||
|
||||
// @phpstan-ignore-next-line
|
||||
require_once ABSPATH . 'wp-admin/includes/plugin.php';
|
||||
|
||||
/**
|
||||
@ -39,13 +42,6 @@ require_once ABSPATH . 'wp-admin/includes/plugin.php';
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class Setup {
|
||||
/**
|
||||
* Keep the information whether the ActivityPub plugin is active.
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
protected $activitypub_plugin_is_active = false;
|
||||
|
||||
/**
|
||||
* Keep the current version of the current ActivityPub plugin.
|
||||
*
|
||||
@ -68,9 +64,8 @@ class Setup {
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected function __construct() {
|
||||
// Detect the presence/active-status and version of the ActivityPub plugin.
|
||||
$this->activitypub_plugin_is_active = defined( 'ACTIVITYPUB_PLUGIN_VERSION' ) || \is_plugin_active( 'activitypub/activitypub.php' );
|
||||
$this->activitypub_plugin_version = self::get_activitypub_plugin_version();
|
||||
// Detect the version of the ActivityPub plugin.
|
||||
$this->activitypub_plugin_version = self::get_activitypub_plugin_version();
|
||||
|
||||
// Register main action that load the Event Bridge For ActivityPub.
|
||||
\add_action( 'plugins_loaded', array( $this, 'setup_hooks' ) );
|
||||
@ -101,22 +96,13 @@ class Setup {
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter function for whether the ActivityPub plugin is active.
|
||||
*
|
||||
* @return bool True when the ActivityPub plugin is active.
|
||||
*/
|
||||
public function is_activitypub_plugin_active(): bool {
|
||||
return $this->activitypub_plugin_is_active;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current version of the ActivityPub plugin.
|
||||
*
|
||||
* @return string The semantic Version.
|
||||
*/
|
||||
private static function get_activitypub_plugin_version(): string {
|
||||
if ( defined( 'ACTIVITYPUB_PLUGIN_VERSION' ) ) {
|
||||
if ( \defined( 'ACTIVITYPUB_PLUGIN_VERSION' ) ) {
|
||||
return constant( 'ACTIVITYPUB_PLUGIN_VERSION' );
|
||||
}
|
||||
return '0.0.0';
|
||||
@ -178,6 +164,7 @@ class Setup {
|
||||
\Event_Bridge_For_ActivityPub\Integrations\Event_Organiser::class,
|
||||
\Event_Bridge_For_ActivityPub\Integrations\EventPrime::class,
|
||||
\Event_Bridge_For_ActivityPub\Integrations\EventOn::class,
|
||||
\Event_Bridge_For_ActivityPub\Integrations\Spiffy_Calendar::class,
|
||||
);
|
||||
|
||||
/**
|
||||
@ -186,9 +173,6 @@ class Setup {
|
||||
* @return void
|
||||
*/
|
||||
public function redetect_active_event_plugins(): void {
|
||||
if ( ! $this->activitypub_plugin_is_active ) {
|
||||
return;
|
||||
}
|
||||
\delete_transient( 'event_bridge_for_activitypub_active_event_plugins' );
|
||||
|
||||
$this->detect_active_event_plugins();
|
||||
@ -200,11 +184,6 @@ class Setup {
|
||||
* @return array List of supported event plugins as keys from the SUPPORTED_EVENT_PLUGINS const.
|
||||
*/
|
||||
public function detect_active_event_plugins(): array {
|
||||
// Detection will fail in case the ActivityPub plugin is not active.
|
||||
if ( ! $this->activitypub_plugin_is_active ) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$active_event_plugins = \get_transient( 'event_bridge_for_activitypub_active_event_plugins' );
|
||||
|
||||
if ( $active_event_plugins ) {
|
||||
@ -213,7 +192,6 @@ class Setup {
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'get_plugins' ) ) {
|
||||
// @phpstan-ignore-next-line
|
||||
require_once ABSPATH . 'wp-admin/includes/plugin.php';
|
||||
}
|
||||
|
||||
@ -289,7 +267,7 @@ class Setup {
|
||||
);
|
||||
|
||||
// If we don't have any active event plugins, or the ActivityPub plugin is not enabled, abort here.
|
||||
if ( empty( $this->active_event_plugins ) || ! $this->activitypub_plugin_is_active ) {
|
||||
if ( empty( $this->active_event_plugins ) ) {
|
||||
self::shut_down();
|
||||
return;
|
||||
}
|
||||
@ -312,9 +290,6 @@ class Setup {
|
||||
// Register the event reminders.
|
||||
\add_action( 'init', array( Reminder::class, 'init' ) );
|
||||
|
||||
// Initialize the handling of "Join" activities.
|
||||
Join_Handler::init();
|
||||
|
||||
// If the Event-Sources feature is enabled and all requirements are met, initialize it.
|
||||
if ( ! is_user_type_disabled( 'blog' ) && \get_option( 'event_bridge_for_activitypub_event_sources_active' ) ) {
|
||||
Event_Sources::init();
|
||||
@ -340,7 +315,7 @@ class Setup {
|
||||
* @return void
|
||||
*/
|
||||
private function register_plugin_specific_hooks(): void {
|
||||
if ( array_key_exists( \Event_Bridge_For_ActivityPub\Integrations\EventPrime::get_relative_plugin_file(), $this->active_event_plugins ) ) {
|
||||
if ( \array_key_exists( \Event_Bridge_For_ActivityPub\Integrations\EventPrime::get_relative_plugin_file(), $this->active_event_plugins ) ) {
|
||||
\Event_Bridge_For_ActivityPub\Integrations\EventPrime::init();
|
||||
}
|
||||
}
|
||||
@ -403,12 +378,6 @@ class Setup {
|
||||
foreach ( $this->active_event_plugins as $event_plugin ) {
|
||||
new Event_Plugin_Admin_Notices( $event_plugin );
|
||||
}
|
||||
// Check if any general admin notices are needed and add actions to insert the needed admin notices.
|
||||
if ( ! $this->activitypub_plugin_is_active ) {
|
||||
// The ActivityPub plugin is not active.
|
||||
\add_action( 'admin_notices', array( General_Admin_Notices::class, 'activitypub_plugin_not_enabled' ), 10, 0 );
|
||||
return;
|
||||
}
|
||||
if ( ! version_compare( $this->activitypub_plugin_version, EVENT_BRIDGE_FOR_ACTIVITYPUB_ACTIVITYPUB_PLUGIN_MIN_VERSION, '>=' ) ) {
|
||||
// The ActivityPub plugin is too old.
|
||||
\add_action( 'admin_notices', array( General_Admin_Notices::class, 'activitypub_plugin_version_too_old' ), 10, 0 );
|
||||
@ -429,7 +398,7 @@ class Setup {
|
||||
*
|
||||
* @return \Activitypub\Transformer\Base|null|\WP_Error
|
||||
*/
|
||||
public function register_activitypub_transformer( $transformer, $data, $object_class ) {
|
||||
public function register_activitypub_transformer( $transformer, mixed $data, string $object_class ) {
|
||||
// If the current WordPress object is not a post (e.g., a WP_Comment), don't change the transformer.
|
||||
if ( 'WP_Post' === $object_class ) {
|
||||
// Get the transformer for a specific event plugins event or location post type.
|
||||
@ -506,7 +475,7 @@ class Setup {
|
||||
// If someone installs this plugin, we simply enable ActivityPub support for all currently active event post types.
|
||||
$activitypub_supported_post_types = get_option( 'activitypub_support_post_types', array() );
|
||||
foreach ( $this->active_event_plugins as $event_plugin ) {
|
||||
if ( ! in_array( $event_plugin->get_post_type(), $activitypub_supported_post_types, true ) ) {
|
||||
if ( ! \in_array( $event_plugin->get_post_type(), $activitypub_supported_post_types, true ) ) {
|
||||
$activitypub_supported_post_types[] = $event_plugin->get_post_type();
|
||||
add_post_type_support( $event_plugin->get_post_type(), 'activitypub' );
|
||||
}
|
||||
@ -525,17 +494,6 @@ class Setup {
|
||||
*/
|
||||
public function activate(): void {
|
||||
$this->redetect_active_event_plugins();
|
||||
// Don't allow plugin activation, when the ActivityPub plugin is not activated yet.
|
||||
if ( ! $this->activitypub_plugin_is_active ) {
|
||||
\deactivate_plugins( plugin_basename( EVENT_BRIDGE_FOR_ACTIVITYPUB_PLUGIN_FILE ) );
|
||||
$notice = General_Admin_Notices::get_admin_notice_activitypub_plugin_not_enabled();
|
||||
\wp_die(
|
||||
// @phpstan-ignore-next-line
|
||||
wp_kses( $notice, General_Admin_Notices::ALLOWED_HTML ),
|
||||
'Plugin dependency check',
|
||||
array( 'back_link' => true ),
|
||||
);
|
||||
}
|
||||
|
||||
if ( empty( $this->active_event_plugins ) ) {
|
||||
\deactivate_plugins( plugin_basename( EVENT_BRIDGE_FOR_ACTIVITYPUB_PLUGIN_FILE ) );
|
||||
@ -552,7 +510,7 @@ class Setup {
|
||||
}
|
||||
|
||||
/**
|
||||
* Maybe (depending on active event plugins) make it possible to querly event terms by `?term_id=<term_id>`.
|
||||
* Maybe (depending on active event plugins) make it possible to query event terms by `?term_id=<term_id>`.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
@ -579,7 +537,7 @@ class Setup {
|
||||
*
|
||||
* @return array The query variables.
|
||||
*/
|
||||
public static function add_term_query_var( $vars ) {
|
||||
public static function add_term_query_var( array $vars ): array {
|
||||
$vars[] = 'term_id';
|
||||
|
||||
return $vars;
|
||||
@ -588,9 +546,9 @@ class Setup {
|
||||
/**
|
||||
* Filters the queried object.
|
||||
*
|
||||
* @param \WP_Term|\WP_Post_Type|\WP_Post|\WP_User|\WP_Comment|null $queried_object The queried object.
|
||||
* @param WP_Term|WP_Post_Type|WP_Post|WP_User|WP_Comment|null $queried_object The queried object.
|
||||
*/
|
||||
public function maybe_detect_event_plugins_location_term( $queried_object ) {
|
||||
public function maybe_detect_event_plugins_location_term( mixed $queried_object ) {
|
||||
if ( $queried_object ) {
|
||||
return $queried_object;
|
||||
}
|
||||
@ -601,7 +559,7 @@ class Setup {
|
||||
$queried_object = \get_term( $term_id );
|
||||
}
|
||||
|
||||
if ( $queried_object instanceof \WP_Term && $this->is_place_taxonomy_of_active_event_plugin( $queried_object->taxonomy ) ) {
|
||||
if ( $queried_object instanceof WP_Term && $this->is_place_taxonomy_of_active_event_plugin( $queried_object->taxonomy ) ) {
|
||||
return $queried_object;
|
||||
}
|
||||
|
||||
@ -614,7 +572,7 @@ class Setup {
|
||||
* @param string $taxonomy The taxonomy.
|
||||
* @return boolean
|
||||
*/
|
||||
private function is_place_taxonomy_of_active_event_plugin( $taxonomy ): bool {
|
||||
private function is_place_taxonomy_of_active_event_plugin( string $taxonomy ): bool {
|
||||
foreach ( $this->active_event_plugins as $event_plugin ) {
|
||||
if ( $event_plugin::get_place_taxonomy() === $taxonomy ) {
|
||||
return true;
|
||||
@ -684,7 +642,7 @@ class Setup {
|
||||
$event_plugin_integrations = $setup->get_active_event_plugins();
|
||||
foreach ( $event_plugin_integrations as $event_plugin_integration ) {
|
||||
if ( $event_plugin_integration instanceof Feature_Event_Sources ) {
|
||||
return get_class( $event_plugin_integration );
|
||||
return \get_class( $event_plugin_integration );
|
||||
}
|
||||
}
|
||||
return '';
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
namespace Event_Bridge_For_ActivityPub;
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
define(
|
||||
'EVENT_BRIDGE_FOR_ACTIVITYPUB_EVENT_CATEGORIES',
|
||||
|
||||
@ -13,11 +13,13 @@
|
||||
namespace Event_Bridge_For_ActivityPub\Integrations;
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
use Activitypub\Query;
|
||||
use Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Event\Event_Organiser as Event_Organiser_Transformer;
|
||||
use Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Place\Event_Organiser as Event_Organiser_Place_Transformer;
|
||||
use WP_Post;
|
||||
use WP_Term;
|
||||
|
||||
/**
|
||||
* Event Organiser.
|
||||
@ -79,17 +81,21 @@ final class Event_Organiser extends Event_Plugin_Integration {
|
||||
* @param \WP_Post $post The WordPress post object of the Event.
|
||||
* @return Event_Organiser_Transformer
|
||||
*/
|
||||
public static function get_activitypub_event_transformer( $post ): Event_Organiser_Transformer {
|
||||
public static function get_activitypub_event_transformer( WP_Post $post ): Event_Organiser_Transformer {
|
||||
return new Event_Organiser_Transformer( $post, self::get_event_category_taxonomy() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ActivityPub transformer for a Event_Organiser event venue which is stored in a taxonomy.
|
||||
*
|
||||
* @param \WP_Term $term The WordPress Term/Taxonomy of the venue.
|
||||
* @param WP_Post|WP_Term $term The WordPress Term/Taxonomy of the venue.
|
||||
* @return Event_Organiser_Place_Transformer
|
||||
*/
|
||||
public static function get_activitypub_place_transformer( $term ): Event_Organiser_Place_Transformer {
|
||||
public static function get_activitypub_place_transformer( WP_Post|WP_Term $term ): ?Event_Organiser_Place_Transformer {
|
||||
if ( $term instanceof WP_Post ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ( Query::get_instance()->is_activitypub_request() && defined( 'EVENT_ORGANISER_DIR' ) ) {
|
||||
$class_path = constant( EVENT_ORGANISER_DIR ) . 'includes/class-eo-theme-compatability.php';
|
||||
|
||||
|
||||
@ -12,12 +12,13 @@
|
||||
namespace Event_Bridge_For_ActivityPub\Integrations;
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
use Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Event\Event as ActivityPub_Event_Transformer;
|
||||
use Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Place\Base_Post_Place;
|
||||
use Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Place\Base_Term_Place;
|
||||
use WP_Post;
|
||||
use WP_Term;
|
||||
|
||||
require_once EVENT_BRIDGE_FOR_ACTIVITYPUB_PLUGIN_DIR . 'includes/integrations/interface-feature-event-sources.php';
|
||||
|
||||
@ -56,7 +57,7 @@ abstract class Event_Plugin_Integration {
|
||||
* @param WP_Post $post The WordPress post object of the Event.
|
||||
* @return ActivityPub_Event_Transformer
|
||||
*/
|
||||
abstract public static function get_activitypub_event_transformer( $post ): ActivityPub_Event_Transformer;
|
||||
abstract public static function get_activitypub_event_transformer( WP_Post $post ): ActivityPub_Event_Transformer;
|
||||
|
||||
/**
|
||||
* In case an event plugin uses a custom post type for the locations/venues return it here.
|
||||
@ -79,10 +80,10 @@ abstract class Event_Plugin_Integration {
|
||||
/**
|
||||
* Returns the Activitypub transformer for places of the event plugins location post type.
|
||||
*
|
||||
* @param WP_Post $post The WordPress post object of the Event.
|
||||
* @param WP_Post|WP_Term $data The WordPress post object of the Event.
|
||||
* @return Base_Post_Place|Base_Term_Place|null
|
||||
*/
|
||||
public static function get_activitypub_place_transformer( $post ) { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter
|
||||
public static function get_activitypub_place_transformer( WP_Post|WP_Term $data ) { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -108,7 +109,7 @@ abstract class Event_Plugin_Integration {
|
||||
* Get the plugins name from the main plugin-file's top-level-file-comment.
|
||||
*/
|
||||
public static function get_plugin_name(): string {
|
||||
$all_plugins = array_merge( get_plugins(), get_mu_plugins() );
|
||||
$all_plugins = array_merge( \get_plugins(), \get_mu_plugins() );
|
||||
if ( isset( $all_plugins[ static::get_relative_plugin_file() ]['Name'] ) ) {
|
||||
return $all_plugins[ static::get_relative_plugin_file() ]['Name'];
|
||||
} else {
|
||||
@ -121,11 +122,11 @@ abstract class Event_Plugin_Integration {
|
||||
*/
|
||||
public static function is_plugin_page(): bool {
|
||||
// Get the current page.
|
||||
$screen = get_current_screen();
|
||||
$screen = \get_current_screen();
|
||||
|
||||
// Check if we are on a edit page for the event, or on the settings page of the event plugin.
|
||||
$is_event_plugins_edit_page = 'edit' === $screen->base && static::get_post_type() === $screen->post_type;
|
||||
$is_event_plugins_settings_page = in_array( $screen->id, static::get_settings_pages(), true );
|
||||
$is_event_plugins_settings_page = \in_array( $screen->id, static::get_settings_pages(), true );
|
||||
|
||||
return $is_event_plugins_edit_page || $is_event_plugins_settings_page;
|
||||
}
|
||||
|
||||
@ -13,9 +13,10 @@
|
||||
namespace Event_Bridge_For_ActivityPub\Integrations;
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
use Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Event\Eventin as Eventin_Transformer;
|
||||
use WP_Post;
|
||||
|
||||
/**
|
||||
* Eventin.
|
||||
@ -65,10 +66,10 @@ final class Eventin extends Event_Plugin_Integration {
|
||||
/**
|
||||
* Returns the ActivityPub transformer for a Eventin event post.
|
||||
*
|
||||
* @param \WP_Post $post The WordPress post object of the Event.
|
||||
* @param WP_Post $post The WordPress post object of the Event.
|
||||
* @return Eventin_Transformer
|
||||
*/
|
||||
public static function get_activitypub_event_transformer( $post ): Eventin_Transformer {
|
||||
public static function get_activitypub_event_transformer( WP_Post $post ): Eventin_Transformer {
|
||||
return new Eventin_Transformer( $post, self::get_event_category_taxonomy() );
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,10 +13,12 @@
|
||||
namespace Event_Bridge_For_ActivityPub\Integrations;
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
use Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Event\EventOn as EventOn_Event_Transformer;
|
||||
use Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Place\EventOn as EventOn_Location_Transformer;
|
||||
use WP_Post;
|
||||
use WP_Term;
|
||||
|
||||
/**
|
||||
* EventON – Events Calendar
|
||||
@ -66,10 +68,10 @@ final class EventOn extends Event_Plugin_Integration {
|
||||
/**
|
||||
* Returns the ActivityPub transformer for a VS_Event_List event post.
|
||||
*
|
||||
* @param \WP_Post $post The WordPress post object of the Event.
|
||||
* @param WP_Post $post The WordPress post object of the Event.
|
||||
* @return EventOn_Event_Transformer
|
||||
*/
|
||||
public static function get_activitypub_event_transformer( $post ): EventOn_Event_Transformer {
|
||||
public static function get_activitypub_event_transformer( WP_Post $post ): EventOn_Event_Transformer {
|
||||
return new EventOn_Event_Transformer( $post, self::get_event_category_taxonomy() );
|
||||
}
|
||||
|
||||
@ -85,10 +87,10 @@ final class EventOn extends Event_Plugin_Integration {
|
||||
/**
|
||||
* Returns the ActivityPub transformer for a Event_Organiser event venue which is stored in a taxonomy.
|
||||
*
|
||||
* @param \WP_Term $term The WordPress Term/Taxonomy of the venue.
|
||||
* @param WP_Post|WP_Term $term The WordPress Term/Taxonomy of the venue.
|
||||
* @return EventOn_Location_Transformer
|
||||
*/
|
||||
public static function get_activitypub_place_transformer( $term ): EventOn_Location_Transformer {
|
||||
return new EventOn_Location_Transformer( $term );
|
||||
public static function get_activitypub_place_transformer( WP_Post|WP_Term $term ): ?EventOn_Location_Transformer {
|
||||
return $term instanceof WP_Term ? new EventOn_Location_Transformer( $term ) : null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,11 +12,12 @@ namespace Event_Bridge_For_ActivityPub\Integrations;
|
||||
use Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Event\EventPrime as EventPrime_Event_Transformer;
|
||||
use Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Place\EventPrime as EventPrime_Place_Transformer;
|
||||
use Eventprime_Basic_Functions;
|
||||
use WP_Post;
|
||||
|
||||
use function Activitypub\is_activitypub_request;
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
/**
|
||||
* This class defines which information is necessary for the EventPrime event plugin.
|
||||
@ -72,10 +73,10 @@ final class EventPrime extends Event_Plugin_Integration {
|
||||
/**
|
||||
* Returns the ActivityPub transformer.
|
||||
*
|
||||
* @param \WP_Post $post The WordPress post object of the Event.
|
||||
* @param WP_Post $post The WordPress post object of the Event.
|
||||
* @return EventPrime_Event_Transformer
|
||||
*/
|
||||
public static function get_activitypub_event_transformer( $post ): EventPrime_Event_Transformer {
|
||||
public static function get_activitypub_event_transformer( WP_Post $post ): EventPrime_Event_Transformer {
|
||||
return new EventPrime_Event_Transformer( $post, self::get_event_category_taxonomy() );
|
||||
}
|
||||
|
||||
@ -150,7 +151,7 @@ final class EventPrime extends Event_Plugin_Integration {
|
||||
* @return bool|int The post ID, or term ID if found, false otherwise.
|
||||
*/
|
||||
private static function get_object_id( $type = 'event' ) {
|
||||
if ( ! in_array( $type, array( 'venue', 'event' ), true ) ) {
|
||||
if ( ! \in_array( $type, array( 'venue', 'event' ), true ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@ -13,11 +13,12 @@
|
||||
namespace Event_Bridge_For_ActivityPub\Integrations;
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
use Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Event\Events_Manager as Events_Manager_Event_Transformer;
|
||||
use Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Place\Events_Manager as Events_Manager_Place_Transformer;
|
||||
|
||||
use WP_Post;
|
||||
use WP_Term;
|
||||
|
||||
/**
|
||||
* Events Manager.
|
||||
@ -43,7 +44,7 @@ final class Events_Manager extends Event_Plugin_Integration {
|
||||
* @return string
|
||||
*/
|
||||
public static function get_post_type(): string {
|
||||
return defined( 'EM_POST_TYPE_EVENT' ) ? constant( 'EM_POST_TYPE_EVENT' ) : 'event';
|
||||
return \defined( 'EM_POST_TYPE_EVENT' ) ? constant( 'EM_POST_TYPE_EVENT' ) : 'event';
|
||||
}
|
||||
|
||||
/**
|
||||
@ -52,17 +53,17 @@ final class Events_Manager extends Event_Plugin_Integration {
|
||||
* @return string
|
||||
*/
|
||||
public static function get_place_post_type(): string {
|
||||
return defined( 'EM_POST_TYPE_LOCATION' ) ? constant( 'EM_POST_TYPE_LOCATION' ) : 'location';
|
||||
return \defined( 'EM_POST_TYPE_LOCATION' ) ? constant( 'EM_POST_TYPE_LOCATION' ) : 'location';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Activitypub transformer for places of the event plugins location post type.
|
||||
*
|
||||
* @param \WP_Post $post The WordPress post object of the Event.
|
||||
* @param WP_Post|WP_Term $post The WordPress post object of the Event.
|
||||
* @return Events_Manager_Place_Transformer
|
||||
*/
|
||||
public static function get_activitypub_place_transformer( $post ): Events_Manager_Place_Transformer {
|
||||
return new Events_Manager_Place_Transformer( $post );
|
||||
public static function get_activitypub_place_transformer( WP_Post|WP_Term $post ): ?Events_Manager_Place_Transformer {
|
||||
return $post instanceof WP_Post ? new Events_Manager_Place_Transformer( $post ) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -80,16 +81,16 @@ final class Events_Manager extends Event_Plugin_Integration {
|
||||
* @return string
|
||||
*/
|
||||
public static function get_event_category_taxonomy(): string {
|
||||
return defined( 'EM_TAXONOMY_CATEGORY' ) ? constant( 'EM_TAXONOMY_CATEGORY' ) : 'event-categories';
|
||||
return \defined( 'EM_TAXONOMY_CATEGORY' ) ? constant( 'EM_TAXONOMY_CATEGORY' ) : 'event-categories';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ActivityPub transformer for a Events_Manager event post.
|
||||
*
|
||||
* @param \WP_Post $post The WordPress post object of the Event.
|
||||
* @param WP_Post $post The WordPress post object of the Event.
|
||||
* @return Events_Manager_Event_Transformer
|
||||
*/
|
||||
public static function get_activitypub_event_transformer( $post ): Events_Manager_Event_Transformer {
|
||||
public static function get_activitypub_event_transformer( WP_Post $post ): Events_Manager_Event_Transformer {
|
||||
return new Events_Manager_Event_Transformer( $post, self::get_event_category_taxonomy() );
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,10 +13,11 @@
|
||||
namespace Event_Bridge_For_ActivityPub\Integrations;
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
use Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Event\GatherPress as GatherPress_Transformer;
|
||||
use Event_Bridge_For_ActivityPub\ActivityPub\Transmogrifier\GatherPress as GatherPress_Transmogrifier;
|
||||
use WP_Post;
|
||||
|
||||
/**
|
||||
* GatherPress.
|
||||
@ -66,10 +67,10 @@ final class GatherPress extends Event_Plugin_Integration implements Feature_Even
|
||||
/**
|
||||
* Returns the ActivityPub transformer for a GatherPress event post.
|
||||
*
|
||||
* @param \WP_Post $post The WordPress post object of the Event.
|
||||
* @param WP_Post $post The WordPress post object of the Event.
|
||||
* @return GatherPress_Transformer
|
||||
*/
|
||||
public static function get_activitypub_event_transformer( $post ): GatherPress_Transformer {
|
||||
public static function get_activitypub_event_transformer( WP_Post $post ): GatherPress_Transformer {
|
||||
return new GatherPress_Transformer( $post, self::get_event_category_taxonomy() );
|
||||
}
|
||||
|
||||
@ -80,6 +81,15 @@ final class GatherPress extends Event_Plugin_Integration implements Feature_Even
|
||||
return GatherPress_Transmogrifier::class;
|
||||
}
|
||||
|
||||
/**
|
||||
* GatherPress uses a taxonomy to store venues.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_place_taxonomy() {
|
||||
return '_gatherpress_venue';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of Post IDs of events that have ended.
|
||||
*
|
||||
@ -87,11 +97,12 @@ final class GatherPress extends Event_Plugin_Integration implements Feature_Even
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function get_cached_remote_events( $ends_before_time ): array {
|
||||
public static function get_cached_remote_events( int $ends_before_time ): array {
|
||||
global $wpdb;
|
||||
|
||||
$ends_before_time_string = gmdate( 'Y-m-d H:i:s', $ends_before_time );
|
||||
|
||||
// phpcs:disable WordPress.DB.DirectDatabaseQuery
|
||||
$results = $wpdb->get_results(
|
||||
$wpdb->prepare(
|
||||
"SELECT DISTINCT {$wpdb->prefix}posts.ID
|
||||
|
||||
@ -13,9 +13,10 @@
|
||||
namespace Event_Bridge_For_ActivityPub\Integrations;
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
use Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Event\Modern_Events_Calendar_Lite as Modern_Events_Calendar_Lite_Transformer;
|
||||
use WP_Post;
|
||||
|
||||
/**
|
||||
* Modern Events Calendar (Lite)
|
||||
@ -66,10 +67,10 @@ final class Modern_Events_Calendar_Lite extends Event_Plugin_Integration {
|
||||
/**
|
||||
* Returns the ActivityPub transformer for a Modern_Events_Calendar_Lite event post.
|
||||
*
|
||||
* @param \WP_Post $post The WordPress post object of the Event.
|
||||
* @param WP_Post $post The WordPress post object of the Event.
|
||||
* @return Modern_Events_Calendar_Lite_Transformer
|
||||
*/
|
||||
public static function get_activitypub_event_transformer( $post ): Modern_Events_Calendar_Lite_Transformer {
|
||||
public static function get_activitypub_event_transformer( WP_Post $post ): Modern_Events_Calendar_Lite_Transformer {
|
||||
return new Modern_Events_Calendar_Lite_Transformer( $post, self::get_event_category_taxonomy() );
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,81 @@
|
||||
<?php
|
||||
/**
|
||||
* Integration with the Plugin "Spiffy Calendar".
|
||||
*
|
||||
* Defines all the necessary meta information and methods for the integration of the
|
||||
* WordPress plugin "Spiffy Calendar".
|
||||
*
|
||||
* @link https://wordpress.org/plugins/eventin/
|
||||
* @package Event_Bridge_For_ActivityPub
|
||||
* @since 1.0.0
|
||||
*/
|
||||
|
||||
namespace Event_Bridge_For_ActivityPub\Integrations;
|
||||
|
||||
// Exit if accessed directly.
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
use Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Event\Spiffy_Calendar as Spiffy_Calendar_Transformer;
|
||||
use WP_Post;
|
||||
|
||||
/**
|
||||
* Eventin.
|
||||
*
|
||||
* Defines all the necessary meta information and methods for the integration of the
|
||||
* WordPress plugin "Eventin".
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
final class Spiffy_Calendar extends Event_Plugin_Integration {
|
||||
/**
|
||||
* Returns the full plugin file.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_relative_plugin_file(): string {
|
||||
return 'spiffy-calendar/spiffy-calendar.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the event post type of the plugin.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_post_type(): string {
|
||||
return 'spiffy_event';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the IDs of the admin pages of the plugin.
|
||||
*
|
||||
* @return array The settings page url.
|
||||
*/
|
||||
public static function get_settings_pages(): array {
|
||||
return array(
|
||||
'spiffy_event_page_settings',
|
||||
'spiffy_event_page_theme',
|
||||
'spiffy_event_page_frontend_submit',
|
||||
'spiffy_event_page_custom_fields',
|
||||
'edit-spiffy_event',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the taxonomy used for the plugin's event categories.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_event_category_taxonomy(): string {
|
||||
return 'spiffy_categories';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ActivityPub transformer for a Eventin event post.
|
||||
*
|
||||
* @param WP_Post $post The WordPress post object of the Event.
|
||||
* @return Spiffy_Calendar_Transformer
|
||||
*/
|
||||
public static function get_activitypub_event_transformer( WP_Post $post ): Spiffy_Calendar_Transformer {
|
||||
return new Spiffy_Calendar_Transformer( $post, self::get_event_category_taxonomy() );
|
||||
}
|
||||
}
|
||||
@ -12,12 +12,15 @@
|
||||
|
||||
namespace Event_Bridge_For_ActivityPub\Integrations;
|
||||
|
||||
use WP_Term;
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
use Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Event\The_Events_Calendar as The_Events_Calendar_Event_Transformer;
|
||||
use Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Place\The_Events_Calendar as The_Events_Calendar_Place_Transformer;
|
||||
use Event_Bridge_For_ActivityPub\ActivityPub\Transmogrifier\The_Events_Calendar as The_Events_Calendar_Transmogrifier;
|
||||
use WP_Post;
|
||||
|
||||
/**
|
||||
* The Events Calendar.
|
||||
@ -61,7 +64,7 @@ final class The_Events_Calendar extends Event_Plugin_Integration implements Feat
|
||||
* @param \WP_Post $post The WordPress post object of the Event.
|
||||
* @return The_Events_Calendar_Event_Transformer
|
||||
*/
|
||||
public static function get_activitypub_event_transformer( $post ): The_Events_Calendar_Event_Transformer {
|
||||
public static function get_activitypub_event_transformer( WP_Post $post ): The_Events_Calendar_Event_Transformer {
|
||||
return new The_Events_Calendar_Event_Transformer( $post, self::get_event_category_taxonomy() );
|
||||
}
|
||||
|
||||
@ -86,10 +89,10 @@ final class The_Events_Calendar extends Event_Plugin_Integration implements Feat
|
||||
/**
|
||||
* Returns the ActivityPub transformer for a The_Events_Calendar venue post.
|
||||
*
|
||||
* @param \WP_Post $post The WordPress post object of the venue.
|
||||
* @param mixed $post The WordPress post object of the venue.
|
||||
* @return The_Events_Calendar_Place_Transformer
|
||||
*/
|
||||
public static function get_activitypub_place_transformer( $post ): The_Events_Calendar_Place_Transformer {
|
||||
public static function get_activitypub_place_transformer( mixed $post ): The_Events_Calendar_Place_Transformer {
|
||||
return new The_Events_Calendar_Place_Transformer( $post );
|
||||
}
|
||||
|
||||
|
||||
@ -13,10 +13,11 @@
|
||||
namespace Event_Bridge_For_ActivityPub\Integrations;
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
use Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Event\VS_Event_List as VS_Event_List_Transformer;
|
||||
use Event_Bridge_For_ActivityPub\ActivityPub\Transmogrifier\VS_Event_List as VS_Event_List_Transmogrifier;
|
||||
use WP_Post;
|
||||
use WP_Query;
|
||||
|
||||
/**
|
||||
@ -67,10 +68,10 @@ final class VS_Event_List extends Event_Plugin_Integration implements Feature_Ev
|
||||
/**
|
||||
* Returns the ActivityPub transformer for a VS_Event_List event post.
|
||||
*
|
||||
* @param \WP_Post $post The WordPress post object of the Event.
|
||||
* @param WP_Post $post The WordPress post object of the Event.
|
||||
* @return VS_Event_List_Transformer
|
||||
*/
|
||||
public static function get_activitypub_event_transformer( $post ): VS_Event_List_Transformer {
|
||||
public static function get_activitypub_event_transformer( WP_Post $post ): VS_Event_List_Transformer {
|
||||
return new VS_Event_List_Transformer( $post, self::get_event_category_taxonomy() );
|
||||
}
|
||||
|
||||
@ -88,11 +89,12 @@ final class VS_Event_List extends Event_Plugin_Integration implements Feature_Ev
|
||||
*
|
||||
* @return array<int>
|
||||
*/
|
||||
public static function get_cached_remote_events( $ends_before_time ): array {
|
||||
public static function get_cached_remote_events( int $ends_before_time ): array {
|
||||
$args = array(
|
||||
'post_type' => 'event',
|
||||
'posts_per_page' => -1,
|
||||
'fields' => 'ids',
|
||||
// phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
|
||||
'meta_query' => array(
|
||||
'relation' => 'AND',
|
||||
array(
|
||||
|
||||
@ -13,9 +13,10 @@
|
||||
namespace Event_Bridge_For_ActivityPub\Integrations;
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
use Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Event\WP_Event_Manager as WP_Event_Manager_Transformer;
|
||||
use WP_Post;
|
||||
|
||||
/**
|
||||
* Interface for a supported event plugin.
|
||||
@ -64,10 +65,10 @@ final class WP_Event_Manager extends Event_Plugin_Integration {
|
||||
/**
|
||||
* Returns the ActivityPub transformer for a WP_Event_Manager event post.
|
||||
*
|
||||
* @param \WP_Post $post The WordPress post object of the Event.
|
||||
* @param WP_Post $post The WordPress post object of the Event.
|
||||
* @return WP_Event_Manager_Transformer
|
||||
*/
|
||||
public static function get_activitypub_event_transformer( $post ): WP_Event_Manager_Transformer {
|
||||
public static function get_activitypub_event_transformer( WP_Post $post ): WP_Event_Manager_Transformer {
|
||||
return new WP_Event_Manager_Transformer( $post, self::get_event_category_taxonomy() );
|
||||
}
|
||||
}
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
namespace Event_Bridge_For_ActivityPub\Integrations;
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
/**
|
||||
* Interface for an event plugin integration that supports the Event Sources feature.
|
||||
@ -38,5 +38,5 @@ interface Feature_Event_Sources {
|
||||
*
|
||||
* @return int[] List of post IDs for events that match the criteria.
|
||||
*/
|
||||
public static function get_cached_remote_events( $ends_before_time ): array;
|
||||
public static function get_cached_remote_events( int $ends_before_time ): array;
|
||||
}
|
||||
|
||||
@ -13,14 +13,13 @@
|
||||
namespace Event_Bridge_For_ActivityPub\Table;
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
\defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||
|
||||
use WP_List_Table;
|
||||
use Event_Bridge_For_ActivityPub\ActivityPub\Collection\Event_Sources as Event_Sources_Collection;
|
||||
use Event_Bridge_For_ActivityPub\ActivityPub\Model\Event_Source;
|
||||
use WP_List_Table;
|
||||
|
||||
if ( ! \class_exists( '\WP_List_Table' ) ) {
|
||||
// @phpstan-ignore-next-line
|
||||
require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
|
||||
}
|
||||
|
||||
@ -118,7 +117,7 @@ class Event_Sources extends WP_List_Table {
|
||||
foreach ( $event_sources['actors'] as $event_source_post_id => $event_source_activitypub_id ) {
|
||||
$event_source = Event_Source::get_by_id( (int) $event_source_post_id );
|
||||
|
||||
if ( ! $event_source || ! in_array( $event_source->get_status(), array( 'publish', 'pending' ), true ) ) {
|
||||
if ( ! $event_source || ! \in_array( $event_source->get_status(), array( 'publish', 'pending' ), true ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -155,7 +154,7 @@ class Event_Sources extends WP_List_Table {
|
||||
* @return string
|
||||
*/
|
||||
public function column_default( $item, $column_name ) {
|
||||
if ( ! array_key_exists( $column_name, $item ) ) {
|
||||
if ( ! \array_key_exists( $column_name, $item ) ) {
|
||||
return __( 'None', 'event-bridge-for-activitypub' );
|
||||
}
|
||||
return $item[ $column_name ];
|
||||
@ -167,8 +166,8 @@ class Event_Sources extends WP_List_Table {
|
||||
* @param array $item Item.
|
||||
* @return string
|
||||
*/
|
||||
public function column_icon( $item ): string {
|
||||
return sprintf(
|
||||
public function column_icon( array $item ): string {
|
||||
return \sprintf(
|
||||
'<img src="%s" width="25px;" />',
|
||||
$item['icon']
|
||||
);
|
||||
@ -181,7 +180,7 @@ class Event_Sources extends WP_List_Table {
|
||||
* @return string
|
||||
*/
|
||||
public function column_url( $item ): string {
|
||||
return sprintf(
|
||||
return \sprintf(
|
||||
'<a href="%s" target="_blank">%s</a>',
|
||||
esc_url( $item['url'] ),
|
||||
$item['url']
|
||||
@ -195,7 +194,7 @@ class Event_Sources extends WP_List_Table {
|
||||
* @return string
|
||||
*/
|
||||
public function column_cb( $item ): string {
|
||||
return sprintf( '<input type="checkbox" name="event_sources[]" value="%s" />', esc_attr( $item['identifier'] ) );
|
||||
return \sprintf( '<input type="checkbox" name="event_sources[]" value="%s" />', esc_attr( $item['identifier'] ) );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -204,7 +203,7 @@ class Event_Sources extends WP_List_Table {
|
||||
* @param array $item Item.
|
||||
* @return string
|
||||
*/
|
||||
public function column_accepted( $item ): string {
|
||||
public function column_accepted( array $item ): string {
|
||||
if ( $item['accepted'] ) {
|
||||
return esc_html__( 'Accepted', 'event-bridge-for-activitypub' );
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user