From 09ac38e9fa5c8f6a1ada55ad3e0ed2d0b4f70a04 Mon Sep 17 00:00:00 2001 From: Git Manager GUI Date: Mon, 13 Apr 2026 18:52:46 +0200 Subject: [PATCH] Upload folder via GUI - inc --- inc/classes/class-admin.php | 348 ++++++++++++++++++ inc/classes/class-builder.php | 44 +++ inc/classes/class-field-registry.php | 21 ++ inc/classes/class-form-processor.php | 105 ++++++ inc/classes/class-form-renderer.php | 145 ++++++++ inc/classes/class-mailer.php | 102 ++++++ inc/classes/class-post-type.php | 43 +++ inc/classes/class-shortcode.php | 36 ++ inc/classes/class-smtp.php | 54 +++ inc/classes/class-submission.php | 18 + inc/classes/class-submissions-list.php | 481 +++++++++++++++++++++++++ inc/fields/class-field-base.php | 158 ++++++++ inc/fields/class-field-checkbox.php | 23 ++ inc/fields/class-field-date.php | 14 + inc/fields/class-field-divider.php | 13 + inc/fields/class-field-email.php | 19 + inc/fields/class-field-file.php | 64 ++++ inc/fields/class-field-gdpr.php | 34 ++ inc/fields/class-field-hidden.php | 15 + inc/fields/class-field-html.php | 13 + inc/fields/class-field-number.php | 15 + inc/fields/class-field-phone.php | 13 + inc/fields/class-field-radio.php | 21 ++ inc/fields/class-field-range.php | 20 + inc/fields/class-field-rating.php | 21 ++ inc/fields/class-field-select.php | 23 ++ inc/fields/class-field-signature.php | 28 ++ inc/fields/class-field-text.php | 13 + inc/fields/class-field-textarea.php | 22 ++ inc/fields/class-field-url.php | 14 + inc/helpers/helper-functions.php | 118 ++++++ 31 files changed, 2058 insertions(+) create mode 100644 inc/classes/class-admin.php create mode 100644 inc/classes/class-builder.php create mode 100644 inc/classes/class-field-registry.php create mode 100644 inc/classes/class-form-processor.php create mode 100644 inc/classes/class-form-renderer.php create mode 100644 inc/classes/class-mailer.php create mode 100644 inc/classes/class-post-type.php create mode 100644 inc/classes/class-shortcode.php create mode 100644 inc/classes/class-smtp.php create mode 100644 inc/classes/class-submission.php create mode 100644 inc/classes/class-submissions-list.php create mode 100644 inc/fields/class-field-base.php create mode 100644 inc/fields/class-field-checkbox.php create mode 100644 inc/fields/class-field-date.php create mode 100644 inc/fields/class-field-divider.php create mode 100644 inc/fields/class-field-email.php create mode 100644 inc/fields/class-field-file.php create mode 100644 inc/fields/class-field-gdpr.php create mode 100644 inc/fields/class-field-hidden.php create mode 100644 inc/fields/class-field-html.php create mode 100644 inc/fields/class-field-number.php create mode 100644 inc/fields/class-field-phone.php create mode 100644 inc/fields/class-field-radio.php create mode 100644 inc/fields/class-field-range.php create mode 100644 inc/fields/class-field-rating.php create mode 100644 inc/fields/class-field-select.php create mode 100644 inc/fields/class-field-signature.php create mode 100644 inc/fields/class-field-text.php create mode 100644 inc/fields/class-field-textarea.php create mode 100644 inc/fields/class-field-url.php create mode 100644 inc/helpers/helper-functions.php diff --git a/inc/classes/class-admin.php b/inc/classes/class-admin.php new file mode 100644 index 0000000..3890fae --- /dev/null +++ b/inc/classes/class-admin.php @@ -0,0 +1,348 @@ +hook();} + return self::$instance; + } + public function hook() { + add_action('admin_menu', array($this,'register_menu')); + add_action('admin_enqueue_scripts', array($this,'enqueue_assets')); + add_action('admin_init', array($this,'handle_actions')); + add_action('admin_notices', array($this,'admin_notices')); + } + public function register_menu() { + add_menu_page('WP Multi Formular','Formulare','manage_options','wp-multi-formular', + array($this,'page_router'),'dashicons-feedback',25); + add_submenu_page('wp-multi-formular','Alle Formulare','Alle Formulare','manage_options','wp-multi-formular',array($this,'page_router')); + add_submenu_page('wp-multi-formular','Neues Formular','+ Neues Formular','manage_options','wmf-new-form',array($this,'page_builder')); + // Neue Einreichungen zaehlen fuer Badge + $new_count = 0; + $forms = get_posts(array('post_type'=>'wmf-form','post_status'=>'publish','numberposts'=>-1,'fields'=>'ids')); + foreach($forms as $fid) $new_count += wmf_count_submissions($fid,'neu'); + $badge = $new_count > 0 ? ' '.intval($new_count).'' : ''; + add_submenu_page('wp-multi-formular','Einreichungen','Einreichungen'.$badge,'manage_options','wmf-submissions',array($this,'page_submissions')); + } + public function page_router() { + // Einzelne Einreichung anzeigen + if(!empty($_GET['view_submission']) && !empty($_GET['form_id'])) { + $sid = intval($_GET['view_submission']); + $form_id = intval($_GET['form_id']); + require WMF_TPL.'admin/page-submission-detail.php'; + return; + } + // Einreichung löschen + if(!empty($_GET['wmf_action'])&&$_GET['wmf_action']==='delete_submission'&&!empty($_GET['submission_id'])) { + if(wp_verify_nonce($_GET['_wpnonce']??'','wmf_delete_submission')) { + WMF_Submission::delete(intval($_GET['submission_id'])); + $this->safe_redirect(add_query_arg('wmf_notice','deleted',admin_url('admin.php?page=wmf-submissions'))); + } + } + // CSV Export + if(!empty($_GET['wmf_action'])&&$_GET['wmf_action']==='export_csv'&&!empty($_GET['form_id'])) { + WMF_Submissions_List::maybe_export(intval($_GET['form_id'])); + } + // Einreichungen anzeigen + if(!empty($_GET['view_submissions'])) { + $form_id=intval($_GET['view_submissions']); + require WMF_TPL.'admin/page-submissions.php'; return; + } + // Builder (Bearbeiten) + if(!empty($_GET['edit'])) { + require WMF_TPL.'admin/page-builder.php'; return; + } + require WMF_TPL.'admin/page-forms-list.php'; + } + public function page_builder() { + require WMF_TPL.'admin/page-builder.php'; + } + + public function page_submissions() { + // Einzelne Einreichung anzeigen + if(!empty($_GET['view_submission']) && !empty($_GET['form_id'])) { + $sid = intval($_GET['view_submission']); + $form_id = intval($_GET['form_id']); + $form = get_post($form_id); + ?> +
+

+ Einreichung # + + aus: post_title : ''); ?> + +

+ +
+ +
+

+ Einreichungen: + post_title : ''); ?> + ← Alle Formulare +

+ +
+ +
+

Einreichungen

+ 'wmf-form', + 'post_status' => 'publish', + 'numberposts' => -1, + 'orderby' => 'date', + 'order' => 'DESC', + )); + + if(empty($forms)): ?> +
+ +

