$saved === false ? ['pcwp_details', 'pcwp_rsvp_settings', 'pcwp_cost_settings', 'pcwp_links_settings'] : $saved); add_filter('get_user_option_closedpostboxes_pcwp_series', static fn (mixed $saved): mixed => $saved === false ? ['pcwp_details', 'pcwp_rsvp_settings', 'pcwp_cost_settings', 'pcwp_links_settings'] : $saved); } public function addSeries(): void { if (get_current_screen()?->is_block_editor()) { return; } foreach (['details' => __('Event details', 'proeventswp'), 'rsvp' => __('RSVP', 'proeventswp'), 'cost' => __('Cost', 'proeventswp'), 'links' => __('Links & map', 'proeventswp')] as $method => $title) { add_meta_box($method === 'details' ? 'pcwp_details' : 'pcwp_' . $method . '_settings', $title, [$this, $method], 'pcwp_series', 'normal', 'default'); } add_meta_box('pcwp_schedule', __('Schedule', 'proeventswp'), static function (): void { echo '
'; }, 'pcwp_series', 'normal', 'high'); add_meta_box('pcwp_series_entities', __('Venues and organizers', 'proeventswp'), static function (): void { echo '
'; }, 'pcwp_series', 'side', 'default'); } public function add(): void { $screen = get_current_screen(); if ($screen === null || ! $screen->is_block_editor()) { add_meta_box('pcwp_schedule', __('Event schedule', 'proeventswp'), [$this, 'schedule'], 'pcwp_event', 'normal', 'high'); add_meta_box('pcwp_details', __('Event details', 'proeventswp'), [$this, 'details'], 'pcwp_event', 'normal', 'default'); add_meta_box('pcwp_rsvp_settings', __('RSVP', 'proeventswp'), [$this, 'rsvp'], 'pcwp_event', 'normal', 'default'); add_meta_box('pcwp_cost_settings', __('Cost', 'proeventswp'), [$this, 'cost'], 'pcwp_event', 'normal', 'default'); add_meta_box('pcwp_links_settings', __('Links & map', 'proeventswp'), [$this, 'links'], 'pcwp_event', 'normal', 'default'); } add_meta_box('pcwp_entities', __('Venues and organizers', 'proeventswp'), [$this, 'entities'], 'pcwp_event', 'side', 'default'); } public function editorAssets(): void { $screen = get_current_screen(); if (! in_array($screen?->post_type, ['pcwp_event', 'pcwp_series'], true)) { return; } $this->scheduleAssets(); wp_enqueue_script( 'pcwp-event-editor', PCWP_URL . 'assets/event-editor.js', ['pcwp-schedule-editor', 'wp-components', 'wp-data', 'wp-edit-post', 'wp-element', 'wp-i18n', 'wp-plugins'], (string) filemtime(PCWP_PATH . 'assets/event-editor.js'), true, ); } public function scheduleAssets(): void { if (! in_array(get_current_screen()?->post_type, ['pcwp_event', 'pcwp_series'], true)) { return; } wp_enqueue_script('pcwp-schedule-editor', PCWP_URL . 'assets/schedule-editor.js', ['wp-components', 'wp-element', 'wp-i18n', 'wp-dom-ready'], (string) filemtime(PCWP_PATH . 'assets/schedule-editor.js'), true); global $post; wp_localize_script('pcwp-schedule-editor', 'pcwpScheduleData', [ 'timezone' => wp_timezone_string(), 'timezones' => timezone_identifiers_list(), 'isNew' => $post instanceof \WP_Post && $post->post_status === 'auto-draft', ]); wp_enqueue_style('wp-components'); wp_enqueue_style('pcwp-schedule-editor', PCWP_URL . 'assets/schedule-editor.css', [], (string) filemtime(PCWP_PATH . 'assets/schedule-editor.css')); wp_enqueue_script('pcwp-classic-details', PCWP_URL . 'assets/classic-details.js', ['wp-dom-ready'], (string) filemtime(PCWP_PATH . 'assets/classic-details.js'), true); } public function schedule(\WP_Post $post): void { wp_nonce_field('pcwp_save_event', 'pcwp_event_nonce'); $timezone = (string) get_post_meta($post->ID, '_pcwp_timezone', true) ?: wp_timezone_string(); $schedule = get_post_meta($post->ID, '_pcwp_schedule', true) ?: ['type' => 'continuous']; $meta = ['_pcwp_schedule' => $schedule, '_pcwp_timezone' => (string) get_post_meta($post->ID, '_pcwp_timezone', true), '_pcwp_start' => get_post_meta($post->ID, '_pcwp_start', true), '_pcwp_end' => get_post_meta($post->ID, '_pcwp_end', true), '_pcwp_all_day' => (bool) get_post_meta($post->ID, '_pcwp_all_day', true)]; echo '
'; echo ''; ?>



'; $this->select('pcwp_status', __('Event status', 'proeventswp'), [ 'scheduled' => __('Scheduled', 'proeventswp'), 'rescheduled' => __('Rescheduled', 'proeventswp'), 'canceled' => __('Canceled', 'proeventswp'), 'postponed' => __('Postponed', 'proeventswp'), 'moved-online' => __('Moved online', 'proeventswp'), ], (string) get_post_meta($post->ID, '_pcwp_status', true) ?: 'scheduled'); $this->select('pcwp_mode', __('Attendance mode', 'proeventswp'), [ 'in-person' => __('In person', 'proeventswp'), 'online' => __('Online', 'proeventswp'), 'hybrid' => __('Hybrid', 'proeventswp'), ], (string) get_post_meta($post->ID, '_pcwp_mode', true) ?: 'in-person'); ?>








prefix . 'pcwp_event_entities'; $selected = $wpdb->get_results($wpdb->prepare("SELECT entity_id,entity_type FROM {$table} WHERE event_id=%d", $post->ID)); $byType = ['venue' => [], 'organizer' => []]; foreach (is_array($selected) ? $selected : [] as $row) { $byType[$row->entity_type][] = (int) $row->entity_id; } $this->entitySelect('pcwp_venue_ids', __('Venues', 'proeventswp'), 'pcwp_venue', $byType['venue']); $this->entitySelect('pcwp_organizer_ids', __('Organizers', 'proeventswp'), 'pcwp_organizer', $byType['organizer']); } public function dateNotice(): void { $screen = get_current_screen(); if ($screen?->post_type === 'pcwp_event' && isset($_GET['post']) && get_post_meta(absint($_GET['post']), '_pcwp_start', true) === '') { echo '

' . esc_html__('Set the event start and end before publishing.', 'proeventswp') . '

'; } } /** @param array $options */ private function select(string $name, string $label, array $options, string $selected): void { echo '


'; } /** @param list $selected */ private function entitySelect(string $name, string $label, string $postType, array $selected): void { $items = get_posts(['post_type' => $postType, 'post_status' => 'publish', 'numberposts' => -1, 'orderby' => 'title', 'order' => 'ASC']); $listed = array_map(static fn (\WP_Post $item): int => $item->ID, $items); foreach (array_diff($selected, $listed) as $id) { $item = get_post($id); if ($item instanceof \WP_Post && $item->post_type === $postType && current_user_can('read_post', $id)) { $items[] = $item; } } echo '


'; echo '
'; } }