get_charset_collate(); $forms_table = $wpdb->prefix . 'als_forms'; $submissions_table = $wpdb->prefix . 'als_form_submissions'; if (!function_exists('dbDelta')) { require_once(ABSPATH . 'wp-admin/includes/upgrade.php'); } $sql1 = "CREATE TABLE $forms_table ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, name VARCHAR(255) NOT NULL, fields LONGTEXT NOT NULL, form_json LONGTEXT NULL, layout VARCHAR(32) DEFAULT 'standard', design LONGTEXT NULL, custom_css LONGTEXT NULL, elegant_image VARCHAR(512) NULL, elegant_gradient VARCHAR(255) NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id) ) $charset_collate;"; $sql2 = "CREATE TABLE $submissions_table ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, form_id BIGINT UNSIGNED NOT NULL, submission_data LONGTEXT NOT NULL, submitted_at DATETIME DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id) ) $charset_collate;"; dbDelta($sql1); dbDelta($sql2); } function als_forms_deactivate() { global $wpdb; $forms_table = $wpdb->prefix . 'als_forms'; $submissions_table = $wpdb->prefix . 'als_form_submissions'; $wpdb->query("DROP TABLE IF EXISTS $forms_table"); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.DirectDatabaseQuery.SchemaChange -- Table name is not user input, safe for plugin lifecycle $wpdb->query("DROP TABLE IF EXISTS $submissions_table"); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.DirectDatabaseQuery.SchemaChange -- Table name is not user input, safe for plugin lifecycle } add_action('wp_ajax_als_forms_save_form', function () { check_ajax_referer('als_forms_nonce', 'nonce'); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce is verified here if (!current_user_can('manage_options')) { wp_send_json_error(['message' => 'Unauthorized'], 403); } global $wpdb; $table = $wpdb->prefix . 'als_forms'; $id = isset($_POST['id']) ? intval($_POST['id']) : 0; $name = isset($_POST['name']) ? sanitize_text_field(wp_unslash($_POST['name'])) : ''; $fields = isset($_POST['fields']) ? wp_unslash($_POST['fields']) : ''; $layout = isset($_POST['layout']) ? sanitize_text_field(wp_unslash($_POST['layout'])) : 'standard'; $form_json = isset($_POST['form_json']) ? wp_unslash($_POST['form_json']) : ''; $design = isset($_POST['design']) ? wp_unslash($_POST['design']) : ''; $elegant_image = isset($_POST['elegant_image']) ? esc_url_raw(wp_unslash($_POST['elegant_image'])) : ''; $elegant_gradient = isset($_POST['elegant_gradient']) ? sanitize_text_field(wp_unslash($_POST['elegant_gradient'])) : ''; $custom_css = isset($_POST['custom_css']) ? wp_strip_all_tags(wp_unslash($_POST['custom_css'])) : ''; if ($fields && is_string($fields)) { $fields_sanitized = sanitize_text_field($fields); $decoded_fields = json_decode($fields_sanitized, true); if (json_last_error() !== JSON_ERROR_NONE) { wp_send_json_error(['message' => 'Invalid fields JSON'], 400); } $fields = wp_json_encode(als_forms_sanitize_json_data($decoded_fields)); } if ($form_json && is_string($form_json)) { $form_json_sanitized = sanitize_text_field($form_json); $decoded_form_json = json_decode($form_json_sanitized, true); if (json_last_error() !== JSON_ERROR_NONE) { wp_send_json_error(['message' => 'Invalid form_json JSON'], 400); } $form_json = wp_json_encode(als_forms_sanitize_json_data($decoded_form_json)); } if ($design && is_string($design)) { $design_sanitized = sanitize_text_field($design); $decoded_design = json_decode($design_sanitized, true); if (json_last_error() !== JSON_ERROR_NONE) { wp_send_json_error(['message' => 'Invalid design JSON'], 400); } $design = wp_json_encode(als_forms_sanitize_json_data($decoded_design)); } if (!$name || !$fields) { wp_send_json_error(['message' => 'Missing data'], 400); } $data = [ 'name' => $name, 'fields' => $fields, 'layout' => $layout, 'design' => $design, 'form_json' => $form_json, 'custom_css' => $custom_css, 'elegant_image' => $elegant_image, 'elegant_gradient' => $elegant_gradient, 'updated_at' => current_time('mysql'), ]; if ($id) { $result = $wpdb->update($table, $data, ['id' => $id]); if ($wpdb->last_error) { wp_send_json_error(['message' => 'DB error: ' . $wpdb->last_error], 500); } if ($result === false) { wp_send_json_error(['message' => 'Update failed.'], 500); } } else { unset($data['updated_at']); $data['created_at'] = current_time('mysql'); $wpdb->insert($table, $data); if ($wpdb->last_error) { wp_send_json_error(['message' => 'DB error: ' . $wpdb->last_error], 500); } $id = $wpdb->insert_id; } wp_send_json_success(['id' => $id]); }); add_action('wp_ajax_als_forms_get_form', function () { check_ajax_referer('als_forms_nonce', 'nonce'); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce is verified here if (!current_user_can('manage_options')) { wp_send_json_error(['message' => 'Unauthorized'], 403); } $id = isset($_GET['id']) ? intval($_GET['id']) : 0; if (!$id) { wp_send_json_error(['message' => 'Missing ID'], 400); } global $wpdb; $table = $wpdb->prefix . 'als_forms'; $form = $wpdb->get_row($wpdb->prepare("SELECT * FROM $table WHERE id = %d", $id), ARRAY_A); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Table name is not user input, $id is parameterized if (!$form) { wp_send_json_error(['message' => 'Form not found'], 404); } if (isset($form['fields']) && is_string($form['fields'])) { $decoded_fields = json_decode($form['fields'], true); if (json_last_error() === JSON_ERROR_NONE) { $form['fields'] = $decoded_fields; } else { $form['fields'] = []; } } else { $form['fields'] = []; } if (isset($form['form_json']) && is_string($form['form_json'])) { $decoded_form_json = json_decode($form['form_json'], true); } wp_send_json_success($form); }); add_action('admin_enqueue_scripts', 'als_forms_admin_enqueue_scripts'); function als_forms_admin_enqueue_scripts($hook) { if (strpos($hook, 'als-forms') !== false) { wp_enqueue_style( 'als-forms-admin-main', plugin_dir_url(__FILE__) . 'assets/css/admin-main.css', array(), '1.0.0' ); wp_enqueue_script( 'als-forms-admin-main', plugin_dir_url(__FILE__) . 'assets/js/admin-main.js', array('jquery'), '1.0.0', true ); wp_localize_script('als-forms-admin-main', 'ALS_FORMS_BUILDER', array( 'ajaxUrl' => esc_url(admin_url('admin-ajax.php')), 'nonce' => esc_js(wp_create_nonce('als_forms_nonce')), 'cssUrl' => esc_url(plugin_dir_url(__FILE__) . 'assets/css/als-forms-layout-standard.css') )); $is_form_builder_page = ( strpos($hook, 'als-forms-add-new') !== false || strpos($hook, 'als-forms_page_als-forms-add-new') !== false || (isset($_GET['page']) && ($_GET['page'] === 'als-forms-add-new' || $_GET['page'] === 'als-forms-new')) || (isset($_GET['edit']) && is_numeric($_GET['edit'])) ); if ($is_form_builder_page) { wp_enqueue_script('jquery'); wp_enqueue_script('underscore'); wp_enqueue_script('backbone'); wp_enqueue_script('media-models'); wp_enqueue_script('media-views'); wp_enqueue_script('media-editor'); wp_enqueue_media(); wp_enqueue_script( 'als-forms-admin-app-vue', plugins_url('/assets/js/admin-new-form.js', __FILE__), ['jquery', 'backbone', 'underscore', 'media-editor', 'media-views', 'media-models'], '1.0.0', true ); wp_localize_script('als-forms-admin-app-vue', 'ALS_FORMS_BUILDER', array( 'ajaxUrl' => esc_url(admin_url('admin-ajax.php')), 'nonce' => esc_js(wp_create_nonce('als_forms_nonce')), 'cssUrl' => esc_url(plugin_dir_url(__FILE__) . 'assets/css/als-forms-layout-standard.css') )); wp_add_inline_script('als-forms-admin-app-vue', 'console.log("ALS Forms Debug: Vue script loaded");'); wp_add_inline_script('als-forms-admin-app-vue', 'console.log("WordPress Media Library status:", { wp: window.wp ? "available" : "missing", media: window.wp && window.wp.media ? "available" : "missing", view: window.wp && window.wp.media && window.wp.media.view ? "available" : "missing" });'); wp_enqueue_style( 'als-forms-admin-style', plugin_dir_url(__FILE__) . 'assets/css/admin-new-form.css', [], '1.0' ); } } $plugin_assets_url = esc_url(plugin_dir_url(__FILE__) . 'dist/'); $inline_css = " @font-face { font-family: 'Font Awesome 6 Brands'; font-style: normal; font-weight: 400; font-display: block; src: url('{$plugin_assets_url}assets/fonts/fa-brands-400.woff2') format('woff2'), url('{$plugin_assets_url}assets/fonts/fa-brands-400.ttf') format('truetype'); } "; wp_add_inline_style('als-forms-admin-style', esc_html($inline_css)); } add_action('wp_enqueue_scripts', function () { wp_enqueue_style( 'als-forms-frontend', plugins_url('assets/css/frontend.css', __FILE__), [], '1.0' ); wp_enqueue_script( 'als-forms-frontend', plugins_url('assets/js/frontend.js', __FILE__), [], '1.0', true ); wp_enqueue_style( 'als-forms-frontend-standard', plugins_url('assets/css/als-forms-layout-standard.css', __FILE__), [], '1.0' ); }); if ( ! function_exists( 'als_forms_fs' ) ) { function als_forms_fs() { global $als_forms_fs; if ( ! isset( $als_forms_fs ) ) { require_once dirname( __FILE__ ) . '/vendor/freemius/start.php'; $als_forms_fs = fs_dynamic_init( array( 'id' => '19461', 'slug' => 'als-forms', 'type' => 'plugin', 'public_key' => 'pk_a59b4f9a5568b9b7ae6fee286f307', 'is_premium' => false, 'premium_suffix' => 'Professional', 'has_premium_version' => true, 'has_addons' => false, 'has_paid_plans' => true, 'is_org_compliant' => true, 'menu' => array( 'slug' => 'als-forms', 'contact' => false, 'support' => false, ), ) ); } return $als_forms_fs; } als_forms_fs(); do_action( 'als_forms_fs_loaded' ); } /** * Recursively sanitize JSON data to prevent XSS attacks * * @param mixed $data The data to sanitize * @return mixed The sanitized data */ function als_forms_sanitize_json_data($data) { if (is_array($data)) { return array_map('als_forms_sanitize_json_data', $data); } elseif (is_object($data)) { return (object) array_map('als_forms_sanitize_json_data', (array) $data); } elseif (is_string($data)) { if (preg_match('/^<[^>]+>/', $data)) { return wp_kses_post($data); } else { return sanitize_text_field($data); } } elseif (is_numeric($data)) { return $data; } elseif (is_bool($data)) { return $data; } else { return sanitize_text_field($data); } }