slug = $slug; $this->postType = jvbCheckBase($slug); $this->registrar = $registrar; $this->addCalendarFields(); add_filter('post_type_link', [$this, 'handleCalendarLinks'], 15, 2); add_filter('post_type_archive_link', [$this, 'handlePostTypeArchiveLinks'], 15, 2); add_filter('query_vars', [$this, 'addQueryVars']); add_action('init', [$this, 'addCalendarRewrites']); } protected function addCalendarFields():void { $fields = [ 'location' => [ 'type' => 'location', 'label' => 'Event Location', ], 'location_notes' => [ 'type' => 'textarea', 'quill' => true, 'label' => 'Location Notes', ], 'date_start' => [ 'type' => 'date', 'label' => __('Date', 'jvb'), ], 'time_start' => [ 'type' => 'time', 'label' => __('Time Start', 'jvb'), ], 'time_end' => [ 'type' => 'time', 'label' => __('Time End', 'jvb'), ], 'make_multiple' => [ 'type' => 'true_false', 'label' => 'Make Multi-Day Event', 'default' => false, ], 'date_end' => [ 'type' => 'date', 'label' => __('Date End', 'jvb'), 'condition' => [ 'field' => 'make_multiple', 'operator' => '==', 'value' => 1 ] ], 'past' => [ 'type' => 'true_false', 'label' => __('Past Event', 'jvb'), 'hidden' => true, ], 'year' => [ 'type' => 'number', 'label' => __('Year', 'jvb'), 'hidden' => true, ], 'month' => [ 'type' => 'number', 'label' => __('Month', 'jvb'), 'hidden' => true, ], 'day' => [ 'type' => 'number', 'label' => __('Day', 'jvb'), 'hidden' => true, ], 'schedule' => [ 'type' => 'repeater', 'label' => 'Daily Schedule', 'description' => 'Set specific times for multi-day events', 'condition' => [ 'field' => 'make_multiple', 'operator' => '==', 'value' => 1, ], 'fields' => [ 'date' => [ 'type' => 'date', 'label' => 'Date' ], 'time_start' => [ 'type' => 'time', 'label' => 'Start Time' ], 'time_end' => [ 'type' => 'time', 'label' => 'End Time' ], 'notes' => [ 'type' => 'textarea', 'label' => 'Notes for this day' ] ] ], 'max_participants' => [ 'type' => 'number', 'label' => __('Maximum Participants', 'jvb'), ], 'is_free' => [ 'type' => 'true_false', 'label' => 'Free Event?', 'default' => 1, ], 'cost' => [ 'type' => 'number', 'label' => 'Cost to Attend', 'description' => 'Leave blank if free', 'condition' => [ 'field' => 'is_free', 'operator' => '!=', 'value' => 1 ], ], 'ticket_url' => [ 'type' => 'url', 'label' => 'Link to Purchase Ticket', 'condition' => [ 'field' => 'is_free', 'operator' => '!=', 'value' => 1 ] ], 'external_url' => [ 'type' => 'url', 'label' => 'Link to More Info' ], 'drop_in_allowed' => [ 'type' => 'true_false', 'label' => 'Drop-ins Welcome?', 'default' => true, ], 'recurrence' => [ 'type' => 'group', 'label' => 'Event Recurrence', 'condition' => [ 'field' => 'status', 'operator' => '==', 'value' => 'repeat', ], 'fields' => [ 'recurrence_type' => [ 'type' => 'select', 'label' => 'Repeats', 'options' => [ 'daily' => 'Daily', 'weekly' => 'Weekly', 'monthly' => 'Monthly', 'custom' => 'Custom' ] ], 'recurrence_interval' => [ 'type' => 'number', 'label' => 'Every', 'description' => 'Repeat every X days/weeks/months', 'default' => 1, ], 'recurrence_days' => [ 'type' => 'set', 'label' => 'On These Days', 'options' => [ 'monday' => 'Monday', 'tuesday' => 'Tuesday', 'wednesday' => 'Wednesday', 'thursday' => 'Thursday', 'friday' => 'Friday', 'saturday' => 'Saturday', 'sunday' => 'Sunday' ], 'condition' => [ 'field' => 'recurrence_type', 'operator' => '==', 'value' => 'weekly' ] ], 'recurrence_ends' => [ 'type' => 'group', 'label' => 'Recurrence Ends', 'fields' => [ 'type' => [ 'type' => 'select', 'label' => 'Recurrence Ends', 'options' => [ 'never' => 'Never', 'after' => 'After X occurrences', 'on' => 'On date' ] ], 'count' => [ 'type' => 'number', 'label' => 'Number of occurrences', 'condition' => [ 'field' => 'type', 'operator' => '==', 'value' => 'after' ] ], 'date' => [ 'type' => 'date', 'label' => 'End date', 'condition' => [ 'field' => 'type', 'operator' => '==', 'value' => 'on' ] ] ], ], 'rsvp_required' => [ 'type' => 'true_false', 'label' => 'RSVP Required?' ], 'rsvp_limit' => [ 'type' => 'number', 'label' => 'RSVP Limit', 'condition' => [ 'field' => 'rsvp_required', 'operator' => '==', 'value' => 1 ] ], 'rsvp_deadline' => [ 'type' => 'datetime', 'label' => 'RSVP Deadline', 'condition' => [ 'field' => 'rsvp_required', 'operator' => '==', 'value' => 1 ] ], ] ] ]; foreach ($fields as $name => $config) { $this->registrar->fields()->addField($name, $config); } $this->registrar->fields()->modifyField('post_status', 'options', [ 'all' => [ 'icon' => 'calendar', 'label' => 'Everything', ], 'future' => [ 'label' => 'Upcoming', 'icon' => 'clock-clockwise', ], 'past' => [ 'label' => 'Past', 'icon' => 'clock-counter-clockwise', ], 'repeat' => [ 'label' => 'Recurring', 'icon' => 'repeat', ], 'draft' => [ 'icon' => 'eye-closed', 'label' => 'Hidden', ], 'trash' => [ 'label' => 'Scrapped', 'icon' => 'trash', ] ]); } public function handleCalendarLinks(string $url, WP_POST $post):string { if ($post->post_type === $this->postType) { $get = ['year', 'month','day']; $values = Meta::forPost($post->ID)->getAll($get); foreach ($values as $key => $value) { if (!empty($value)) { $url = str_replace("%e$key%", $value, $url); } } $doubleCheck = ['eyear', 'emonth', 'eday']; foreach ($doubleCheck as $check) { if (str_contains($url, $check)) { $url = str_replace("/%e$check%", '', $url); } } } return $url; } public function handlePostTypeArchiveLinks(string $url, string $post_type):string { if ($post_type == $this->postType) { $url = get_home_url(null, '/'.$this->registrar->registrar->rewrite['slug']??$this->slug.'/'); } return $url; } public function addQueryVars(array $vars):array { $vars[] = 'eyear'; $vars[] = 'emonth'; $vars[] = 'eday'; return $vars; } public function addCalendarRewrites():void { add_rewrite_tag('%eyear%', '([^&]+)'); add_rewrite_tag('%emonth%', '([^&]+)'); add_rewrite_tag('%eday%', '([^&]+)'); } }