Merge branch 'setting_mapping'

This commit is contained in:
André Menrath 2024-08-28 20:01:43 +02:00
commit 16aa012be0
8 changed files with 379 additions and 20 deletions

View file

@ -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';

View file

@ -0,0 +1,6 @@
.activitypub-settings-page .box {
border: 1px solid #c3c4c7;
background-color: #fff;
padding: 1em 1.5em;
margin-bottom: 1.5em;
}

View file

@ -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' ) );
}
}
/**

View file

@ -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';

View file

@ -0,0 +1,101 @@
<?php
/**
* General settings class.
*
* This file contains the General class definition, which handles the "General" settings
* page for the ActivityPub Event Extension Plugin, providing options for configuring various general settings.
*
* @package Activitypub_Event_Extensions
* @since 1.0.0
*/
namespace Activitypub_Event_Extensions\Admin;
use Activitypub_Event_Extensions\Setup;
// Exit if accessed directly.
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
/**
* Class responsible for the ActivityPui Event Extension related Settings.
*
* Class responsible for the ActivityPui Event Extension related Settings.
*
* @since 1.0.0
*/
class Settings_Page {
const STATIC = 'Activitypub_Event_Extensions\Admin\Settings_Page';
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_event_extensions' ),
'manage_options',
self::SETTINGS_SLUG,
array( self::STATIC, 'settings_page' )
);
}
/**
* Adds Link to the settings page in the plugin page.
* It's called via apply_filter('plugin_action_links_' . PLUGIN_NAME).
*
* @param array $links Already added links.
* @return array Original links but with link to setting page added.
*/
public static function settings_link( $links ) {
return array_merge(
$links,
array(
'<a href="' . admin_url( 'options-general.php?page=' . self::SETTINGS_SLUG ) . '">Settings</a>',
)
);
}
/**
* 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 );
}
}

View file

@ -0,0 +1,65 @@
<?php
/**
* General settings class.
*
* This file contains the General class definition, which handles the "General" settings
* page for the ActivityPub Event Extension Plugin, providing options for configuring various general settings.
*
* @package Activitypub_Event_Extensions
* @since 1.0.0
*/
namespace Activitypub_Event_Extensions;
use Activitypub\Activity\Extended_Object\Event;
// Exit if accessed directly.
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
/**
* Class responsible for the ActivityPui Event Extension related Settings.
*
* Class responsible for the ActivityPui Event Extension related Settings.
*
* @since 1.0.0
*/
class Settings {
const STATIC = 'Activitypub_Event_Extensions\Admin\Settings_Page';
const SETTINGS_SLUG = 'activitypub-event-extensions';
/**
* Register the settings for the ActivityPub Event Extensions plugin.
*/
public static function register_settings() {
\register_setting(
'activitypub-event-extensions',
'activitypub_event_extensions_default_event_category',
array(
'type' => '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;
},
)
);
}
}

View file

@ -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'] );
}
}

133
templates/settings.php Normal file
View file

@ -0,0 +1,133 @@
<?php
/**
* Template for ActivityPub Event Extensions settings page.
*
* This template is used to display and manage settings for the ActivityPub Event Extensions plugin.
*
* @package ActivityPub_Event_Extensions
* @since 1.0.0
*
* @param array $args An array of arguments for the settings page.
*/
// Exit if accessed directly.
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
use Activitypub\Activity\Extended_Object\Event;
if ( ! isset( $args ) || ! array_key_exists( 'event_terms', $args ) ) {
return;
}
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
$event_terms = $args['event_terms'];
$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() );
?>
<div class="activitypub-settings-header">
<div class="activitypub-settings-title-section">
<h1><?php \esc_html_e( 'ActivityPub Event Extensions', 'activitypub-event-extensions' ); ?></h1>
</div>
</div>
<hr class="wp-header-end">
<div class="activitypub-settings activitypub-settings-page hide-if-no-js">
<form method="post" action="options.php">
<?php \settings_fields( 'activitypub-event-extensions' ); ?>
<div class="box">
<h2> <?php esc_html_e( 'Default ActivityPub Event Category', 'activitypub-event-extensions' ); ?> </h2>
<p> <?php esc_html_e( 'To help visitors find events more easily, the community created a set of basic event categories. Please select the category that best matches the majority of the events you organize.' ); ?> </p>
<table class="form-table">
<tr>
<th scope="row"> <?php esc_html_e( 'Default Category', 'activitypub-event-extensions' ); ?> </th>
<td>
<select id="activitypub_event_extensions_default_event_category" name="activitypub_event_extensions_default_event_category">';
<?php
foreach ( $default_event_category_strings as $value => $label ) {
echo '<option value="' . esc_attr( $value ) . '" ' . selected( $selected_default_event_category, $value, false ) . '>' . esc_html( $label ) . '</option>';
}
?>
</select>
</td>
</tr>
</table>
</div>
<div class="box">
<h2> <?php esc_html_e( 'Advanced Event Category Settings', 'activitypub-event-extensions' ); ?> </h2>
<p> <?php esc_html_e( 'Take more control by adjusting how your event categories are mapped to the basic category set used in ActivityPub. This option lets you override the default selection above, ensuring more accurate categorization and better visibility for your events.' ); ?> </p>
<table class="form-table">
<?php foreach ( $event_terms as $event_term ) { ?>
<tr>
<th scope="row"> <?php echo esc_html( $event_term->name ); ?> </th>
<td>
<select name="activitypub_event_extensions_event_category_mappings[<?php echo esc_attr( $event_term->slug ); ?>]">
<?php
$current_mapping_is_set = false;
if ( ! empty( $current_category_mapping ) ) {
$current_mapping_is_set = array_key_exists( $event_term->slug, $current_category_mapping );
}
if ( $current_mapping_is_set ) {
$mapping = $current_category_mapping[ $event_term->slug ];
} else {
$mapping = 'DEFAULT';
}
if ( 'DEFAULT' === $mapping ) {
echo '<option value="' . esc_attr( $mapping ) . '"> -- ' . esc_html( $default_event_category_strings[ $mapping ] ) . ' -- </option>';
} else {
echo '<option value="' . esc_attr( $mapping ) . '">' . esc_html( $default_event_category_strings[ $mapping ] ) . '</option>';
}
echo '<option value="DEFAULT" ' . selected( $selected_default_event_category, 'DEFAULT', false ) . '> -- ' . esc_html__( 'Default', 'activitypub-event-extensions' ) . ' -- </option>';
foreach ( Event::DEFAULT_EVENT_CATEGORIES as $event_category ) {
echo '<option value="' . esc_attr( $event_category ) . '" ' . selected( $mappings[ $event_term->slug ] ?? '', $event_category, false ) . '>' . esc_html( $default_event_category_strings[ $event_category ] ) . '</option>';
}
?>
</select>
</td>
</tr>
<?php } ?>
</table>
</div>
<?php \submit_button(); ?>
</form>
</div>