diff --git a/includes/core/classes/class-event-query.php b/includes/core/classes/class-event-query.php index dde9786e5..b9fe9eb39 100644 --- a/includes/core/classes/class-event-query.php +++ b/includes/core/classes/class-event-query.php @@ -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, ), @@ -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, ); @@ -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 ); } ); @@ -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; diff --git a/includes/core/classes/class-event-setup.php b/includes/core/classes/class-event-setup.php new file mode 100644 index 000000000..53b0c555e --- /dev/null +++ b/includes/core/classes/class-event-setup.php @@ -0,0 +1,343 @@ +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' => 'event', + ), + ) + ); + } + + /** + * 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 & 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; + } +} diff --git a/includes/core/classes/class-event.php b/includes/core/classes/class-event.php index fe4176bfb..895300464 100644 --- a/includes/core/classes/class-event.php +++ b/includes/core/classes/class-event.php @@ -55,14 +55,6 @@ class Event { */ const TABLE_FORMAT = '%sgp_events'; - /** - * The taxonomy name for GatherPress event topics. - * - * @since 1.0.0 - * @var string $TAXONOMY - */ - const TAXONOMY = 'gp_topic'; - /** * Event post object. * @@ -95,111 +87,17 @@ public function __construct( int $post_id ) { } } - /** - * Get the arguments for registering the 'Event' custom post type. - * - * This method retrieves an array containing the registration arguments for the custom post type 'Event'. - * These arguments define how the Event post type behaves and appears in the WordPress admin. - * - * @since 1.0.0 - * - * @return array An array containing the registration arguments for the custom post type. - */ - public static function get_post_type_registration_args(): array { - return 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' => 'event', - ), - ); - } - - /** - * Get the registration arguments for custom post meta fields. - * - * This method retrieves an array containing the registration arguments for custom post meta fields. - * These arguments define how specific custom meta fields behave and are used in WordPress. - * - * @since 1.0.0 - * - * @return array An array containing the registration arguments for custom post meta fields. - */ - public static function get_post_meta_registration_args(): array { - return 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', - ), - ); - } - /** * Retrieve the formatted display date and time for the event. * - * Returns a human-readable representation of the event's start and end date/time, - * taking into account whether they fall on the same date or different dates. + * Returns a formatted string representing the event's start and end date/time. + * Adjusts format based on whether start and end are on the same day. * * @since 1.0.0 * - * @return string The formatted display date and time or an em dash if not available. + * @return string Formatted date/time or an em dash if data is unavailable. + * + * @throws Exception If date/time formatting fails or settings cannot be retrieved. */ public function get_display_datetime(): string { $settings = Settings::get_instance(); @@ -224,14 +122,15 @@ public function get_display_datetime(): string { } /** - * Check if the start DateTime and end DateTime fall on the same date. + * Check if the start and end DateTime fall on the same date. * - * This method compares the date portion of the start and end DateTime objects to determine - * if they represent the same date. + * Compares the start and end DateTime objects to determine if they are on the same date. * * @since 1.0.0 * - * @return bool True if the start and end DateTime are on the same date, false otherwise. + * @return bool True if start and end are on the same date, false otherwise. + * + * @throws Exception If date comparison fails. */ public function is_same_date(): bool { $datetime_start = $this->get_datetime_start( 'Y-m-d' ); @@ -367,13 +266,13 @@ protected function get_formatted_datetime( ): string { $dt = $this->get_datetime(); $date = $dt[ sprintf( 'datetime_%s_gmt', $which ) ]; - $dt['timezone'] = static::maybe_convert_offset( $dt['timezone'] ); + $dt['timezone'] = Utility::maybe_convert_utc_offset( $dt['timezone'] ); $tz = null; if ( true === $local && ! empty( $dt['timezone'] ) - && in_array( $dt['timezone'], static::list_identifiers(), true ) + && in_array( $dt['timezone'], Utility::list_timezone_and_utc_offsets(), true ) ) { $tz = new DateTimeZone( $dt['timezone'] ); } elseif ( false === $local ) { @@ -388,110 +287,6 @@ protected function get_formatted_datetime( return (string) $date; } - /** - * Convert a UTC offset to a format compatible with DateTimeZone. - * - * This method takes a UTC offset in the form of "+HH:mm" or "-HH:mm" and converts it to a format - * that can be used with the DateTimeZone constructor. - * - * @since 1.0.0 - * - * @param string $timezone The UTC offset to convert, e.g., "+05:30" or "-08:00". - * @return string The converted timezone format, e.g., "+0530" or "-0800". - */ - public static function maybe_convert_offset( string $timezone ): string { - // Regex: https://regex101.com/r/wxhjIu/1. - preg_match( '/^UTC([+-])(\d+)(.\d+)?$/', $timezone, $matches ); - - if ( count( $matches ) ) { - if ( empty( $matches[3] ) ) { - $matches[3] = ':00'; - } - - $matches[3] = str_replace( array( '.25', '.5', '.75' ), array( ':15', ':30', ':45' ), $matches[3] ); - - return $matches[1] . str_pad( $matches[2], 2, '0', STR_PAD_LEFT ) . $matches[3]; - } - - return $timezone; - } - - /** - * Get a list of all timezones and UTC offsets. - * - * This method returns an array containing all available timezones along with standard UTC offsets. - * - * @since 1.0.0 - * - * @return array An array of timezone identifiers and UTC offsets. - */ - public static function list_identifiers(): array { - // Get a list of all available timezone identifiers. - $identifiers = timezone_identifiers_list(); - - // Define an array of standard UTC offsets. - $offset_range = array( - '-12:00', - '-11:30', - '-11:00', - '-10:30', - '-10:00', - '-09:30', - '-09:00', - '-08:30', - '-08:00', - '-07:30', - '-07:00', - '-06:30', - '-06:00', - '-05:30', - '-05:00', - '-04:30', - '-04:00', - '-03:30', - '-03:00', - '-02:30', - '-02:00', - '-01:30', - '-01:00', - '-00:30', - '+00:00', - '+00:30', - '+01:00', - '+01:30', - '+02:00', - '+02:30', - '+03:00', - '+03:30', - '+04:00', - '+04:30', - '+05:00', - '+05:30', - '+05:45', - '+06:00', - '+06:30', - '+07:00', - '+07:30', - '+08:00', - '+08:30', - '+08:45', - '+09:00', - '+09:30', - '+10:00', - '+10:30', - '+11:00', - '+11:30', - '+12:00', - '+12:45', - '+13:00', - '+13:45', - '+14:00', - ); - - // Merge the timezone identifiers and UTC offsets into a single array. - return array_merge( $identifiers, $offset_range ); - } - /** * Retrieve event date and time from the custom table. * @@ -831,7 +626,6 @@ public function save_datetimes( array $params ): bool { global $wpdb; $params['post_id'] = $this->event->ID; - $retval = false; $fields = array_filter( $params, function ( $key ) { @@ -850,7 +644,7 @@ function ( $key ) { ); if ( 1 > intval( $fields['post_id'] ) ) { - return $retval; + return false; } $fields['timezone'] = ( ! empty( $fields['timezone'] ) ) ? $fields['timezone'] : wp_timezone_string(); @@ -870,17 +664,17 @@ function ( $key ) { ); if ( ! empty( $exists ) ) { - $retval = $wpdb->update( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching + $value = $wpdb->update( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching $table, $fields, array( 'post_id' => $fields['post_id'] ) ); delete_transient( sprintf( self::DATETIME_CACHE_KEY, $fields['post_id'] ) ); } else { - $retval = $wpdb->insert( $table, $fields ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery + $value = $wpdb->insert( $table, $fields ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery } - return (bool) $retval; + return (bool) $value; } /** @@ -888,8 +682,7 @@ function ( $key ) { * * This method retrieves the online event link for a user who is attending an event * and ensures that the event has not already occurred. It evaluates various conditions - * to determine whether to provide the online event link. The method is marked with a @todo - * to indicate that it should be refactored for improved readability and reduced conditionals. + * to determine whether to provide the online event link. * * @return string The online event link if all conditions are met; otherwise, an empty string. */ diff --git a/includes/core/classes/class-rest-api.php b/includes/core/classes/class-rest-api.php index 1452cacdb..05695e91f 100644 --- a/includes/core/classes/class-rest-api.php +++ b/includes/core/classes/class-rest-api.php @@ -359,7 +359,7 @@ public function validate_datetime( string $param ): bool { * @return bool True if the parameter is a valid timezone identifier, false otherwise. */ public function validate_timezone( string $param ): bool { - return in_array( Event::maybe_convert_offset( $param ), Event::list_identifiers(), true ); + return in_array( Utility::maybe_convert_utc_offset( $param ), Utility::list_timezone_and_utc_offsets(), true ); } /** @@ -378,7 +378,7 @@ public function validate_timezone( string $param ): bool { */ public function update_datetime( WP_REST_Request $request ): WP_REST_Response { $params = wp_parse_args( $request->get_params(), $request->get_default_params() ); - $params['timezone'] = Event::maybe_convert_offset( $params['timezone'] ); + $params['timezone'] = Utility::maybe_convert_utc_offset( $params['timezone'] ); $event = new Event( $params['post_id'] ); unset( $params['post_id'] ); diff --git a/includes/core/classes/class-setup.php b/includes/core/classes/class-setup.php index a3b2d51f0..868612175 100644 --- a/includes/core/classes/class-setup.php +++ b/includes/core/classes/class-setup.php @@ -58,9 +58,11 @@ protected function instantiate_classes(): void { Block::get_instance(); Cli::get_instance(); Event_Query::get_instance(); + Event_Setup::get_instance(); Rest_Api::get_instance(); Settings::get_instance(); User::get_instance(); + Topic::get_instance(); Venue::get_instance(); } @@ -78,31 +80,12 @@ protected function setup_hooks(): void { register_deactivation_hook( GATHERPRESS_CORE_FILE, array( $this, 'deactivate_gatherpress_plugin' ) ); add_action( 'init', array( $this, 'load_textdomain' ) ); - add_action( 'init', array( $this, 'register' ) ); - 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_action( 'init', array( $this, 'maybe_flush_gatherpress_rewrite_rules' ) ); add_action( 'admin_notices', array( $this, 'check_users_can_register' ) ); add_filter( 'block_categories_all', array( $this, 'register_gatherpress_block_category' ) ); add_filter( 'wpmu_drop_tables', array( $this, 'on_site_delete' ) ); - 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( 'body_class', array( $this, 'add_gatherpress_body_classes' ) ); - add_filter( 'display_post_states', array( $this, 'set_event_archive_labels' ), 10, 2 ); add_filter( sprintf( 'plugin_action_links_%s/%s', @@ -270,120 +253,6 @@ public function register_gatherpress_block_category( array $block_categories ): return $block_categories; } - /** - * Register GatherPress post types and taxonomies. - * - * This method is responsible for registering the GatherPress post types and taxonomies, - * as well as adding the online event term. It initializes the necessary content structures - * for the plugin. - * - * @since 1.0.0 - * - * @return void - */ - public function register(): void { - $this->register_post_types(); - $this->register_taxonomies(); - } - - /** - * Register GatherPress post types. - * - * This method is responsible for registering the GatherPress post types, including - * 'Event' and 'Venue' post types. It sets up their labels, supports, and other parameters. - * - * @since 1.0.0 - * - * @return void - */ - public function register_post_types(): void { - // Register Event post type and meta. - register_post_type( - Event::POST_TYPE, - Event::get_post_type_registration_args() - ); - - foreach ( Event::get_post_meta_registration_args() as $meta_key => $args ) { - register_post_meta( - Event::POST_TYPE, - $meta_key, - $args - ); - } - - // Register Venue post type and meta. - register_post_type( - Venue::POST_TYPE, - Venue::get_post_type_registration_args() - ); - - foreach ( Venue::get_post_meta_registration_args() as $meta_key => $args ) { - register_post_meta( - Venue::POST_TYPE, - $meta_key, - $args - ); - } - } - - /** - * Register GatherPress taxonomies. - * - * This method is responsible for registering the GatherPress taxonomies, including - * the 'Topics' taxonomy. It sets up their labels, hierarchical structure, and other parameters. - * - * @since 1.0.0 - * - * @return void - */ - public function register_taxonomies(): void { - // Register Event taxonomy. - register_taxonomy( - Event::TAXONOMY, - Event::POST_TYPE, - array( - 'labels' => array( - 'name' => _x( 'Topics', 'taxonomy general name', 'gatherpress' ), - 'singular_name' => _x( 'Topic', 'taxonomy singular name', 'gatherpress' ), - 'search_items' => __( 'Search Topics', 'gatherpress' ), - 'all_items' => __( 'All Topics', 'gatherpress' ), - 'view_item' => __( 'View Topic', 'gatherpress' ), - 'parent_item' => __( 'Parent Topic', 'gatherpress' ), - 'parent_item_colon' => __( 'Parent Topic:', 'gatherpress' ), - 'edit_item' => __( 'Edit Topic', 'gatherpress' ), - 'update_item' => __( 'Update Topic', 'gatherpress' ), - 'add_new_item' => __( 'Add New Topic', 'gatherpress' ), - 'new_item_name' => __( 'New Topic Name', 'gatherpress' ), - 'not_found' => __( 'No Topics Found', 'gatherpress' ), - 'back_to_items' => __( 'Back to Topics', 'gatherpress' ), - 'menu_name' => __( 'Topics', 'gatherpress' ), - ), - 'hierarchical' => true, - 'public' => true, - 'show_ui' => true, - 'show_admin_column' => true, - 'query_var' => true, - 'rewrite' => array( 'slug' => 'topic' ), - 'show_in_rest' => true, - ) - ); - - // Register Venue taxonomy. - register_taxonomy( - Venue::TAXONOMY, - Event::POST_TYPE, - array( - 'labels' => array(), - 'hierarchical' => false, - 'public' => true, - 'show_ui' => false, - 'show_admin_column' => false, - 'query_var' => true, - 'show_in_rest' => true, - ) - ); - } - /** * Add the 'Online event' term to the venue taxonomy. * @@ -395,7 +264,7 @@ public function register_taxonomies(): void { * @return void */ public function add_online_event_term(): void { - $this->register_taxonomies(); + Venue::get_instance()->register_taxonomy(); $term_name = __( 'Online event', 'gatherpress' ); $term_slug = 'online-event'; @@ -442,34 +311,6 @@ public function on_site_delete( array $tables ): array { return $tables; } - /** - * 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, - ) - ); - } - /** * Create a custom table if it doesn't exist for the main site or the current site in a network. * @@ -508,8 +349,9 @@ protected function create_tables(): void { $sql = array(); $charset_collate = $wpdb->get_charset_collate(); + $prefix = $wpdb->prefix; - $table = sprintf( Event::TABLE_FORMAT, $wpdb->prefix ); + $table = sprintf( Event::TABLE_FORMAT, $prefix ); $sql[] = "CREATE TABLE {$table} ( post_id bigint(20) unsigned NOT NULL default '0', datetime_start datetime NOT NULL default '0000-00-00 00:00:00', @@ -522,7 +364,7 @@ protected function create_tables(): void { KEY datetime_end_gmt (datetime_end_gmt) ) {$charset_collate};"; - $table = sprintf( Rsvp::TABLE_FORMAT, $wpdb->prefix ); + $table = sprintf( Rsvp::TABLE_FORMAT, $prefix ); $sql[] = "CREATE TABLE {$table} ( id bigint(20) unsigned NOT NULL auto_increment, post_id bigint(20) unsigned NOT NULL default '0', @@ -542,133 +384,6 @@ protected function create_tables(): void { dbDelta( $sql ); } - /** - * Populate custom columns for Event post type in the admin dashboard. - * - * This method is used to display custom columns for Event post types in the WordPress admin dashboard. - * It provides additional information for each event, such as its datetime. - * - * @since 1.0.0 - * - * @param string $column The name of the column to display. - * @param int $post_id The current post ID. - * @return void - */ - public function custom_columns( string $column, int $post_id ): void { - if ( 'datetime' === $column ) { - $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 & 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 instead of the publish date for events - * based on the plugin settings. It checks if the event date should be used instead - * of the publish date and returns the formatted event date accordingly. - * - * @since 1.0.0 - * - * @param string $the_date The formatted date. - * @return string The updated date string, representing the event date. - */ - 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; - } - /** * Display a notification to recommend enabling user registration for GatherPress functionality. * diff --git a/includes/core/classes/class-topic.php b/includes/core/classes/class-topic.php new file mode 100644 index 000000000..5befbc182 --- /dev/null +++ b/includes/core/classes/class-topic.php @@ -0,0 +1,102 @@ +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_taxonomy' ) ); + } + + /** + * Registers the Topic taxonomy for the Event post type. + * + * Sets up the Topic taxonomy with labels and settings for admin visibility, REST API support, + * and hierarchical structuring. This method ensures Topics are properly integrated within + * WordPress for management and querying. + * + * @since 1.0.0 + * + * @return void + */ + public function register_taxonomy(): void { + register_taxonomy( + self::TAXONOMY, + Event::POST_TYPE, + array( + 'labels' => array( + 'name' => _x( 'Topics', 'taxonomy general name', 'gatherpress' ), + 'singular_name' => _x( 'Topic', 'taxonomy singular name', 'gatherpress' ), + 'search_items' => __( 'Search Topics', 'gatherpress' ), + 'all_items' => __( 'All Topics', 'gatherpress' ), + 'view_item' => __( 'View Topic', 'gatherpress' ), + 'parent_item' => __( 'Parent Topic', 'gatherpress' ), + 'parent_item_colon' => __( 'Parent Topic:', 'gatherpress' ), + 'edit_item' => __( 'Edit Topic', 'gatherpress' ), + 'update_item' => __( 'Update Topic', 'gatherpress' ), + 'add_new_item' => __( 'Add New Topic', 'gatherpress' ), + 'new_item_name' => __( 'New Topic Name', 'gatherpress' ), + 'not_found' => __( 'No Topics Found', 'gatherpress' ), + 'back_to_items' => __( 'Back to Topics', 'gatherpress' ), + 'menu_name' => __( 'Topics', 'gatherpress' ), + ), + 'hierarchical' => true, + 'public' => true, + 'show_ui' => true, + 'show_admin_column' => true, + 'query_var' => true, + 'rewrite' => array( 'slug' => 'topic' ), + 'show_in_rest' => true, + ) + ); + } +} diff --git a/includes/core/classes/class-utility.php b/includes/core/classes/class-utility.php index 099a1449e..8f990012c 100644 --- a/includes/core/classes/class-utility.php +++ b/includes/core/classes/class-utility.php @@ -116,4 +116,108 @@ public static function timezone_choices(): array { return $timezones_clean; } + + /** + * Get a list of all timezones and UTC offsets. + * + * This method returns an array containing all available timezones along with standard UTC offsets. + * + * @since 1.0.0 + * + * @return array An array of timezone identifiers and UTC offsets. + */ + public static function list_timezone_and_utc_offsets(): array { + // Get a list of all available timezone identifiers. + $identifiers = timezone_identifiers_list(); + + // Define an array of standard UTC offsets. + $offset_range = array( + '-12:00', + '-11:30', + '-11:00', + '-10:30', + '-10:00', + '-09:30', + '-09:00', + '-08:30', + '-08:00', + '-07:30', + '-07:00', + '-06:30', + '-06:00', + '-05:30', + '-05:00', + '-04:30', + '-04:00', + '-03:30', + '-03:00', + '-02:30', + '-02:00', + '-01:30', + '-01:00', + '-00:30', + '+00:00', + '+00:30', + '+01:00', + '+01:30', + '+02:00', + '+02:30', + '+03:00', + '+03:30', + '+04:00', + '+04:30', + '+05:00', + '+05:30', + '+05:45', + '+06:00', + '+06:30', + '+07:00', + '+07:30', + '+08:00', + '+08:30', + '+08:45', + '+09:00', + '+09:30', + '+10:00', + '+10:30', + '+11:00', + '+11:30', + '+12:00', + '+12:45', + '+13:00', + '+13:45', + '+14:00', + ); + + // Merge the timezone identifiers and UTC offsets into a single array. + return array_merge( $identifiers, $offset_range ); + } + + /** + * Convert a UTC offset to a format compatible with DateTimeZone. + * + * This method takes a UTC offset in the form of "+HH:mm" or "-HH:mm" and converts it to a format + * that can be used with the DateTimeZone constructor. + * + * @since 1.0.0 + * + * @param string $timezone The UTC offset to convert, e.g., "+05:30" or "-08:00". + * @return string The converted timezone format, e.g., "+0530" or "-0800". + */ + public static function maybe_convert_utc_offset( string $timezone ): string { + // Regex: https://regex101.com/r/wxhjIu/1. + preg_match( '/^UTC([+-])(\d+)(.\d+)?$/', $timezone, $matches ); + + if ( ! count( $matches ) ) { + return $timezone; + } + + if ( empty( $matches[3] ) ) { + $matches[3] = ':00'; + } + + $matches[3] = str_replace( array( '.25', '.5', '.75' ), array( ':15', ':30', ':45' ), $matches[3] ); + + return $matches[1] . str_pad( $matches[2], 2, '0', STR_PAD_LEFT ) . $matches[3]; + } } diff --git a/includes/core/classes/class-venue.php b/includes/core/classes/class-venue.php index 55dcbbede..a31e3344e 100644 --- a/includes/core/classes/class-venue.php +++ b/includes/core/classes/class-venue.php @@ -74,72 +74,82 @@ protected function setup_hooks(): void { 10, 3 ); + add_action( 'init', array( $this, 'register_post_type' ) ); + add_action( 'init', array( $this, 'register_post_meta' ) ); + add_action( 'init', array( $this, 'register_taxonomy' ) ); add_action( 'post_updated', array( $this, 'maybe_update_term_slug' ), 10, 3 ); add_action( 'delete_post', array( $this, 'delete_venue_term' ) ); } /** - * Get the arguments for registering the 'Venue' custom post type. + * Registers the custom post type for Venues. * - * This method returns an array containing the registration arguments for the custom post type 'Venue.' - * These arguments define aspects of the post type, such as labels, REST API support, visibility in the admin menu, - * supported features, icons, and rewrite rules. + * Initializes the Venues post type with all its associated labels, settings, + * and supports features, making it accessible within the WordPress REST API, + * searchable, and manageable within the custom 'Venues' menu in the dashboard. + * It is designed to handle venue information for events, including titles, + * descriptions, images, and custom fields. * * @since 1.0.0 * - * @return array An array containing the registration arguments for the 'Venue' custom post type. + * @return void */ - public static function get_post_type_registration_args(): array { - return array( - 'labels' => array( - 'name' => _x( 'Venues', 'Post Type General Name', 'gatherpress' ), - 'singular_name' => _x( 'Venue', 'Post Type Singular Name', 'gatherpress' ), - 'menu_name' => __( 'Venues', 'gatherpress' ), - 'all_items' => __( 'Venues', 'gatherpress' ), - 'view_item' => __( 'View Venue', 'gatherpress' ), - 'add_new_item' => __( 'Add New Venue', 'gatherpress' ), - 'add_new' => __( 'Add New', 'gatherpress' ), - 'edit_item' => __( 'Edit Venue', 'gatherpress' ), - 'update_item' => __( 'Update Venue', 'gatherpress' ), - 'search_items' => __( 'Search Venues', 'gatherpress' ), - 'not_found' => __( 'Not Found', 'gatherpress' ), - 'not_found_in_trash' => __( 'Not found in Trash', 'gatherpress' ), - ), - 'show_in_rest' => true, - 'rest_base' => 'gp_venues', - 'public' => true, - 'hierarchical' => false, - 'show_in_menu' => 'edit.php?post_type=gp_event', - 'supports' => array( - 'title', - 'editor', - 'thumbnail', - 'revisions', - 'custom-fields', - ), - 'menu_icon' => 'dashicons-location', - 'template' => array( - array( 'gatherpress/venue' ), - ), - 'rewrite' => array( - 'slug' => 'venue', - ), + public function register_post_type(): void { + register_post_type( + self::POST_TYPE, + array( + 'labels' => array( + 'name' => _x( 'Venues', 'Post Type General Name', 'gatherpress' ), + 'singular_name' => _x( 'Venue', 'Post Type Singular Name', 'gatherpress' ), + 'menu_name' => __( 'Venues', 'gatherpress' ), + 'all_items' => __( 'Venues', 'gatherpress' ), + 'view_item' => __( 'View Venue', 'gatherpress' ), + 'add_new_item' => __( 'Add New Venue', 'gatherpress' ), + 'add_new' => __( 'Add New', 'gatherpress' ), + 'edit_item' => __( 'Edit Venue', 'gatherpress' ), + 'update_item' => __( 'Update Venue', 'gatherpress' ), + 'search_items' => __( 'Search Venues', 'gatherpress' ), + 'not_found' => __( 'Not Found', 'gatherpress' ), + 'not_found_in_trash' => __( 'Not found in Trash', 'gatherpress' ), + ), + 'show_in_rest' => true, + 'rest_base' => 'gp_venues', + 'public' => true, + 'hierarchical' => false, + 'show_in_menu' => 'edit.php?post_type=gp_event', + 'supports' => array( + 'title', + 'editor', + 'thumbnail', + 'revisions', + 'custom-fields', + ), + 'menu_icon' => 'dashicons-location', + 'template' => array( + array( 'gatherpress/venue' ), + ), + 'rewrite' => array( + 'slug' => 'venue', + ), + ) ); } /** - * Get the registration arguments for custom post meta fields. + * Registers custom meta fields for the Venue post type. * - * This method returns an array containing the registration arguments for custom post meta fields - * associated with the 'Venue' custom post type. These arguments include callbacks for authorization - * and data sanitization, support for the REST API, data type, and more. + * Sets up meta fields associated with the Venue post type, such as 'venue_information', + * configuring capabilities, sanitization, and REST API visibility. This method ensures + * that only users with the appropriate permissions can edit these fields, and that + * the data stored is properly sanitized. Each meta field is registered to be + * single and of a string type, optimized for use within the WordPress REST API. * * @since 1.0.0 * - * @return array An array containing the registration arguments for custom post meta fields. + * @return void */ - public static function get_post_meta_registration_args(): array { - return array( + public function register_post_meta(): void { + $post_meta = array( 'venue_information' => array( 'auth_callback' => static function () { return current_user_can( 'edit_posts' ); @@ -150,6 +160,42 @@ public static function get_post_meta_registration_args(): array { 'type' => 'string', ), ); + + foreach ( $post_meta as $meta_key => $args ) { + register_post_meta( + self::POST_TYPE, + $meta_key, + $args + ); + } + } + + /** + * Registers a custom taxonomy for the Venue post type, not accessible to users. + * + * This taxonomy, programmatically managed and linked to the Venue post type, is hidden from users + * and designed for internal purposes only. Slugs for taxonomy terms are prefixed with an underscore, + * emphasizing their programmatic nature and ensuring they remain uneditable through the WordPress UI. + * It supports query var and REST API interactions but is entirely excluded from the admin UI and user-facing interfaces. + * + * @since 1.0.0 + * + * @return void + */ + public function register_taxonomy(): void { + register_taxonomy( + self::TAXONOMY, + Event::POST_TYPE, + array( + 'labels' => array(), + 'hierarchical' => false, + 'public' => true, + 'show_ui' => false, + 'show_admin_column' => false, + 'query_var' => true, + 'show_in_rest' => true, + ) + ); } /** diff --git a/test/unit/php/includes/core/classes/class-test-event-query.php b/test/unit/php/includes/core/classes/class-test-event-query.php index 2654c7216..24bab2cb9 100644 --- a/test/unit/php/includes/core/classes/class-test-event-query.php +++ b/test/unit/php/includes/core/classes/class-test-event-query.php @@ -11,6 +11,8 @@ use DateTime; use GatherPress\Core\Event; use GatherPress\Core\Event_Query; +use GatherPress\Core\Setup; +use GatherPress\Core\Topic; use GatherPress\Core\Venue; use PMC\Unit_Test\Base; @@ -142,7 +144,7 @@ public function test_get_events_list(): void { $event_1->save_datetimes( $params ); $event_2->save_datetimes( $params ); - $venue = wp_insert_term( + wp_insert_term( 'Unit Test Venue', Venue::TAXONOMY, array( @@ -151,13 +153,13 @@ public function test_get_events_list(): void { ); $topic = wp_insert_term( 'Unit Test Topic', - Event::TAXONOMY, + Topic::TAXONOMY, array( 'slug' => 'unit-test-topic', ) ); - wp_set_post_terms( $post_1->ID, $topic['term_id'], Event::TAXONOMY ); + wp_set_post_terms( $post_1->ID, $topic['term_id'], Topic::TAXONOMY ); wp_set_post_terms( $post_1->ID, '_unit-test-venue', Venue::TAXONOMY ); $results = $instance->get_events_list( diff --git a/test/unit/php/includes/core/classes/class-test-event-setup.php b/test/unit/php/includes/core/classes/class-test-event-setup.php new file mode 100644 index 000000000..e3773b12e --- /dev/null +++ b/test/unit/php/includes/core/classes/class-test-event-setup.php @@ -0,0 +1,96 @@ + 'action', + 'name' => 'delete_post', + 'priority' => 10, + 'callback' => array( $instance, 'delete_event' ), + ), + array( + 'type' => 'filter', + 'name' => sprintf( 'manage_%s_posts_columns', Event::POST_TYPE ), + 'priority' => 10, + 'callback' => array( $instance, 'set_custom_columns' ), + ), + array( + 'type' => 'filter', + 'name' => sprintf( 'manage_edit-%s_sortable_columns', Event::POST_TYPE ), + 'priority' => 10, + 'callback' => array( $instance, 'sortable_columns' ), + ), + array( + 'type' => 'filter', + 'name' => 'get_the_date', + 'priority' => 10, + 'callback' => array( $instance, 'get_the_event_date' ), + ), + array( + 'type' => 'filter', + 'name' => 'the_time', + 'priority' => 10, + 'callback' => array( $instance, 'get_the_event_date' ), + ), + array( + 'type' => 'filter', + 'name' => 'display_post_states', + 'priority' => 10, + 'callback' => array( $instance, 'set_event_archive_labels' ), + ), + ); + + $this->assert_hooks( $hooks, $instance ); + } + /** + * Coverage for sortable_columns method. + * + * @covers ::sortable_columns + * + * @return void + */ + public function test_sortable_columns(): void { + $instance = Event_Setup::get_instance(); + $default = array( 'unit' => 'test' ); + $expects = array( + 'unit' => 'test', + 'datetime' => 'datetime', + ); + + $this->assertSame( + $expects, + $instance->sortable_columns( $default ), + 'Failed to assert correct sortable columns.' + ); + } +} diff --git a/test/unit/php/includes/core/classes/class-test-event.php b/test/unit/php/includes/core/classes/class-test-event.php index 0f75fd3d3..85d755798 100644 --- a/test/unit/php/includes/core/classes/class-test-event.php +++ b/test/unit/php/includes/core/classes/class-test-event.php @@ -44,63 +44,6 @@ public function test___construct(): void { $this->assertInstanceOf( Rsvp::class, Utility::get_hidden_property( $event, 'rsvp' ) ); } - /** - * Coverage for get_post_type_registration_args method. - * - * @covers ::get_post_type_registration_args - * - * @return void - */ - public function test_get_post_type_registration_args(): void { - $args = Event::get_post_type_registration_args(); - - $this->assertIsArray( $args['labels'], 'Failed to assert that labels are an array.' ); - $this->assertTrue( $args['show_in_rest'], 'Failed to assert that show_in_rest is true.' ); - $this->assertTrue( $args['public'], 'Failed to assert that public is true.' ); - $this->assertSame( 'dashicons-nametag', $args['menu_icon'], 'Failed to assert that menu_icon is nametag.' ); - $this->assertSame( 'event', $args['rewrite']['slug'], 'Failed to assert that slug is events.' ); - } - - /** - * Coverage for get_post_meta_registration_args method. - * - * @covers ::get_post_meta_registration_args - * - * @return void - */ - public function test_get_post_meta_registration_args(): void { - $args = Event::get_post_meta_registration_args(); - - $this->assertIsArray( - $args['online_event_link'], - 'Failed to assert that online_event_link is an array.' - ); - $this->assertIsArray( - $args['enable_anonymous_rsvp'], - 'Failed to assert that online_event_link is an array.' - ); - - $this->mock->user( 'subscriber' ); - $this->assertFalse( - $args['online_event_link']['auth_callback'](), - 'Failed to assert that user cannot edit posts.' - ); - $this->assertFalse( - $args['enable_anonymous_rsvp']['auth_callback'](), - 'Failed to assert that user cannot edit posts.' - ); - - $this->mock->user( 'admin' ); - $this->assertTrue( - $args['online_event_link']['auth_callback'](), - 'Failed to assert that user can edit posts.' - ); - $this->assertTrue( - $args['enable_anonymous_rsvp']['auth_callback'](), - 'Failed to assert that user can edit posts.' - ); - } - /** * Data provider for get_display_datetime test. * @@ -330,84 +273,6 @@ public function test_get_gmt_datetime(): void { ); } - /** - * Data provider for maybe_convert_offset test. - * - * @return array - */ - public function data_maybe_convert_offset(): array { - return array( - array( - 'America/New_York', - 'America/New_York', - ), - array( - 'UTC', - 'UTC', - ), - array( - 'UTC+9.5', - '+09:30', - ), - array( - 'UTC-7.25', - '-07:15', - ), - array( - 'UTC-5.75', - '-05:45', - ), - array( - 'UTC+1', - '+01:00', - ), - ); - } - - /** - * Coverage for maybe_convert_offset method. - * - * @dataProvider data_maybe_convert_offset - * - * @covers ::maybe_convert_offset - * - * @param string $input Value to pass to method. - * @param string $expects Expected response. - * - * @return void - */ - public function test_maybe_convert_offset( $input, $expects ): void { - $this->assertSame( - $expects, - Event::maybe_convert_offset( $input ), - 'Failed to assert that conversion matches.' - ); - } - - /** - * Coverage for list_identifiers method. - * - * @covers ::list_identifiers - * - * @return void - */ - public function test_list_identifiers(): void { - $list = Event::list_identifiers(); - $timezones = array( - 'America/Belem', - 'Asia/Chita', - 'Europe/Vilnius', - 'UTC', - '-12:00', - '-00:30', - '+09:30', - '+13:45', - ); - foreach ( $timezones as $timezone ) { - $this->assertContains( $timezone, $list, 'Failed to assert timezone is in list.' ); - } - } - /** * Coverage for get_venue_information method. * diff --git a/test/unit/php/includes/core/classes/class-test-rest-api.php b/test/unit/php/includes/core/classes/class-test-rest-api.php index 099f8b6f2..6e8ba0590 100644 --- a/test/unit/php/includes/core/classes/class-test-rest-api.php +++ b/test/unit/php/includes/core/classes/class-test-rest-api.php @@ -576,7 +576,7 @@ public function test_events_list(): void { $event_ids = $this->get_event_ids( $response->data ); $this->assertContains( $upcoming_event_id, $event_ids, 'Failed to assert event ID is in array.' ); - $this->assertNotContains( $past_event_id, $event_ids, 'Failed to asssert event ID is not in array.' ); + $this->assertNotContains( $past_event_id, $event_ids, 'Failed to assert event ID is not in array.' ); $request->set_query_params( array( diff --git a/test/unit/php/includes/core/classes/class-test-setup.php b/test/unit/php/includes/core/classes/class-test-setup.php index 15a390c04..e950da38e 100644 --- a/test/unit/php/includes/core/classes/class-test-setup.php +++ b/test/unit/php/includes/core/classes/class-test-setup.php @@ -31,18 +31,6 @@ class Test_Setup extends Base { public function test_setup_hooks(): void { $instance = Setup::get_instance(); $hooks = array( - array( - 'type' => 'action', - 'name' => 'init', - 'priority' => 10, - 'callback' => array( $instance, 'register' ), - ), - array( - 'type' => 'action', - 'name' => 'delete_post', - 'priority' => 10, - 'callback' => array( $instance, 'delete_event' ), - ), array( 'type' => 'action', 'name' => 'init', @@ -61,42 +49,12 @@ public function test_setup_hooks(): void { 'priority' => 10, 'callback' => array( $instance, 'on_site_delete' ), ), - array( - 'type' => 'filter', - 'name' => sprintf( 'manage_%s_posts_columns', Event::POST_TYPE ), - 'priority' => 10, - 'callback' => array( $instance, 'set_custom_columns' ), - ), - array( - 'type' => 'filter', - 'name' => sprintf( 'manage_edit-%s_sortable_columns', Event::POST_TYPE ), - 'priority' => 10, - 'callback' => array( $instance, 'sortable_columns' ), - ), - array( - 'type' => 'filter', - 'name' => 'get_the_date', - 'priority' => 10, - 'callback' => array( $instance, 'get_the_event_date' ), - ), - array( - 'type' => 'filter', - 'name' => 'the_time', - 'priority' => 10, - 'callback' => array( $instance, 'get_the_event_date' ), - ), array( 'type' => 'filter', 'name' => 'body_class', 'priority' => 10, 'callback' => array( $instance, 'add_gatherpress_body_classes' ), ), - array( - 'type' => 'filter', - 'name' => 'display_post_states', - 'priority' => 10, - 'callback' => array( $instance, 'set_event_archive_labels' ), - ), array( 'type' => 'filter', 'name' => sprintf( 'plugin_action_links_%s/%s', basename( GATHERPRESS_CORE_PATH ), basename( GATHERPRESS_CORE_FILE ) ), @@ -263,26 +221,4 @@ static function ( $translation ): string { $this->assertSame( $slug, $term->slug, 'Failed to assert that term slugs match.' ); $this->assertSame( 'Online', $term->name, 'Failed to assert that term names match.' ); } - - /** - * Coverage for sortable_columns method. - * - * @covers ::sortable_columns - * - * @return void - */ - public function test_sortable_columns(): void { - $instance = Setup::get_instance(); - $default = array( 'unit' => 'test' ); - $expects = array( - 'unit' => 'test', - 'datetime' => 'datetime', - ); - - $this->assertSame( - $expects, - $instance->sortable_columns( $default ), - 'Failed to assert correct sortable columns.' - ); - } } diff --git a/test/unit/php/includes/core/classes/class-test-utility.php b/test/unit/php/includes/core/classes/class-test-utility.php index cff6e04d6..8fc51da71 100644 --- a/test/unit/php/includes/core/classes/class-test-utility.php +++ b/test/unit/php/includes/core/classes/class-test-utility.php @@ -105,4 +105,82 @@ public function test_timezone_choices(): void { $this->assertIsArray( $timezones[ $key ] ); } } + + /** + * Data provider for maybe_convert_utc_offset test. + * + * @return array + */ + public function data_maybe_convert_utc_offset(): array { + return array( + array( + 'America/New_York', + 'America/New_York', + ), + array( + 'UTC', + 'UTC', + ), + array( + 'UTC+9.5', + '+09:30', + ), + array( + 'UTC-7.25', + '-07:15', + ), + array( + 'UTC-5.75', + '-05:45', + ), + array( + 'UTC+1', + '+01:00', + ), + ); + } + + /** + * Coverage for maybe_convert_utc_offset method. + * + * @dataProvider data_maybe_convert_utc_offset + * + * @covers ::maybe_convert_utc_offset + * + * @param string $input Value to pass to method. + * @param string $expects Expected response. + * + * @return void + */ + public function test_maybe_convert_utc_offset( $input, $expects ): void { + $this->assertSame( + $expects, + Utility::maybe_convert_utc_offset( $input ), + 'Failed to assert that conversion matches.' + ); + } + + /** + * Coverage for list_timezone_and_utc_offsets method. + * + * @covers ::list_timezone_and_utc_offsets + * + * @return void + */ + public function test_list_timezone_and_utc_offsets(): void { + $list = Utility::list_timezone_and_utc_offsets(); + $timezones = array( + 'America/Belem', + 'Asia/Chita', + 'Europe/Vilnius', + 'UTC', + '-12:00', + '-00:30', + '+09:30', + '+13:45', + ); + foreach ( $timezones as $timezone ) { + $this->assertContains( $timezone, $list, 'Failed to assert timezone is in list.' ); + } + } } diff --git a/test/unit/php/includes/core/classes/class-test-venue.php b/test/unit/php/includes/core/classes/class-test-venue.php index 99e7b19b8..a772985d3 100644 --- a/test/unit/php/includes/core/classes/class-test-venue.php +++ b/test/unit/php/includes/core/classes/class-test-venue.php @@ -52,50 +52,6 @@ public function test_setup_hooks(): void { $this->assert_hooks( $hooks, $instance ); } - /** - * Coverage for get_post_type_registration_args method. - * - * @covers ::get_post_type_registration_args - * - * @return void - */ - public function test_get_post_type_registration_args(): void { - $args = Venue::get_post_type_registration_args(); - - $this->assertIsArray( $args['labels'], 'Failed to assert that labels are an array.' ); - $this->assertTrue( $args['show_in_rest'], 'Failed to assert that show_in_rest is true.' ); - $this->assertTrue( $args['public'], 'Failed to assert that public is true.' ); - $this->assertSame( 'dashicons-location', $args['menu_icon'], 'Failed to assert that menu_icon is location.' ); - $this->assertSame( 'venue', $args['rewrite']['slug'], 'Failed to assert that slug is events.' ); - } - - /** - * Coverage for get_post_meta_registration_args method. - * - * @covers ::get_post_meta_registration_args - * - * @return void - */ - public function test_get_post_meta_registration_args(): void { - $args = Venue::get_post_meta_registration_args(); - - $this->assertIsArray( $args['venue_information'], 'Failed to assert that _online_event_link is an array.' ); - - $this->mock->user( 'subscriber' ); - - $this->assertFalse( - $args['venue_information']['auth_callback'](), - 'Failed to assert false on auth_callback for subscriber' - ); - - $this->mock->user( 'admin' ); - - $this->assertTrue( - $args['venue_information']['auth_callback'](), - 'Failed to assert true on auth_callback for admin' - ); - } - /** * Coverage for add_venue_term. *