Noch keine Formulare vorhanden

+

Erstellen Sie zuerst ein Formular und binden Sie es auf einer Seite ein.

+ Formular erstellen +
+ + + + + + + + + + + + + + + ID); + $count_new = wmf_count_submissions($form->ID, 'neu'); + $count_read = wmf_count_submissions($form->ID, 'gelesen'); + $count_arch = wmf_count_submissions($form->ID, 'archiviert'); + global $wpdb; + $last = $wpdb->get_var($wpdb->prepare( + "SELECT created_at FROM {$wpdb->prefix}wmf_submissions WHERE form_id=%d ORDER BY created_at DESC LIMIT 1", + $form->ID + )); + $view_url = add_query_arg(array('page'=>'wmf-submissions','form_id'=>$form->ID), admin_url('admin.php')); + $export_url = WMF_Submissions_List::export_url($form->ID); + ?> + + + + + + + + + + + +
FormularGesamtNeuGelesenArchiviertLetzte EinreichungAktionen
+ + + post_title); ?> + + +
+ ID)); ?> +
+
+ + + + + 0): ?> + + + + + 0 + + + + + Anzeigen + 0): ?> + CSV + +
+ +
+ window.location.href=' . wp_json_encode($url) . ';'; + echo ''; + exit; + } + + public function handle_actions() { + // Globale Einstellungen speichern (via admin-post.php) + add_action('admin_post_wmf_save_global_settings', array($this, 'save_global_settings')); + add_action('admin_post_wmf_update_submission_status', array($this, 'update_submission_status')); + + if(empty($_POST['wmf_admin_action'])||!current_user_can('manage_options')) return; + if($_POST['wmf_admin_action']==='save_form') { + check_admin_referer('wmf_save_form'); $this->save_form(); + } + if($_POST['wmf_admin_action']==='delete_form'&&!empty($_POST['form_id'])) { + check_admin_referer('wmf_delete_form_'.intval($_POST['form_id'])); + wp_delete_post(intval($_POST['form_id']),true); + $this->safe_redirect(add_query_arg('wmf_notice','form_deleted',admin_url('admin.php?page=wp-multi-formular'))); + } + } + private function save_form() { + $form_id=intval($_POST['form_id']??0); + $title=sanitize_text_field($_POST['form_title']??'Neues Formular'); + $fields_raw=stripslashes($_POST['wmf_form_fields']??'[]'); + $fields=json_decode($fields_raw,true); + if(!is_array($fields)) $fields=array(); + + // Felder bereinigen + $clean_fields=array(); + foreach($fields as $f) { + if(empty($f['id'])||empty($f['type'])) continue; + $f['name']=sanitize_key($f['name']??$f['id']); + $f['label']=sanitize_text_field($f['label']??''); + $f['placeholder']=sanitize_text_field($f['placeholder']??''); + $f['description']=sanitize_text_field($f['description']??''); + $f['required']=in_array($f['required']??'0',array('0','1'))?$f['required']:'0'; + $f['width']=in_array($f['width']??'full',array('full','half','third'))?$f['width']:'full'; + $clean_fields[]=$f; + } + + $step_labels=array(); + if(!empty($_POST['step_labels'])&&is_array($_POST['step_labels'])) { + $step_labels=array_map('sanitize_text_field',$_POST['step_labels']); + } + + $data=array( + 'fields' => $clean_fields, + 'submit_label' => sanitize_text_field($_POST['submit_label']??'Absenden'), + 'success_message' => sanitize_textarea_field($_POST['success_message']??''), + 'error_message' => sanitize_textarea_field($_POST['error_message']??''), + 'notify_admin' => !empty($_POST['notify_admin'])?'1':'0', + 'admin_email' => sanitize_email($_POST['admin_email']??''), + 'admin_subject' => sanitize_text_field($_POST['admin_subject']??''), + 'admin_reply_to' => !empty($_POST['admin_reply_to'])?'1':'0', + 'notify_sender' => !empty($_POST['notify_sender'])?'1':'0', + 'sender_subject' => sanitize_text_field($_POST['sender_subject']??''), + 'sender_message' => sanitize_textarea_field($_POST['sender_message']??''), + 'from_name' => sanitize_text_field($_POST['from_name']??''), + 'from_email' => sanitize_email($_POST['from_email']??''), + 'save_submissions' => !empty($_POST['save_submissions'])?'1':'0', + 'recaptcha_enabled' => !empty($_POST['recaptcha_enabled'])?'1':'0', + 'honeypot_enabled' => !empty($_POST['honeypot_enabled'])?'1':'0', + 'redirect_url' => esc_url_raw($_POST['redirect_url']??''), + 'css_class' => sanitize_html_class($_POST['css_class']??''), + 'multi_step' => !empty($_POST['multi_step'])?'1':'0', + 'step_labels' => $step_labels, + 'show_progress' => !empty($_POST['show_progress'])?'1':'0', + ); + + if($form_id) { + wp_update_post(array('ID'=>$form_id,'post_title'=>$title,'post_status'=>'publish')); + } else { + $form_id=wp_insert_post(array('post_type'=>'wmf-form','post_title'=>$title,'post_status'=>'publish')); + } + wmf_save_form_meta($form_id,$data); + $this->safe_redirect(add_query_arg(array('page'=>'wp-multi-formular','edit'=>$form_id,'wmf_notice'=>'saved'),admin_url('admin.php'))); + } + public function admin_notices() { + $n=$_GET['wmf_notice']??''; + $msgs=array('saved'=>array('success','Formular gespeichert.'),'deleted'=>array('success','Einreichung gelöscht.'),'form_deleted'=>array('success','Formular gelöscht.'),'global_saved'=>array('success','Globale E-Mail-Einstellungen gespeichert.')); + if(isset($msgs[$n])) printf('

%s

