From a84a5955fc6c70024729607dd86ef488e223dced Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Menrath?= Date: Thu, 12 Dec 2024 21:34:01 +0100 Subject: [PATCH 1/3] Improving detection of active event plugins: use caching and don't use WordPress internal constant WP_PLUGINS_DIR --- .../class-event-plugin-admin-notices.php | 12 ++++- includes/admin/class-health-check.php | 6 ++- includes/admin/class-settings-page.php | 3 ++ includes/class-setup.php | 50 +++++++++++++++---- .../integrations/class-event-organiser.php | 2 +- includes/integrations/class-event-plugin.php | 10 ++-- includes/integrations/class-eventin.php | 2 +- includes/integrations/class-eventprime.php | 7 ++- .../integrations/class-events-manager.php | 2 +- includes/integrations/class-gatherpress.php | 2 +- .../class-modern-events-calendar-lite.php | 2 +- .../class-the-events-calendar.php | 2 +- includes/integrations/class-vs-event-list.php | 2 +- .../integrations/class-wp-event-manager.php | 2 +- 14 files changed, 74 insertions(+), 30 deletions(-) diff --git a/includes/admin/class-event-plugin-admin-notices.php b/includes/admin/class-event-plugin-admin-notices.php index 823472e..cb4af54 100644 --- a/includes/admin/class-event-plugin-admin-notices.php +++ b/includes/admin/class-event-plugin-admin-notices.php @@ -69,7 +69,15 @@ class Event_Plugin_Admin_Notices { * @return void */ private function do_admin_notice_post_type_not_activitypub_enabled(): void { - $event_plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . $this->event_plugin::get_plugin_file() ); + $all_plugins = get_plugins(); + $event_plugin_file = $this->event_plugin::get_relative_plugin_file(); + if ( isset( $all_plugins[ $event_plugin_file ]['Name'] ) ) { + $event_plugin_name = $all_plugins[ $event_plugin_file ]['Name']; + } elseif ( isset( get_mu_plugins()[ $event_plugin_file ]['Name'] ) ) { + $event_plugin_name = get_mu_plugins()[ $event_plugin_file ]['Name']; + } else { + return; + } $activitypub_plugin_data = get_plugin_data( ACTIVITYPUB_PLUGIN_FILE ); $notice = sprintf( /* translators: 1: the name of the event plugin a admin notice is shown. 2: The name of the ActivityPub plugin. */ @@ -79,7 +87,7 @@ class Event_Plugin_Admin_Notices { 'event-bridge-for-activitypub' ), esc_html( $activitypub_plugin_data['Name'] ), - esc_html( $event_plugin_data['Name'] ), + esc_html( $event_plugin_name ), admin_url( 'options-general.php?page=activitypub&tab=settings' ) ); $allowed_html = array( diff --git a/includes/admin/class-health-check.php b/includes/admin/class-health-check.php index 61faa18..45d4ea0 100644 --- a/includes/admin/class-health-check.php +++ b/includes/admin/class-health-check.php @@ -114,7 +114,9 @@ class Health_Check { */ public static function get_most_recent_event_posts( $event_post_type = null, $number_of_posts = 5 ) { if ( ! $event_post_type ) { - $event_post_type = Setup::get_instance()->get_active_event_plugins()[0]->get_post_type(); + $active_event_plugins = Setup::get_instance()->get_active_event_plugins(); + $active_event_plugin = reset( $active_event_plugins ); + $event_post_type = $active_event_plugin->get_post_type(); } $args = array( @@ -148,7 +150,7 @@ class Health_Check { $active_event_plugins = Setup::get_instance()->get_active_event_plugins(); $info = array(); foreach ( $active_event_plugins as $active_event_plugin ) { - $event_plugin_file = $active_event_plugin->get_plugin_file(); + $event_plugin_file = $active_event_plugin->get_relative_plugin_file(); $event_plugin_data = \get_plugin_data( $event_plugin_file ); $event_plugin_name = isset( $event_plugin_data['Plugin Name'] ) ? $event_plugin_data['Plugin Name'] : 'Name not found'; $event_plugin_version = isset( $event_plugin_version['Plugin Version'] ) ? $event_plugin_version['Plugin Version'] : 'Version not found'; diff --git a/includes/admin/class-settings-page.php b/includes/admin/class-settings-page.php index 3a3903f..e901064 100644 --- a/includes/admin/class-settings-page.php +++ b/includes/admin/class-settings-page.php @@ -97,6 +97,9 @@ class Settings_Page { $tab = sanitize_key( $_GET['tab'] ); } + // Fallback to always re-scan active event plugins, when user visits admin area of this plugin. + Setup::get_instance()->redetect_active_event_plugins(); + switch ( $tab ) { case 'settings': $plugin_setup = Setup::get_instance(); diff --git a/includes/class-setup.php b/includes/class-setup.php index ce6afc4..b2ccb24 100644 --- a/includes/class-setup.php +++ b/includes/class-setup.php @@ -67,9 +67,8 @@ class Setup { // deactivate_plugins( EVENT_BRIDGE_FOR_ACTIVITYPUB_PLUGIN_FILE ); // return; // }. - $this->active_event_plugins = self::detect_active_event_plugins(); $this->activitypub_plugin_version = self::get_activitypub_plugin_version(); - $this->setup_hooks(); + add_action( 'plugins_loaded', array( $this, 'setup_hooks' ) ); } /** @@ -106,8 +105,7 @@ class Setup { if ( defined( 'ACTIVITYPUB_PLUGIN_VERSION' ) ) { return constant( 'ACTIVITYPUB_PLUGIN_VERSION' ); } - $version = get_file_data( WP_PLUGIN_DIR . '/activitypub/activitypub.php', array( 'Version' ) )[0]; - return $version ?? '0.0.0'; + return '0.0.0'; } /** @@ -136,23 +134,47 @@ class Setup { '\Event_Bridge_For_ActivityPub\Integrations\Event_Organiser', ); + /** + * Force the re-scan for active event plugins without using the cached transient. + * + * @return void + */ + public function redetect_active_event_plugins(): void { + delete_transient( 'event_bridge_for_activitypub_active_event_plugins' ); + $this->detect_active_event_plugins(); + } + /** * Function that checks for supported activated event plugins. * * @return array List of supported event plugins as keys from the SUPPORTED_EVENT_PLUGINS const. */ - public static function detect_active_event_plugins(): array { - $active_event_plugins = array(); + public function detect_active_event_plugins(): array { + $active_event_plugins = get_transient( 'event_bridge_for_activitypub_active_event_plugins' ); + if ( $active_event_plugins ) { + $this->active_event_plugins = $active_event_plugins; + return $active_event_plugins; + } + + if ( ! function_exists( 'get_plugins' ) ) { + require_once ABSPATH . 'wp-admin/includes/plugin.php'; + } + + $all_plugins = array_merge( get_plugins(), get_mu_plugins() ); + + $active_event_plugins = array(); foreach ( self::EVENT_PLUGIN_CLASSES as $event_plugin_class ) { - if ( ! class_exists( $event_plugin_class ) || ! method_exists( $event_plugin_class, 'get_plugin_file' ) ) { + $event_plugin_file = call_user_func( array( $event_plugin_class, 'get_relative_plugin_file' ) ); + if ( ! $event_plugin_file ) { continue; } - $event_plugin_file = call_user_func( array( $event_plugin_class, 'get_plugin_file' ) ); - if ( \is_plugin_active( $event_plugin_file ) ) { - $active_event_plugins[] = new $event_plugin_class(); + if ( array_key_exists( $event_plugin_file, $all_plugins ) && \is_plugin_active( $event_plugin_file ) ) { + $active_event_plugins[ $event_plugin_file ] = new $event_plugin_class(); } } + set_transient( 'event_bridge_for_activitypub_active_event_plugins', $active_event_plugins ); + $this->active_event_plugins = $active_event_plugins; return $active_event_plugins; } @@ -165,9 +187,14 @@ class Setup { * * @return void */ - protected function setup_hooks(): void { + public function setup_hooks(): void { + $this->detect_active_event_plugins(); + register_activation_hook( EVENT_BRIDGE_FOR_ACTIVITYPUB_PLUGIN_FILE, array( $this, 'activate' ) ); + add_action( 'activated_plugin', array( $this, 'redetect_active_event_plugins' ) ); + add_action( 'deactivated_plugin', array( $this, 'redetect_active_event_plugins' ) ); + add_action( 'admin_init', array( $this, 'do_admin_notices' ) ); add_action( 'admin_init', array( Settings::class, 'register_settings' ) ); add_action( 'admin_enqueue_scripts', array( self::class, 'enqueue_styles' ) ); @@ -303,6 +330,7 @@ class Setup { * @return void */ 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 ) ); diff --git a/includes/integrations/class-event-organiser.php b/includes/integrations/class-event-organiser.php index 9278f43..0fbd190 100644 --- a/includes/integrations/class-event-organiser.php +++ b/includes/integrations/class-event-organiser.php @@ -27,7 +27,7 @@ final class Event_Organiser extends Event_Plugin { * * @return string */ - public static function get_plugin_file(): string { + public static function get_relative_plugin_file(): string { return 'event-organiser/event-organiser.php'; } diff --git a/includes/integrations/class-event-plugin.php b/includes/integrations/class-event-plugin.php index 56d020a..c5e7c40 100644 --- a/includes/integrations/class-event-plugin.php +++ b/includes/integrations/class-event-plugin.php @@ -24,11 +24,11 @@ defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore */ abstract class Event_Plugin { /** - * Returns the full plugin file. + * Returns the plugin file relative to the plugins dir. * * @return string */ - abstract public static function get_plugin_file(): string; + abstract public static function get_relative_plugin_file(): string; /** * Returns the event post type of the plugin. @@ -57,9 +57,9 @@ abstract class Event_Plugin { * Get the plugins name from the main plugin-file's top-level-file-comment. */ final public static function get_plugin_name(): string { - $plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . static::get_plugin_file() ); - if ( isset( $plugin_data['Name'] ) ) { - return $plugin_data['Name']; + $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 { return ''; } diff --git a/includes/integrations/class-eventin.php b/includes/integrations/class-eventin.php index 6ce88a6..364a2a8 100644 --- a/includes/integrations/class-eventin.php +++ b/includes/integrations/class-eventin.php @@ -27,7 +27,7 @@ final class Eventin extends Event_plugin { * * @return string */ - public static function get_plugin_file(): string { + public static function get_relative_plugin_file(): string { return 'wp-event-solution/eventin.php'; } diff --git a/includes/integrations/class-eventprime.php b/includes/integrations/class-eventprime.php index af78347..44d0530 100644 --- a/includes/integrations/class-eventprime.php +++ b/includes/integrations/class-eventprime.php @@ -33,7 +33,7 @@ final class EventPrime extends Event_Plugin { * * @return string */ - public static function get_plugin_file(): string { + public static function get_relative_plugin_file(): string { return 'eventprime-event-calendar-management/event-prime.php'; } @@ -75,6 +75,9 @@ final class EventPrime extends Event_Plugin { /** * Determine whether the current request is an EventPrime ActivityPub request. + * + * Forked from https://github.com/Automattic/wordpress-activitypub/blob/trunk/includes/functions.php + * the function is_activitypub_request. */ private static function is_eventprime_activitypub_request() { global $wp_query; @@ -192,7 +195,7 @@ final class EventPrime extends Event_Plugin { * @see https://www.w3.org/wiki/SocialCG/ActivityPub/Primer/Authentication_Authorization#Authorized_fetch * @see https://swicg.github.io/activitypub-http-signature/#authorized-fetch */ - if ( $activitypub_template && ACTIVITYPUB_AUTHORIZED_FETCH ) { + if ( $activitypub_template && defined( 'ACTIVITYPUB_AUTHORIZED_FETCH') && constant( 'ACTIVITYPUB_AUTHORIZED_FETCH' ) ) { $verification = Signature::verify_http_signature( $_SERVER ); if ( \is_wp_error( $verification ) ) { header( 'HTTP/1.1 401 Unauthorized' ); diff --git a/includes/integrations/class-events-manager.php b/includes/integrations/class-events-manager.php index 2f22620..9208126 100644 --- a/includes/integrations/class-events-manager.php +++ b/includes/integrations/class-events-manager.php @@ -27,7 +27,7 @@ final class Events_Manager extends Event_Plugin { * * @return string */ - public static function get_plugin_file(): string { + public static function get_relative_plugin_file(): string { return 'events-manager/events-manager.php'; } diff --git a/includes/integrations/class-gatherpress.php b/includes/integrations/class-gatherpress.php index 57cd222..f68fbbc 100644 --- a/includes/integrations/class-gatherpress.php +++ b/includes/integrations/class-gatherpress.php @@ -27,7 +27,7 @@ final class GatherPress extends Event_Plugin { * * @return string */ - public static function get_plugin_file(): string { + public static function get_relative_plugin_file(): string { return 'gatherpress/gatherpress.php'; } diff --git a/includes/integrations/class-modern-events-calendar-lite.php b/includes/integrations/class-modern-events-calendar-lite.php index 02329ae..95bfef7 100644 --- a/includes/integrations/class-modern-events-calendar-lite.php +++ b/includes/integrations/class-modern-events-calendar-lite.php @@ -27,7 +27,7 @@ final class Modern_Events_Calendar_Lite extends Event_plugin { * * @return string */ - public static function get_plugin_file(): string { + public static function get_relative_plugin_file(): string { return 'modern-events-calendar-lite/modern-events-calendar-lite.php'; } diff --git a/includes/integrations/class-the-events-calendar.php b/includes/integrations/class-the-events-calendar.php index 42d295e..6f6e17b 100644 --- a/includes/integrations/class-the-events-calendar.php +++ b/includes/integrations/class-the-events-calendar.php @@ -27,7 +27,7 @@ final class The_Events_Calendar extends Event_plugin { * * @return string */ - public static function get_plugin_file(): string { + public static function get_relative_plugin_file(): string { return 'the-events-calendar/the-events-calendar.php'; } diff --git a/includes/integrations/class-vs-event-list.php b/includes/integrations/class-vs-event-list.php index 6ce4ba6..dc2747d 100644 --- a/includes/integrations/class-vs-event-list.php +++ b/includes/integrations/class-vs-event-list.php @@ -30,7 +30,7 @@ final class VS_Event_List extends Event_Plugin { * * @return string */ - public static function get_plugin_file(): string { + public static function get_relative_plugin_file(): string { return 'very-simple-event-list/vsel.php'; } diff --git a/includes/integrations/class-wp-event-manager.php b/includes/integrations/class-wp-event-manager.php index 18c217d..2adc473 100644 --- a/includes/integrations/class-wp-event-manager.php +++ b/includes/integrations/class-wp-event-manager.php @@ -30,7 +30,7 @@ final class WP_Event_Manager extends Event_Plugin { * * @return string */ - public static function get_plugin_file(): string { + public static function get_relative_plugin_file(): string { return 'wp-event-manager/wp-event-manager.php'; } -- 2.39.5 From 216665e0029078a52c04bbec90444e90d895d68e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Menrath?= Date: Thu, 12 Dec 2024 21:37:29 +0100 Subject: [PATCH 2/3] phpcs --- includes/class-setup.php | 2 +- includes/integrations/class-eventprime.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/includes/class-setup.php b/includes/class-setup.php index b2ccb24..f75721f 100644 --- a/includes/class-setup.php +++ b/includes/class-setup.php @@ -188,7 +188,7 @@ class Setup { * @return void */ public function setup_hooks(): void { - $this->detect_active_event_plugins(); + $this->detect_active_event_plugins(); register_activation_hook( EVENT_BRIDGE_FOR_ACTIVITYPUB_PLUGIN_FILE, array( $this, 'activate' ) ); diff --git a/includes/integrations/class-eventprime.php b/includes/integrations/class-eventprime.php index 44d0530..a50f7ff 100644 --- a/includes/integrations/class-eventprime.php +++ b/includes/integrations/class-eventprime.php @@ -195,7 +195,7 @@ final class EventPrime extends Event_Plugin { * @see https://www.w3.org/wiki/SocialCG/ActivityPub/Primer/Authentication_Authorization#Authorized_fetch * @see https://swicg.github.io/activitypub-http-signature/#authorized-fetch */ - if ( $activitypub_template && defined( 'ACTIVITYPUB_AUTHORIZED_FETCH') && constant( 'ACTIVITYPUB_AUTHORIZED_FETCH' ) ) { + if ( $activitypub_template && defined( 'ACTIVITYPUB_AUTHORIZED_FETCH' ) && constant( 'ACTIVITYPUB_AUTHORIZED_FETCH' ) ) { $verification = Signature::verify_http_signature( $_SERVER ); if ( \is_wp_error( $verification ) ) { header( 'HTTP/1.1 401 Unauthorized' ); -- 2.39.5 From 06ecbe66f34d7e33701761be994ef8bd39cc1c27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Menrath?= Date: Thu, 12 Dec 2024 21:40:58 +0100 Subject: [PATCH 3/3] bump version to 0.3.2 --- CHANGELOG.md | 2 +- README.md | 2 +- event-bridge-for-activitypub.php | 2 +- readme.txt | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 870d722..d7e4577 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Add custom summary via shortcodes -## [0.3.1] - 2024-11-16 +## [0.3.2] - 2024-12-12 * Initial release on WordPress.org diff --git a/README.md b/README.md index f61876b..30f63c1 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ **Tags:** events, fediverse, activitypub, calendar **Requires at least:** 6.5 **Tested up to:** 6.7 -**Stable tag:** 0.3.1 +**Stable tag:** 0.3.2 **Requires PHP:** 7.4 **License:** AGPL-3.0-or-later **License URI:** https://www.gnu.org/licenses/agpl-3.0.html diff --git a/event-bridge-for-activitypub.php b/event-bridge-for-activitypub.php index 4bb34cf..ec9cfad 100644 --- a/event-bridge-for-activitypub.php +++ b/event-bridge-for-activitypub.php @@ -3,7 +3,7 @@ * Plugin Name: Event Bridge for ActivityPub * Description: Integrating popular event plugins with the ActivityPub plugin. * Plugin URI: https://event-federation.eu/ - * Version: 0.3.1.1 + * Version: 0.3.2 * Author: André Menrath * Author URI: https://graz.social/@linos * Text Domain: event-bridge-for-activitypub diff --git a/readme.txt b/readme.txt index 3386f69..eb89bf1 100644 --- a/readme.txt +++ b/readme.txt @@ -3,7 +3,7 @@ Contributors: andremenrath Tags: events, fediverse, activitypub, calendar Requires at least: 6.5 Tested up to: 6.7 -Stable tag: 0.3.1 +Stable tag: 0.3.2 Requires PHP: 7.4 License: AGPL-3.0-or-later License URI: https://www.gnu.org/licenses/agpl-3.0.html -- 2.39.5