Improving detection of active event plugins: use caching and don't use WordPress internal constant WP_PLUGINS_DIR (#87)
Some checks failed
PHPUnit / PHPUnit – PHP 8.3 (push) Waiting to run
PHPUnit / PHPUnit – PHP 8.4 (push) Waiting to run
PHP Code Checker / PHP Code Checker (push) Successful in 45s
PHPUnit / PHPUnit – PHP 7.4 (push) Successful in 1m2s
PHPUnit / PHPUnit – PHP 8.0 (push) Successful in 1m2s
PHPUnit / PHPUnit – PHP 8.1 (push) Successful in 1m6s
/ upload-release (push) Has been cancelled
PHPUnit / PHPUnit – PHP 8.2 (push) Has been cancelled

Reviewed-on: #87
Co-authored-by: André Menrath <andre.menrath@posteo.de>
Co-committed-by: André Menrath <andre.menrath@posteo.de>
This commit is contained in:
André Menrath 2024-12-12 23:24:36 +01:00
parent 44daeb5b59
commit 6dd511e4b0
20 changed files with 80 additions and 37 deletions

View file

@ -11,7 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* Add custom summary via shortcodes * Add custom summary via shortcodes
## [0.3.1] - 2024-11-16 ## [0.3.2] - 2024-12-12
* Initial release on WordPress.org * Initial release on WordPress.org

View file

@ -3,7 +3,7 @@
**Tags:** events, fediverse, activitypub, calendar **Tags:** events, fediverse, activitypub, calendar
**Requires at least:** 6.5 **Requires at least:** 6.5
**Tested up to:** 6.7 **Tested up to:** 6.7
**Stable tag:** 0.3.1 **Stable tag:** 0.3.2
**Requires PHP:** 7.4 **Requires PHP:** 7.4
**License:** AGPL-3.0-or-later **License:** AGPL-3.0-or-later
**License URI:** https://www.gnu.org/licenses/agpl-3.0.html **License URI:** https://www.gnu.org/licenses/agpl-3.0.html

View file

@ -3,7 +3,7 @@
* Plugin Name: Event Bridge for ActivityPub * Plugin Name: Event Bridge for ActivityPub
* Description: Integrating popular event plugins with the ActivityPub plugin. * Description: Integrating popular event plugins with the ActivityPub plugin.
* Plugin URI: https://event-federation.eu/ * Plugin URI: https://event-federation.eu/
* Version: 0.3.1.1 * Version: 0.3.2
* Author: André Menrath * Author: André Menrath
* Author URI: https://graz.social/@linos * Author URI: https://graz.social/@linos
* Text Domain: event-bridge-for-activitypub * Text Domain: event-bridge-for-activitypub

View file

