Skip to content

Translation Events: Make event end date optional#683

Open
ocean90 wants to merge 1 commit into
WordPress:trunkfrom
ocean90:translation-events-optional-end-date
Open

Translation Events: Make event end date optional#683
ocean90 wants to merge 1 commit into
WordPress:trunkfrom
ocean90:translation-events-optional-end-date

Conversation

@ocean90
Copy link
Copy Markdown
Member

@ocean90 ocean90 commented Jun 6, 2026

Generated with Claude Code, initially reviewed by myself.


Summary

Makes the event end date optional, providing a semantically explicit way to model open-ended events (e.g. WordPress Credits Contributions) instead of relying on a fake far-future date.

This is an alternative to #676, which only hides the misleading "Ends: in 9 years" display when the configured end date is more than one year out — the underlying fake 2036 date persists. With this change, organizers can mark events as Ongoing via a checkbox; the end date meta is removed and the UI shows "Ongoing event" instead.

Fixes https://meta.trac.wordpress.org/ticket/8280

Key changes

  • Domain (Event): $end is now ?Event_End_Date; is_active(), is_past(), validate_times() are null-safe; new is_open_ended() helper.
  • Repository: helper meta_query_end_after_or_unbounded() is applied to all current/upcoming queries so open-ended events (no _event_end meta) appear in current/upcoming lists. update_event_meta() deletes _event_end when null. get_event_meta() tolerates missing end.
  • Cached repository: active-filter callback accepts null end.
  • Capabilities: has_edit_field only modifies end when the event is past.
  • Attendee_Adder: stats import clamps lookback to max(start, now − 1 year) for open-ended events to avoid unbounded SELECTs.
  • Form: new "Ongoing event (no end date)" checkbox; the date input is disabled (so the browser doesn't POST a stale value) when ongoing.
  • JS: checkbox toggles input state and skips end-date validation/WordCamp pre-fill when active.
  • Display: details/list templates and the event-end theme block render an "Ongoing" label.
  • RSS: <ev:enddate> is omitted for open-ended events.
  • Legacy admin metabox: required removed and an empty value deletes the meta so admins can edit ongoing events from the WP Admin too.

Backward compatibility

All existing events have _event_end set, so their behavior is unchanged. No migration required.

Test plan

  • Create a new event with the Ongoing event checkbox enabled — detail view shows "Ongoing event (no end date)"; _event_end meta is absent.
  • Edit an existing event to open-ended — _event_end meta is deleted. Toggle back: meta is repopulated.
  • An open-ended event with start in the future appears under Upcoming; with start in the past, under Current; never in Past.
  • A bounded event with end < now continues to appear under Past (regression check).
  • Host of an open-ended event can edit title/end after start.
  • Attending an open-ended event with multi-year start does not run an unbounded translations scan.
  • RSS feed (/events/rss) omits <ev:enddate> for open-ended events and remains well-formed.
  • JS: toggling the checkbox enables/disables the end-date input and seeds a sensible default when unchecked.
  • Cache: switching an active event between bounded and open-ended is reflected on the home page after the next request.

Adds an "Ongoing event (no end date)" checkbox so events with no
scheduled end (e.g. WordPress Credits Contributions) can be modeled
explicitly instead of using a fake far-future end date.

Fixes https://meta.trac.wordpress.org/ticket/8280
Copilot AI review requested due to automatic review settings June 6, 2026 14:50
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 6, 2026

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

Core Committers: Use this line as a base for the props when committing in SVN:

Props ocean90.

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the Translation Events plugin to support open-ended events by making the event end date optional, removing the need for placeholder far-future end dates. It updates the domain model, queries, UI rendering, RSS output, and stats import behavior so events without _event_end are treated as “Ongoing”.

Changes:

  • Make Event::$end nullable and add is_open_ended(), with null-safe is_active(), is_past(), and validate_times().
  • Update repository queries/meta handling so events missing _event_end appear in current/upcoming listings and can be saved/edited.
  • Update UI (form, templates, block, RSS, JS/CSS) to support and display “Ongoing” events and avoid misleading end-date rendering.

Reviewed changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
wordpress.org/public_html/wp-content/plugins/wporg-gp-translation-events/wporg-gp-translation-events.php Makes WP Admin metabox end date optional and deletes _event_end when empty.
wordpress.org/public_html/wp-content/plugins/wporg-gp-translation-events/themes/wporg-translate-events-2024/blocks/event-date/index.php Renders “Ongoing” in the event-date block when open-ended.
wordpress.org/public_html/wp-content/plugins/wporg-gp-translation-events/templates/parts/event-list.php Displays “Ongoing” in event lists and avoids end-date output for open-ended events.
wordpress.org/public_html/wp-content/plugins/wporg-gp-translation-events/templates/parts/event-form.php Adds an “Ongoing event” checkbox and disables end date input when selected.
wordpress.org/public_html/wp-content/plugins/wporg-gp-translation-events/templates/event-details.php Shows “Ongoing event (no end date)” on the details page and uses is_past().
wordpress.org/public_html/wp-content/plugins/wporg-gp-translation-events/includes/routes/event/rss.php Omits <ev:enddate> for open-ended events.
wordpress.org/public_html/wp-content/plugins/wporg-gp-translation-events/includes/event/event.php Makes end date nullable and updates time/status helpers accordingly.
wordpress.org/public_html/wp-content/plugins/wporg-gp-translation-events/includes/event/event-repository.php Includes open-ended events in current/upcoming queries; deletes _event_end when null.
wordpress.org/public_html/wp-content/plugins/wporg-gp-translation-events/includes/event/event-repository-cached.php Updates cached “current events” filtering to accept null end.
wordpress.org/public_html/wp-content/plugins/wporg-gp-translation-events/includes/event/event-form-handler.php Parses new open-ended flag and allows null end dates on create/edit.
wordpress.org/public_html/wp-content/plugins/wporg-gp-translation-events/includes/event/event-capabilities.php Makes end-edit capability logic null-safe for past checks.
wordpress.org/public_html/wp-content/plugins/wporg-gp-translation-events/includes/attendee/attendee-adder.php Caps stats lookback window for open-ended events to avoid unbounded scans.
wordpress.org/public_html/wp-content/plugins/wporg-gp-translation-events/assets/js/translation-events.js Adds toggle behavior + validation adjustments for open-ended end date field.
wordpress.org/public_html/wp-content/plugins/wporg-gp-translation-events/assets/css/translation-events.css Styles the new end-date/ongoing toggle UI.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

<?php if ( $event->end()->is_in_the_past() ) : ?>
<span class="event-list-date"><?php $print_time( $event->end() ); ?></span>
<?php else : ?>
<span class="event-list-date"><?php $print_time( $event->end() ); ?></time></span>
Comment on lines +220 to +232
$endInput.prop( 'disabled', false );
if ( '' === $endInput.val() ) {
const startVal = $( '#event-start' ).val();
if ( startVal ) {
const start = new Date( startVal );
start.setHours( start.getHours() + 1 );
const pad = ( n ) => String( n ).padStart( 2, '0' );
$endInput.val(
start.getFullYear() + '-' + pad( start.getMonth() + 1 ) + '-' + pad( start.getDate() )
+ 'T' + pad( start.getHours() ) + ':' + pad( start.getMinutes() )
);
}
}
Comment on lines 213 to +215
<input type="datetime-local" id="event_start" name="event_start" value="<?php echo esc_attr( $event->start() ); ?>" required><br>
<label for="event_end">End Date (UTC): </label>
<input type="datetime-local" id="event_end" name="event_end" value="<?php echo esc_attr( $event->end() ); ?>" required><br>
<label for="event_end">End Date (UTC, leave empty for ongoing event): </label>
<input type="datetime-local" id="event_end" name="event_end" value="<?php echo esc_attr( null === $event->end() ? '' : (string) $event->end() ); ?>"><br>
Comment on lines +56 to +58
$is_open_ended = $event->is_open_ended();
$end_value = $is_open_ended ? '' : $event->end()->format( 'Y-m-d H:i' );
$can_edit_end = $is_create_form || current_user_can( 'edit_translation_event_end', $event->id() );
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants