id; return self::$registration_form_id; } return null; } /** * Get the job submission form ID * * @return int|null Form ID or null if not found */ public static function get_job_submission_form_id() { if ( null !== self::$job_submission_form_id ) { return self::$job_submission_form_id; } // Look up form by key $form = FrmForm::getOne( 'job_submission' ); if ( $form ) { self::$job_submission_form_id = $form->id; return self::$job_submission_form_id; } 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; } /** * Get the job deactivation form ID * * @return int|null Form ID or null if not found */ public static function get_job_deactivation_form_id() { if ( null !== self::$job_deactivation_form_id ) { return self::$job_deactivation_form_id; } // Look up form by key $form = FrmForm::getOne( 'job_deactivation' ); if ( $form ) { self::$job_deactivation_form_id = $form->id; return self::$job_deactivation_form_id; } return null; } /** * Get the job application form ID * * @return int|null Form ID or null if not found */ public static function get_job_application_form_id() { if ( null !== self::$job_application_form_id ) { return self::$job_application_form_id; } // Look up form by key $form = FrmForm::getOne( 'job_application' ); if ( $form ) { self::$job_application_form_id = $form->id; return self::$job_application_form_id; } return null; } /** * Setup registration hooks */ public static function setup_registration_hooks() { // 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 ); add_action( 'init', array( __CLASS__, 'create_job_deactivation_form' ), 11 ); add_action( 'init', array( __CLASS__, 'create_job_application_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 ); add_filter( 'frm_validate_entry', array( __CLASS__, 'validate_job_deactivation_ownership' ), 10, 2 ); } /** * Create the registration form programmatically if it doesn't exist */ public static function create_registration_form() { // Check if Formidable is active if ( ! class_exists( 'FrmForm' ) ) { return; } // Check if form already exists $existing_form = FrmForm::getOne( 'provider_registration' ); if ( $existing_form ) { self::$registration_form_id = $existing_form->id; return; } // Create form $form_values = array( 'name' => 'Provider Registration', 'form_key' => 'provider_registration', 'description' => 'Anbieter-Registrierung für Digital Dabei Hamburg', 'status' => 'published', 'options' => array( 'submit_value' => 'Registrieren', 'success_msg' => 'Registrierung erfolgreich! Sie werden weitergeleitet...', ), ); $form_id = FrmForm::create( $form_values ); if ( ! $form_id ) { return; } self::$registration_form_id = $form_id; // Create form fields $fields = array( array( 'name' => 'Organisationsname', 'field_key' => 'organization_name', 'type' => 'text', 'required' => '1', 'form_id' => $form_id, 'field_order' => 1, ), array( 'name' => 'Ansprechperson', 'field_key' => 'contact_person', 'type' => 'text', 'required' => '1', 'form_id' => $form_id, 'field_order' => 2, ), array( 'name' => 'E-Mail', 'field_key' => 'email', 'type' => 'email', 'required' => '1', 'form_id' => $form_id, 'field_order' => 3, 'field_options' => array( 'unique' => '1', ), ), array( 'name' => 'Passwort', 'field_key' => 'password', 'type' => 'password', 'required' => '1', 'form_id' => $form_id, 'field_order' => 4, 'field_options' => array( 'minlength' => 8, ), ), array( 'name' => 'Passwort bestätigen', 'field_key' => 'password_confirm', 'type' => 'password', 'required' => '1', 'form_id' => $form_id, 'field_order' => 5, 'field_options' => array( 'minlength' => 8, ), ), ); foreach ( $fields as $field ) { FrmField::create( $field ); } } /** * Handle registration form submission * * @param int $entry_id Entry ID. * @param int $form_id Form ID. */ public static function handle_registration_submission( $entry_id, $form_id ) { error_log('DDHH Registration: Hook fired for form ' . $form_id . ' (' . gettype($form_id) . '), entry ' . $entry_id); // Only process our registration form (use loose comparison for type coercion) if ( $form_id != self::get_registration_form_id() ) { error_log('DDHH Registration: Wrong form ID. Expected ' . self::get_registration_form_id() . ' (' . gettype(self::get_registration_form_id()) . ')'); return; } error_log('DDHH Registration: Processing registration form'); // Get entry data $entry = FrmEntry::getOne( $entry_id, true ); if ( ! $entry ) { error_log('DDHH Registration: Failed to get entry'); return; } error_log('DDHH Registration: Entry retrieved successfully'); // Extract field values $email = ''; $password = ''; $password_confirm = ''; $organization_name = ''; $contact_person = ''; foreach ( $entry->metas as $field_id => $value ) { $field = FrmField::getOne( $field_id ); if ( ! $field ) { continue; } switch ( $field->field_key ) { case 'email': $email = sanitize_email( $value ); break; case 'password': $password = $value; break; case 'password_confirm': $password_confirm = $value; break; case 'organization_name': $organization_name = sanitize_text_field( $value ); break; case 'contact_person': $contact_person = sanitize_text_field( $value ); break; } } error_log('DDHH Registration: email=' . $email . ', org=' . $organization_name . ', contact=' . $contact_person); // Validate required fields if ( empty( $email ) || empty( $password ) || empty( $organization_name ) || empty( $contact_person ) ) { error_log('DDHH Registration: Validation failed - missing required fields'); return; } // Validate passwords match if ( $password !== $password_confirm ) { error_log('DDHH Registration: Passwords do not match'); return; } // Check if user already exists if ( email_exists( $email ) ) { error_log('DDHH Registration: Email already exists'); return; } error_log('DDHH Registration: Validation passed, creating user...'); // Create username from email (part before @) $username = sanitize_user( strstr( $email, '@', true ) ); // Ensure username is unique $username_base = $username; $counter = 1; while ( username_exists( $username ) ) { $username = $username_base . $counter; $counter++; } // Create WordPress user $user_id = wp_insert_user( array( 'user_login' => $username, 'user_email' => $email, 'user_pass' => $password, 'role' => 'ddhh_provider', 'display_name' => $contact_person, 'first_name' => $contact_person, ) ); // Check for errors if ( is_wp_error( $user_id ) ) { error_log('DDHH Registration: wp_insert_user failed - ' . $user_id->get_error_message()); return; } error_log('DDHH Registration: User created successfully with ID ' . $user_id); // Store organization name as user meta update_user_meta( $user_id, 'ddhh_org_name', $organization_name ); // Auto-login the user wp_set_auth_cookie( $user_id, true ); wp_set_current_user( $user_id ); error_log('DDHH Registration: User logged in, triggering redirect...'); // Optionally redirect (handled by JavaScript or form settings) do_action( 'ddhh_provider_registered', $user_id, $organization_name ); } /** * Create the job submission form programmatically if it doesn't exist */ public static function create_job_submission_form() { // Check if Formidable is active if ( ! class_exists( 'FrmForm' ) || ! class_exists( 'FrmFormActionsController' ) ) { return; } // Check if form already exists $existing_form = FrmForm::getOne( 'job_submission' ); if ( $existing_form ) { self::$job_submission_form_id = $existing_form->id; return; } // Create form $form_values = array( 'name' => 'Stellenangebot einreichen', 'form_key' => 'job_submission', 'description' => 'Alle Felder mit * sind Pflichtfelder. Ihr Angebot wird vor Veröffentlichung geprüft.', 'status' => 'published', 'options' => array( 'submit_value' => 'Stellenangebot einreichen', 'success_msg' => 'Ihr Stellenangebot wurde zur Prüfung eingereicht!', 'success_action' => 'redirect', 'success_url' => home_url( '/anbieter-dashboard/' ), ), ); $form_id = FrmForm::create( $form_values ); if ( ! $form_id ) { return; } self::$job_submission_form_id = $form_id; // Create form fields $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 Create 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_author' => 'current_user', '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'], ), ), ), ); // Create the form action using the proper API FrmFormActionsController::create_action( $form_id, array( 'post_excerpt' => 'wppost', 'post_content' => $action_values, 'menu_order' => 1, ) ); } } /** * 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( 'FrmFormActionsController' ) ) { 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'], ), ), ), ); // Create the form action using the proper API FrmFormActionsController::create_action( $form_id, array( 'post_excerpt' => 'wppost', 'post_content' => $action_values, 'menu_order' => 1, ) ); } } /** * 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; } /** * Create the job deactivation form programmatically if it doesn't exist */ public static function create_job_deactivation_form() { // Check if Formidable is active if ( ! class_exists( 'FrmForm' ) || ! class_exists( 'FrmFormActionsController' ) ) { return; } // Check if form already exists $existing_form = FrmForm::getOne( 'job_deactivation' ); if ( $existing_form ) { self::$job_deactivation_form_id = $existing_form->id; return; } // Create form $form_values = array( 'name' => 'Stellenangebot deaktivieren', 'form_key' => 'job_deactivation', 'description' => '', 'status' => 'published', 'options' => array( 'submit_value' => 'Stellenangebot deaktivieren', 'success_msg' => 'Ihr Stellenangebot wurde deaktiviert.', 'success_action' => 'redirect', 'success_url' => home_url( '/anbieter-dashboard/' ), ), ); $form_id = FrmForm::create( $form_values ); if ( ! $form_id ) { return; } self::$job_deactivation_form_id = $form_id; // Create form fields $fields_data = array( array( 'name' => 'Grund für Deaktivierung', 'description' => 'Bitte geben Sie an, warum Sie dieses Stellenangebot deaktivieren möchten', 'field_key' => 'deactivation_reason', 'type' => 'textarea', 'required' => '1', 'form_id' => $form_id, 'field_order' => 1, ), array( 'name' => 'Job ID', 'field_key' => 'job_id', 'type' => 'hidden', 'required' => '0', 'form_id' => $form_id, 'field_order' => 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' => 'draft', 'post_id' => 'id_param', 'post_custom_fields' => array( array( 'meta_name' => 'job_deactivation_reason', 'field_id' => $field_ids['deactivation_reason'], ), ), ), ); // Create the form action using the proper API FrmFormActionsController::create_action( $form_id, array( 'post_excerpt' => 'wppost', 'post_content' => $action_values, 'menu_order' => 1, ) ); } } /** * Validate job ownership before allowing deactivation * * @param array $errors Validation errors. * @param array $values Form values. * @return array Modified errors. */ public static function validate_job_deactivation_ownership( $errors, $values ) { // Only validate for the job deactivation form if ( absint( $values['form_id'] ) !== self::get_job_deactivation_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 deaktivieren.'; return $errors; } return $errors; } /** * Create the job application form programmatically if it doesn't exist */ public static function create_job_application_form() { // Check if Formidable is active if ( ! class_exists( 'FrmForm' ) ) { return; } // Check if form already exists $existing_form = FrmForm::getOne( 'job_application' ); if ( $existing_form ) { self::$job_application_form_id = $existing_form->id; return; } // Create form $form_values = array( 'name' => 'Jetzt bewerben', 'form_key' => 'job_application', 'description' => '', 'status' => 'published', 'options' => array( 'submit_value' => 'Bewerbung absenden', 'success_msg' => 'Ihre Bewerbung wurde versendet. Der Anbieter wird sich bei Ihnen melden.', ), ); $form_id = FrmForm::create( $form_values ); if ( ! $form_id ) { return; } self::$job_application_form_id = $form_id; // Get current user email if logged in $current_user = wp_get_current_user(); $default_email = ''; if ( $current_user && $current_user->ID ) { $default_email = $current_user->user_email; } // Create form fields $fields_data = array( array( 'name' => 'Name', 'field_key' => 'applicant_name', 'type' => 'text', 'required' => '1', 'form_id' => $form_id, 'field_order' => 1, ), array( 'name' => 'E-Mail', 'field_key' => 'applicant_email', 'type' => 'email', 'required' => '1', 'form_id' => $form_id, 'field_order' => 2, 'default_value' => $default_email, ), array( 'name' => 'Nachricht', 'description' => 'Warum interessieren Sie sich für diese Stelle?', 'field_key' => 'applicant_message', 'type' => 'textarea', 'required' => '1', 'form_id' => $form_id, 'field_order' => 3, ), array( 'name' => 'Job ID', 'field_key' => 'job_id', 'type' => 'hidden', 'required' => '0', 'form_id' => $form_id, 'field_order' => 4, ), ); foreach ( $fields_data as $field ) { FrmField::create( $field ); } } }