diff --git a/activitypub-event-extensions.php b/activitypub-event-extensions.php index a8638f7..7981a5a 100644 --- a/activitypub-event-extensions.php +++ b/activitypub-event-extensions.php @@ -3,7 +3,7 @@ * Plugin Name: ActivityPub Event Extensions * Description: Custom ActivityPub Transformers and Integrations for common Event Plugins. * Plugin URI: https://event-federation.eu/ - * Version: 1.0.0 + * Version: 0.1.0 * Author: André Menrath * Author URI: https://graz.social/@linos * Text Domain: activitypub-event-extensions @@ -18,12 +18,11 @@ // Exit if accessed directly. defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore -define( 'ACTIVITYPUB_EVENT_EXTENSIONS_PLUGIN_VERSION', '1.0.0' ); - define( 'ACTIVITYPUB_EVENT_EXTENSIONS_PLUGIN_DIR', plugin_dir_path( __FILE__ ) ); define( 'ACTIVITYPUB_EVENT_EXTENSIONS_PLUGIN_BASENAME', plugin_basename( __FILE__ ) ); define( 'ACTIVITYPUB_EVENT_EXTENSIONS_PLUGIN_FILE', plugin_dir_path( __FILE__ ) . '/' . basename( __FILE__ ) ); define( 'ACTIVITYPUB_EVENT_EXTENSIONS_PLUGIN_URL', plugin_dir_url( __FILE__ ) ); +define( 'ACTIVITYPUB_EVENT_EXTENSIONS_PLUGIN_VERSION', current( get_file_data( __FILE__, array( 'Version' ), 'plugin' ) ) ); // Include and register the autoloader class for automatic loading of plugin classes. require_once ACTIVITYPUB_EVENT_EXTENSIONS_PLUGIN_DIR . '/includes/class-autoloader.php'; diff --git a/assets/css/activitypub-event-extensions-admin.css b/assets/css/activitypub-event-extensions-admin.css new file mode 100644 index 0000000..c1d76b6 --- /dev/null +++ b/assets/css/activitypub-event-extensions-admin.css @@ -0,0 +1,6 @@ +.activitypub-settings-page .box { + border: 1px solid #c3c4c7; + background-color: #fff; + padding: 1em 1.5em; + margin-bottom: 1.5em; +} diff --git a/includes/activitypub/transformer/class-event.php b/includes/activitypub/transformer/class-event.php index d7951f8..ae1d9d6 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. * @@ -42,14 +53,30 @@ class Event extends Post { } /** - * Format a human readable HTML summary. + * Extend the construction of the Post Transformer to also set the according taxonomy of the event post type. * - * @param string $summary_text The base string to be formatted. - * - * @return string + * @param WP_Post $wp_object The WordPress post object (event). + * @param string $wp_taxonomy The taxonomy slug of the event post type. */ - protected function format_html_summary( $summary_text ): string { - return $summary_text; + public function __construct( $wp_object, $wp_taxonomy ) { + parent::__construct( $wp_object ); + $this->wp_taxonomy = $wp_taxonomy; + } + + /** + * 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 ); + + // Check if the event has a category set and if that category has a specific mapping return that one. + if ( ! is_wp_error( $terms ) && $terms && array_key_exists( $terms[0]->slug, $current_category_mapping ) ) { + return sanitize_text_field( $current_category_mapping[ $terms[0]->slug ] ); + } else { + // Return the default event category. + return sanitize_text_field( \get_option( 'activitypub_event_extensions_default_event_category', 'MEETING' ) ); + } } /** diff --git a/includes/activitypub/transformer/class-vs-event-list.php b/includes/activitypub/transformer/class-vs-event-list.php index a518824..9ab1769 100644 --- a/includes/activitypub/transformer/class-vs-event-list.php +++ b/includes/activitypub/transformer/class-vs-event-list.php @@ -45,7 +45,6 @@ class VS_Event_List extends Event_Transformer { * @return string Widget name. */ public function get_transformer_name() { - return 'activitypub-event-transformers/vs-event'; } @@ -59,7 +58,6 @@ class VS_Event_List extends Event_Transformer { * @return string Widget title. */ public function get_transformer_label() { - return 'VS Event'; } @@ -73,7 +71,6 @@ class VS_Event_List extends Event_Transformer { * @return array Widget categories. */ public static function get_supported_post_types() { - return array( 'event' ); } @@ -85,7 +82,6 @@ class VS_Event_List extends Event_Transformer { * @return string The Event Object-Type. */ protected function get_type() { - return 'Event'; } @@ -95,7 +91,6 @@ class VS_Event_List extends Event_Transformer { * @return array The Place. */ public function get_location() { - $address = get_post_meta( $this->wp_object->ID, 'event-location', true ); $place = new Place(); $place->set_type( 'Place' ); @@ -108,7 +103,6 @@ class VS_Event_List extends Event_Transformer { * Get the end time from the events metadata. */ protected function get_end_time() { - $end_time = get_post_meta( $this->wp_object->ID, 'event-date', true ); return \gmdate( 'Y-m-d\TH:i:s\Z', $end_time ); } @@ -117,7 +111,6 @@ class VS_Event_List extends Event_Transformer { * Get the end time from the events metadata. */ protected function get_start_time() { - $start_time = get_post_meta( $this->wp_object->ID, 'event-start-date', true ); return \gmdate( 'Y-m-d\TH:i:s\Z', $start_time ); } @@ -126,7 +119,6 @@ class VS_Event_List extends Event_Transformer { * 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( @@ -142,7 +134,6 @@ class VS_Event_List extends Event_Transformer { * 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'; diff --git a/includes/admin/class-settings-page.php b/includes/admin/class-settings-page.php new file mode 100644 index 0000000..22c8b1a --- /dev/null +++ b/includes/admin/class-settings-page.php @@ -0,0 +1,101 @@ +Settings', + ) + ); + } + + /** + * 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 { + 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 = array_merge( $event_terms, 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/class-settings.php b/includes/class-settings.php new file mode 100644 index 0000000..f5e781a --- /dev/null +++ b/includes/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-setup.php b/includes/class-setup.php index 4aec937..4189545 100644 --- a/includes/class-setup.php +++ b/includes/class-setup.php @@ -14,7 +14,7 @@ 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_Page; // Exit if accessed directly. defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore @@ -53,6 +53,7 @@ class Setup { 'post_type' => 'event', 'settings_page_id' => 'settings_page_vsel', 'transformer_class' => 'VS_Event', + 'taxonomy' => 'event_cat', ), ); @@ -123,6 +124,14 @@ class Setup { return $active_event_plugins; } + /** + * Getter function for the active event plugins. + */ + public function get_active_event_plugins() { + return $this->active_event_plugins; + } + + /** * Set up hooks for various purposes. * @@ -136,15 +145,43 @@ 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_enqueue_scripts', array( self::class, 'enqueue_styles' ) ); + + add_action( 'admin_menu', array( Settings_Page::class, 'admin_menu' ) ); + + add_filter( + 'plugin_action_links_' . ACTIVITYPUB_EVENT_EXTENSIONS_PLUGIN_BASENAME, + array( Settings_Page::class, 'settings_link' ) + ); add_filter( 'activitypub_transformer', array( $this, 'register_activitypub_event_transformer' ), 10, 3 ); } + /** + * Add the CSS for the admin pages. + * + * @param string $hook_suffix The suffix of the hook. + */ + public static function enqueue_styles( $hook_suffix ) { + if ( false !== strpos( $hook_suffix, 'activitypub-event-extensions' ) ) { + wp_enqueue_style( + 'activitypub-event-extensions-admin-styles', + plugins_url( + 'assets/css/activitypub-event-extensions-admin.css', + ACTIVITYPUB_EVENT_EXTENSIONS_PLUGIN_FILE + ), + array(), + ACTIVITYPUB_EVENT_EXTENSIONS_PLUGIN_VERSION + ); + } + } + /** * Fires the initialization of admin notices. */ @@ -183,7 +220,7 @@ class Setup { foreach ( $this->active_event_plugins as $event_plugin ) { if ( $wp_object->post_type === $event_plugin['post_type'] ) { $transformer_class = 'Activitypub_Event_Extensions\Activitypub\Transformer\\' . $event_plugin['transformer_class']; - return new $transformer_class( $wp_object ); + return new $transformer_class( $wp_object, $event_plugin['taxonomy'] ); } } diff --git a/templates/settings.php b/templates/settings.php new file mode 100644 index 0000000..d988327 --- /dev/null +++ b/templates/settings.php @@ -0,0 +1,133 @@ + __( '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() ); +?> + +