@ -69,7 +69,15 @@ class Event_Plugin_Admin_Notices {
* @return void * @return void
*/ */
private function do_admin_notice_post_type_not_activitypub_enabled(): 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 ); $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. */ /* 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' 'event-bridge-for-activitypub'
), ),
esc_html( $activitypub_plugin_data['Name'] ), 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' ) admin_url( 'options-general.php?page=activitypub&tab=settings' )
); );
$allowed_html = array( $allowed_html = array(

View file

@ -114,7 +114,9 @@ class Health_Check {
*/ */
public static function get_most_recent_event_posts( $event_post_type = null, $number_of_posts = 5 ) { public static function get_most_recent_event_posts( $event_post_type = null, $number_of_posts = 5 ) {
if ( ! $event_post_type ) { 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( $args = array(
@ -148,7 +150,7 @@ class Health_Check {
$active_event_plugins = Setup::get_instance()->get_active_event_plugins(); $active_event_plugins = Setup::get_instance()->get_active_event_plugins();
$info = array(); $info = array();
foreach ( $active_event_plugins as $active_event_plugin ) { 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_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_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'; $event_plugin_version = isset( $event_plugin_version['Plugin Version'] ) ? $event_plugin_version['Plugin Version'] : 'Version not found';

View file

@ -97,6 +97,9 @@ class Settings_Page {
$tab = sanitize_key( $_GET['tab'] ); $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 ) { switch ( $tab ) {
case 'settings': case 'settings':
$plugin_setup = Setup::get_instance(); $plugin_setup = Setup::get_instance();

View file

@ -67,9 +67,8 @@ class Setup {
// deactivate_plugins( EVENT_BRIDGE_FOR_ACTIVITYPUB_PLUGIN_FILE ); // deactivate_plugins( EVENT_BRIDGE_FOR_ACTIVITYPUB_PLUGIN_FILE );
// return; // return;
// }. // }.
$this->active_event_plugins = self::detect_active_event_plugins();
$this->activitypub_plugin_version = self::get_activitypub_plugin_version(); $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' ) ) { if ( defined( 'ACTIVITYPUB_PLUGIN_VERSION' ) ) {
return constant( 'ACTIVITYPUB_PLUGIN_VERSION' ); return constant( 'ACTIVITYPUB_PLUGIN_VERSION' );
} }
$version = get_file_data( WP_PLUGIN_DIR . '/activitypub/activitypub.php', array( 'Version' ) )[0]; return '0.0.0';
return $version ?? '0.0.0';
} }
/** /**
@ -136,23 +134,47 @@ class Setup {
'\Event_Bridge_For_ActivityPub\Integrations\Event_Organiser', '\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. * Function that checks for supported activated event plugins.
* *
* @return array List of supported event plugins as keys from the SUPPORTED_EVENT_PLUGINS const. * @return array List of supported event plugins as keys from the SUPPORTED_EVENT_PLUGINS const.
*/ */
public static function detect_active_event_plugins(): array { public function detect_active_event_plugins(): array {
$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 ) { 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; continue;
} }
$event_plugin_file = call_user_func( array( $event_plugin_class, 'get_plugin_file' ) ); if ( array_key_exists( $event_plugin_file, $all_plugins ) && \is_plugin_active( $event_plugin_file ) ) {
if ( \is_plugin_active( $event_plugin_file ) ) { $active_event_plugins[ $event_plugin_file ] = new $event_plugin_class();
$active_event_plugins[] = 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; return $active_event_plugins;
} }
@ -165,9 +187,14 @@ class Setup {
* *
* @return void * @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' ) ); 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( $this, 'do_admin_notices' ) );
add_action( 'admin_init', array( Settings::class, 'register_settings' ) ); add_action( 'admin_init', array( Settings::class, 'register_settings' ) );
add_action( 'admin_enqueue_scripts', array( self::class, 'enqueue_styles' ) ); add_action( 'admin_enqueue_scripts', array( self::class, 'enqueue_styles' ) );
@ -303,6 +330,7 @@ class Setup {
* @return void * @return void
*/ */
public function activate(): void { public function activate(): void {
$this->redetect_active_event_plugins();
// Don't allow plugin activation, when the ActivityPub plugin is not activated yet. // Don't allow plugin activation, when the ActivityPub plugin is not activated yet.
if ( ! $this->activitypub_plugin_is_active ) { if ( ! $this->activitypub_plugin_is_active ) {
deactivate_plugins( plugin_basename( EVENT_BRIDGE_FOR_ACTIVITYPUB_PLUGIN_FILE ) ); deactivate_plugins( plugin_basename( EVENT_BRIDGE_FOR_ACTIVITYPUB_PLUGIN_FILE ) );

View file

@ -27,7 +27,7 @@ final class Event_Organiser extends Event_Plugin {
* *
* @return string * @return string
*/ */
public static function get_plugin_file(): string { public static function get_relative_plugin_file(): string {
return 'event-organiser/event-organiser.php'; return 'event-organiser/event-organiser.php';
} }

View file

@ -24,11 +24,11 @@ defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
*/ */
abstract class Event_Plugin { abstract class Event_Plugin {
/** /**
* Returns the full plugin file. * Returns the plugin file relative to the plugins dir.
* *
* @return string * @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. * 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. * Get the plugins name from the main plugin-file's top-level-file-comment.
*/ */
final public static function get_plugin_name(): string { final public static function get_plugin_name(): string {
$plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . static::get_plugin_file() ); $all_plugins = array_merge( get_plugins(), get_mu_plugins() );
if ( isset( $plugin_data['Name'] ) ) { if ( isset( $all_plugins[ static::get_relative_plugin_file() ]['Name'] ) ) {
return $plugin_data['Name']; return $all_plugins[ static::get_relative_plugin_file() ]['Name'];
} else { } else {
return ''; return '';
} }

View file

@ -27,7 +27,7 @@ final class Eventin extends Event_plugin {
* *
* @return string * @return string
*/ */
public static function get_plugin_file(): string { public static function get_relative_plugin_file(): string {
return 'wp-event-solution/eventin.php'; return 'wp-event-solution/eventin.php';
} }

View file

@ -33,7 +33,7 @@ final class EventPrime extends Event_Plugin {
* *
* @return string * @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'; 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. * 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() { private static function is_eventprime_activitypub_request() {
global $wp_query; 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://www.w3.org/wiki/SocialCG/ActivityPub/Primer/Authentication_Authorization#Authorized_fetch
* @see https://swicg.github.io/activitypub-http-signature/#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 ); $verification = Signature::verify_http_signature( $_SERVER );
if ( \is_wp_error( $verification ) ) { if ( \is_wp_error( $verification ) ) {
header( 'HTTP/1.1 401 Unauthorized' ); header( 'HTTP/1.1 401 Unauthorized' );

View file

@ -27,7 +27,7 @@ final class Events_Manager extends Event_Plugin {
* *
* @return string * @return string
*/ */
public static function get_plugin_file(): string { public static function get_relative_plugin_file(): string {
return 'events-manager/events-manager.php'; return 'events-manager/events-manager.php';
} }

View file

@ -27,7 +27,7 @@ final class GatherPress extends Event_Plugin {
* *
* @return string * @return string
*/ */
public static function get_plugin_file(): string { public static function get_relative_plugin_file(): string {
return 'gatherpress/gatherpress.php'; return 'gatherpress/gatherpress.php';
} }

View file

@ -27,7 +27,7 @@ final class Modern_Events_Calendar_Lite extends Event_plugin {
* *
* @return string * @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'; return 'modern-events-calendar-lite/modern-events-calendar-lite.php';
} }

View file

@ -27,7 +27,7 @@ final class The_Events_Calendar extends Event_plugin {
* *
* @return string * @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'; return 'the-events-calendar/the-events-calendar.php';
} }

View file

@ -30,7 +30,7 @@ final class VS_Event_List extends Event_Plugin {
* *
* @return string * @return string
*/ */
public static function get_plugin_file(): string { public static function get_relative_plugin_file(): string {
return 'very-simple-event-list/vsel.php'; return 'very-simple-event-list/vsel.php';
} }

View file

@ -30,7 +30,7 @@ final class WP_Event_Manager extends Event_Plugin {
* *
* @return string * @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'; return 'wp-event-manager/wp-event-manager.php';
} }

View file

@ -109,7 +109,6 @@
<properties> <properties>
<property name="text_domain" type="array"> <property name="text_domain" type="array">
<element value="event-bridge-for-activitypub"/> <element value="event-bridge-for-activitypub"/>
<element value="activitypub"/>
</property> </property>
</properties> </properties>
</rule> </rule>

View file

@ -3,7 +3,7 @@ Contributors: andremenrath
Tags: events, fediverse, activitypub, calendar Tags: events, fediverse, activitypub, calendar
Requires at least: 6.5 Requires at least: 6.5
Tested up to: 6.7 Tested up to: 6.7
Stable tag: 0.3.1 Stable tag: 0.3.2
Requires PHP: 7.4 Requires PHP: 7.4
License: AGPL-3.0-or-later License: AGPL-3.0-or-later
License URI: https://www.gnu.org/licenses/agpl-3.0.html License URI: https://www.gnu.org/licenses/agpl-3.0.html

View file

@ -48,7 +48,7 @@ $current_category_mapping = \get_option( 'event_bridge_for_activitypub_ev
<p> <p>
<label for="event_bridge_for_activitypub_summary_type_preset"> <label for="event_bridge_for_activitypub_summary_type_preset">
<input type="radio" name="event_bridge_for_activitypub_summary_type" id="event_bridge_for_activitypub_summary_type_preset" value="preset" <?php echo \checked( 'preset', \get_option( 'event_bridge_for_activitypub_summary_type', EVENT_BRIDGE_FOR_ACTIVITYPUB_DEFAULT_SUMMARY_TYPE ) ); ?> /> <input type="radio" name="event_bridge_for_activitypub_summary_type" id="event_bridge_for_activitypub_summary_type_preset" value="preset" <?php echo \checked( 'preset', \get_option( 'event_bridge_for_activitypub_summary_type', EVENT_BRIDGE_FOR_ACTIVITYPUB_DEFAULT_SUMMARY_TYPE ) ); ?> />
<?php \esc_html_e( 'Automatic (default)', 'activitypub' ); ?> <?php \esc_html_e( 'Automatic (default)', 'event-bridge-for-activitypub' ); ?>
- -
<span class="description"> <span class="description">
<?php \esc_html_e( 'Let the plugin compose a summary for you. ', 'event-bridge-for-activitypub' ); ?> <?php \esc_html_e( 'Let the plugin compose a summary for you. ', 'event-bridge-for-activitypub' ); ?>
@ -68,7 +68,7 @@ $current_category_mapping = \get_option( 'event_bridge_for_activitypub_ev
<div id="event_bridge_for_activitypub_summary_type_custom-details"> <div id="event_bridge_for_activitypub_summary_type_custom-details">
<textarea name="event_bridge_for_activitypub_custom_summary" id="event_bridge_for_activitypub_custom_summary" rows="10" cols="50" class="large-text" placeholder="<?php echo wp_kses( EVENT_BRIDGE_FOR_ACTIVITYPUB_CUSTOM_SUMMARY, 'post' ); ?>"><?php echo esc_textarea( wp_kses( \get_option( 'event_bridge_for_activitypub_custom_summary', EVENT_BRIDGE_FOR_ACTIVITYPUB_CUSTOM_SUMMARY ), 'post' ) ); ?></textarea> <textarea name="event_bridge_for_activitypub_custom_summary" id="event_bridge_for_activitypub_custom_summary" rows="10" cols="50" class="large-text" placeholder="<?php echo wp_kses( EVENT_BRIDGE_FOR_ACTIVITYPUB_CUSTOM_SUMMARY, 'post' ); ?>"><?php echo esc_textarea( wp_kses( \get_option( 'event_bridge_for_activitypub_custom_summary', EVENT_BRIDGE_FOR_ACTIVITYPUB_CUSTOM_SUMMARY ), 'post' ) ); ?></textarea>
<details> <details>
<summary><?php esc_html_e( 'See a list Template Tags available for the summary.', 'activitypub' ); ?></summary> <summary><?php esc_html_e( 'See a list Template Tags available for the summary.', 'event-bridge-for-activitypub' ); ?></summary>
<div class="description"> <div class="description">
<dl> <dl>
<dt><code>[ap_start_time]</code><dt> <dt><code>[ap_start_time]</code><dt>