class-avcf-abilities-wpforms-pro.php
1 month ago
class-avcf-abilities-wpforms.php
1 month ago
class-avcf-wpforms-detector.php
1 month ago
class-avcf-wpforms-helpers.php
1 month ago
class-avcf-wpforms-helpers.php
190 lines
| 1 | <?php |
| 2 | /** |
| 3 | * WPForms — shared helpers for the standalone WPForms ability cluster. |
| 4 | * |
| 5 | * Lifts the proven access logic out of the old unified adapter so the cluster is |
| 6 | * fully self-contained. Forms are the `wpforms` CPT with their definition stored |
| 7 | * as JSON in post_content (wpforms_decode / wpforms_encode); notifications and |
| 8 | * confirmations live under form_data['settings']. Entries are Pro-only |
| 9 | * (wpforms()->entry + {prefix}wpforms_entries table); Lite stores none. |
| 10 | * |
| 11 | * Built on WPForms' public helpers/API; not runtime-tested here. |
| 12 | * |
| 13 | * @package atarim-visual-collaboration |
| 14 | */ |
| 15 | |
| 16 | if ( ! defined('ABSPATH') ) { |
| 17 | exit; |
| 18 | } |
| 19 | |
| 20 | class AVCF_WPForms_Helpers { |
| 21 | |
| 22 | const PLUGIN_SLUG = 'wpforms'; |
| 23 | const PLUGIN_LABEL = 'WPForms'; |
| 24 | const LITE_NOTE = 'WPForms Lite does not store form entries — upgrade to WPForms Pro for entry storage and reporting.'; |
| 25 | |
| 26 | public static function map_form_summary( $post, $is_pro ) { |
| 27 | $form_id = (int) $post->ID; |
| 28 | return [ |
| 29 | 'id' => $form_id, |
| 30 | 'plugin' => self::PLUGIN_SLUG, |
| 31 | 'title' => (string) $post->post_title, |
| 32 | 'status' => $post->post_status === 'publish' ? 'active' : (string) $post->post_status, |
| 33 | 'entries_total' => $is_pro ? self::count_entries( $form_id, false ) : null, |
| 34 | 'last_submission' => $is_pro ? self::last_submission_at( $form_id ) : null, |
| 35 | 'created_at' => (string) $post->post_date, |
| 36 | ]; |
| 37 | } |
| 38 | |
| 39 | public static function map_field( $fid, $f ) { |
| 40 | $options = []; |
| 41 | if ( isset( $f['choices'] ) && is_array( $f['choices'] ) ) { |
| 42 | foreach ( $f['choices'] as $choice ) { |
| 43 | if ( isset( $choice['label'] ) ) { $options[] = (string) $choice['label']; } |
| 44 | } |
| 45 | } |
| 46 | return [ |
| 47 | 'id' => (string) $fid, |
| 48 | 'type' => isset( $f['type'] ) ? (string) $f['type'] : 'unknown', |
| 49 | 'label' => isset( $f['label'] ) ? (string) $f['label'] : '', |
| 50 | 'required' => ! empty( $f['required'] ), |
| 51 | 'options' => $options, |
| 52 | ]; |
| 53 | } |
| 54 | |
| 55 | public static function map_form_full( $post, $form_data, $include_raw = false ) { |
| 56 | if ( ! is_array( $form_data ) ) { $form_data = []; } |
| 57 | $form_id = (int) $post->ID; |
| 58 | |
| 59 | $fields = []; |
| 60 | if ( isset( $form_data['fields'] ) && is_array( $form_data['fields'] ) ) { |
| 61 | foreach ( $form_data['fields'] as $fid => $f ) { |
| 62 | if ( is_array( $f ) ) { $fields[] = self::map_field( $fid, $f ); } |
| 63 | } |
| 64 | } |
| 65 | |
| 66 | $notifications = []; |
| 67 | $nset = isset( $form_data['settings']['notifications'] ) && is_array( $form_data['settings']['notifications'] ) ? $form_data['settings']['notifications'] : []; |
| 68 | foreach ( $nset as $nid => $n ) { |
| 69 | if ( ! is_array( $n ) ) { continue; } |
| 70 | $notifications[] = [ |
| 71 | 'id' => (string) $nid, |
| 72 | 'name' => isset( $n['notification_name'] ) ? (string) $n['notification_name'] : ( 'Notification ' . $nid ), |
| 73 | 'recipients' => self::parse_recipients( isset( $n['email'] ) ? (string) $n['email'] : '' ), |
| 74 | 'subject' => isset( $n['subject'] ) ? (string) $n['subject'] : '', |
| 75 | 'enabled' => ! isset( $n['enable'] ) || ! empty( $n['enable'] ), |
| 76 | ]; |
| 77 | } |
| 78 | |
| 79 | $confirmations = []; |
| 80 | $cset = isset( $form_data['settings']['confirmations'] ) && is_array( $form_data['settings']['confirmations'] ) ? $form_data['settings']['confirmations'] : []; |
| 81 | foreach ( $cset as $cid => $c ) { |
| 82 | if ( ! is_array( $c ) ) { continue; } |
| 83 | $confirmations[] = [ |
| 84 | 'id' => (string) $cid, |
| 85 | 'name' => isset( $c['name'] ) ? (string) $c['name'] : '', |
| 86 | 'type' => isset( $c['type'] ) ? (string) $c['type'] : 'message', |
| 87 | ]; |
| 88 | } |
| 89 | |
| 90 | return [ |
| 91 | 'id' => $form_id, |
| 92 | 'plugin' => self::PLUGIN_SLUG, |
| 93 | 'title' => isset( $form_data['settings']['form_title'] ) ? (string) $form_data['settings']['form_title'] : (string) $post->post_title, |
| 94 | 'status' => $post->post_status === 'publish' ? 'active' : (string) $post->post_status, |
| 95 | 'field_count' => count( $fields ), |
| 96 | 'fields' => $fields, |
| 97 | 'notifications' => $notifications, |
| 98 | 'confirmations' => $confirmations, |
| 99 | 'created_at' => (string) $post->post_date, |
| 100 | 'modified_at' => (string) $post->post_modified, |
| 101 | 'shortcode' => sprintf( '[wpforms id="%d"]', $form_id ), |
| 102 | 'raw' => $include_raw ? $form_data : null, |
| 103 | ]; |
| 104 | } |
| 105 | |
| 106 | public static function normalize_entry( $raw_entry, $form_id, $include_raw = true ) { |
| 107 | $entry_id = isset( $raw_entry->entry_id ) ? (int) $raw_entry->entry_id : 0; |
| 108 | $form_id = (int) $form_id; |
| 109 | |
| 110 | $fields = []; |
| 111 | $raw_fields = isset( $raw_entry->fields ) ? $raw_entry->fields : ''; |
| 112 | if ( is_string( $raw_fields ) && $raw_fields !== '' ) { |
| 113 | $decoded = wpforms_decode( $raw_fields ); |
| 114 | if ( is_array( $decoded ) ) { |
| 115 | foreach ( $decoded as $fid => $field ) { |
| 116 | if ( ! is_array( $field ) ) { continue; } |
| 117 | $fields[] = [ 'id' => (string) $fid, 'label' => isset( $field['name'] ) ? (string) $field['name'] : '', 'type' => isset( $field['type'] ) ? (string) $field['type'] : '', 'value' => isset( $field['value'] ) ? $field['value'] : '' ]; |
| 118 | } |
| 119 | } |
| 120 | } |
| 121 | |
| 122 | $status = isset( $raw_entry->status ) ? (string) $raw_entry->status : ''; |
| 123 | $norm = $status === 'spam' ? 'spam' : ( $status === 'trash' ? 'trash' : 'published' ); |
| 124 | |
| 125 | return [ |
| 126 | 'id' => $entry_id, |
| 127 | 'plugin' => self::PLUGIN_SLUG, |
| 128 | 'form_id' => $form_id, |
| 129 | 'submitted_at' => isset( $raw_entry->date ) ? (string) $raw_entry->date : '', |
| 130 | 'source_url' => isset( $raw_entry->referer ) ? (string) $raw_entry->referer : null, |
| 131 | 'ip_address' => isset( $raw_entry->ip_address ) ? (string) $raw_entry->ip_address : null, |
| 132 | 'user_id' => isset( $raw_entry->user_id ) ? (int) $raw_entry->user_id : 0, |
| 133 | 'starred' => isset( $raw_entry->starred ) ? (bool) $raw_entry->starred : false, |
| 134 | 'viewed' => isset( $raw_entry->viewed ) ? (bool) $raw_entry->viewed : false, |
| 135 | 'status' => $norm, |
| 136 | 'fields' => $fields, |
| 137 | 'raw' => $include_raw ? $raw_entry : null, |
| 138 | ]; |
| 139 | } |
| 140 | |
| 141 | public static function parse_recipients( $str ) { |
| 142 | if ( (string) $str === '' ) { return []; } |
| 143 | $out = []; |
| 144 | foreach ( (array) preg_split( '/[,\n;]+/', (string) $str ) as $part ) { |
| 145 | $clean = trim( (string) $part ); |
| 146 | if ( $clean !== '' ) { $out[] = $clean; } |
| 147 | } |
| 148 | return $out; |
| 149 | } |
| 150 | |
| 151 | public static function count_entries( $form_id, $include_spam, $args = [] ) { |
| 152 | global $wpdb; |
| 153 | $form_id = (int) $form_id; |
| 154 | $table = $wpdb->prefix . 'wpforms_entries'; |
| 155 | $where = [ 'form_id = %d' ]; $params = [ $form_id ]; |
| 156 | if ( ! $include_spam ) { $where[] = "status != 'spam'"; } |
| 157 | if ( ! empty( $args['date_from'] ) ) { $where[] = 'date >= %s'; $params[] = (string) $args['date_from']; } |
| 158 | if ( ! empty( $args['date_to'] ) ) { $where[] = 'date <= %s'; $params[] = (string) $args['date_to']; } |
| 159 | $where_sql = implode( ' AND ', $where ); |
| 160 | $count = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM `{$table}` WHERE {$where_sql}", $params ) ); |
| 161 | return $count === null ? 0 : (int) $count; |
| 162 | } |
| 163 | |
| 164 | public static function last_submission_at( $form_id ) { |
| 165 | global $wpdb; |
| 166 | $form_id = (int) $form_id; |
| 167 | $table = $wpdb->prefix . 'wpforms_entries'; |
| 168 | $row = $wpdb->get_var( $wpdb->prepare( "SELECT MAX(date) FROM `{$table}` WHERE form_id = %d", $form_id ) ); |
| 169 | return $row ? (string) $row : null; |
| 170 | } |
| 171 | |
| 172 | public static function stats( $form_id, $args = [] ) { |
| 173 | global $wpdb; |
| 174 | $form_id = (int) $form_id; |
| 175 | $table = $wpdb->prefix . 'wpforms_entries'; |
| 176 | $where = [ 'form_id = %d' ]; $params = [ $form_id ]; |
| 177 | if ( ! empty( $args['date_from'] ) ) { $where[] = 'date >= %s'; $params[] = (string) $args['date_from']; } |
| 178 | if ( ! empty( $args['date_to'] ) ) { $where[] = 'date <= %s'; $params[] = (string) $args['date_to']; } |
| 179 | $where_sql = implode( ' AND ', $where ); |
| 180 | $by_day = $wpdb->get_results( $wpdb->prepare( "SELECT DATE(date) AS day, COUNT(*) AS count FROM `{$table}` WHERE {$where_sql} GROUP BY DATE(date) ORDER BY day ASC", $params ), 'ARRAY_A' ); |
| 181 | $ext = $wpdb->get_row( $wpdb->prepare( "SELECT MIN(date) AS first_date, MAX(date) AS last_date, COUNT(*) AS total FROM `{$table}` WHERE {$where_sql}", $params ), 'ARRAY_A' ); |
| 182 | return [ |
| 183 | 'total' => $ext && isset( $ext['total'] ) ? (int) $ext['total'] : 0, |
| 184 | 'first_date' => $ext && isset( $ext['first_date'] ) ? $ext['first_date'] : null, |
| 185 | 'last_date' => $ext && isset( $ext['last_date'] ) ? $ext['last_date'] : null, |
| 186 | 'by_day' => is_array( $by_day ) ? $by_day : [], |
| 187 | ]; |
| 188 | } |
| 189 | } |
| 190 |