Skip to content

Commit

Permalink
Merge pull request #565 from GatherPress/GP-564
Browse files Browse the repository at this point in the history
  • Loading branch information
mauteri authored Feb 25, 2024
2 parents 19e928f + 04cf3c3 commit a71446b
Show file tree
Hide file tree
Showing 15 changed files with 965 additions and 849 deletions.
22 changes: 12 additions & 10 deletions includes/core/classes/class-event-query.php
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ public function get_events_list(
$tax_query[] = array(
'relation' => 'AND',
array(
'taxonomy' => Event::TAXONOMY,
'taxonomy' => Topic::TAXONOMY,
'field' => 'slug',
'terms' => $topics,
),
Expand All @@ -128,7 +128,7 @@ public function get_events_list(
);
} elseif ( ! empty( $topics ) ) {
$tax_query[] = array(
'taxonomy' => Event::TAXONOMY,
'taxonomy' => Topic::TAXONOMY,
'field' => 'slug',
'terms' => $topics,
);
Expand Down Expand Up @@ -216,7 +216,7 @@ static function ( $pre, $option ) {
// Pass original page title as archive title.
add_filter(
'get_the_archive_title',
function () use ( $page_id ) {
static function () use ( $page_id ) {
return get_the_title( $page_id );
}
);
Expand Down Expand Up @@ -330,14 +330,16 @@ public function adjust_event_sql( array $pieces, string $type = 'all', string $o
$pieces['orderby'] = sprintf( esc_sql( $table ) . '.datetime_start_gmt %s', esc_sql( $order ) );
}

if ( 'all' !== $type ) {
$current = gmdate( Event::DATETIME_FORMAT, time() );
if ( 'all' === $type ) {
return $pieces;
}

if ( 'upcoming' === $type ) {
$pieces['where'] .= $wpdb->prepare( ' AND ' . esc_sql( $table ) . '.datetime_end_gmt >= %s', esc_sql( $current ) );
} elseif ( 'past' === $type ) {
$pieces['where'] .= $wpdb->prepare( ' AND ' . esc_sql( $table ) . '.datetime_end_gmt < %s', esc_sql( $current ) );
}
$current = gmdate( Event::DATETIME_FORMAT, time() );

if ( 'upcoming' === $type ) {
$pieces['where'] .= $wpdb->prepare( ' AND ' . esc_sql( $table ) . '.datetime_end_gmt >= %s', esc_sql( $current ) );
} elseif ( 'past' === $type ) {
$pieces['where'] .= $wpdb->prepare( ' AND ' . esc_sql( $table ) . '.datetime_end_gmt < %s', esc_sql( $current ) );
}

return $pieces;
Expand Down
343 changes: 343 additions & 0 deletions includes/core/classes/class-event-setup.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,343 @@
<?php
/**
* Handles the setup and management of events in GatherPress.
*
* This class is responsible for integrating events into the WordPress environment, including the creation
* of the custom post type for events, managing event metadata, and enhancing the admin dashboard for event management.
*
* @package GatherPress\Core
* @since 1.0.0
*/

namespace GatherPress\Core;

use Exception;
use GatherPress\Core\Traits\Singleton;
use WP_Post;

/**
* Class Event_Setup.
*
* Manages event-related functionalities, including registration of event post types and metadata.
*
* @since 1.0.0
*/
class Event_Setup {
/**
* Enforces a single instance of this class.
*/
use Singleton;

/**
* Class constructor.
*
* This method initializes the object and sets up necessary hooks.
*
* @since 1.0.0
*/
public function __construct() {
$this->setup_hooks();
}

/**
* Set up hooks for various purposes.
*
* This method adds hooks for different purposes as needed.
*
* @since 1.0.0
*
* @return void
*/
protected function setup_hooks(): void {
add_action( 'init', array( $this, 'register_post_type' ) );
add_action( 'init', array( $this, 'register_post_meta' ) );
add_action( 'delete_post', array( $this, 'delete_event' ) );
add_action(
sprintf( 'manage_%s_posts_custom_column', Event::POST_TYPE ),
array( $this, 'custom_columns' ),
10,
2
);

add_filter(
sprintf( 'manage_%s_posts_columns', Event::POST_TYPE ),
array( $this, 'set_custom_columns' )
);
add_filter(
sprintf( 'manage_edit-%s_sortable_columns', Event::POST_TYPE ),
array( $this, 'sortable_columns' )
);
add_filter( 'get_the_date', array( $this, 'get_the_event_date' ) );
add_filter( 'the_time', array( $this, 'get_the_event_date' ) );
add_filter( 'display_post_states', array( $this, 'set_event_archive_labels' ), 10, 2 );
}

/**
* Registers the custom post type for Events.
*
* This method sets up the custom post type 'Event' with all necessary labels and settings,
* enabling it to be used within the WordPress REST API, and configuring its appearance and capabilities
* within the WordPress admin area. It defines labels for various UI elements, enables Gutenberg support,
* sets the post type to be public, and configures other settings such as the menu position and icon.
*
* @since 1.0.0
*
* @return void
*/
public function register_post_type(): void {
register_post_type(
Event::POST_TYPE,
array(
'labels' => array(
'name' => _x( 'Events', 'Post Type General Name', 'gatherpress' ),
'singular_name' => _x( 'Event', 'Post Type Singular Name', 'gatherpress' ),
'menu_name' => __( 'Events', 'gatherpress' ),
'all_items' => __( 'All Events', 'gatherpress' ),
'view_item' => __( 'View Event', 'gatherpress' ),
'add_new_item' => __( 'Add New Event', 'gatherpress' ),
'add_new' => __( 'Add New', 'gatherpress' ),
'edit_item' => __( 'Edit Event', 'gatherpress' ),
'update_item' => __( 'Update Event', 'gatherpress' ),
'search_items' => __( 'Search Events', 'gatherpress' ),
'not_found' => __( 'Not Found', 'gatherpress' ),
'not_found_in_trash' => __( 'Not found in Trash', 'gatherpress' ),
),
'show_in_rest' => true,
'rest_base' => 'gp_events',
'public' => true,
'hierarchical' => false,
'template' => array(
array( 'gatherpress/event-date' ),
array( 'gatherpress/add-to-calendar' ),
array( 'gatherpress/venue' ),
array( 'gatherpress/rsvp' ),
array(
'core/paragraph',
array(
'placeholder' => __(
'Add a description of the event and let people know what to expect, including the agenda, what they need to bring, and how to find the group.',
'gatherpress'
),
),
),
array( 'gatherpress/rsvp-response' ),
),
'menu_position' => 4,
'supports' => array(
'title',
'editor',
'excerpt',
'thumbnail',
'comments',
'revisions',
'custom-fields',
),
'menu_icon' => 'dashicons-nametag',
'rewrite' => array(
'slug' => _x( 'event', 'Post Type Slug', 'gatherpress' ),
),
)
);
}

/**
* Registers post meta for the Event custom post type.
*
* This method sets up custom metadata fields associated with Event posts, including
* an online event link and an option to enable anonymous RSVPs. Each meta field is configured
* with authorization, sanitization callbacks, visibility in the REST API, and data type specifications.
*
* @since 1.0.0
*
* @return void
*/
public function register_post_meta(): void {
$post_meta = array(
'online_event_link' => array(
'auth_callback' => function () {
return current_user_can( 'edit_posts' );
},
'sanitize_callback' => 'sanitize_url',
'show_in_rest' => true,
'single' => true,
'type' => 'string',
),
'enable_anonymous_rsvp' => array(
'auth_callback' => function () {
return current_user_can( 'edit_posts' );
},
'sanitize_callback' => 'rest_sanitize_boolean',
'show_in_rest' => true,
'single' => true,
'type' => 'boolean',
),
);

foreach ( $post_meta as $meta_key => $args ) {
register_post_meta(
Event::POST_TYPE,
$meta_key,
$args
);
}
}

/**
* Delete event record from custom table when an event is deleted.
*
* This method is called when an event post is deleted, and it ensures that the corresponding
* record in the custom table associated with the event is also deleted.
*
* @since 1.0.0
*
* @param int $post_id An event post ID.
* @return void
*/
public function delete_event( int $post_id ): void {
global $wpdb;

if ( Event::POST_TYPE !== get_post_type( $post_id ) ) {
return;
}

$table = sprintf( Event::TABLE_FORMAT, $wpdb->prefix, Event::POST_TYPE );

$wpdb->delete( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
$table,
array(
'post_id' => $post_id,
)
);
}

/**
* Populate custom columns for Event post type in the admin dashboard.
*
* Displays additional information, like event datetime, for Event post types.
*
* @since 1.0.0
*
* @param string $column The name of the column to display.
* @param int $post_id The current post ID.
* @return void
*
* @throws Exception If initializing Event object fails, due to invalid post ID or database issues.
*/
public function custom_columns( string $column, int $post_id ): void {
if ( 'datetime' !== $column ) {
return;
}

$event = new Event( $post_id );

echo esc_html( $event->get_display_datetime() );
}

/**
* Set custom columns for Event post type in the admin dashboard.
*
* This method is used to define custom columns for Event post types in the WordPress admin dashboard.
* It adds an additional column for displaying event date and time.
*
* @since 1.0.0
*
* @param array $columns An associative array of column headings.
* @return array An updated array of column headings, including the custom columns.
*/
public function set_custom_columns( array $columns ): array {
$placement = 2;
$insert = array(
'datetime' => __( 'Event date &amp; time', 'gatherpress' ),
);

return array_slice( $columns, 0, $placement, true ) + $insert + array_slice( $columns, $placement, null, true );
}

/**
* Make custom columns sortable for Event post type in the admin dashboard.
*
* This method allows the custom columns, including the 'Event date & time' column,
* to be sortable in the WordPress admin dashboard for Event post types.
*
* @since 1.0.0
*
* @param array $columns An array of sortable columns.
* @return array An updated array of sortable columns.
*/
public function sortable_columns( array $columns ): array {
// Add 'datetime' as a sortable column.
$columns['datetime'] = 'datetime';

return $columns;
}

/**
* Returns the event date instead of the publish date for events.
*
* This method retrieves the event date based on plugin settings, replacing the publish date
* for event posts when appropriate.
*
* @since 1.0.0
*
* @param string $the_date The formatted date.
* @return string The event date as a formatted string.
*
* @throws Exception If initializing the Event object fails or event data cannot be retrieved.
*/
public function get_the_event_date( $the_date ): string {
$settings = Settings::get_instance();
$use_event_date = $settings->get_value( 'general', 'general', 'post_or_event_date' );

// Check if the post is of the 'Event' post type and if event date should be used.
if ( Event::POST_TYPE !== get_post_type() || 1 !== intval( $use_event_date ) ) {
return $the_date;
}

// Get the event date and return it as the formatted date.
$event = new Event( get_the_ID() );

return $event->get_display_datetime();
}

/**
* Add Upcoming and Past Events display states to assigned pages.
*
* This method adds custom display states to assigned pages for "Upcoming Events" and "Past Events"
* based on the plugin settings. It checks if the current post object corresponds to any of the assigned
* pages and adds display states accordingly.
*
* @since 1.0.0
*
* @param array $post_states An array of post display states.
* @param WP_Post $post The current post object.
* @return array An updated array of post display states with custom labels if applicable.
*/
public function set_event_archive_labels( array $post_states, WP_Post $post ): array {
// Retrieve plugin general settings.
$general = get_option( Utility::prefix_key( 'general' ) );
$pages = $general['pages'] ?? '';

if ( empty( $pages ) || ! is_array( $pages ) ) {
return $post_states;
}

// Define archive pages for "Upcoming Events" and "Past Events".
$archive_pages = array(
'past_events' => json_decode( $pages['past_events'] ),
'upcoming_events' => json_decode( $pages['upcoming_events'] ),
);

// Check if the current post corresponds to any assigned archive page and add display states.
foreach ( $archive_pages as $key => $value ) {
if ( ! empty( $value ) && is_array( $value ) ) {
$page = $value[0];

if ( $page->id === $post->ID ) {
$post_states[ sprintf( 'gp_%s', $key ) ] = sprintf( 'GP %s', $page->value );
}
}
}

return $post_states;
}
}
Loading

0 comments on commit a71446b

Please sign in to comment.