queueService = $queueService; $this->connectionRepository = $connectionRepository; $this->normalizer = new ElementorSubmissionNormalizer(); } /** * Get unique action identifier name. * * @return string */ public function get_name(): string { return 'oneclickformsync_google_sheets'; } /** * Get action label. * * @return string */ public function get_label(): string { return __('Google Sheets', '1-click-form-sync'); } /** * Register Elementor editor side-panel settings controls. * * @param \Elementor\Widget_Base $widget * @return void */ public function register_settings_section($widget): void { $widget->start_controls_section( 'section_oneclickformsync_google_sheets', [ 'label' => __('Google Sheets', '1-click-form-sync'), 'condition' => [ 'submit_actions' => $this->get_name(), ], ] ); $widget->add_control( 'oneclickformsync_connection_id', [ 'label' => __('Google Connection', '1-click-form-sync'), 'type' => \Elementor\Controls_Manager::SELECT, 'options' => $this->getConnectionOptions(), 'default' => '', ] ); $widget->add_control( 'oneclickformsync_spreadsheet_id', [ 'label' => __('Spreadsheet URL or ID', '1-click-form-sync'), 'type' => \Elementor\Controls_Manager::TEXT, 'placeholder' => 'https://docs.google.com/spreadsheets/d/.../edit', 'label_block' => true, ] ); $widget->add_control( 'oneclickformsync_worksheet_name', [ 'label' => __('Worksheet Name', '1-click-form-sync'), 'type' => \Elementor\Controls_Manager::TEXT, 'default' => 'Sheet1', ] ); $widget->add_control( 'oneclickformsync_create_headers', [ 'label' => __('Create Headers if Empty', '1-click-form-sync'), 'type' => \Elementor\Controls_Manager::SWITCHER, 'default' => 'yes', 'label_on' => __('Yes', '1-click-form-sync'), 'label_off' => __('No', '1-click-form-sync'), 'return_value' => 'yes', ] ); $widget->add_control( 'oneclickformsync_mapping_mode', [ 'label' => __('Mapping Mode', '1-click-form-sync'), 'type' => \Elementor\Controls_Manager::SELECT, 'options' => [ 'auto' => __('Automatic Mapping', '1-click-form-sync'), 'custom' => __('Custom Mapping', '1-click-form-sync'), ], 'default' => 'auto', ] ); // Repeater for custom field mapping rows. $repeater = new \Elementor\Repeater(); $repeater->add_control( 'sheet_column', [ 'label' => __('Sheet Column Header', '1-click-form-sync'), 'type' => \Elementor\Controls_Manager::TEXT, 'label_block' => true, ] ); $repeater->add_control( 'form_field', [ 'label' => __('Form Field ID', '1-click-form-sync'), 'type' => \Elementor\Controls_Manager::TEXT, 'description' => __('Enter the field ID exactly (e.g. name, email).', '1-click-form-sync'), ] ); $repeater->add_control( 'default_value', [ 'label' => __('Default / Static Value', '1-click-form-sync'), 'type' => \Elementor\Controls_Manager::TEXT, 'description' => __('Used if form field is empty. Supports tags like {submission_id}, {submission_date}, {page_url}.', '1-click-form-sync'), ] ); $repeater->add_control( 'formatting', [ 'label' => __('Formatting', '1-click-form-sync'), 'type' => \Elementor\Controls_Manager::SELECT, 'options' => [ 'raw' => __('No Formatting', '1-click-form-sync'), 'uppercase' => __('UPPERCASE', '1-click-form-sync'), 'lowercase' => __('lowercase', '1-click-form-sync'), ], 'default' => 'raw', ] ); $widget->add_control( 'oneclickformsync_custom_mapping', [ 'label' => __('Custom Field Mappings', '1-click-form-sync'), 'type' => \Elementor\Controls_Manager::REPEATER, 'fields' => $repeater->get_controls(), 'title_field' => '{{{ sheet_column }}} ← {{{ form_field || default_value }}}', 'condition' => [ 'oneclickformsync_mapping_mode' => 'custom', ], ] ); // Form Metadata config. $widget->add_control( 'oneclickformsync_meta_heading', [ 'label' => __('Include Metadata Columns (Auto Mode)', '1-click-form-sync'), 'type' => \Elementor\Controls_Manager::HEADING, 'separator' => 'before', 'condition' => [ 'oneclickformsync_mapping_mode' => 'auto', ], ] ); $metaFields = [ 'oneclickformsync_include_submission_id' => __('Submission ID', '1-click-form-sync'), 'oneclickformsync_include_submission_date' => __('Date', '1-click-form-sync'), 'oneclickformsync_include_submission_time' => __('Submission Time', '1-click-form-sync'), 'oneclickformsync_include_form_id' => __('Form ID', '1-click-form-sync'), 'oneclickformsync_include_form_name' => __('Form Name', '1-click-form-sync'), 'oneclickformsync_include_page_url' => __('Page URL', '1-click-form-sync'), 'oneclickformsync_include_utm_source' => __('UTM Source', '1-click-form-sync'), 'oneclickformsync_include_utm_medium' => __('UTM Medium', '1-click-form-sync'), 'oneclickformsync_include_utm_campaign' => __('UTM Campaign', '1-click-form-sync'), 'oneclickformsync_include_utm_term' => __('UTM Term', '1-click-form-sync'), 'oneclickformsync_include_utm_content' => __('UTM Content', '1-click-form-sync'), ]; foreach ($metaFields as $key => $label) { $widget->add_control( $key, [ 'label' => $label, 'type' => \Elementor\Controls_Manager::SWITCHER, 'default' => '', 'return_value' => 'yes', 'condition' => [ 'oneclickformsync_mapping_mode' => 'auto', ], ] ); } $widget->add_control( 'oneclickformsync_header_bg_color', [ 'label' => __('Header Background Color', '1-click-form-sync'), 'type' => \Elementor\Controls_Manager::COLOR, 'default' => '#2d3748', ] ); $widget->add_control( 'oneclickformsync_header_fg_color', [ 'label' => __('Header Text Color', '1-click-form-sync'), 'type' => \Elementor\Controls_Manager::COLOR, 'default' => '#ffffff', ] ); $widget->add_control( 'oneclickformsync_header_sticky', [ 'label' => __('Freeze Header Row (Sticky)', '1-click-form-sync'), 'type' => \Elementor\Controls_Manager::SWITCHER, 'default' => 'yes', 'label_on' => __('Yes', '1-click-form-sync'), 'label_off' => __('No', '1-click-form-sync'), 'return_value' => 'yes', ] ); $widget->add_control( 'oneclickformsync_custom_utm_params', [ 'label' => __('Custom Tracking Parameters', '1-click-form-sync'), 'type' => \Elementor\Controls_Manager::TEXT, 'placeholder' => 'gclid, fbclid, msclkid', 'description' => __('Enter a comma-separated list of additional query parameters to track.', '1-click-form-sync'), 'label_block' => true, ] ); $widget->end_controls_section(); } /** * Process the form submission. * * @param \ElementorPro\Modules\Forms\Classes\Form_Record $record * @param \ElementorPro\Modules\Forms\Classes\Ajax_Handler $ajax_handler * @return void */ public function run($record, $ajax_handler): void { $settings = $record->get('form_settings') ?: []; $connectionId = $settings['oneclickformsync_connection_id'] ?? ''; $spreadsheetId = $settings['oneclickformsync_spreadsheet_id'] ?? ''; $worksheetName = $settings['oneclickformsync_worksheet_name'] ?? 'Sheet1'; if (empty($connectionId) || empty($spreadsheetId) || empty($worksheetName)) { return; } $configSettings = [ 'connection_id' => $connectionId, 'spreadsheet_id' => $spreadsheetId, 'worksheet_name' => $worksheetName, 'mapping_mode' => $settings['oneclickformsync_mapping_mode'] ?? 'auto', 'custom_mapping' => $settings['oneclickformsync_custom_mapping'] ?? [], 'create_headers' => ($settings['oneclickformsync_create_headers'] ?? '') === 'yes', 'include_submission_id' => ($settings['oneclickformsync_include_submission_id'] ?? '') === 'yes', 'include_submission_date' => ($settings['oneclickformsync_include_submission_date'] ?? '') === 'yes', 'include_submission_time' => ($settings['oneclickformsync_include_submission_time'] ?? '') === 'yes', 'include_form_id' => ($settings['oneclickformsync_include_form_id'] ?? '') === 'yes', 'include_form_name' => ($settings['oneclickformsync_include_form_name'] ?? '') === 'yes', 'include_page_url' => ($settings['oneclickformsync_include_page_url'] ?? '') === 'yes', 'include_utm_source' => ($settings['oneclickformsync_include_utm_source'] ?? '') === 'yes', 'include_utm_medium' => ($settings['oneclickformsync_include_utm_medium'] ?? '') === 'yes', 'include_utm_campaign' => ($settings['oneclickformsync_include_utm_campaign'] ?? '') === 'yes', 'include_utm_term' => ($settings['oneclickformsync_include_utm_term'] ?? '') === 'yes', 'include_utm_content' => ($settings['oneclickformsync_include_utm_content'] ?? '') === 'yes', 'custom_utm_params' => $settings['oneclickformsync_custom_utm_params'] ?? '', 'header_bg_color' => $settings['oneclickformsync_header_bg_color'] ?? '', 'header_fg_color' => $settings['oneclickformsync_header_fg_color'] ?? '', 'header_sticky' => ($settings['oneclickformsync_header_sticky'] ?? '') === 'yes', ]; // 1. Normalize the submission data into DTO. $submission = $this->normalizer->normalize($record, $configSettings['custom_utm_params']); // Apply filters to allow external customization of the submission DTO. $submission = apply_filters('oneclickformsync_normalized_submission', $submission, $configSettings); // 2. Dispatch to reliability queue. $this->queueService->enqueue($submission, $configSettings); } /** * Get connections list helper. * * @return array */ private function getConnectionOptions(): array { $connections = $this->connectionRepository->findAll(); $options = [ '' => __('Select Connection...', '1-click-form-sync'), ]; foreach ($connections as $conn) { $options[$conn->getId()] = $conn->getName() . ' (' . $conn->getEmail() . ')'; } return $options; } /** * Elementor Pro Action_Base on_export requirement stub. */ public function on_export($element) { } }