',esc_attr($msgs[$n][0]),esc_html($msgs[$n][1])); + } + public function enqueue_assets($hook) { + $page=$_GET['page']??''; + if(!in_array($page,array('wp-multi-formular','wmf-new-form','wmf-integrations'))&&strpos($hook,'wmf')=== false) return; + wp_enqueue_style('wmf-admin',WMF_URL.'assets/css/admin.css',array(),WMF_VERSION); + wp_enqueue_script('wmf-admin',WMF_URL.'assets/js/admin.js',array('jquery','jquery-ui-sortable','jquery-ui-draggable'),WMF_VERSION,true); + wp_enqueue_style('dashicons'); + wp_localize_script('wmf-admin','WMF',array( + 'ajax_url' => admin_url('admin-ajax.php'), + 'nonce' => wp_create_nonce('wmf_admin'), + 'fields' => $this->fields_for_js(), + 'i18n' => array( + 'confirm_delete' => 'Feld wirklich löschen?', + 'confirm_delete_form' => 'Formular und alle Einreichungen wirklich löschen?', + 'no_label' => '(kein Titel)', + 'loading' => 'Lade …', + 'preview' => 'Vorschau', + 'close_preview' => 'Vorschau schließen', + ), + )); + } + public function update_submission_status() { + if(!wp_verify_nonce($_POST['_wpnonce'] ?? '', 'wmf_update_status') || !current_user_can('manage_options')) wp_die('Fehler.'); + $sid = intval($_POST['submission_id'] ?? 0); + $status = sanitize_text_field($_POST['status'] ?? 'neu'); + $form_id = intval($_POST['form_id'] ?? 0); + $redirect = esc_url_raw($_POST['redirect_url'] ?? admin_url('admin.php?page=wp-multi-formular')); + if($sid && in_array($status, array('neu','gelesen','archiviert'))) { + WMF_Submission::update_status($sid, $status); + } + $this->safe_redirect($redirect); + } + + public function save_global_settings() { + if(!wp_verify_nonce($_POST['wmf_global_nonce'] ?? '', 'wmf_global_settings_save')) { + wp_die('Sicherheitsfehler.'); + } + if(!current_user_can('manage_options')) wp_die('Keine Berechtigung.'); + + $settings = array( + 'from_name' => sanitize_text_field($_POST['wmf_from_name'] ?? ''), + 'from_email' => sanitize_email( $_POST['wmf_from_email'] ?? ''), + 'smtp_enabled' => !empty($_POST['wmf_smtp_enabled']) ? '1' : '0', + 'smtp_host' => sanitize_text_field($_POST['wmf_smtp_host'] ?? ''), + 'smtp_port' => intval( $_POST['wmf_smtp_port'] ?? 587), + 'smtp_enc' => sanitize_text_field($_POST['wmf_smtp_enc'] ?? 'tls'), + 'smtp_user' => sanitize_text_field($_POST['wmf_smtp_user'] ?? ''), + 'smtp_pass' => $_POST['wmf_smtp_pass'] ?? '', // Passwort nicht strippen + ); + + update_option('wmf_global_settings', $settings); + + $this->safe_redirect(add_query_arg(array('page'=>'wmf-integrations','wmf_notice'=>'global_saved'), admin_url('admin.php'))); + } + + private function fields_for_js() { + $r=array(); + foreach(wmf_get_fields() as $type=>$f) { + $r[]=array('type'=>$type,'label'=>$f->label,'icon'=>$f->icon,'category'=>$f->category,'defaults'=>$f->defaults()); + } + return $r; + } +} diff --git a/inc/classes/class-builder.php b/inc/classes/class-builder.php new file mode 100644 index 0000000..ad1db91 --- /dev/null +++ b/inc/classes/class-builder.php @@ -0,0 +1,44 @@ +hook();} + return self::$instance; + } + public function hook() { + add_action('wp_ajax_wmf_get_field_settings',array($this,'ajax_field_settings')); + add_action('wp_ajax_wmf_preview_form', array($this,'ajax_preview')); + } + public function ajax_field_settings() { + check_ajax_referer('wmf_admin','nonce'); + if(!current_user_can('manage_options')) wp_die(); + $type=sanitize_text_field($_POST['field_type']??''); + $field=json_decode(stripslashes($_POST['field_data']??'{}'),true); + $obj=wmf_get_field($type); + if(!$obj) wp_send_json_error('Unbekannter Feldtyp: '.$type); + ob_start(); $obj->settings_panel($field); $html=ob_get_clean(); + wp_send_json_success(array('html'=>$html)); + } + public function ajax_preview() { + check_ajax_referer('wmf_admin','nonce'); + if(!current_user_can('manage_options')) wp_die(); + $form_id=intval($_POST['form_id']??0); + $fields=json_decode(stripslashes($_POST['fields']??'[]'),true); + $meta=wmf_get_form_meta($form_id); + $meta['fields']=$fields; + ob_start(); + echo '
'; + foreach($fields as $field) { + $obj=wmf_get_field($field['type']??''); + if(!$obj) continue; + echo '
'; + $obj->render($field,''); + echo '
'; + } + echo '
'; + echo '
'; + $html=ob_get_clean(); + wp_send_json_success(array('html'=>$html)); + } +} diff --git a/inc/classes/class-field-registry.php b/inc/classes/class-field-registry.php new file mode 100644 index 0000000..9d7e367 --- /dev/null +++ b/inc/classes/class-field-registry.php @@ -0,0 +1,21 @@ +register_defaults();} + return self::$instance; + } + private function register_defaults() { + foreach(array('WMF_Field_Text','WMF_Field_Email','WMF_Field_Textarea','WMF_Field_Select', + 'WMF_Field_Checkbox','WMF_Field_Radio','WMF_Field_Number','WMF_Field_Phone', + 'WMF_Field_URL','WMF_Field_Date','WMF_Field_File','WMF_Field_Rating', + 'WMF_Field_Range','WMF_Field_GDPR','WMF_Field_Signature', + 'WMF_Field_Hidden','WMF_Field_HTML','WMF_Field_Divider') as $cls) { + $f=new $cls(); $this->fields[$f->type]=$f; + } + } + public function get_fields() { return $this->fields; } + public function get_field($type) { return $this->fields[$type]??null; } +} diff --git a/inc/classes/class-form-processor.php b/inc/classes/class-form-processor.php new file mode 100644 index 0000000..2632b71 --- /dev/null +++ b/inc/classes/class-form-processor.php @@ -0,0 +1,105 @@ +hook();} + return self::$instance; + } + public function hook() { + add_action('init',array($this,'maybe_process'),20); + } + public function maybe_process() { + if(empty($_POST['wmf_action'])||$_POST['wmf_action']!=='submit') return; + if(empty($_POST['wmf_form_id'])) return; + if(!session_id()) session_start(); + + $form_id=intval($_POST['wmf_form_id']); + if(!wp_verify_nonce($_POST['wmf_nonce']??'','wmf_submit_'.$form_id)) { + $this->fail($form_id,'Sicherheitsüberprüfung fehlgeschlagen.'); return; + } + $form=get_post($form_id); + if(!$form||$form->post_type!=='wmf-form') return; + + $meta = wmf_get_form_meta($form_id); + $fields = $meta['fields']??array(); + + // Honeypot prüfen + if(!empty($meta['honeypot_enabled'])&&$meta['honeypot_enabled']==='1') { + if(!empty($_POST['wmf_hp_'.md5($form_id)])) { $this->ok($form_id,$meta); return; } // stille Ablehnung + } + + // Werte sammeln + validieren + $values=array(); $errors=array(); + foreach($fields as $field) { + $type=$field['type']??''; + $obj=wmf_get_field($type); + if(!$obj) continue; + if(in_array($type,array('html','divider'))) continue; + + $raw=$_POST['wmf_fields'][$field['id']]??''; + $val=$obj->sanitize($raw,$field); + $valid=$obj->validate($val,$field); + $values[$field['id']]=$val; + if($valid!==true) $errors[$field['id']]=$valid; + } + + // Datei-Uploads + $file_values=array(); + if(!empty($_FILES['wmf_files'])) { + foreach($fields as $field) { + if(($field['type']??'')!=='file') continue; + $uploaded=WMF_Field_File::handle_upload($field,$form_id); + if(!empty($uploaded)) $file_values[$field['id']]=$uploaded; + // Validierung nochmal mit Upload-Ergebnis + $valid=wmf_get_field('file')->validate('',$field); + if($valid!==true&&!isset($errors[$field['id']])) $errors[$field['id']]=$valid; + } + } + + if(!empty($errors)) { + $_SESSION['wmf_values_'.$form_id]=$values; + $_SESSION['wmf_errors_'.$form_id]=$errors; + wp_redirect($this->current_url()); exit; + } + + // Datei-URLs in Werte mergen + foreach($file_values as $fid=>$uploads) { + $urls=array_map(fn($u)=>$u['url'],$uploads); + $values[$fid]=implode(', ',$urls); + } + + // Speichern + $submission_id=null; + if(!empty($meta['save_submissions'])&&$meta['save_submissions']==='1') { + $submission_id=WMF_Submission::save($form_id,$values); + } + + // E-Mails + if(!empty($meta['notify_admin'])&&$meta['notify_admin']==='1') { + WMF_Mailer::notify_admin($form_id,$meta,$fields,$values,$file_values); + } + if(!empty($meta['notify_sender'])&&$meta['notify_sender']==='1') { + WMF_Mailer::notify_sender($form_id,$meta,$fields,$values); + } + + do_action('wmf_form_submitted',$form_id,$meta,$fields,$values,$submission_id); + $this->ok($form_id,$meta); + } + + private function ok($form_id,$meta) { + if(!empty($meta['redirect_url'])) { wp_redirect(esc_url_raw($meta['redirect_url'])); exit; } + if(!session_id()) session_start(); + $_SESSION['wmf_success_'.$form_id]=true; + wp_redirect($this->current_url()); exit; + } + private function fail($form_id,$msg) { + if(!session_id()) session_start(); + $_SESSION['wmf_errors_'.$form_id]=array('_global'=>$msg); + wp_redirect($this->current_url()); exit; + } + private function current_url() { + return (is_ssl()?'https':'http').'://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']; + } +} diff --git a/inc/classes/class-form-renderer.php b/inc/classes/class-form-renderer.php new file mode 100644 index 0000000..39d91e9 --- /dev/null +++ b/inc/classes/class-form-renderer.php @@ -0,0 +1,145 @@ +post_type!=='wmf-form'||$form->post_status!=='publish') + return '

