feat(07-01): implement complete job management workflow
Adds comprehensive job submission, editing, and deactivation functionality with proper form handling and permissions. Includes administrator capabilities for job_offer management and fixed dashboard navigation. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -161,6 +161,9 @@ class DDHH_JM_Formidable {
|
||||
|
||||
// Hook into Formidable form submission
|
||||
add_action( 'frm_after_create_entry', array( __CLASS__, 'handle_registration_submission' ), 30, 2 );
|
||||
add_action( 'frm_after_create_entry', array( __CLASS__, 'handle_job_submission' ), 30, 2 );
|
||||
add_action( 'frm_after_create_entry', array( __CLASS__, 'handle_job_edit_submission' ), 30, 2 );
|
||||
add_action( 'frm_after_create_entry', array( __CLASS__, 'handle_job_deactivation_submission' ), 30, 2 );
|
||||
|
||||
// Add JavaScript redirect for registration form
|
||||
add_action( 'wp_footer', array( __CLASS__, 'add_registration_redirect_script' ) );
|
||||
@@ -168,6 +171,9 @@ class DDHH_JM_Formidable {
|
||||
// Hook into Formidable form validation for ownership check
|
||||
add_filter( 'frm_validate_entry', array( __CLASS__, 'validate_job_ownership' ), 10, 2 );
|
||||
add_filter( 'frm_validate_entry', array( __CLASS__, 'validate_job_deactivation_ownership' ), 10, 2 );
|
||||
|
||||
// Hook to pre-populate edit form fields
|
||||
add_filter( 'frm_get_default_value', array( __CLASS__, 'prepopulate_edit_form_fields' ), 10, 3 );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -437,6 +443,324 @@ class DDHH_JM_Formidable {
|
||||
do_action( 'ddhh_provider_registered', $user_id, $organization_name );
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle job submission form entry
|
||||
*
|
||||
* @param int $entry_id Entry ID.
|
||||
* @param int $form_id Form ID.
|
||||
*/
|
||||
public static function handle_job_submission( $entry_id, $form_id ) {
|
||||
// Only process our job submission form
|
||||
if ( $form_id != self::get_job_submission_form_id() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
error_log( 'DDHH Job Submission: Processing form entry ' . $entry_id );
|
||||
|
||||
// Get entry data
|
||||
$entry = FrmEntry::getOne( $entry_id, true );
|
||||
if ( ! $entry ) {
|
||||
error_log( 'DDHH Job Submission: Failed to get entry' );
|
||||
return;
|
||||
}
|
||||
|
||||
// Extract field values
|
||||
$job_title = '';
|
||||
$job_description = '';
|
||||
$job_location = '';
|
||||
$job_type = '';
|
||||
$job_deadline = '';
|
||||
$job_contact_email = '';
|
||||
$job_logo = '';
|
||||
|
||||
foreach ( $entry->metas as $field_id => $value ) {
|
||||
$field = FrmField::getOne( $field_id );
|
||||
if ( ! $field ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch ( $field->field_key ) {
|
||||
case 'job_title':
|
||||
$job_title = sanitize_text_field( $value );
|
||||
break;
|
||||
case 'job_description':
|
||||
$job_description = wp_kses_post( $value );
|
||||
break;
|
||||
case 'job_location':
|
||||
$job_location = sanitize_text_field( $value );
|
||||
break;
|
||||
case 'job_type':
|
||||
$job_type = sanitize_text_field( $value );
|
||||
break;
|
||||
case 'job_deadline':
|
||||
$job_deadline = sanitize_text_field( $value );
|
||||
break;
|
||||
case 'job_contact_email':
|
||||
$job_contact_email = sanitize_email( $value );
|
||||
break;
|
||||
case 'job_logo':
|
||||
$job_logo = $value; // File ID
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Validate required fields
|
||||
if ( empty( $job_title ) || empty( $job_description ) || empty( $job_location ) || empty( $job_type ) || empty( $job_contact_email ) ) {
|
||||
error_log( 'DDHH Job Submission: Validation failed - missing required fields' );
|
||||
return;
|
||||
}
|
||||
|
||||
// Create job_offer post
|
||||
$post_data = array(
|
||||
'post_title' => $job_title,
|
||||
'post_content' => $job_description,
|
||||
'post_type' => 'job_offer',
|
||||
'post_status' => 'pending',
|
||||
'post_author' => get_current_user_id(),
|
||||
);
|
||||
|
||||
$post_id = wp_insert_post( $post_data );
|
||||
|
||||
// Check for errors
|
||||
if ( is_wp_error( $post_id ) ) {
|
||||
error_log( 'DDHH Job Submission: wp_insert_post failed - ' . $post_id->get_error_message() );
|
||||
return;
|
||||
}
|
||||
|
||||
error_log( 'DDHH Job Submission: Post created successfully with ID ' . $post_id );
|
||||
|
||||
// Save custom fields
|
||||
update_post_meta( $post_id, 'job_location', $job_location );
|
||||
update_post_meta( $post_id, 'job_type', $job_type );
|
||||
update_post_meta( $post_id, 'job_contact_email', $job_contact_email );
|
||||
|
||||
if ( ! empty( $job_deadline ) ) {
|
||||
update_post_meta( $post_id, 'job_deadline', $job_deadline );
|
||||
}
|
||||
|
||||
// Handle logo upload if present
|
||||
if ( ! empty( $job_logo ) && is_numeric( $job_logo ) ) {
|
||||
set_post_thumbnail( $post_id, absint( $job_logo ) );
|
||||
error_log( 'DDHH Job Submission: Logo set as featured image' );
|
||||
}
|
||||
|
||||
error_log( 'DDHH Job Submission: Job offer created successfully' );
|
||||
|
||||
do_action( 'ddhh_job_submitted', $post_id, $entry_id );
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle job edit form submission
|
||||
*
|
||||
* @param int $entry_id Entry ID.
|
||||
* @param int $form_id Form ID.
|
||||
*/
|
||||
public static function handle_job_edit_submission( $entry_id, $form_id ) {
|
||||
// Only process our job edit form
|
||||
if ( $form_id != self::get_job_edit_form_id() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if we have a job_id to update
|
||||
if ( ! isset( $_GET['job_id'] ) ) {
|
||||
error_log( 'DDHH Job Edit: No job_id provided' );
|
||||
return;
|
||||
}
|
||||
|
||||
$post_id = absint( $_GET['job_id'] );
|
||||
error_log( 'DDHH Job Edit: Processing form entry ' . $entry_id . ' for post ' . $post_id );
|
||||
|
||||
// Verify post exists and user owns it
|
||||
$post = get_post( $post_id );
|
||||
if ( ! $post || 'job_offer' !== $post->post_type ) {
|
||||
error_log( 'DDHH Job Edit: Invalid post' );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( absint( $post->post_author ) !== get_current_user_id() ) {
|
||||
error_log( 'DDHH Job Edit: User does not own this post' );
|
||||
return;
|
||||
}
|
||||
|
||||
// Get entry data
|
||||
$entry = FrmEntry::getOne( $entry_id, true );
|
||||
if ( ! $entry ) {
|
||||
error_log( 'DDHH Job Edit: Failed to get entry' );
|
||||
return;
|
||||
}
|
||||
|
||||
// Extract field values (accounting for "2" suffix)
|
||||
$job_title = '';
|
||||
$job_description = '';
|
||||
$job_location = '';
|
||||
$job_type = '';
|
||||
$job_deadline = '';
|
||||
$job_contact_email = '';
|
||||
$job_logo = '';
|
||||
|
||||
foreach ( $entry->metas as $field_id => $value ) {
|
||||
$field = FrmField::getOne( $field_id );
|
||||
if ( ! $field ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch ( $field->field_key ) {
|
||||
case 'job_title':
|
||||
case 'job_title2':
|
||||
$job_title = sanitize_text_field( $value );
|
||||
break;
|
||||
case 'job_description':
|
||||
case 'job_description2':
|
||||
$job_description = wp_kses_post( $value );
|
||||
break;
|
||||
case 'job_location':
|
||||
case 'job_location2':
|
||||
$job_location = sanitize_text_field( $value );
|
||||
break;
|
||||
case 'job_type':
|
||||
case 'job_type2':
|
||||
$job_type = sanitize_text_field( $value );
|
||||
break;
|
||||
case 'job_deadline':
|
||||
case 'job_deadline2':
|
||||
$job_deadline = sanitize_text_field( $value );
|
||||
break;
|
||||
case 'job_contact_email':
|
||||
case 'job_contact_email2':
|
||||
$job_contact_email = sanitize_email( $value );
|
||||
break;
|
||||
case 'job_logo':
|
||||
case 'job_logo2':
|
||||
$job_logo = $value; // File ID
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Validate required fields
|
||||
if ( empty( $job_title ) || empty( $job_description ) || empty( $job_location ) || empty( $job_type ) || empty( $job_contact_email ) ) {
|
||||
error_log( 'DDHH Job Edit: Validation failed - missing required fields' );
|
||||
return;
|
||||
}
|
||||
|
||||
// Update job_offer post
|
||||
$post_data = array(
|
||||
'ID' => $post_id,
|
||||
'post_title' => $job_title,
|
||||
'post_content' => $job_description,
|
||||
'post_status' => 'pending', // Reset to pending for admin review
|
||||
);
|
||||
|
||||
$result = wp_update_post( $post_data );
|
||||
|
||||
// Check for errors
|
||||
if ( is_wp_error( $result ) ) {
|
||||
error_log( 'DDHH Job Edit: wp_update_post failed - ' . $result->get_error_message() );
|
||||
return;
|
||||
}
|
||||
|
||||
error_log( 'DDHH Job Edit: Post updated successfully with ID ' . $post_id );
|
||||
|
||||
// Update custom fields
|
||||
update_post_meta( $post_id, 'job_location', $job_location );
|
||||
update_post_meta( $post_id, 'job_type', $job_type );
|
||||
update_post_meta( $post_id, 'job_contact_email', $job_contact_email );
|
||||
|
||||
if ( ! empty( $job_deadline ) ) {
|
||||
update_post_meta( $post_id, 'job_deadline', $job_deadline );
|
||||
}
|
||||
|
||||
// Handle logo upload if present
|
||||
if ( ! empty( $job_logo ) && is_numeric( $job_logo ) ) {
|
||||
set_post_thumbnail( $post_id, absint( $job_logo ) );
|
||||
error_log( 'DDHH Job Edit: Logo updated' );
|
||||
}
|
||||
|
||||
error_log( 'DDHH Job Edit: Job offer updated successfully' );
|
||||
|
||||
do_action( 'ddhh_job_edited', $post_id, $entry_id );
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle job deactivation form submission
|
||||
*
|
||||
* @param int $entry_id Entry ID.
|
||||
* @param int $form_id Form ID.
|
||||
*/
|
||||
public static function handle_job_deactivation_submission( $entry_id, $form_id ) {
|
||||
// Only process our job deactivation form
|
||||
if ( $form_id != self::get_job_deactivation_form_id() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if we have a job_id to deactivate
|
||||
if ( ! isset( $_GET['job_id'] ) ) {
|
||||
error_log( 'DDHH Job Deactivation: No job_id provided' );
|
||||
return;
|
||||
}
|
||||
|
||||
$post_id = absint( $_GET['job_id'] );
|
||||
error_log( 'DDHH Job Deactivation: Processing form entry ' . $entry_id . ' for post ' . $post_id );
|
||||
|
||||
// Verify post exists and user owns it
|
||||
$post = get_post( $post_id );
|
||||
if ( ! $post || 'job_offer' !== $post->post_type ) {
|
||||
error_log( 'DDHH Job Deactivation: Invalid post' );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( absint( $post->post_author ) !== get_current_user_id() ) {
|
||||
error_log( 'DDHH Job Deactivation: User does not own this post' );
|
||||
return;
|
||||
}
|
||||
|
||||
// Get entry data
|
||||
$entry = FrmEntry::getOne( $entry_id, true );
|
||||
if ( ! $entry ) {
|
||||
error_log( 'DDHH Job Deactivation: Failed to get entry' );
|
||||
return;
|
||||
}
|
||||
|
||||
// Extract deactivation reason
|
||||
$deactivation_reason = '';
|
||||
|
||||
foreach ( $entry->metas as $field_id => $value ) {
|
||||
$field = FrmField::getOne( $field_id );
|
||||
if ( ! $field ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( 'deactivation_reason' === $field->field_key ) {
|
||||
$deactivation_reason = sanitize_textarea_field( $value );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Update post status to draft (deactivated)
|
||||
$result = wp_update_post( array(
|
||||
'ID' => $post_id,
|
||||
'post_status' => 'draft',
|
||||
) );
|
||||
|
||||
// Check for errors
|
||||
if ( is_wp_error( $result ) ) {
|
||||
error_log( 'DDHH Job Deactivation: wp_update_post failed - ' . $result->get_error_message() );
|
||||
return;
|
||||
}
|
||||
|
||||
error_log( 'DDHH Job Deactivation: Post status updated to draft for post ' . $post_id );
|
||||
|
||||
// Save deactivation reason (using ACF field name)
|
||||
if ( ! empty( $deactivation_reason ) ) {
|
||||
update_post_meta( $post_id, 'job_deactivation_reason', $deactivation_reason );
|
||||
update_post_meta( $post_id, 'job_deactivation_date', current_time( 'mysql' ) );
|
||||
error_log( 'DDHH Job Deactivation: Saved deactivation reason' );
|
||||
}
|
||||
|
||||
error_log( 'DDHH Job Deactivation: Job deactivated successfully' );
|
||||
|
||||
do_action( 'ddhh_job_deactivated', $post_id, $entry_id );
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the job submission form programmatically if it doesn't exist
|
||||
*/
|
||||
@@ -777,6 +1101,71 @@ class DDHH_JM_Formidable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pre-populate edit form fields with existing post data
|
||||
*
|
||||
* @param mixed $default_value The default value.
|
||||
* @param object $field The field object.
|
||||
* @param bool $dynamic_default Whether to use dynamic default.
|
||||
* @return mixed The modified default value.
|
||||
*/
|
||||
public static function prepopulate_edit_form_fields( $default_value, $field, $dynamic_default ) {
|
||||
// Only process for the job edit form
|
||||
if ( absint( $field->form_id ) !== self::get_job_edit_form_id() ) {
|
||||
return $default_value;
|
||||
}
|
||||
|
||||
// Check if we're editing - look for job_id in URL
|
||||
if ( ! isset( $_GET['job_id'] ) ) {
|
||||
return $default_value;
|
||||
}
|
||||
|
||||
$post_id = absint( $_GET['job_id'] );
|
||||
$post = get_post( $post_id );
|
||||
|
||||
if ( ! $post || 'job_offer' !== $post->post_type ) {
|
||||
return $default_value;
|
||||
}
|
||||
|
||||
// Map field keys to post data (handle both with and without "2" suffix)
|
||||
switch ( $field->field_key ) {
|
||||
case 'job_title':
|
||||
case 'job_title2':
|
||||
return $post->post_title;
|
||||
|
||||
case 'job_description':
|
||||
case 'job_description2':
|
||||
return $post->post_content;
|
||||
|
||||
case 'job_location':
|
||||
case 'job_location2':
|
||||
$value = get_post_meta( $post_id, 'job_location', true );
|
||||
return $value ? $value : $default_value;
|
||||
|
||||
case 'job_type':
|
||||
case 'job_type2':
|
||||
$value = get_post_meta( $post_id, 'job_type', true );
|
||||
return $value ? $value : $default_value;
|
||||
|
||||
case 'job_deadline':
|
||||
case 'job_deadline2':
|
||||
$value = get_post_meta( $post_id, 'job_deadline', true );
|
||||
return $value ? $value : $default_value;
|
||||
|
||||
case 'job_contact_email':
|
||||
case 'job_contact_email2':
|
||||
$value = get_post_meta( $post_id, 'job_contact_email', true );
|
||||
return $value ? $value : $default_value;
|
||||
|
||||
case 'job_logo':
|
||||
case 'job_logo2':
|
||||
$value = get_post_thumbnail_id( $post_id );
|
||||
return $value ? $value : $default_value;
|
||||
}
|
||||
|
||||
return $default_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate job ownership before allowing edit
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user