From 771a95aa0c3f57cab9a3b4e24f0c29ee31e7877f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Menrath?= Date: Tue, 27 Aug 2024 19:26:54 +0200 Subject: [PATCH] mindmap on category mapping and class-based event-plugin definition --- .../activitypub/transformer/class-event.php | 24 ++++ .../transformer/class-gatherpress.php | 22 ++- .../transformer/class-vs-event.php | 9 +- includes/admin/class-settings-page.php | 117 ++++++--------- includes/admin/class-settings.php | 65 +++++++++ includes/class-plugin-manager.php | 56 ++++++++ includes/class-setup.php | 54 +++---- includes/plugins/class-events-manager.php | 71 ++++++++++ includes/plugins/class-gatherpress.php | 76 ++++++++++ .../plugins/class-the-events-calendar.php | 76 ++++++++++ includes/plugins/class-vs-event-list.php | 72 ++++++++++ includes/plugins/interface-event-plugin.php | 58 ++++++++ templates/admin-header.php | 21 --- templates/settings-extractor.php | 13 -- templates/settings-general.php | 13 -- templates/settings.php | 134 ++++++++++++++++++ 16 files changed, 713 insertions(+), 168 deletions(-) create mode 100644 includes/admin/class-settings.php create mode 100644 includes/class-plugin-manager.php create mode 100644 includes/plugins/class-events-manager.php create mode 100644 includes/plugins/class-gatherpress.php create mode 100644 includes/plugins/class-the-events-calendar.php create mode 100644 includes/plugins/class-vs-event-list.php create mode 100644 includes/plugins/interface-event-plugin.php delete mode 100644 templates/admin-header.php delete mode 100644 templates/settings-extractor.php delete mode 100644 templates/settings-general.php create mode 100644 templates/settings.php diff --git a/includes/activitypub/transformer/class-event.php b/includes/activitypub/transformer/class-event.php index e1ff34d..569e194 100644 --- a/includes/activitypub/transformer/class-event.php +++ b/includes/activitypub/transformer/class-event.php @@ -16,8 +16,19 @@ use function Activitypub\get_rest_url_by_path; /** * Base transformer for WordPress event post types to ActivityPub events. + * + * Everything that transforming several WordPress post types that represent events + * have in common, as well as sane defaults for events should be defined here. */ class Event extends Post { + + /** + * The WordPress event taxonomy. + * + * @var string + */ + protected $wp_taxonomy; + /** * Returns the User-URL of the Author of the Post. * @@ -41,6 +52,19 @@ class Event extends Post { return 'Event'; } + /** + * Set the event category, via the mapping setting. + */ + public function get_category() { + $current_category_mapping = \get_option( 'activitypub_event_extensions_event_category_mappings', array() ); + $terms = \get_the_terms( $this->wp_object, $this->wp_taxonomy ); + if ( ! is_wp_error( $terms ) && $terms ) { + return $current_category_mapping[ $terms[0]->slug ]; + } else { + return \get_option( 'activitypub_event_extensions_default_event_category', 'MEETING' ); + } + } + /** * Generic function that converts an WP-Event object to an ActivityPub-Event object. * diff --git a/includes/activitypub/transformer/class-gatherpress.php b/includes/activitypub/transformer/class-gatherpress.php index e0c0b80..23bcc98 100644 --- a/includes/activitypub/transformer/class-gatherpress.php +++ b/includes/activitypub/transformer/class-gatherpress.php @@ -6,8 +6,14 @@ * @license AGPL-3.0-or-later */ -use Activitypub\Transformer\Post; -use Activitypub\Model\Blog_user; +namespace Activitypub_Event_Extensions\Activitypub\Transformer; + +if ( ! defined( 'ABSPATH' ) ) { + exit; // Exit if accessed directly. +} + +use Activitypub_Event_Extensions\Activitypub\Transformer\Event; +use Activitypub\Model\Blog; use Activitypub\Activity\Extended_Object\Event as Event_Object; use Activitypub\Activity\Extended_Object\Place; use GatherPress\Core\Event as GatherPress_Event; @@ -23,7 +29,7 @@ if ( ! defined( 'ABSPATH' ) ) { * * @since 1.0.0 */ -class GatherPress extends Post { +class GatherPress extends Event { /** * The target ActivityPub Event object of the transformer. @@ -84,7 +90,6 @@ class GatherPress extends Post { * @return array Widget categories. */ public static function get_supported_post_types() { - return array( GatherPress_Event::POST_TYPE ); } @@ -96,7 +101,6 @@ class GatherPress extends Post { * @return string The Event Object-Type. */ protected function get_type() { - return 'Event'; } @@ -119,7 +123,6 @@ class GatherPress extends Post { * Get the end time from the event object. */ protected function get_end_time() { - return $this->gp_event->get_datetime_end( 'Y-m-d\TH:i:s\Z' ); } @@ -127,7 +130,6 @@ class GatherPress extends Post { * Get the end time from the event object. */ protected function get_start_time() { - return $this->gp_event->get_datetime_start( 'Y-m-d\TH:i:s\Z' ); } @@ -135,7 +137,6 @@ class GatherPress extends Post { * Get the event link from the events metadata. */ private function get_event_link() { - $event_link = get_post_meta( $this->wp_object->ID, 'event-link', true ); if ( $event_link ) { return array( @@ -151,7 +152,6 @@ class GatherPress extends Post { * Overrides/extends the get_attachments function to also add the event Link. */ protected function get_attachment() { - $attachments = parent::get_attachment(); if ( count( $attachments ) ) { $attachments[0]['type'] = 'Document'; @@ -170,7 +170,6 @@ class GatherPress extends Post { * @return string $category */ protected function get_category() { - return 'MEETING'; } @@ -182,8 +181,7 @@ class GatherPress extends Post { * @return string The User-URL. */ protected function get_attributed_to() { - - $user = new Blog_User(); + $user = new Blog(); return $user->get_url(); } diff --git a/includes/activitypub/transformer/class-vs-event.php b/includes/activitypub/transformer/class-vs-event.php index a48e596..b009bbd 100644 --- a/includes/activitypub/transformer/class-vs-event.php +++ b/includes/activitypub/transformer/class-vs-event.php @@ -9,7 +9,6 @@ namespace Activitypub_Event_Extensions\Activitypub\Transformer; use Activitypub_Event_Extensions\Activitypub\Transformer\Event as Event_Transformer; -use Activitypub\Model\Blog; use Activitypub\Activity\Extended_Object\Event; use Activitypub\Activity\Extended_Object\Place; @@ -25,7 +24,7 @@ if ( ! defined( 'ABSPATH' ) ) { * * @since 1.0.0 */ -class VS_Event extends Event_Transformer { +class VSEL extends Event_Transformer { /** * The target transformet ActivityPub Event object. @@ -205,7 +204,7 @@ class VS_Event extends Event_Transformer { $setter_function = 'set_' . $key; $getter_function = 'get_' . $key; - if ( in_array( $getter_function, get_class_methods( $this ) ) ) { + if ( in_array( $getter_function, get_class_methods( $this ), true ) ) { $this->ap_object->$setter_function( $this->$getter_function() ); } else { $this->ap_object->$setter_function( $value ); @@ -220,7 +219,7 @@ class VS_Event extends Event_Transformer { * @param string $method The method name. * @param string $params The method params. * - * @return void + * @return function */ public function __call( $method, $params ) { @@ -230,8 +229,6 @@ class VS_Event extends Event_Transformer { return $this->set( $var, $params[0] ); } - // when do we need: call_user_func( array( $activitypub_object, $setter ), $value ); - return $this; } diff --git a/includes/admin/class-settings-page.php b/includes/admin/class-settings-page.php index 7d7bb59..2cd16dd 100644 --- a/includes/admin/class-settings-page.php +++ b/includes/admin/class-settings-page.php @@ -11,43 +11,29 @@ namespace Activitypub_Event_Extensions\Admin; +use Activitypub_Event_Extensions\Setup; + // Exit if accessed directly. defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore /** - * Class responsible for Event Plugin related admin notices. + * Class responsible for the ActivityPui Event Extension related Settings. * - * Notices for guiding to proper configuration of ActivityPub with event plugins. + * Class responsible for the ActivityPui Event Extension related Settings. * * @since 1.0.0 */ class Settings_Page { - - /** - * TODO: - * - [ ] create settings page - * - [ ] skeleton - * - [ ] Autoloader - * - [ ] Common settings? - * - [ ] Hook points - * - [ ] let transformers hook settings into the page - * - [ ] provide setting-type-classes for hooks - * - [ ] True/False - * - [ ] Number - * - [ ] advanced for mapping - */ - const STATIC = 'Activitypub_Event_Extensions\Admin\Settings_Page'; - const SETTINGS_SLUG = 'activitypub-events'; - + const SETTINGS_SLUG = 'activitypub-event-extensions'; /** * Warning if the plugin is Active and the ActivityPub plugin is not. */ public static function admin_menu() { \add_options_page( 'Activitypub Event Extension', - 'Activitypub Events', + __( 'ActivityPub Events', 'activitypub_event_extensions' ), 'manage_options', self::SETTINGS_SLUG, array( self::STATIC, 'settings_page' ) @@ -70,59 +56,46 @@ class Settings_Page { ); } - public static function settings_page() { - if ( empty( $_GET['tab'] ) ) { - $tab = 'general'; + /** + * Receive the event categories (terms) used by the event plugin. + * + * @param array $event_plugin Contains info about a certain event plugin. + * + * @return array An array of Terms. + */ + private static function get_event_terms( $event_plugin ) { + if ( isset( $event_plugin['taxonomy'] ) ) { + $event_terms = get_terms( + array( + 'taxonomy' => $event_plugin['taxonomy'], + 'hide_empty' => true, + ) + ); + return $event_terms; } else { - $tab = sanitize_key( $_GET['tab'] ); - } - - /* - submenu_options = { - tab => {name => '' - active => true|false} - } - */ - - // TODO: generate this somehow. - // Maybe with filters, similar as with the settings! - $submenu_options = array( - 'general' => array( - 'name' => 'General', - 'active' => false, - ), - 'events_manager' => array( - 'name' => 'Events Manager', - 'active' => false, - ), - 'gatherpress' => array( - 'name' => 'Gatherpress', - 'active' => false, - ), - 'the_events_calendar' => array( - 'name' => 'The Events Calendar', - 'active' => false, - ), - 'vsel' => array( - 'name' => 'VS Event', - 'active' => false, - ), - ); - - $submenu_options[ $tab ]['active'] = true; - - $args = array( - 'slug' => self::SETTINGS_SLUG, - 'options' => $submenu_options, - ); - - switch ( $tab ) { - case 'general': - \load_template( ACTIVITYPUB_EVENT_EXTENSIONS_PLUGIN_DIR . 'templates/settings-general.php', true, $args ); - break; - default: - \load_template( ACTIVITYPUB_EVENT_EXTENSIONS_PLUGIN_DIR . 'templates/settings-extractor.php', true, $args ); - break; + return array(); } } + + /** + * Settings page. + */ + public static function settings_page() { + $plugin_setup = Setup::get_instance(); + + $event_plugins = $plugin_setup->get_active_event_plugins(); + + $event_terms = array(); + + foreach ( $event_plugins as $event_plugin_name => $events_plugin_info ) { + $event_terms[ $event_plugin_name ] = self::get_event_terms( $events_plugin_info ); + } + + $args = array( + 'slug' => self::SETTINGS_SLUG, + 'event_terms' => $event_terms, + ); + + \load_template( ACTIVITYPUB_EVENT_EXTENSIONS_PLUGIN_DIR . 'templates/settings.php', true, $args ); + } } diff --git a/includes/admin/class-settings.php b/includes/admin/class-settings.php new file mode 100644 index 0000000..4b79127 --- /dev/null +++ b/includes/admin/class-settings.php @@ -0,0 +1,65 @@ + 'string', + 'description' => \__( 'Define your own custom post template', 'activitypub' ), + 'show_in_rest' => true, + 'default' => 'MEETING', + ) + ); + + \register_setting( + 'activitypub-event-extensions', + 'activitypub_event_extensions_event_category_mappings', + array( + 'type' => 'array', + 'description' => \__( 'Define your own custom post template', 'activitypub' ), + 'default' => array(), + 'sanitize_callback' => function ( $event_category_mappings ) { + $allowed_mappings = Event::DEFAULT_EVENT_CATEGORIES; + foreach ( $event_category_mappings as $key => $value ) { + if ( ! in_array( $value, $allowed_mappings, true ) ) { + unset( $event_category_mappings[ $key ] ); + } + } + return $event_category_mappings; + }, + ) + ); + } +} diff --git a/includes/class-plugin-manager.php b/includes/class-plugin-manager.php new file mode 100644 index 0000000..db5c3e8 --- /dev/null +++ b/includes/class-plugin-manager.php @@ -0,0 +1,56 @@ +isAbstract() || $reflection->isInterface()) { + continue; + } + + if ($reflection->hasMethod('get_plugin_file')) { + $instance = $reflection->newInstance(); + $plugin_file = $instance->get_plugin_file(); + + if (is_plugin_active($plugin_file)) { + $active_event_plugins[$class] = $plugin_file; + } + } + } + } + + // Now you can use $active_event_plugins for further processing + return $active_event_plugins; + } +} diff --git a/includes/class-setup.php b/includes/class-setup.php index 5a8fa14..f7eaa5a 100644 --- a/includes/class-setup.php +++ b/includes/class-setup.php @@ -13,7 +13,9 @@ namespace Activitypub_Event_Extensions; use Activitypub_Event_Extensions\Admin\Event_Plugin_Admin_Notices; use Activitypub_Event_Extensions\Admin\General_Admin_Notices; +use Activitypub_Event_Extensions\Admin\Settings; use Activitypub_Event_Extensions\Admin\Settings_Page; +use Activitypub_Event_Extensions\Plugins\Gatherpress; // Exit if accessed directly. defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore @@ -29,30 +31,10 @@ require_once ABSPATH . 'wp-admin/includes/plugin.php'; */ class Setup { const SUPPORTED_EVENT_PLUGINS = array( - 'events_manager' => array( - 'plugin_file' => 'events-manager/events-manager.php', - 'post_type' => 'event', - 'settings_page' => 'options-general.php?page=vsel', - 'transformer_class' => 'Events_Manager', - ), - 'gatherpress' => array( - 'plugin_file' => 'gatherpress/gatherpress.php', - 'post_type' => 'gatherpress_event', - 'transformer_class' => 'GatherPress', - 'settings_page_id' => 'gatherpress_general', - ), - 'the_events_calendar' => array( - 'plugin_file' => 'the-events-calendar/the-events-calendar.php', - 'post_type' => 'tribe_events', - 'transformer_class' => 'Tribe', - 'settings_page_id' => 'tribe_general', - ), - 'vsel' => array( - 'plugin_file' => 'very-simple-event-list/vsel.php', - 'post_type' => 'event', - 'settings_page_id' => 'settings_page_vsel', - 'transformer_class' => 'VS_Event', - ), + 'Events_Manager', + 'GatherPress', + 'The_Events_Calendar', + 'VS_Event_List', ); /** @@ -69,6 +51,13 @@ class Setup { */ protected $active_event_plugins = array(); + /** + * Getter function for the active event plugins. + */ + public function get_active_event_plugins() { + return $this->active_event_plugins; + } + /** * Constructor for the Setup class. * @@ -114,9 +103,10 @@ class Setup { */ public static function detect_supported_event_plugins(): array { $active_event_plugins = array(); - foreach ( self::SUPPORTED_EVENT_PLUGINS as $event_plugin_key => $event_plugin ) { - if ( \is_plugin_active( $event_plugin['plugin_file'] ) ) { - $active_event_plugins[ $event_plugin_key ] = $event_plugin; + foreach ( self::SUPPORTED_EVENT_PLUGINS as $event_plugin ) { + $event_plugin_class = 'Activitypub_Event_Extensions\Plugins\\' . $event_plugin; + if ( \is_plugin_active( $event_plugin_class::get_plugin_file() ) ) { + $active_event_plugins[ $event_plugin ] = $event_plugin_class; } } return $active_event_plugins; @@ -135,17 +125,18 @@ class Setup { register_activation_hook( ACTIVITYPUB_EVENT_EXTENSIONS_PLUGIN_FILE, array( $this, 'activate' ) ); add_action( 'admin_init', array( $this, 'do_admin_notices' ) ); + add_action( 'admin_init', array( Settings::class, 'register_settings' ) ); // 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 ) { return; } - add_action( 'admin_menu', array( Settings_Page::STATIC, 'admin_menu' ) ); + add_action( 'admin_menu', array( Settings_Page::class, 'admin_menu' ) ); add_filter( 'plugin_action_links_' . ACTIVITYPUB_EVENT_EXTENSIONS_PLUGIN_BASENAME, - array( Settings_Page::STATIC, 'settings_link' ) + array( Settings_Page::class, 'settings_link' ) ); add_filter( 'activitypub_transformer', array( $this, 'register_activitypub_event_transformer' ), 10, 3 ); } @@ -186,7 +177,7 @@ class Setup { // Get the transformer for a specific event plugins event-post type. foreach ( $this->active_event_plugins as $event_plugin ) { - if ( $wp_object->post_type === $event_plugin['post_type'] ) { + if ( $wp_object->post_type === $event_plugin::get_post_type() ) { $transformer_class = 'Activitypub_Event_Extensions\Activitypub\Transformer\\' . $event_plugin['transformer_class']; return new $transformer_class( $wp_object ); } @@ -226,10 +217,11 @@ class Setup { array( 'back_link' => true ), ); } + // 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['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['post_type']; } } diff --git a/includes/plugins/class-events-manager.php b/includes/plugins/class-events-manager.php new file mode 100644 index 0000000..f50920e --- /dev/null +++ b/includes/plugins/class-events-manager.php @@ -0,0 +1,71 @@ + -
-
-

-
- - -
-
diff --git a/templates/settings-extractor.php b/templates/settings-extractor.php deleted file mode 100644 index ac089a5..0000000 --- a/templates/settings-extractor.php +++ /dev/null @@ -1,13 +0,0 @@ - \ No newline at end of file diff --git a/templates/settings-general.php b/templates/settings-general.php deleted file mode 100644 index ac089a5..0000000 --- a/templates/settings-general.php +++ /dev/null @@ -1,13 +0,0 @@ - \ No newline at end of file diff --git a/templates/settings.php b/templates/settings.php new file mode 100644 index 0000000..6e0a6cb --- /dev/null +++ b/templates/settings.php @@ -0,0 +1,134 @@ + 'tribe_events_cat', + 'hide_empty' => true, + ) +); + +$default_event_category_strings = array( + 'ARTS' => __( 'Arts', 'activitypub-event-extensions' ), + 'BOOK_CLUBS' => __( 'Book clubs', 'activitypub-event-extensions' ), + 'BUSINESS' => __( 'Business', 'activitypub-event-extensions' ), + 'CAUSES' => __( 'Causes', 'activitypub-event-extensions' ), + 'COMEDY' => __( 'Comedy', 'activitypub-event-extensions' ), + 'CRAFTS' => __( 'Crafts', 'activitypub-event-extensions' ), + 'FOOD_DRINK' => __( 'Food & Drink', 'activitypub-event-extensions' ), + 'HEALTH' => __( 'Health', 'activitypub-event-extensions' ), + 'MUSIC' => __( 'Music', 'activitypub-event-extensions' ), + 'AUTO_BOAT_AIR' => __( 'Auto, boat and air', 'activitypub-event-extensions' ), + 'COMMUNITY' => __( 'Community', 'activitypub-event-extensions' ), + 'FAMILY_EDUCATION' => __( 'Family & Education', 'activitypub-event-extensions' ), + 'FASHION_BEAUTY' => __( 'Fashion & Beauty', 'activitypub-event-extensions' ), + 'FILM_MEDIA' => __( 'Film & Media', 'activitypub-event-extensions' ), + 'GAMES' => __( 'Games', 'activitypub-event-extensions' ), + 'LANGUAGE_CULTURE' => __( 'Language & Culture', 'activitypub-event-extensions' ), + 'LEARNING' => __( 'Learning', 'activitypub-event-extensions' ), + 'LGBTQ' => __( 'LGBTQ', 'activitypub-event-extensions' ), + 'MOVEMENTS_POLITICS' => __( 'Movements and politics', 'activitypub-event-extensions' ), + 'NETWORKING' => __( 'Networking', 'activitypub-event-extensions' ), + 'PARTY' => __( 'Party', 'activitypub-event-extensions' ), + 'PERFORMING_VISUAL_ARTS' => __( 'Performing & Visual Arts', 'activitypub-event-extensions' ), + 'PETS' => __( 'Pets', 'activitypub-event-extensions' ), + 'PHOTOGRAPHY' => __( 'Photography', 'activitypub-event-extensions' ), + 'OUTDOORS_ADVENTURE' => __( 'Outdoors & Adventure', 'activitypub-event-extensions' ), + 'SPIRITUALITY_RELIGION_BELIEFS' => __( 'Spirituality, Religion & Beliefs', 'activitypub-event-extensions' ), + 'SCIENCE_TECH' => __( 'Science & Tech', 'activitypub-event-extensions' ), + 'SPORTS' => __( 'Sports', 'activitypub-event-extensions' ), + 'THEATRE' => __( 'Theatre', 'activitypub-event-extensions' ), + 'MEETING' => __( 'Meeting', 'activitypub-event-extensions' ), // Default value in federation. + 'DEFAULT' => __( 'Default', 'activitypub-event-extensions' ), // Internal default for overrides. +); + +$selected_default_event_category = \get_option( 'activitypub_event_extensions_default_event_category', 'MEETING' ); +$current_category_mapping = \get_option( 'activitypub_event_extensions_event_category_mappings', array() ); +?> + +
+
+ + +
+ +

+ +

+ + + + + + +
+ +
+ +

+ +

+ + + + + + + + +
name ); ?> + +
+
+ +
+