Formular nicht gefunden.

'; + + if(!session_id()) session_start(); + + $meta = wmf_get_form_meta($form_id); + $fields = $meta['fields']??array(); + $saved_values = $_SESSION['wmf_values_'.$form_id]??array(); + $errors = $_SESSION['wmf_errors_'.$form_id]??array(); + $success = $_SESSION['wmf_success_'.$form_id]??false; + + unset($_SESSION['wmf_values_'.$form_id],$_SESSION['wmf_errors_'.$form_id],$_SESSION['wmf_success_'.$form_id]); + + ob_start(); + + if($success) { + echo ''; + if(empty($args['always_show'])) return ob_get_clean(); + } + if(!empty($errors['_global'])) + echo ''; + + $multi_step=!empty($meta['multi_step'])&&$meta['multi_step']==='1'; + // Schritte ermitteln + $steps=array(); + foreach($fields as $f) { $s=intval($f['step']??0); if(!isset($steps[$s])) $steps[$s]=array(); $steps[$s][]=$f; } + ksort($steps); + $total_steps=count($steps); + if($total_steps<2) $multi_step=false; + + $form_cls='wmf-form'.(!empty($meta['css_class'])?' '.esc_attr($meta['css_class']):''); + $field_json=wp_json_encode($fields); + ?> +
+ + +
+ $snum): $lbl=$step_labels[$si]??'Schritt '.($si+1); ?> +
+ + +
+ +
+ + +
+ + + + + + + + + + + $step_fields): ?> +
0?'style="display:none;"':''; ?>> +
+ +
+
+ 0): ?> + + + + + +
+
+ + +
+ +
+ + +
+
+ '; + $obj->render($field,$value); + if($err) echo '

'.esc_html($err).'

'; + echo ''; + } + } + + private static function render_submit($meta,$form_id) { + // reCAPTCHA + $integrations=wmf_get_integrations(); + if(!empty($meta['recaptcha_enabled'])&&$meta['recaptcha_enabled']==='1') { + $rv3=$integrations->get_service('recaptchav3'); + $rv2=$integrations->get_service('recaptcha'); + if($rv3&&$rv3->is_connected()) { + $creds=$rv3->get_credentials(); + echo ''; + echo ''; + } elseif($rv2&&$rv2->is_connected()) { + $creds=$rv2->get_credentials(); + echo '
'; + echo ''; + } + } + ?> +
+ + +
+ ', + ); + + // Reply-To auf Absender-E-Mail-Feld setzen + if(!empty($meta['admin_reply_to']) && $meta['admin_reply_to'] === '1') { + foreach($fields as $f) { + if(($f['type'] ?? '') === 'email' && !empty($values[$f['id']]) && is_email($values[$f['id']])) { + $headers[] = 'Reply-To: ' . $values[$f['id']]; + break; + } + } + } + + wp_mail($to, $subject, self::build_body($fields, $values, $file_values), $headers); + } + + /** + * Absender-Bestaetigung + */ + public static function notify_sender($form_id, $meta, $fields, $values) { + $global = get_option('wmf_global_settings', array()); + $from_name = !empty($meta['from_name']) ? $meta['from_name'] : ($global['from_name'] ?? get_bloginfo('name')); + $from_email = !empty($meta['from_email']) ? $meta['from_email'] : ($global['from_email'] ?? get_option('admin_email')); + + $email = ''; + foreach($fields as $f) { + if(($f['type'] ?? '') === 'email' && !empty($values[$f['id']]) && is_email($values[$f['id']])) { + $email = $values[$f['id']]; + break; + } + } + if(!$email) return; + + $headers = array( + 'Content-Type: text/html; charset=UTF-8', + 'From: ' . $from_name . ' <' . $from_email . '>', + ); + + $body = '' + . wpautop(esc_html($meta['sender_message'] ?? '')) + . '

Gesendet ueber ' . get_bloginfo('name') . '

' + . ''; + + wp_mail($email, $meta['sender_subject'] ?? 'Ihre Nachricht wurde empfangen', $body, $headers); + } + + /** + * E-Mail-Body aufbauen + */ + private static function build_body($fields, $values, $file_values) { + $rows = ''; + foreach($fields as $f) { + if(in_array($f['type'] ?? '', array('html','divider','hidden'))) continue; + $lbl = $f['label'] ?? $f['id']; + $val = $values[$f['id']] ?? ''; + if(is_array($val)) $val = implode(', ', $val); + if(($f['type'] ?? '') === 'gdpr') + $val = ($val === '1') ? '✓ Zugestimmt' : '✗ Nicht zugestimmt'; + if(($f['type'] ?? '') === 'signature' && !empty($val)) + $val = ''; + if(isset($file_values[$f['id']])) { + $links = array_map( + fn($u) => '' . esc_html($u['name']) . '', + $file_values[$f['id']] + ); + $val = implode('
', $links); + } + $rows .= '' + . '' . esc_html($lbl) . '' + . '' . $val . '' + . ''; + } + + return '' + . '
' + . '

Neue Formulareinreichung

' + . '

' . get_bloginfo('name') . ' · ' . current_time('d.m.Y H:i') . '

' + . '
' + . '
' + . '' . $rows . '
' + . '
' + . '

Diese E-Mail wurde automatisch gesendet von WP Multi Formular

