Skip to content

Enable Expiry Date in Frontend Form#2895

Open
masteradhoc wants to merge 7 commits intoAutomattic:trunkfrom
masteradhoc:expirydate
Open

Enable Expiry Date in Frontend Form#2895
masteradhoc wants to merge 7 commits intoAutomattic:trunkfrom
masteradhoc:expirydate

Conversation

@masteradhoc
Copy link
Copy Markdown
Contributor

Fixes #2886

Changes Proposed in this Pull Request

  • Allow Expiry Date to be set in Frontend Form for Job Submissions

Testing Instructions

  • Go to Settings -> Job Submissions and activate "Expiry Date field"
  • Visit Job Submissions Frontend Form
  • add a new job including an expiry date
  • see in wp-admin if the expiry date was set correctly

Release Notes

  • Allow Expiry Date to be set in Frontend Form for Job Submissions

New or Updated Hooks and Templates

Deprecated Code

Screenshot / Video

image

@masteradhoc
Copy link
Copy Markdown
Contributor Author

@donnchawp could you check this PR as well?

Copy link
Copy Markdown
Contributor

@donnchawp donnchawp left a comment

Choose a reason for hiding this comment

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

Thanks for your PR. Some changes here.

Comment thread includes/forms/class-wp-job-manager-form-submit-job.php Outdated
Comment thread includes/forms/class-wp-job-manager-form-submit-job.php Outdated
Comment thread includes/forms/class-wp-job-manager-form-submit-job.php Outdated
Comment thread includes/forms/class-wp-job-manager-form-submit-job.php Outdated
Comment thread includes/forms/class-wp-job-manager-form-submit-job.php Outdated
@masteradhoc masteradhoc requested a review from donnchawp May 3, 2026 08:37
Copy link
Copy Markdown
Contributor

@donnchawp donnchawp left a comment

Choose a reason for hiding this comment

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

I used 3 AIs to review this PR and they found issues. I was able to reproduce the "preview->submit" deletion of the expiry date too.

Multi-AI adversarial review (Claude + Gemini + Codex). Three of these findings have multi-reviewer consensus; two HIGH-severity findings were each surfaced solo and then independently confirmed via direct code reading.

Summary

  • 6 distinct findings — 1 consensus (3/3), 2 partial-consensus (2/3), 2 solo HIGH, 1 LOW
  • Severity mix: 2 HIGH, 2 MEDIUM, 2 LOW
  • Verdict: BLOCK — the feature is broken end-to-end on the standard new-submission flow

The single most important issue: a user's chosen expiry date is silently discarded between preview and publish, so the feature never actually works for new submissions.

Findings

[HIGH] includes/forms/class-wp-job-manager-form-submit-job.php:1158 — User-chosen expiry is wiped between preview and publish

Status: Solo (Codex, confirmed by Claude via direct code read)

update_job_data() saves the user's date via set_job_expiration() while the post is in preview status. Then preview_handler() runs on "Continue" and unconditionally calls delete_post_meta( $job->ID, '_job_expires' )
(line 1158) before transitioning the post to publish/pending. The set_expiry() hook on the transition reads $_POST['_job_expires'], which is never set by this form (it submits job[job_expires]), so it falls into
the ! $expiration_date branch and writes the default duration. Net result: the user's date never survives a normal submission.

Fix: In preview_handler, only delete _job_expires when the new field is disabled or empty; or copy the saved value into $_POST['_job_expires'] before wp_update_post() so set_expiry() honors it (mirrors how the
admin write panel feeds the same key).

[HIGH] includes/forms/class-wp-job-manager-form-submit-job.php:586 — Past-date validator traps owners of expired listings

Status: Solo (Gemini, confirmed by Claude via direct code read)

WP_Job_Manager_Form_Edit_Job::populate_fields() (line 126) pre-fills every field's value from get_post_meta($id, '_' . $key, true) — i.e., the existing _job_expires. For an expired listing this is a past date. When the
owner edits any unrelated field and saves, $_POST['job']['job_expires'] carries the unchanged past date, and validate_fields() throws "Expiry date cannot be in the past". The user is locked out of editing expired listings
until they also pick a new future date — even for typo fixes.

Fix: Skip the past-date check when the submitted value is unchanged from the stored meta, or when the listing is already expired.

[MEDIUM] includes/forms/class-wp-job-manager-form-submit-job.php:1029-1037 — Clearing the field on edit doesn't reset to default

Status: Consensus (Claude + Codex + Gemini, 3/3)

The new elseif ( 'job_expires' === $key ) branch only writes when the value is non-empty. On the inherited frontend edit form, clearing the date submits empty → no write → existing _job_expires persists. The field's own
description says "Leave blank to use default duration." It doesn't.

Fix: When empty( $values[$group_key][$key] ), call set_job_expiration( $this->job_id, null ) so the default is recomputed on next transition.

[MEDIUM] includes/forms/class-wp-job-manager-form-submit-job.php:579-588 — Date-component overflow not validated

Status: Consensus (Claude + Codex)

Codex confirmed via REPL: DateTimeImmutable::createFromFormat('Y-m-d|', '2026-02-31', wp_timezone()) returns 2026-03-03 (warning_count=1, error_count=0). The ! $expires_date check passes, and an impossible date silently
becomes a different valid date. The HTML5/datepicker UI normally prevents this, but a JS-disabled client or direct POST bypasses both. Server validation should not depend on the UI.

Fix: After createFromFormat, also reject if DateTimeImmutable::getLastErrors()['warning_count'] > 0, or compare $expires_date->format('Y-m-d') === $values['job']['job_expires'].

[LOW] includes/forms/class-wp-job-manager-form-submit-job.php:399-401attributes['min'] and class keys are dead code

Status: Consensus (Claude + Gemini)

templates/form-fields/date-field.php does not iterate $field['attributes'] and hardcodes the class — so min => current_time('Y-m-d') and class => 'job-manager-datepicker' are silently dropped. type=>'date' reads as
native HTML5 to a casual reviewer, but the template actually renders <input type="text"> plus a jQuery UI datepicker. Min-date enforcement comes from datepicker.js using browser-local "today", not server time.

Fix: Remove the attributes and class keys from the field definition (or extend the template to honor them).

[LOW] Notes

  • type => 'date' is misleading; ensure the feature description doesn't imply native HTML5 date-picker UX.
  • No automated test coverage was added. Given two HIGH bugs slipped through, an integration test for submit-with-date → preview → publish → assert _job_expires is strongly recommended.

Highest-priority single action

Fix the preview→publish regression first — without it, the feature ships broken regardless of every other issue.

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.

Enable Expiry Date in Frontend Form

2 participants