From a4e2fbfe1756bf247c85f2fd353dc73bb27aee86 Mon Sep 17 00:00:00 2001 From: Viktor Miller Date: Wed, 14 Jan 2026 19:44:29 +0900 Subject: [PATCH] feat(03-02): create job edit form with ownership validation - Add create_job_edit_form() method to programmatically create edit form - Form uses 'job_edit' key and matches submission form fields exactly - Configure Update Post action to update existing job_offer posts - Add validate_job_ownership() method with frm_validate_entry hook - Security: Validates job_id parameter, post_type, and post_author match - Prevents URL parameter tampering by malicious providers - Add get_job_edit_form_id() helper method - Form pre-populates from post ID via URL parameter Co-Authored-By: Claude Sonnet 4.5 --- includes/class-formidable.php | 231 ++++++++++++++++++++++++++++++++++ 1 file changed, 231 insertions(+) diff --git a/includes/class-formidable.php b/includes/class-formidable.php index a57ad41..5c38f89 100644 --- a/includes/class-formidable.php +++ b/includes/class-formidable.php @@ -27,6 +27,13 @@ class DDHH_JM_Formidable { */ private static $job_submission_form_id = null; + /** + * Form ID for job edit + * + * @var int|null + */ + private static $job_edit_form_id = null; + /** * Get the registration form ID * @@ -67,6 +74,26 @@ class DDHH_JM_Formidable { return null; } + /** + * Get the job edit form ID + * + * @return int|null Form ID or null if not found + */ + public static function get_job_edit_form_id() { + if ( null !== self::$job_edit_form_id ) { + return self::$job_edit_form_id; + } + + // Look up form by key + $form = FrmForm::getOne( 'job_edit' ); + if ( $form ) { + self::$job_edit_form_id = $form->id; + return self::$job_edit_form_id; + } + + return null; + } + /** * Setup registration hooks */ @@ -74,9 +101,13 @@ class DDHH_JM_Formidable { // Create forms on plugin activation if they don't exist add_action( 'init', array( __CLASS__, 'create_registration_form' ), 11 ); add_action( 'init', array( __CLASS__, 'create_job_submission_form' ), 11 ); + add_action( 'init', array( __CLASS__, 'create_job_edit_form' ), 11 ); // Hook into Formidable form submission add_action( 'frm_after_create_entry', array( __CLASS__, 'handle_registration_submission' ), 30, 2 ); + + // Hook into Formidable form validation for ownership check + add_filter( 'frm_validate_entry', array( __CLASS__, 'validate_job_ownership' ), 10, 2 ); } /** @@ -438,4 +469,204 @@ class DDHH_JM_Formidable { FrmFormAction::create( 'wppost', $form_id, $action_values ); } } + + /** + * Create the job edit form programmatically if it doesn't exist + */ + public static function create_job_edit_form() { + // Check if Formidable is active + if ( ! class_exists( 'FrmForm' ) || ! class_exists( 'FrmFormAction' ) ) { + return; + } + + // Check if form already exists + $existing_form = FrmForm::getOne( 'job_edit' ); + if ( $existing_form ) { + self::$job_edit_form_id = $existing_form->id; + return; + } + + // Create form + $form_values = array( + 'name' => 'Stellenangebot bearbeiten', + 'form_key' => 'job_edit', + 'description' => 'Bearbeiten Sie Ihr Stellenangebot. Alle Felder mit * sind Pflichtfelder.', + 'status' => 'published', + 'options' => array( + 'submit_value' => 'Änderungen speichern', + 'success_msg' => 'Ihre Änderungen wurden gespeichert!', + 'success_action' => 'redirect', + 'success_url' => home_url( '/anbieter-dashboard/' ), + ), + ); + + $form_id = FrmForm::create( $form_values ); + + if ( ! $form_id ) { + return; + } + + self::$job_edit_form_id = $form_id; + + // Create form fields (identical to submission form) + $fields_data = array( + array( + 'name' => 'Stellentitel', + 'field_key' => 'job_title', + 'type' => 'text', + 'required' => '1', + 'form_id' => $form_id, + 'field_order' => 1, + ), + array( + 'name' => 'Stellenbeschreibung', + 'field_key' => 'job_description', + 'type' => 'textarea', + 'required' => '1', + 'form_id' => $form_id, + 'field_order' => 2, + ), + array( + 'name' => 'Standort', + 'field_key' => 'job_location', + 'type' => 'text', + 'required' => '1', + 'form_id' => $form_id, + 'field_order' => 3, + ), + array( + 'name' => 'Art', + 'field_key' => 'job_type', + 'type' => 'select', + 'required' => '1', + 'form_id' => $form_id, + 'field_order' => 4, + 'field_options' => array( + 'options' => array( + 'Vollzeit' => 'Vollzeit', + 'Teilzeit' => 'Teilzeit', + 'Ehrenamt' => 'Ehrenamt', + ), + ), + ), + array( + 'name' => 'Bewerbungsfrist', + 'field_key' => 'job_deadline', + 'type' => 'date', + 'required' => '0', + 'form_id' => $form_id, + 'field_order' => 5, + 'field_options' => array( + 'format' => 'd.m.Y', + ), + ), + array( + 'name' => 'Kontakt-E-Mail', + 'field_key' => 'job_contact_email', + 'type' => 'email', + 'required' => '1', + 'form_id' => $form_id, + 'field_order' => 6, + ), + array( + 'name' => 'Logo', + 'field_key' => 'job_logo', + 'type' => 'file', + 'required' => '0', + 'form_id' => $form_id, + 'field_order' => 7, + 'field_options' => array( + 'restrict' => '1', + 'allowed_types' => 'image/jpeg,image/png', + 'max_size' => '2', + ), + ), + ); + + // Store field IDs for form action mapping + $field_ids = array(); + foreach ( $fields_data as $field ) { + $field_id = FrmField::create( $field ); + if ( $field_id ) { + $field_ids[ $field['field_key'] ] = $field_id; + } + } + + // Create the Update Post action + if ( ! empty( $field_ids ) ) { + $action_values = array( + 'menu_order' => 1, + 'post_status' => 'published', + 'post_content' => array( + 'post_type' => 'job_offer', + 'post_status' => 'pending', + 'post_title' => $field_ids['job_title'], + 'post_content' => $field_ids['job_description'], + 'post_id' => 'id_param', + 'post_custom_fields' => array( + array( + 'meta_name' => 'job_location', + 'field_id' => $field_ids['job_location'], + ), + array( + 'meta_name' => 'job_type', + 'field_id' => $field_ids['job_type'], + ), + array( + 'meta_name' => 'job_deadline', + 'field_id' => $field_ids['job_deadline'], + ), + array( + 'meta_name' => 'job_contact_email', + 'field_id' => $field_ids['job_contact_email'], + ), + array( + 'meta_name' => 'job_logo', + 'field_id' => $field_ids['job_logo'], + ), + ), + ), + ); + + FrmFormAction::create( 'wppost', $form_id, $action_values ); + } + } + + /** + * Validate job ownership before allowing edit + * + * @param array $errors Validation errors. + * @param array $values Form values. + * @return array Modified errors. + */ + public static function validate_job_ownership( $errors, $values ) { + // Only validate for the job edit form + if ( absint( $values['form_id'] ) !== self::get_job_edit_form_id() ) { + return $errors; + } + + // Check if job_id parameter exists + if ( ! isset( $_GET['job_id'] ) ) { + $errors[''] = 'Keine Stellenangebot-ID angegeben.'; + return $errors; + } + + $job_id = absint( $_GET['job_id'] ); + + // Verify post exists and is a job_offer + $post = get_post( $job_id ); + if ( ! $post || 'job_offer' !== $post->post_type ) { + $errors[''] = 'Ungültige Stellenangebot-ID.'; + return $errors; + } + + // Verify post author matches current user + $current_user_id = get_current_user_id(); + if ( absint( $post->post_author ) !== $current_user_id ) { + $errors[''] = 'Sie haben keine Berechtigung, dieses Stellenangebot zu bearbeiten.'; + return $errors; + } + + return $errors; + } }