' + . ''; + } +} diff --git a/inc/classes/class-post-type.php b/inc/classes/class-post-type.php new file mode 100644 index 0000000..e6989af --- /dev/null +++ b/inc/classes/class-post-type.php @@ -0,0 +1,43 @@ +hook(); } + return self::$instance; + } + public function hook() { + add_action( 'init', array( $this, 'register' ) ); + add_action( 'admin_init', array( $this, 'redirect_cpt' ) ); + } + public static function register() { + register_post_type( 'wmf-form', array( + 'labels' => array( + 'name' => 'Formulare', + 'singular_name' => 'Formular', + 'not_found' => 'Keine Formulare gefunden.', + ), + 'public' => false, + 'show_ui' => true, + 'show_in_menu' => false, + 'supports' => array( 'title' ), + 'capability_type' => 'post', + 'has_archive' => false, + 'rewrite' => false, + ) ); + } + public function redirect_cpt() { + if ( ! is_admin() ) return; + $pt = $_GET['post_type'] ?? ''; + if ( $pt === 'wmf-form' && basename( $_SERVER['PHP_SELF'] ) === 'edit.php' ) { + wp_redirect( admin_url( 'admin.php?page=wp-multi-formular' ) ); exit; + } + if ( isset( $_GET['post'], $_GET['action'] ) && $_GET['action'] === 'edit' ) { + $p = get_post( intval( $_GET['post'] ) ); + if ( $p && $p->post_type === 'wmf-form' ) { + wp_redirect( admin_url( 'admin.php?page=wp-multi-formular&edit=' . $p->ID ) ); exit; + } + } + } +} diff --git a/inc/classes/class-shortcode.php b/inc/classes/class-shortcode.php new file mode 100644 index 0000000..a3c9224 --- /dev/null +++ b/inc/classes/class-shortcode.php @@ -0,0 +1,36 @@ +hook();} + return self::$instance; + } + public function hook() { + add_shortcode('wp_multi_formular',array($this,'render')); + add_action('wp_enqueue_scripts',array($this,'enqueue_assets')); + add_action('init',array($this,'start_session'),1); + } + public function start_session() { if(!session_id()&&!headers_sent()) session_start(); } + public function render($atts) { + $atts=shortcode_atts(array('id'=>0),$atts,'wp_multi_formular'); + $id=intval($atts['id']); + if(!$id) return '

Bitte geben Sie eine Formular-ID an.

'; + return WMF_Form_Renderer::render($id); + } + public function enqueue_assets() { + wp_enqueue_style('wp-multi-formular',WMF_URL.'assets/css/frontend.css',array(),WMF_VERSION); + wp_enqueue_script('wp-multi-formular',WMF_URL.'assets/js/frontend.js',array('jquery'),WMF_VERSION,true); + wp_localize_script('wp-multi-formular','WMF_Frontend',array( + 'ajax_url'=>admin_url('admin-ajax.php'), + 'i18n'=>array( + 'required' =>'Dieses Feld ist ein Pflichtfeld.', + 'email' =>'Bitte geben Sie eine gültige E-Mail-Adresse ein.', + 'url' =>'Bitte geben Sie eine gültige URL ein.', + 'step_of' =>'Schritt %1 von %2', + 'next' =>'Weiter', + 'prev' =>'Zurück', + ), + )); + } +} diff --git a/inc/classes/class-smtp.php b/inc/classes/class-smtp.php new file mode 100644 index 0000000..6556877 --- /dev/null +++ b/inc/classes/class-smtp.php @@ -0,0 +1,54 @@ +hook(); + } + return self::$instance; + } + + public function hook() { + $opts = get_option('wmf_global_settings', array()); + if(!empty($opts['smtp_enabled']) && $opts['smtp_enabled'] === '1' && !empty($opts['smtp_host'])) { + add_action('phpmailer_init', array($this, 'configure_smtp')); + } + } + + public function configure_smtp($phpmailer) { + $opts = get_option('wmf_global_settings', array()); + if(empty($opts['smtp_host'])) return; + + $phpmailer->isSMTP(); + $phpmailer->Host = $opts['smtp_host']; + $phpmailer->Port = intval($opts['smtp_port'] ?? 587); + $phpmailer->SMTPSecure = $opts['smtp_enc'] ?? 'tls'; + + if(!empty($opts['smtp_user'])) { + $phpmailer->SMTPAuth = true; + $phpmailer->Username = $opts['smtp_user']; + $phpmailer->Password = $opts['smtp_pass'] ?? ''; + } else { + $phpmailer->SMTPAuth = false; + } + + // From-Adresse global setzen falls nicht per Mail-Header gesetzt + if(!empty($opts['from_email'])) { + $phpmailer->From = $opts['from_email']; + $phpmailer->FromName = $opts['from_name'] ?? get_bloginfo('name'); + } + + $phpmailer->SMTPOptions = array( + 'ssl' => array( + 'verify_peer' => false, + 'verify_peer_name' => false, + 'allow_self_signed' => true, + ) + ); + } +} diff --git a/inc/classes/class-submission.php b/inc/classes/class-submission.php new file mode 100644 index 0000000..d2a9f8c --- /dev/null +++ b/inc/classes/class-submission.php @@ -0,0 +1,18 @@ +insert($wpdb->prefix.'wmf_submissions',array( + 'form_id'=>$form_id,'data'=>wp_json_encode($values), + 'ip'=>wmf_get_client_ip(),'user_agent'=>$_SERVER['HTTP_USER_AGENT']??'', + 'status'=>'neu','created_at'=>current_time('mysql'), + ),array('%d','%s','%s','%s','%s','%s')); + return $wpdb->insert_id; + } + public static function delete($id) { global $wpdb; $wpdb->delete($wpdb->prefix.'wmf_submissions',array('id'=>$id),array('%d')); } + public static function update_status($id,$status) { + global $wpdb; + $wpdb->update($wpdb->prefix.'wmf_submissions',array('status'=>sanitize_text_field($status)),array('id'=>$id),array('%s'),array('%d')); + } +} diff --git a/inc/classes/class-submissions-list.php b/inc/classes/class-submissions-list.php new file mode 100644 index 0000000..ab63f46 --- /dev/null +++ b/inc/classes/class-submissions-list.php @@ -0,0 +1,481 @@ + $per_page, + 'offset' => $offset, + 'status' => $status_filter, + 'search' => $search, + )); + $total = wmf_count_submissions($form_id, $status_filter, $search); + $total_pages = ceil($total / $per_page); + + $base_url = add_query_arg(array( + 'page' => 'wp-multi-formular', + 'view_submissions' => $form_id, + ), admin_url('admin.php')); + ?> + +
+ + +
+

+ Einreichungen + +

+ +
+ + +
+
+ + + + +
+ 'Alle', 'neu' => 'Neu', 'gelesen' => 'Gelesen', 'archiviert' => 'Archiviert'); + foreach($statuses as $s_key => $s_label): + $cnt = ($s_key === '') ? wmf_count_submissions($form_id) : wmf_count_submissions($form_id, $s_key); + $active = ($status_filter === $s_key) ? 'current' : ''; + ?> + + + () + + +
+ + + +
+
+ + +
+ + +

Keine Einreichungen gefunden.

+ Filter zurücksetzen + +

Noch keine Einreichungen vorhanden.

