diff --git a/.gitignore b/.gitignore index e9adf39..fd51142 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ composer.lock .phpunit.result.cache node_modules/ package-lock.json +.phpdoc diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..9ac1310 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,71 @@ +## Developer documentation + +### Overview + +The entry point of the plugin is the initialization of the singleton class `\Event_Bridge_For_ActivityPub\Setup` in the main plugin file `event-bridge-for-activitypub.php`. +The constructor of that class calls its `setup_hooks()` function. This function provides hooks that initialize all parts of the _Event Bridge For ActivityPub_ whenever needed. + +### File structure + +Note that almost all files and folder within the `activitypub` folders are structured the same way as in the WordPress ActivityPub plugin. + +### Event Plugin Integrations + +This plugin supports multiple event plugins, even at the same time. To add a new one you first need to add some basic information about your event plugin. Just create a new file in `./includes/integrations/my-event-plugin.php`. Implement at least all abstract functions of the `Event_Plugin_Integration` class. + +#### Basic Event Plugin Integration + +```php + namespace Event_Bridge_For_ActivityPub\Integrations; + + // Exit if accessed directly. + defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore + + /** + * Integration information for My Event Plugin + * + * This class defines necessary meta information is for the integration of My Event Plugin with the ActivityPub plugin. + */ + final class My_Event_Plugin extends Event_Plugin_Integration { +``` + +#### Registering an Event Plugin Integration + +Then you need to tell the Event Bridge for ActivityPub about that class by adding it to the `EVENT_PLUGIN_INTEGRATIONS` constant in the `includes/setup.php` file: + +```php + private const EVENT_PLUGIN_INTEGRATIONS = array( + ... + \Event_Bridge_For_ActivityPub\Integrations\My_Event_Plugin::class, + ); +``` + +#### Additional Feature: Event Sources + +Not all _Event Plugin Integrations_ support the event-sources feature. To add support for it an integration must implement the `Feature_Event_Sources` interface. + +```php +namespace Event_Bridge_For_ActivityPub\Integrations; + +// Exit if accessed directly. +defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore + + /** + * Integration information for My Event Plugin. + * + * This class defines necessary meta information is for the integration of My Event Plugin with the ActivityPub plugin. + * This integration supports the Event Sources Feature. + */ +final class GatherPress extends Event_Plugin_Integration implements Feature_Event_Sources { +``` + +### Transformer + +Transformers are the classes that convert an WordPress post type (e.g. one used for events) to _ActivityStreams_. +The Event Bridge for ActivityPub then takes care of applying the transformer, so you can jump right into [implementing it](./implement_an_activitypub_event_transformer.md). + +### Event Sources Feature – Transmogrifier + +The event sources feature allows to aggregate events from external ActivityPub actors. As the initialization of the Event-Sources feature is quite complex all of that initialization is done in the `init` function of the file `includes/class-event-sources.php` which is called by the `\Event_Bridge_For_ActivityPub\Setup` class (`includes/class-setup.php`). + +In this plugin we call a **_Transmogrifier_** the **opposite** of a **_Transformer_**. It takes care of converting an ActivityPub (`Event`) object in _ActivityStreams_ to the WordPress representation of an event plugin. The transmogrifier classes are only used when the `Event Sources` feature is activated. The _Event Bridge For ActivityPub_ can register transformers for multiple event plugins at the same time, however only one transmogrifier, that is one target even plugin can be used as a target for incoming external ActivityPub `Event` objects. diff --git a/docs/event_plugin_integrations.md b/docs/event_plugin_integrations.md new file mode 100644 index 0000000..e654184 --- /dev/null +++ b/docs/event_plugin_integrations.md @@ -0,0 +1,50 @@ + +## Event Plugin Integrations + +First you need to add some basic information about your event plugin. Just create a new file in `./includes/integrations/my-event-plugin.php`. Implement at least all abstract functions of the `Event_Plugin_Integration` class. + +### Basic Event Plugin Integration + +```php + namespace Event_Bridge_For_ActivityPub\Integrations; + + // Exit if accessed directly. + defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore + + /** + * Integration information for My Event Plugin + * + * This class defines necessary meta information is for the integration of My Event Plugin with the ActivityPub plugin. + */ + final class My_Event_Plugin extends Event_Plugin_Integration { +``` + +### Registering an Event Plugin Integration + +Then you need to tell the Event Bridge for ActivityPub about that class by adding it to the `EVENT_PLUGIN_INTEGRATIONS` constant in the `includes/setup.php` file: + +```php + private const EVENT_PLUGIN_INTEGRATIONS = array( + ... + \Event_Bridge_For_ActivityPub\Integrations\My_Event_Plugin::class, + ); +``` + +### Additional Feature: Event Sources + +Not all _Event Plugin Integrations_ support the event-sources feature. To add support for it an integration must implement the `Feature_Event_Sources` interface. + +```php +namespace Event_Bridge_For_ActivityPub\Integrations; + +// Exit if accessed directly. +defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore + + /** + * Integration information for My Event Plugin. + * + * This class defines necessary meta information is for the integration of My Event Plugin with the ActivityPub plugin. + * This integration supports the Event Sources Feature. + */ +final class GatherPress extends Event_Plugin_Integration implements Feature_Event_Sources { +``` diff --git a/docs/add_your_event_plugin.md b/docs/transformer.md similarity index 88% rename from docs/add_your_event_plugin.md rename to docs/transformer.md index 3b79f84..333e17e 100644 --- a/docs/add_your_event_plugin.md +++ b/docs/transformer.md @@ -2,43 +2,12 @@ > **_NOTE:_** This documentation is also likely to be useful for content types other than events. -The ActivityPub plugin offers a basic support for all post types out of the box, but it also allows the registration of external transformers. A transformer is a class that implements the [abstract transformer class](https://github.com/Automattic/wordpress-activitypub/blob/fb0e23e8854d149fdedaca7a9ea856f5fd965ec9/includes/transformer/class-base.php) and is responsible for generating the ActivityPub JSON representation of an WordPress post or comment object. +The ActivityPub plugin offers a basic support for all post types out of the box, but it also allows the registration of external transformers. A transformer is a class that implements the [abstract transformer class](https://github.com/Automattic/wordpress-activitypub/blob/fb0e23e8854d149fdedaca7a9ea856f5fd965ec9/includes/transformer/class-base.php) and is responsible for generating the ActivityPub JSON representation of an WordPress post or comment object. ## How it works To make the WordPress ActivityPub plugin use a custom transformer simply add a filter to the `activitypub_transformer` hook which provides access to the transformer factory. The [transformer factory](https://github.com/Automattic/wordpress-activitypub/blob/master/includes/transformer/class-factory.php#L12) determines which transformer is used to transform a WordPress object to ActivityPub. We provide a parent event transformer, that comes with common tasks needed for events. Furthermore, we provide admin notices, to prevent users from misconfiguration issues. -## Add your event plugin - -First you need to add some basic information about your event plugin. Just create a new file in `./includes/plugins/my-event-plugin.php`. Implement at least all abstract functions of the `Event_Plugin` class. - -```php - namespace Event_Bridge_For_ActivityPub\Integrations; - - // Exit if accessed directly. - defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore - - /** - * Integration information for My Event Plugin - * - * This class defines necessary meta information is for the integration of My Event Plugin with the ActivityPub plugin. - * - * @since 1.0.0 - */ - final class My_Event_Plugin extends Event_Plugin { -``` - -Then you need to tell the Event Bridge for ActivityPub about that class by adding it to the `EVENT_PLUGIN_INTEGRATIONS` constant in the `includes/setup.php` file: - -```php - private const EVENT_PLUGIN_INTEGRATIONS = array( - ... - '\Event_Bridge_For_ActivityPub\Integrations\My_Event_Plugin', - ); -``` - -The Event Bridge for ActivityPub then takes care of applying the transformer, so you can jump right into implementing it. - ## Writing an event transformer class Within WordPress most content types are stored as a custom post type in the posts table. The ActivityPub plugin offers a basic support for all post types out of the box. So-called transformers take care of converting WordPress WP_Post objects to ActivityStreams JSON. The ActivityPub plugin offers a generic transformer for all post types. Additionally, custom transformers can be implemented to better fit a custom post type, and they can be easily registered with the ActivityPub plugin. @@ -48,9 +17,9 @@ If you are writing a transformer for your event post type we recommend to start So create a new file at `./includes/activitypub/transformer/my-event-plugin.php`. ```php -namespace Event_Bridge_For_ActivityPub\Activitypub\Transformer; +namespace Event_Bridge_For_ActivityPub\ActivityPub\Transformer; -use Event_Bridge_For_ActivityPub\Activitypub\Transformer\Event as Event_Transformer; +use Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Event as Event_Transformer; /** * ActivityPub Transformer for My Event Plugin' event post type. diff --git a/includes/activitypub/class-handler.php b/includes/activitypub/class-handler.php index 0fa1433..47a6f7c 100644 --- a/includes/activitypub/class-handler.php +++ b/includes/activitypub/class-handler.php @@ -12,6 +12,9 @@ namespace Event_Bridge_For_ActivityPub\ActivityPub; // Exit if accessed directly. defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore +use DateTime; +use DateTimeZone; +use Event_Bridge_For_ActivityPub\ActivityPub\Collection\Event_Sources; use Event_Bridge_For_ActivityPub\ActivityPub\Handler\Accept; use Event_Bridge_For_ActivityPub\ActivityPub\Handler\Update; use Event_Bridge_For_ActivityPub\ActivityPub\Handler\Create; @@ -29,5 +32,94 @@ class Handler { Update::init(); Create::init(); Delete::init(); + \add_filter( + 'activitypub_validate_object', + array( self::class, 'validate_object' ), + 12, + 3 + ); + } + + + /** + * Validate the object. + * + * @param bool $valid The validation state. + * @param string $param The object parameter. + * @param \WP_REST_Request $request The request object. + * + * @return bool The validation state: true if valid, false if not. + */ + public static function validate_object( $valid, $param, $request ) { + $json_params = $request->get_json_params(); + + if ( isset( $json_params['object']['type'] ) && 'Event' === $json_params['object']['type'] ) { + $valid = true; + } else { + return $valid; + } + + if ( empty( $json_params['type'] ) ) { + return false; + } + + if ( empty( $json_params['actor'] ) ) { + return false; + } + + if ( ! in_array( $json_params['type'], array( 'Create', 'Update', 'Delete', 'Announce' ), true ) || is_wp_error( $request ) ) { + return $valid; + } + + $object = $json_params['object']; + + if ( ! is_array( $object ) ) { + return false; + } + + $required = array( + 'id', + 'startTime', + 'name', + ); + + if ( array_intersect( $required, array_keys( $object ) ) !== $required ) { + return false; + } + + return $valid; + } + + /** + * Check if a given DateTime is already passed. + * + * @param string $time_string The ActivityPub like time string. + * @return bool + */ + public static function is_time_passed( $time_string ) { + // Create a DateTime object from the ActivityPub time string. + $time = new DateTime( $time_string, new DateTimeZone( 'UTC' ) ); + + // Get the current time in UTC. + $current_time = new DateTime( 'now', new DateTimeZone( 'UTC' ) ); + + // Compare the event time with the current time. + return $time < $current_time; + } + + /** + * Check that an ActivityPub actor is an event source (i.e. it is followed by the ActivityPub blog actor). + * + * @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 ) { + $event_sources = Event_Sources::get_event_sources(); + foreach ( $event_sources as $event_source ) { + if ( $actor_id === $event_source->get_id() ) { + return true; + } + } + return false; } } diff --git a/includes/activitypub/collection/class-event-sources.php b/includes/activitypub/collection/class-event-sources.php index 79a5a93..b3fb37e 100644 --- a/includes/activitypub/collection/class-event-sources.php +++ b/includes/activitypub/collection/class-event-sources.php @@ -1,6 +1,17 @@ save( $activity['object'] ); } - - /** - * Validate the object. - * - * @param bool $valid The validation state. - * @param string $param The object parameter. - * @param \WP_REST_Request $request The request object. - * - * @return bool The validation state: true if valid, false if not. - */ - public static function validate_object( $valid, $param, $request ) { - $json_params = $request->get_json_params(); - - if ( isset( $json_params['object']['type'] ) && 'Event' === $json_params['object']['type'] ) { - $valid = true; - } else { - return $valid; - } - - if ( empty( $json_params['type'] ) ) { - return false; - } - - if ( empty( $json_params['actor'] ) ) { - return false; - } - - if ( ! in_array( $json_params['type'], array( 'Create', 'Update', 'Delete', 'Announce' ), true ) || is_wp_error( $request ) ) { - return $valid; - } - - $object = $json_params['object']; - - if ( ! is_array( $object ) ) { - return false; - } - - $required = array( - 'id', - 'startTime', - 'name', - ); - - if ( array_intersect( $required, array_keys( $object ) ) !== $required ) { - return false; - } - - return $valid; - } - - /** - * Check if a given DateTime is already passed. - * - * @param string $time_string The ActivityPub like time string. - * @return bool - */ - private static function is_time_passed( $time_string ) { - // Create a DateTime object from the ActivityPub time string. - $time = new DateTime( $time_string, new DateTimeZone( 'UTC' ) ); - - // Get the current time in UTC. - $current_time = new DateTime( 'now', new DateTimeZone( 'UTC' ) ); - - // Compare the event time with the current time. - return $time < $current_time; - } - - /** - * Check if an ActivityPub actor is an event source. - * - * @param string $actor_id The actor ID. - * @return bool - */ - public static function actor_is_event_source( $actor_id ) { - $event_sources = Event_Sources::get_event_sources(); - foreach ( $event_sources as $event_source ) { - if ( $actor_id === $event_source->get_id() ) { - return true; - } - } - return false; - } } diff --git a/includes/activitypub/handler/class-delete.php b/includes/activitypub/handler/class-delete.php index 9fa2224..ae8eb8f 100644 --- a/includes/activitypub/handler/class-delete.php +++ b/includes/activitypub/handler/class-delete.php @@ -9,13 +9,14 @@ namespace Event_Bridge_For_ActivityPub\ActivityPub\Handler; use Activitypub\Collection\Actors; use Event_Bridge_For_ActivityPub\Setup; +use Event_Bridge_For_ActivityPub\ActivityPub\Handler; /** * Handle Delete requests. */ class Delete { /** - * Initialize the class, registering WordPress hooks. + * Initialize the class, registering the handler for incoming `Delete` activities to the ActivityPub plugin. */ public static function init() { \add_action( @@ -38,7 +39,7 @@ class Delete { return; } - if ( ! Create::actor_is_event_source( $activity['actor'] ) ) { + if ( ! Handler::actor_is_event_source( $activity['actor'] ) ) { return; } @@ -47,6 +48,10 @@ class Delete { return; } + if ( Handler::is_time_passed( $activity['object']['startTime'] ) ) { + return; + } + $transmogrifier = Setup::get_transmogrifier(); if ( ! $transmogrifier ) { diff --git a/includes/activitypub/handler/class-update.php b/includes/activitypub/handler/class-update.php index 06d046d..bbc918f 100644 --- a/includes/activitypub/handler/class-update.php +++ b/includes/activitypub/handler/class-update.php @@ -9,6 +9,7 @@ namespace Event_Bridge_For_ActivityPub\ActivityPub\Handler; use Activitypub\Collection\Actors; use Event_Bridge_For_ActivityPub\Setup; +use Event_Bridge_For_ActivityPub\ActivityPub\Handler; use function Activitypub\is_activity_public; @@ -17,7 +18,7 @@ use function Activitypub\is_activity_public; */ class Update { /** - * Initialize the class, registering WordPress hooks. + * Initialize the class, registering the handler for incoming `Update` activities to the ActivityPub plugin. */ public static function init() { \add_action( @@ -29,17 +30,21 @@ class Update { } /** - * Handle "Follow" requests. + * Handle incoming "Update" activities.. * * @param array $activity The activity-object. * @param int $user_id The id of the local blog-user. */ public static function handle_update( $activity, $user_id ) { - // We only process activities that are target the application user. + // We only process activities that are target to the application user. if ( Actors::BLOG_USER_ID !== $user_id ) { return; } + if ( ! Handler::actor_is_event_source( $activity['actor'] ) ) { + return; + } + // Check if Activity is public or not. if ( ! is_activity_public( $activity ) ) { return; @@ -50,6 +55,10 @@ class Update { return; } + if ( Handler::is_time_passed( $activity['object']['startTime'] ) ) { + return; + } + $transmogrifier = Setup::get_transmogrifier(); if ( ! $transmogrifier ) { diff --git a/includes/activitypub/model/class-event-source.php b/includes/activitypub/model/class-event-source.php index 800a82b..df9d882 100644 --- a/includes/activitypub/model/class-event-source.php +++ b/includes/activitypub/model/class-event-source.php @@ -2,6 +2,10 @@ /** * Event-Source (=ActivityPub Actor that is followed) model. * + * This class holds methods needed for relating an ActivityPub actor + * that is followed with the custom post type structure how it is + * stored within WordPress. + * * @package Event_Bridge_For_ActivityPub * @license AGPL-3.0-or-later */ @@ -16,6 +20,10 @@ use function Activitypub\sanitize_url; /** * Event-Source (=ActivityPub Actor that is followed) model. + * + * This class holds methods needed for relating an ActivityPub actor + * that is followed with the custom post type structure how it is + * stored within WordPress. */ class Event_Source extends Actor { const ACTIVITYPUB_USER_HANDLE_REGEXP = '(?:([A-Za-z0-9_.-]+)@((?:[A-Za-z0-9_-]+\.)+[A-Za-z]+))'; diff --git a/includes/activitypub/transformer/class-event-organiser.php b/includes/activitypub/transformer/class-event-organiser.php index 6574f54..7a34b12 100644 --- a/includes/activitypub/transformer/class-event-organiser.php +++ b/includes/activitypub/transformer/class-event-organiser.php @@ -6,13 +6,13 @@ * @license AGPL-3.0-or-later */ -namespace Event_Bridge_For_ActivityPub\Activitypub\Transformer; +namespace Event_Bridge_For_ActivityPub\ActivityPub\Transformer; // Exit if accessed directly. defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore use Activitypub\Activity\Extended_Object\Place; -use Event_Bridge_For_ActivityPub\Activitypub\Transformer\Event; +use Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Event; /** * ActivityPub Transformer for Event Organiser. diff --git a/includes/activitypub/transformer/class-event.php b/includes/activitypub/transformer/class-event.php index cb388c2..88c78b3 100644 --- a/includes/activitypub/transformer/class-event.php +++ b/includes/activitypub/transformer/class-event.php @@ -6,7 +6,7 @@ * @license AGPL-3.0-or-later */ -namespace Event_Bridge_For_ActivityPub\Activitypub\Transformer; +namespace Event_Bridge_For_ActivityPub\ActivityPub\Transformer; // Exit if accessed directly. defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore diff --git a/includes/activitypub/transformer/class-eventin.php b/includes/activitypub/transformer/class-eventin.php index 7b4131d..f1417e0 100644 --- a/includes/activitypub/transformer/class-eventin.php +++ b/includes/activitypub/transformer/class-eventin.php @@ -8,13 +8,13 @@ * @license AGPL-3.0-or-later */ -namespace Event_Bridge_For_ActivityPub\Activitypub\Transformer; +namespace Event_Bridge_For_ActivityPub\ActivityPub\Transformer; // Exit if accessed directly. defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore use Activitypub\Activity\Extended_Object\Place; -use Event_Bridge_For_ActivityPub\Activitypub\Transformer\Event; +use Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Event; use DateTime; use DateTimeZone; use Etn\Core\Event\Event_Model; diff --git a/includes/activitypub/transformer/class-eventprime.php b/includes/activitypub/transformer/class-eventprime.php index c85548e..68a7f0d 100644 --- a/includes/activitypub/transformer/class-eventprime.php +++ b/includes/activitypub/transformer/class-eventprime.php @@ -6,13 +6,13 @@ * @license AGPL-3.0-or-later */ -namespace Event_Bridge_For_ActivityPub\Activitypub\Transformer; +namespace Event_Bridge_For_ActivityPub\ActivityPub\Transformer; // Exit if accessed directly. defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore use Activitypub\Activity\Extended_Object\Place; -use Event_Bridge_For_ActivityPub\Activitypub\Transformer\Event; +use Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Event; /** * ActivityPub Transformer for VS Event diff --git a/includes/activitypub/transformer/class-events-manager.php b/includes/activitypub/transformer/class-events-manager.php index 92fbad2..bc84e2e 100644 --- a/includes/activitypub/transformer/class-events-manager.php +++ b/includes/activitypub/transformer/class-events-manager.php @@ -6,13 +6,13 @@ * @license AGPL-3.0-or-later */ -namespace Event_Bridge_For_ActivityPub\Activitypub\Transformer; +namespace Event_Bridge_For_ActivityPub\ActivityPub\Transformer; // Exit if accessed directly. defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore use Activitypub\Activity\Extended_Object\Place; -use Event_Bridge_For_ActivityPub\Activitypub\Transformer\Event as Event_Transformer; +use Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Event as Event_Transformer; use DateTime; use DateTimeZone; use EM_Event; diff --git a/includes/activitypub/transformer/class-gatherpress.php b/includes/activitypub/transformer/class-gatherpress.php index 79eb601..d58dc2b 100644 --- a/includes/activitypub/transformer/class-gatherpress.php +++ b/includes/activitypub/transformer/class-gatherpress.php @@ -6,14 +6,14 @@ * @license AGPL-3.0-or-later */ -namespace Event_Bridge_For_ActivityPub\Activitypub\Transformer; +namespace Event_Bridge_For_ActivityPub\ActivityPub\Transformer; // Exit if accessed directly. 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; +use Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Event; use GatherPress\Core\Event as GatherPress_Event; /** diff --git a/includes/activitypub/transformer/class-modern-events-calendar-lite.php b/includes/activitypub/transformer/class-modern-events-calendar-lite.php index edff084..3dfbd10 100644 --- a/includes/activitypub/transformer/class-modern-events-calendar-lite.php +++ b/includes/activitypub/transformer/class-modern-events-calendar-lite.php @@ -6,13 +6,13 @@ * @license AGPL-3.0-or-later */ -namespace Event_Bridge_For_ActivityPub\Activitypub\Transformer; +namespace Event_Bridge_For_ActivityPub\ActivityPub\Transformer; // Exit if accessed directly. defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore use Activitypub\Activity\Extended_Object\Place; -use Event_Bridge_For_ActivityPub\Activitypub\Transformer\Event; +use Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Event; use MEC; use MEC\Events\Event as MEC_Event; diff --git a/includes/activitypub/transformer/class-the-events-calendar.php b/includes/activitypub/transformer/class-the-events-calendar.php index 880fee3..08aab3f 100644 --- a/includes/activitypub/transformer/class-the-events-calendar.php +++ b/includes/activitypub/transformer/class-the-events-calendar.php @@ -6,13 +6,13 @@ * @license AGPL-3.0-or-later */ -namespace Event_Bridge_For_ActivityPub\Activitypub\Transformer; +namespace Event_Bridge_For_ActivityPub\ActivityPub\Transformer; // Exit if accessed directly. defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore use Activitypub\Activity\Extended_Object\Place; -use Event_Bridge_For_ActivityPub\Activitypub\Transformer\Event; +use Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Event; use WP_Post; use function Activitypub\esc_hashtag; diff --git a/includes/activitypub/transformer/class-vs-event-list.php b/includes/activitypub/transformer/class-vs-event-list.php index 42fdb14..329880b 100644 --- a/includes/activitypub/transformer/class-vs-event-list.php +++ b/includes/activitypub/transformer/class-vs-event-list.php @@ -6,13 +6,13 @@ * @license AGPL-3.0-or-later */ -namespace Event_Bridge_For_ActivityPub\Activitypub\Transformer; +namespace Event_Bridge_For_ActivityPub\ActivityPub\Transformer; // Exit if accessed directly. defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore use Activitypub\Activity\Extended_Object\Place; -use Event_Bridge_For_ActivityPub\Activitypub\Transformer\Event as Event_Transformer; +use Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Event as Event_Transformer; /** * ActivityPub Transformer for VS Event. diff --git a/includes/activitypub/transformer/class-wp-event-manager.php b/includes/activitypub/transformer/class-wp-event-manager.php index 7985291..aec0d58 100644 --- a/includes/activitypub/transformer/class-wp-event-manager.php +++ b/includes/activitypub/transformer/class-wp-event-manager.php @@ -6,13 +6,13 @@ * @license AGPL-3.0-or-later */ -namespace Event_Bridge_For_ActivityPub\Activitypub\Transformer; +namespace Event_Bridge_For_ActivityPub\ActivityPub\Transformer; // Exit if accessed directly. defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore use Activitypub\Activity\Extended_Object\Place; -use Event_Bridge_For_ActivityPub\Activitypub\Transformer\Event as Event_Transformer; +use Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Event as Event_Transformer; use DateTime; /** diff --git a/includes/activitypub/transmogrifier/class-base.php b/includes/activitypub/transmogrifier/class-base.php index b32d264..6f399ae 100644 --- a/includes/activitypub/transmogrifier/class-base.php +++ b/includes/activitypub/transmogrifier/class-base.php @@ -7,7 +7,7 @@ * @license AGPL-3.0-or-later */ -namespace Event_Bridge_For_ActivityPub\Activitypub\Transmogrifier; +namespace Event_Bridge_For_ActivityPub\ActivityPub\Transmogrifier; use Activitypub\Activity\Extended_Object\Event; use DateTime; diff --git a/includes/activitypub/transmogrifier/class-gatherpress.php b/includes/activitypub/transmogrifier/class-gatherpress.php index 78128c6..9420eb5 100644 --- a/includes/activitypub/transmogrifier/class-gatherpress.php +++ b/includes/activitypub/transmogrifier/class-gatherpress.php @@ -9,7 +9,7 @@ * @license AGPL-3.0-or-later */ -namespace Event_Bridge_For_ActivityPub\Activitypub\Transmogrifier; +namespace Event_Bridge_For_ActivityPub\ActivityPub\Transmogrifier; use DateTime; diff --git a/includes/activitypub/transmogrifier/class-the-events-calendar-event-repository.php b/includes/activitypub/transmogrifier/class-the-events-calendar-event-repository.php index 6952087..32c940c 100644 --- a/includes/activitypub/transmogrifier/class-the-events-calendar-event-repository.php +++ b/includes/activitypub/transmogrifier/class-the-events-calendar-event-repository.php @@ -7,7 +7,7 @@ * @license AGPL-3.0-or-later */ -namespace Event_Bridge_For_ActivityPub\Activitypub\Transmogrifier; +namespace Event_Bridge_For_ActivityPub\ActivityPub\Transmogrifier; use DateTime; diff --git a/includes/activitypub/transmogrifier/class-the-events-calendar.php b/includes/activitypub/transmogrifier/class-the-events-calendar.php index 4b52457..2106b20 100644 --- a/includes/activitypub/transmogrifier/class-the-events-calendar.php +++ b/includes/activitypub/transmogrifier/class-the-events-calendar.php @@ -9,7 +9,7 @@ * @license AGPL-3.0-or-later */ -namespace Event_Bridge_For_ActivityPub\Activitypub\Transmogrifier; +namespace Event_Bridge_For_ActivityPub\ActivityPub\Transmogrifier; use DateTime; diff --git a/includes/class-event-sources.php b/includes/class-event-sources.php index 8b8f629..7b6d3ff 100644 --- a/includes/class-event-sources.php +++ b/includes/class-event-sources.php @@ -11,8 +11,7 @@ namespace Event_Bridge_For_ActivityPub; use Activitypub\Model\Blog; use Event_Bridge_For_ActivityPub\ActivityPub\Collection\Event_Sources as Event_Sources_Collection; -use Event_Bridge_For_ActivityPub\Activitypub\Transmogrifier\GatherPress; -use Event_Bridge_For_ActivityPub\Activitypub\Handler; +use Event_Bridge_For_ActivityPub\ActivityPub\Handler; use Event_Bridge_For_ActivityPub\Admin\User_Interface; use Event_Bridge_For_ActivityPub\Integrations\Event_Plugin_Integration; use Event_Bridge_For_ActivityPub\Integrations\Feature_Event_Sources; @@ -30,17 +29,30 @@ class Event_Sources { * Init. */ public static function init() { + // Register the Event Sources Collection which takes care of managing the event sources. \add_action( 'init', array( Event_Sources_Collection::class, 'init' ) ); + + // Register handlers for incoming activities to the ActivityPub plugin, e.g. incoming `Event` objects. \add_action( 'activitypub_register_handlers', array( Handler::class, 'register_handlers' ) ); + + // Apply modifications to the UI, e.g. disable editing of remote event posts. \add_action( 'init', array( User_Interface::class, 'init' ) ); + + // Register post meta to the event plugins post types needed for easier handling of this feature. \add_action( 'init', array( self::class, 'register_post_meta' ) ); + + // Register filters that prevent cached remote events from being federated again. \add_filter( 'activitypub_is_post_disabled', array( self::class, 'is_cached_external_post' ), 10, 2 ); + \add_filter( 'template_include', array( self::class, 'redirect_activitypub_requests_for_cached_external_events' ), 100 ); + + // Register daily schedule to cleanup cached remote events that have ended. if ( ! \wp_next_scheduled( 'event_bridge_for_activitypub_event_sources_clear_cache' ) ) { \wp_schedule_event( time(), 'daily', 'event_bridge_for_activitypub_event_sources_clear_cache' ); } \add_action( 'event_bridge_for_activitypub_event_sources_clear_cache', array( self::class, 'clear_cache' ) ); + + // Add the actors followed by the event sources feature to the `follow` collection of the used ActivityPub actor. \add_filter( 'activitypub_rest_following', array( self::class, 'add_event_sources_to_following_collection' ), 10, 2 ); - \add_filter( 'template_include', array( self::class, 'redirect_activitypub_requests_for_cached_external_events' ), 100 ); } diff --git a/includes/class-setup.php b/includes/class-setup.php index d74aab5..364dbcb 100644 --- a/includes/class-setup.php +++ b/includes/class-setup.php @@ -64,14 +64,6 @@ class Setup { * @since 1.0.0 */ protected function __construct() { - $this->activitypub_plugin_is_active = defined( 'ACTIVITYPUB_PLUGIN_VERSION' ) || - is_plugin_active( 'activitypub/activitypub.php' ); - // BeforeFirstRelease: decide whether we want to do anything at all when ActivityPub plugin is note active. - // if ( ! $this->activitypub_plugin_is_active ) { - // deactivate_plugins( EVENT_BRIDGE_FOR_ACTIVITYPUB_PLUGIN_FILE ); - // return; - // }. - $this->activitypub_plugin_version = self::get_activitypub_plugin_version(); add_action( 'plugins_loaded', array( $this, 'setup_hooks' ) ); } @@ -204,7 +196,7 @@ class Setup { } /** - * Set up hooks for various purposes. + * Main setup function of the plugin "Event Bridge For ActivityPub". * * This method adds hooks for different purposes as needed. * @@ -213,16 +205,30 @@ class Setup { * @return void */ public function setup_hooks(): void { + // Detect the presence 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 active supported event plugins. $this->detect_active_event_plugins(); + // Register self-activation hook. register_activation_hook( EVENT_BRIDGE_FOR_ACTIVITYPUB_PLUGIN_FILE, array( $this, 'activate' ) ); + // Register listeners whenever any plugin gets activated or deactivated. add_action( 'activated_plugin', array( $this, 'redetect_active_event_plugins' ) ); add_action( 'deactivated_plugin', array( $this, 'redetect_active_event_plugins' ) ); + // Add hook that takes care of all notices in the Admin UI. add_action( 'admin_init', array( $this, 'do_admin_notices' ) ); + + // Add hook that registers all settings to WordPress. add_action( 'admin_init', array( Settings::class, 'register_settings' ) ); + + // Add hook that loads CSS and JavaScript files fr the Admin UI. add_action( 'admin_enqueue_scripts', array( self::class, 'enqueue_styles' ) ); + + // Register the settings page(s) of this plugin to WordPress. add_action( 'admin_menu', array( Settings_Page::class, 'admin_menu' ) ); add_filter( 'plugin_action_links_' . EVENT_BRIDGE_FOR_ACTIVITYPUB_PLUGIN_BASENAME, @@ -234,18 +240,21 @@ class Setup { return; } + // Register health checks and status reports to the WordPress status report site. add_action( 'init', array( Health_Check::class, 'init' ) ); - // Check if the minimum required version of the ActivityPub plugin is installed. + // Check if the minimum required version of the ActivityPub plugin is installed, if not abort. if ( ! version_compare( $this->activitypub_plugin_version, EVENT_BRIDGE_FOR_ACTIVITYPUB_ACTIVITYPUB_PLUGIN_MIN_VERSION ) ) { return; } + // 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(); } + + // Lastly but most importantly: register the ActivityPub transformers for events to the ActivityPub plugin. add_filter( 'activitypub_transformer', array( $this, 'register_activitypub_event_transformer' ), 10, 3 ); - self::get_default_integration_class_name_used_for_event_sources_feature(); } /** diff --git a/includes/integrations/class-event-organiser.php b/includes/integrations/class-event-organiser.php index d6c0348..55c03d4 100644 --- a/includes/integrations/class-event-organiser.php +++ b/includes/integrations/class-event-organiser.php @@ -2,7 +2,8 @@ /** * Event Organiser. * - * Defines all the necessary meta information for the Event Organiser plugin. + * Defines all the necessary meta information and methods for the integration + * of the WordPress "Event Organiser" plugin. * * @link https://wordpress.org/plugins/event-organiser/ * @package Event_Bridge_For_ActivityPub @@ -17,9 +18,10 @@ use Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Event_Organiser as Even defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore /** - * Interface for a supported event plugin. + * Event Organiser. * - * This interface defines which information is necessary for a supported event plugin. + * Defines all the necessary meta information and methods for the integration + * of the WordPress "Event Organiser" plugin. * * @since 1.0.0 */ diff --git a/includes/integrations/class-event-plugin-integration.php b/includes/integrations/class-event-plugin-integration.php index 252bb64..d18d2ee 100644 --- a/includes/integrations/class-event-plugin-integration.php +++ b/includes/integrations/class-event-plugin-integration.php @@ -1,8 +1,8 @@ assertInstanceOf( \Event_Bridge_For_ActivityPub\Activitypub\Transformer\Event_Organiser::class, $transformer ); + $this->assertInstanceOf( \Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Event_Organiser::class, $transformer ); } /** diff --git a/tests/test-class-plugin-eventin.php b/tests/test-class-plugin-eventin.php index 51ec62a..d316f2b 100644 --- a/tests/test-class-plugin-eventin.php +++ b/tests/test-class-plugin-eventin.php @@ -64,7 +64,7 @@ class Test_Eventin extends WP_UnitTestCase { $transformer = \Activitypub\Transformer\Factory::get_transformer( get_post( $event->id ) ); // Check that we got the right transformer. - $this->assertInstanceOf( \Event_Bridge_For_ActivityPub\Activitypub\Transformer\Eventin::class, $transformer ); + $this->assertInstanceOf( \Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Eventin::class, $transformer ); } /** diff --git a/tests/test-class-plugin-eventprime.php b/tests/test-class-plugin-eventprime.php index e8c8ce3..1e750ff 100644 --- a/tests/test-class-plugin-eventprime.php +++ b/tests/test-class-plugin-eventprime.php @@ -93,7 +93,7 @@ class Test_EventPrime extends WP_UnitTestCase { $transformer = \Activitypub\Transformer\Factory::get_transformer( $wp_object ); // Check that we got the right transformer. - $this->assertInstanceOf( \Event_Bridge_For_ActivityPub\Activitypub\Transformer\EventPrime::class, $transformer ); + $this->assertInstanceOf( \Event_Bridge_For_ActivityPub\ActivityPub\Transformer\EventPrime::class, $transformer ); } /** diff --git a/tests/test-class-plugin-events-manger.php b/tests/test-class-plugin-events-manger.php index ae87919..956a332 100644 --- a/tests/test-class-plugin-events-manger.php +++ b/tests/test-class-plugin-events-manger.php @@ -61,7 +61,7 @@ class Test_Events_Manager extends WP_UnitTestCase { $transformer = \Activitypub\Transformer\Factory::get_transformer( $wp_object ); // Check that we got the right transformer. - $this->assertInstanceOf( \Event_Bridge_For_ActivityPub\Activitypub\Transformer\Events_Manager::class, $transformer ); + $this->assertInstanceOf( \Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Events_Manager::class, $transformer ); } /** diff --git a/tests/test-class-plugin-gatherpress.php b/tests/test-class-plugin-gatherpress.php index 9a7a076..2fae248 100644 --- a/tests/test-class-plugin-gatherpress.php +++ b/tests/test-class-plugin-gatherpress.php @@ -65,7 +65,7 @@ class Test_GatherPress extends WP_UnitTestCase { $transformer = \Activitypub\Transformer\Factory::get_transformer( $event->event ); // Check that we got the right transformer. - $this->assertInstanceOf( \Event_Bridge_For_ActivityPub\Activitypub\Transformer\GatherPress::class, $transformer ); + $this->assertInstanceOf( \Event_Bridge_For_ActivityPub\ActivityPub\Transformer\GatherPress::class, $transformer ); } /** diff --git a/tests/test-class-plugin-modern-events-calendar-lite.php b/tests/test-class-plugin-modern-events-calendar-lite.php index 16db755..3e84a81 100644 --- a/tests/test-class-plugin-modern-events-calendar-lite.php +++ b/tests/test-class-plugin-modern-events-calendar-lite.php @@ -74,7 +74,7 @@ class Test_Modern_Events_Calendar_Lite extends WP_UnitTestCase { $transformer = \Activitypub\Transformer\Factory::get_transformer( $wp_object ); // Check that we got the right transformer. - $this->assertInstanceOf( \Event_Bridge_For_ActivityPub\Activitypub\Transformer\Modern_Events_Calendar_Lite::class, $transformer ); + $this->assertInstanceOf( \Event_Bridge_For_ActivityPub\ActivityPub\Transformer\Modern_Events_Calendar_Lite::class, $transformer ); } /** diff --git a/tests/test-class-plugin-the-events-calendar.php b/tests/test-class-plugin-the-events-calendar.php index b2ef602..c88bef7 100644 --- a/tests/test-class-plugin-the-events-calendar.php +++ b/tests/test-class-plugin-the-events-calendar.php @@ -91,7 +91,7 @@ class Test_The_Events_Calendar extends WP_UnitTestCase { $transformer = \Activitypub\Transformer\Factory::get_transformer( $wp_object ); // Check that we got the right transformer. - $this->assertInstanceOf( \Event_Bridge_For_ActivityPub\Activitypub\Transformer\The_Events_Calendar::class, $transformer ); + $this->assertInstanceOf( \Event_Bridge_For_ActivityPub\ActivityPub\Transformer\The_Events_Calendar::class, $transformer ); } /** diff --git a/tests/test-class-plugin-vs-event-list.php b/tests/test-class-plugin-vs-event-list.php index 96ce9e0..a99d43f 100644 --- a/tests/test-class-plugin-vs-event-list.php +++ b/tests/test-class-plugin-vs-event-list.php @@ -58,7 +58,7 @@ class Test_VS_Event_List extends WP_UnitTestCase { $transformer = \Activitypub\Transformer\Factory::get_transformer( $wp_object ); // Check that we got the right transformer. - $this->assertInstanceOf( \Event_Bridge_For_ActivityPub\Activitypub\Transformer\VS_Event_List::class, $transformer ); + $this->assertInstanceOf( \Event_Bridge_For_ActivityPub\ActivityPub\Transformer\VS_Event_List::class, $transformer ); } /** diff --git a/tests/test-class-plugin-wp-event-manager.php b/tests/test-class-plugin-wp-event-manager.php index cfc5191..af68b20 100644 --- a/tests/test-class-plugin-wp-event-manager.php +++ b/tests/test-class-plugin-wp-event-manager.php @@ -58,7 +58,7 @@ class Test_WP_Event_Manager extends WP_UnitTestCase { $transformer = \Activitypub\Transformer\Factory::get_transformer( $wp_object ); // Check that we got the right transformer. - $this->assertInstanceOf( \Event_Bridge_For_ActivityPub\Activitypub\Transformer\WP_Event_Manager::class, $transformer ); + $this->assertInstanceOf( \Event_Bridge_For_ActivityPub\ActivityPub\Transformer\WP_Event_Manager::class, $transformer ); } /**