+ +
+ + + +
+ + + + + + + + + + + + + + data, true) ?? array(); + $view_url = add_query_arg(array( + 'page' => 'wp-multi-formular', + 'view_submission' => $row->id, + 'form_id' => $form_id, + ), admin_url('admin.php')); + ?> + + + + 60 ? mb_substr($v, 0, 60).'…' : $v; + ?> + + + + + + + +
#DatumStatusAktionen
+ + #id); ?> + + + + created_at))); ?> + created_at))); ?> + + + + + + +
+ + + + + + +
+
+ + 👁 Ansehen + + + 🗑 Löschen + +
+
+ + + 1): ?> +
+ 1): ?> + « Zurück + + + Seite von + + + Weiter » + +
+ + + +
+ get_row($wpdb->prepare( + "SELECT * FROM {$wpdb->prefix}wmf_submissions WHERE id = %d AND form_id = %d", + $submission_id, $form_id + )); + + if(!$row) { + echo '

Einreichung nicht gefunden.

'; + return; + } + + // Als gelesen markieren + if($row->status === 'neu') { + WMF_Submission::update_status($submission_id, 'gelesen'); + $row->status = 'gelesen'; + } + + $data = json_decode($row->data, true) ?? array(); + $meta = wmf_get_form_meta($form_id); + $fields = self::get_display_fields($meta); + $form = get_post($form_id); + + $back_url = add_query_arg(array( + 'page' => 'wp-multi-formular', + 'view_submissions' => $form_id, + ), admin_url('admin.php')); + + $prev_url = self::get_adjacent_url($submission_id, $form_id, 'prev'); + $next_url = self::get_adjacent_url($submission_id, $form_id, 'next'); + ?> + +
+ + +
+ + ← Alle Einreichungen + +
+ + « Vorherige + + + + + Nächste » + + + +
+
+ + +
+
+ Einreichung + #id); ?> +
+
+ Formular + post_title : 'Unbekannt'); ?> +
+
+ Datum + created_at))); ?> +
+
+ IP-Adresse + ip ?: '—'); ?> +
+
+ Status +
+ + + + + + +
+
+
+ + 🗑 Löschen + + +
+
+ + +
+

Eingereichte Daten

+
+ +
+
+ + +
+
+ +
+
+ +
+
+ + +
+ Technische Informationen + + + + +
User-Agentuser_agent ?: '—'); ?>
Erstellt amcreated_at); ?>
Datenbank-IDid); ?>
+
+ +
+ + + —'; + return; + } + + switch($type) { + case 'checkbox': + $vals = is_array($val) ? $val : explode(', ', $val); + echo ''; + break; + + case 'gdpr': + $icon = $val === '1' ? '✅' : '❌'; + echo $icon . ' ' . ($val === '1' ? 'Zugestimmt' : 'Nicht zugestimmt'); + break; + + case 'signature': + if(strpos($val, 'data:image') === 0) { + echo ''; + } else { + echo 'Keine Unterschrift'; + } + break; + + case 'file': + $urls = is_array($val) ? $val : explode(', ', $val); + echo '
'; + foreach($urls as $url) { + $url = trim($url); + if(!$url) continue; + $filename = basename(parse_url($url, PHP_URL_PATH)); + $ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION)); + $is_image = in_array($ext, array('jpg','jpeg','png','gif','webp')); + if($is_image) { + echo ''; + } else { + echo '📎 ' . esc_html($filename) . ''; + } + } + echo '
'; + break; + + case 'rating': + $stars = intval($val); + $max = intval($field['max_stars'] ?? 5); + echo '
'; + for($i = 1; $i <= $max; $i++) { + echo ''; + } + echo ' ' . $stars . '/' . $max . '
'; + break; + + case 'url': + echo '' . esc_html($val) . ''; + break; + + case 'email': + echo '' . esc_html($val) . ''; + break; + + case 'textarea': + echo '
' . nl2br(esc_html($val)) . '
'; + break; + + default: + if(is_array($val)) { + echo ''; + } else { + echo '' . esc_html($val) . ''; + } + } + } + + /* ================================================================ + HILFSFUNKTIONEN + ================================================================ */ + private static function get_display_fields($meta) { + return array_values(array_filter($meta['fields'] ?? array(), function($f) { + return !in_array($f['type'] ?? '', array('html','divider','hidden')); + })); + } + + private static function get_adjacent_url($submission_id, $form_id, $direction) { + global $wpdb; + $op = $direction === 'prev' ? '>' : '<'; + $order = $direction === 'prev' ? 'ASC' : 'DESC'; + $adj = $wpdb->get_var($wpdb->prepare( + "SELECT id FROM {$wpdb->prefix}wmf_submissions WHERE form_id = %d AND id {$op} %d ORDER BY id {$order} LIMIT 1", + $form_id, $submission_id + )); + if(!$adj) return null; + return add_query_arg(array('page'=>'wp-multi-formular','view_submission'=>$adj,'form_id'=>$form_id), admin_url('admin.php')); + } + + public static function status_label($s) { + return array('neu'=>'Neu','gelesen'=>'Gelesen','archiviert'=>'Archiviert')[$s] ?? $s; + } + + public static function export_url($form_id) { + return wp_nonce_url(add_query_arg(array('wmf_action'=>'export_csv','form_id'=>$form_id,'page'=>'wp-multi-formular'), admin_url('admin.php')), 'wmf_export_csv'); + } + + public static function maybe_export($form_id) { + if(empty($_GET['wmf_action']) || $_GET['wmf_action'] !== 'export_csv') return; + if(!wp_verify_nonce($_GET['_wpnonce'] ?? '', 'wmf_export_csv')) return; + $meta = wmf_get_form_meta($form_id); + $fields = self::get_display_fields($meta); + $rows = wmf_get_submissions($form_id, array('limit'=>9999)); + header('Content-Type: text/csv; charset=utf-8'); + header('Content-Disposition: attachment; filename="formular-' . $form_id . '-einreichungen.csv"'); + $out = fopen('php://output', 'w'); + fprintf($out, chr(0xEF).chr(0xBB).chr(0xBF)); + $header = array('ID','Datum','Status','IP'); + foreach($fields as $f) $header[] = $f['label']; + fputcsv($out, $header, ';'); + foreach($rows as $row) { + $data = json_decode($row->data, true) ?? array(); + $line = array($row->id, date_i18n('d.m.Y H:i', strtotime($row->created_at)), self::status_label($row->status), $row->ip); + foreach($fields as $f) { + $v = $data[$f['id']] ?? ''; + if(is_array($v)) $v = implode(', ', $v); + if(($f['type']??'') === 'signature') $v = '(Unterschrift)'; + $line[] = $v; + } + fputcsv($out, $line, ';'); + } + fclose($out); + exit; + } +} diff --git a/inc/fields/class-field-base.php b/inc/fields/class-field-base.php new file mode 100644 index 0000000..d22eda6 --- /dev/null +++ b/inc/fields/class-field-base.php @@ -0,0 +1,158 @@ + '', + 'type' => $this->type, + 'label' => $this->label, + 'name' => '', + 'placeholder' => '', + 'description' => '', + 'required' => '0', + 'css_class' => '', + 'width' => 'full', + // Bedingte Logik + 'conditional_logic' => '0', + 'conditional_action' => 'show', // show|hide + 'conditional_rules' => array(), // [{field,operator,value}] + 'conditional_match' => 'all', // all|any + // Schritt (mehrstufige Formulare) + 'step' => 0, + ); + } + + abstract public function render( $field, $value = '' ); + + public function validate( $value, $field ) { + if ( ! empty( $field['required'] ) && $field['required'] === '1' ) { + $empty = ( $value === '' || $value === null || $value === array() ); + if ( $empty ) return sprintf( 'Das Feld „%s" ist ein Pflichtfeld.', $field['label'] ); + } + return true; + } + + public function sanitize( $value, $field ) { + return sanitize_text_field( (string) $value ); + } + + /* Einstellungs-Panel im Builder */ + public function settings_panel( $field ) { + ?> +
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ +
+
+ + +
+
+ + +
+
+
+ + +
+
+
+ + +
+
+ + +
+
+ '','operator'=>'=','value'=>'')); + foreach($rules as $rule): ?> +
+ + + + +
+ +
+ +
+ type ); + $w = $field['width'] ?? 'full'; + if ( $w !== 'full' ) $cls[] = 'wmf-field-width-' . $w; + if ( ! empty($field['css_class']) ) $cls[] = $field['css_class']; + if ( !empty($field['required']) && $field['required']==='1' ) $cls[] = 'wmf-required'; + if ( !empty($field['conditional_logic']) && $field['conditional_logic']==='1' ) $cls[] = 'wmf-has-condition'; + return implode(' ', $cls); + } + + protected function render_label( $field ) { + if ( empty($field['label']) ) return; + $req = (!empty($field['required']) && $field['required']==='1') ? ' ' : ''; + printf( '', esc_attr($field['id']), esc_html($field['label']), $req ); + } + + protected function render_description( $field ) { + if ( empty($field['description']) ) return; + printf( '

%s

', esc_html($field['description']) ); + } + + protected function conditional_attrs( $field ) { + if ( empty($field['conditional_logic']) || $field['conditional_logic'] !== '1' ) return ''; + return sprintf( + ' data-condition="%s" data-condition-action="%s" data-condition-match="%s" data-condition-rules="%s"', + '1', + esc_attr($field['conditional_action'] ?? 'show'), + esc_attr($field['conditional_match'] ?? 'all'), + esc_attr(wp_json_encode($field['conditional_rules'] ?? array())) + ); + } +} diff --git a/inc/fields/class-field-checkbox.php b/inc/fields/class-field-checkbox.php new file mode 100644 index 0000000..4a6dea5 --- /dev/null +++ b/inc/fields/class-field-checkbox.php @@ -0,0 +1,23 @@ +array(array('label'=>'Option 1','value'=>'option_1')),'layout'=>'vertical')); } + public function render($field,$value='') { + $checked=is_array($value)?$value:($value?array($value):array()); ?> +
conditional_attrs($field); ?> data-field-id=""> + render_label($field); ?> +
+ + + +
+ render_description($field); ?> + +
'','max_date'=>'')); } + public function render($field,$value='') { ?> +
conditional_attrs($field); ?> data-field-id=""> + render_label($field); ?> + class="wmf-input"> + render_description($field); ?> + +
+
conditional_attrs($field); ?>> +


+ render_description($field); ?> +
+
conditional_attrs($field); ?> data-field-id=""> + render_label($field); ?> + class="wmf-input" autocomplete="email"> + render_description($field); ?> + +
'jpg,jpeg,png,pdf,doc,docx','max_size_mb'=>'5','multiple'=>'0','save_to_media'=>'1')); } + public function render($field,$value='') { ?> +
conditional_attrs($field); ?> data-field-id=""> + render_label($field); ?> + class="wmf-input wmf-file-input"> +

Erlaubt: — Max. MB

+ render_description($field); ?> + +
'.'.$t,$types)); + } + public function validate($value,$field) { + $key=$field['id']; + if(!isset($_FILES['wmf_files']['error'][$key])) return true; + $err=$_FILES['wmf_files']['error'][$key]; + if(is_array($err)) $err=array_filter($err,fn($e)=>$e!==UPLOAD_ERR_NO_FILE); + if(empty($err)||$err===UPLOAD_ERR_NO_FILE) { + if(!empty($field['required'])&&$field['required']==='1') return sprintf('Bitte laden Sie eine Datei für „%s" hoch.',$field['label']); + return true; + } + $max=intval($field['max_size_mb']??5)*1024*1024; + $sizes=$_FILES['wmf_files']['size'][$key]; + if(is_array($sizes)) { foreach($sizes as $s) if($s>$max) return sprintf('Max. %s MB erlaubt.',$field['max_size_mb']??5); } + elseif($sizes>$max) return sprintf('Max. %s MB erlaubt.',$field['max_size_mb']??5); + return true; + } + public function sanitize($v,$f) { return $v; } + + public static function handle_upload($field,$form_id) { + $key=$field['id']; + if(!isset($_FILES['wmf_files']['tmp_name'][$key])) return array(); + require_once ABSPATH.'wp-admin/includes/image.php'; + require_once ABSPATH.'wp-admin/includes/file.php'; + require_once ABSPATH.'wp-admin/includes/media.php'; + $tmp=$_FILES['wmf_files']['tmp_name'][$key]; + $names=$_FILES['wmf_files']['name'][$key]; + $results=array(); + if(!is_array($tmp)) { $tmp=array($tmp); $names=array($names); } + foreach($tmp as $i=>$t) { + if(empty($t)||!is_uploaded_file($t)) continue; + $upload=wp_handle_upload(array( + 'tmp_name'=>$t,'name'=>$names[$i],'type'=>mime_content_type($t),'error'=>0,'size'=>filesize($t) + ),array('test_form'=>false)); + if(isset($upload['url'])) { + if(!empty($field['save_to_media'])&&$field['save_to_media']==='1') { + $att=array('post_mime_type'=>$upload['type'],'post_title'=>sanitize_file_name($names[$i]),'post_content'=>'','post_status'=>'inherit'); + $att_id=wp_insert_attachment($att,$upload['file']); + wp_update_attachment_metadata($att_id,wp_generate_attachment_metadata($att_id,$upload['file'])); + $results[]=array('url'=>$upload['url'],'attachment_id'=>$att_id,'name'=>$names[$i]); + } else { + $results[]=array('url'=>$upload['url'],'name'=>$names[$i]); + } + } + } + return $results; + } +} diff --git a/inc/fields/class-field-gdpr.php b/inc/fields/class-field-gdpr.php new file mode 100644 index 0000000..1395ddf --- /dev/null +++ b/inc/fields/class-field-gdpr.php @@ -0,0 +1,34 @@ + '1', + 'gdpr_text' => 'Ich stimme der Datenschutzerklärung zu.', + 'error_message' => 'Bitte stimmen Sie der Datenschutzerklärung zu.', + )); + } + public function render($field,$value='') { ?> +
conditional_attrs($field); ?> data-field-id=""> + + +
+
+
+ '')); } + public function render($field,$value='') { + $v=$value?:($field['default_value']??''); + // Dynamic values + if($v==='{{user_ip}}') $v=wmf_get_client_ip(); + if($v==='{{page_url}}') $v=home_url(add_query_arg(array())); + if($v==='{{date}}') $v=date('Y-m-d'); + printf('',esc_attr($field['id']),esc_attr($v)); + } + public function validate($v,$f) { return true; } +} diff --git a/inc/fields/class-field-html.php b/inc/fields/class-field-html.php new file mode 100644 index 0000000..ceb50cb --- /dev/null +++ b/inc/fields/class-field-html.php @@ -0,0 +1,13 @@ +'')); } + public function render($field,$value='') { ?> +
conditional_attrs($field); ?>> + +
'','max'=>'','step'=>'1')); } + public function render($field,$value='') { ?> +
conditional_attrs($field); ?> data-field-id=""> + render_label($field); ?> + step="" class="wmf-input"> + render_description($field); ?> + +
+
conditional_attrs($field); ?> data-field-id=""> + render_label($field); ?> + class="wmf-input" autocomplete="tel"> + render_description($field); ?> + +
array(array('label'=>'Option 1','value'=>'option_1')),'layout'=>'vertical')); } + public function render($field,$value='') { ?> +
conditional_attrs($field); ?> data-field-id=""> + render_label($field); ?> +
+ + + +
+ render_description($field); ?> + +
'0','max'=>'100','step'=>'1','show_value'=>'1')); } + public function render($field,$value='') { + $val=$value!==''?$value:($field['min']??0); ?> +
conditional_attrs($field); ?> data-field-id=""> + render_label($field); ?> +
+ + + + +
+ render_description($field); ?> +
'5','icon'=>'star')); } + public function render($field,$value='') { + $max=intval($field['max_stars']??5); ?> +
conditional_attrs($field); ?> data-field-id=""> + render_label($field); ?> +
+ + + + +
+ render_description($field); ?> + +
array(array('label'=>'Option 1','value'=>'option_1')),'multiple'=>'0')); } + public function render($field,$value='') { + $multi=!empty($field['multiple'])&&$field['multiple']==='1'; + $name='wmf_fields['.esc_attr($field['id']).']'.($multi?'[]':''); ?> +
conditional_attrs($field); ?> data-field-id=""> + render_label($field); ?> + + render_description($field); ?> + +
+
conditional_attrs($field); ?> data-field-id=""> + render_label($field); ?> +
+ +
+ +
+ +
+ render_description($field); ?> + +
+
conditional_attrs($field); ?> data-field-id=""> + render_label($field); ?> + class="wmf-input" autocomplete="on"> + render_description($field); ?> + +
'5','max_chars'=>'')); } + public function render($field,$value='') { ?> +
conditional_attrs($field); ?> data-field-id=""> + render_label($field); ?> + +
0/
+ render_description($field); ?> + +
+
+
+ +
conditional_attrs($field); ?> data-field-id=""> + render_label($field); ?> + class="wmf-input"> + render_description($field); ?> + +
prefix . 'wmf_submissions'; + $charset = $wpdb->get_charset_collate(); + $sql = "CREATE TABLE IF NOT EXISTS {$table} ( + id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, + form_id BIGINT(20) UNSIGNED NOT NULL, + data LONGTEXT NOT NULL, + ip VARCHAR(45) DEFAULT '', + user_agent TEXT DEFAULT '', + status VARCHAR(20) DEFAULT 'neu', + created_at DATETIME DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (id), + KEY form_id (form_id) + ) {$charset};"; + require_once ABSPATH . 'wp-admin/includes/upgrade.php'; + dbDelta( $sql ); + update_option( 'wmf_db_version', '2.0' ); +} + +function wmf_get_fields() { return WMF_Field_Registry::instance()->get_fields(); } +function wmf_get_field( $type ) { return WMF_Field_Registry::instance()->get_field( $type ); } +function wmf_get_shortcode( $id ) { return '[wp_multi_formular id="' . intval($id) . '"]'; } +function wmf_unique_id() { return 'field_' . substr( md5( uniqid( '', true ) ), 0, 8 ); } + +function wmf_get_form_meta( $form_id ) { + $defaults = array( + 'fields' => array(), + 'submit_label' => 'Absenden', + 'success_message' => 'Vielen Dank! Ihre Nachricht wurde gesendet.', + 'error_message' => 'Es ist ein Fehler aufgetreten. Bitte versuchen Sie es erneut.', + 'notify_admin' => '1', + 'admin_email' => get_option('admin_email'), + 'admin_subject' => 'Neue Formulareinreichung', + 'admin_reply_to' => '1', + 'notify_sender' => '0', + 'sender_subject' => 'Ihre Nachricht wurde empfangen', + 'sender_message' => 'Vielen Dank für Ihre Nachricht. Wir melden uns bald.', + 'from_name' => get_bloginfo('name'), + 'from_email' => get_option('admin_email'), + 'save_submissions' => '1', + 'recaptcha_enabled' => '0', + 'honeypot_enabled' => '1', + 'active_email_service' => '', + 'email_list_field' => '', + 'redirect_url' => '', + 'css_class' => '', + 'multi_step' => '0', + 'step_labels' => array(), + 'show_progress' => '1', + ); + $meta = get_post_meta( $form_id, '_wmf_form_data', true ); + if ( ! is_array( $meta ) ) $meta = array(); + return wp_parse_args( $meta, $defaults ); +} + +function wmf_save_form_meta( $form_id, $data ) { + update_post_meta( $form_id, '_wmf_form_data', $data ); +} + +function wmf_get_submissions( $form_id, $args = array() ) { + global $wpdb; + $table = $wpdb->prefix . 'wmf_submissions'; + $defaults = array( 'limit' => 50, 'offset' => 0, 'status' => '', 'search' => '' ); + $args = wp_parse_args( $args, $defaults ); + + $where = $wpdb->prepare( 'WHERE form_id = %d', $form_id ); + if ( $args['status'] ) + $where .= $wpdb->prepare( ' AND status = %s', $args['status'] ); + if ( $args['search'] ) + $where .= $wpdb->prepare( ' AND data LIKE %s', '%' . $wpdb->esc_like( $args['search'] ) . '%' ); + + return $wpdb->get_results( + $wpdb->prepare( + "SELECT * FROM {$table} {$where} ORDER BY created_at DESC LIMIT %d OFFSET %d", + $args['limit'], $args['offset'] + ) + ); +} + +function wmf_count_submissions( $form_id, $status = '', $search = '' ) { + global $wpdb; + $where = $wpdb->prepare( 'WHERE form_id = %d', $form_id ); + if ( $status ) + $where .= $wpdb->prepare( ' AND status = %s', $status ); + if ( $search ) + $where .= $wpdb->prepare( ' AND data LIKE %s', '%' . $wpdb->esc_like( $search ) . '%' ); + return (int) $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->prefix}wmf_submissions {$where}" ); +} + +function wmf_get_client_ip() { + foreach ( array('HTTP_CLIENT_IP','HTTP_X_FORWARDED_FOR','REMOTE_ADDR') as $k ) { + if ( ! empty( $_SERVER[$k] ) ) { + $ip = trim( explode(',', $_SERVER[$k])[0] ); + if ( filter_var($ip, FILTER_VALIDATE_IP) ) return $ip; + } + } + return ''; +} + +/** + * Sicherer Redirect - funktioniert auch wenn Header bereits gesendet wurden + * (z.B. durch Plugins die Output vor wp_redirect() ausgeben) + */ +function wmf_safe_redirect( $url ) { + $url = esc_url_raw( $url ); + if ( ! headers_sent() ) { + wp_redirect( $url ); + exit; + } + // JavaScript-Fallback + echo ''; + echo ''; + exit; +}