197 lines
6.3 KiB
PHP
197 lines
6.3 KiB
PHP
<?php
|
|
namespace ElementorPro\Modules\Forms\Submissions\Actions;
|
|
|
|
use Elementor\Controls_Manager;
|
|
use Elementor\Core\Utils\Collection;
|
|
use ElementorPro\Plugin;
|
|
use ElementorPro\Modules\Forms\Widgets\Form;
|
|
use ElementorPro\Modules\Forms\Classes\Action_Base;
|
|
use ElementorPro\Modules\Forms\Submissions\Component;
|
|
use ElementorPro\Modules\Forms\Submissions\Database\Query;
|
|
use ElementorPro\Modules\Forms\Submissions\Database\Repositories\Form_Snapshot_Repository;
|
|
|
|
if ( ! defined( 'ABSPATH' ) ) {
|
|
exit; // Exit if accessed directly.
|
|
}
|
|
|
|
class Save_To_Database extends Action_Base {
|
|
private $submission_id;
|
|
|
|
private $actions_succeeded_count = 0;
|
|
|
|
public function get_name() {
|
|
return 'save-to-database';
|
|
}
|
|
|
|
public function get_label() {
|
|
return esc_html__( 'Collect Submissions', 'elementor-pro' );
|
|
}
|
|
|
|
public function register_settings_section( $widget ) {
|
|
$widget->start_controls_section(
|
|
'section_submissions',
|
|
[
|
|
'label' => esc_html__( 'Collect Submissions', 'elementor-pro' ),
|
|
'condition' => [
|
|
'submit_actions' => $this->get_name(),
|
|
],
|
|
]
|
|
);
|
|
|
|
$widget->add_control(
|
|
'submissions_action_message',
|
|
[
|
|
'type' => Controls_Manager::ALERT,
|
|
'alert_type' => 'info',
|
|
'content' => sprintf(
|
|
/* translators: 1: Link open tag, 2: Link open tag, 3: Link close tag. */
|
|
esc_html__( 'Collected Submissions will be saved to Elementor > %1$s Submissions %2$s', 'elementor-pro' ),
|
|
sprintf( '<a href="%s" target="_blank" rel="noreferrer">', self_admin_url( 'admin.php?page=' . Component::PAGE_ID ) ),
|
|
'</a>',
|
|
),
|
|
]
|
|
);
|
|
|
|
$widget->add_control(
|
|
'submissions_metadata',
|
|
[
|
|
'label' => esc_html__( 'Metadata', 'elementor-pro' ),
|
|
'type' => Controls_Manager::SELECT2,
|
|
'multiple' => true,
|
|
'options' => [
|
|
'remote_ip' => esc_html__( 'User IP', 'elementor-pro' ),
|
|
'user_agent' => esc_html__( 'User Agent', 'elementor-pro' ),
|
|
],
|
|
'render_type' => 'none',
|
|
'label_block' => true,
|
|
'default' => [ 'remote_ip', 'user_agent' ],
|
|
]
|
|
);
|
|
|
|
$widget->end_controls_section();
|
|
}
|
|
|
|
public function on_export( $element ) {
|
|
// This action does not have to do nothing on export.
|
|
}
|
|
|
|
/**
|
|
* @param \ElementorPro\Modules\Forms\Classes\Form_Record $record
|
|
* @param \ElementorPro\Modules\Forms\Classes\Ajax_Handler $ajax_handler
|
|
*/
|
|
public function run( $record, $ajax_handler ) {
|
|
$meta_keys = array_merge( [ 'page_url', 'page_title' ], $record->get_form_settings( 'submissions_metadata' ) );
|
|
$meta = $record->get_form_meta( $meta_keys );
|
|
|
|
$actions_count = ( new Collection( $record->get_form_settings( 'submit_actions' ) ) )
|
|
->filter(function ( $value ) {
|
|
return $value !== $this->get_name();
|
|
})
|
|
->count();
|
|
|
|
$post_id = $record->get_form_settings( 'form_post_id' );
|
|
$element_id = $ajax_handler->get_current_form()['id'];
|
|
$form_name = $record->get_form_settings( 'form_name' );
|
|
|
|
$this->submission_id = Query::get_instance()->add_submission( [
|
|
'main_meta_id' => 0,
|
|
'post_id' => $post_id,
|
|
'referer' => remove_query_arg(
|
|
[ 'preview_id', 'preview_nonce', 'preview' ],
|
|
$meta['page_url']['value']
|
|
),
|
|
'referer_title' => $meta['page_title']['value'],
|
|
'element_id' => $element_id,
|
|
'form_name' => $form_name,
|
|
'campaign_id' => 0,
|
|
'user_id' => get_current_user_id(),
|
|
'user_ip' => ! empty( $meta['remote_ip'] ) ? $meta['remote_ip']['value'] : '',
|
|
'user_agent' => ! empty( $meta['user_agent'] ) ? $meta['user_agent']['value'] : '',
|
|
'actions_count' => $actions_count,
|
|
'actions_succeeded_count' => 0,
|
|
'meta' => wp_json_encode( [
|
|
// TODO: Should be removed if there is an ability to edit "global widgets"
|
|
'edit_post_id' => $record->get_form_settings( 'edit_post_id' ),
|
|
] ),
|
|
], $record->get_field( null ) );
|
|
|
|
/** @var Form $form_instance */
|
|
$form_instance = Plugin::elementor()->elements_manager->create_element_instance( $ajax_handler->get_current_form() );
|
|
$fields = $record->get_form_settings( 'form_fields' );
|
|
|
|
// When created new submission, it should also update or create
|
|
// a form snapshot to save to new state of the form in case the form changed or will
|
|
// be deleted later.
|
|
Form_Snapshot_Repository::instance()
|
|
->create_or_update( $post_id, $element_id, [
|
|
'name' => $form_name,
|
|
'fields' => array_map( function ( $field, $index ) use ( $form_instance ) {
|
|
// Apply filters to demonstrate the same behavior as the render behavior. (adding select fields dynamically, etc.)
|
|
// Ref: modules/forms/widgets/form.php:2116
|
|
$field = apply_filters( 'elementor_pro/forms/render/item', $field, $index, $form_instance );
|
|
$field = apply_filters( "elementor_pro/forms/render/item/{$field['field_type']}", $field, $index, $form_instance );
|
|
|
|
$mapped_field = [
|
|
'id' => $field['custom_id'],
|
|
'type' => $field['field_type'],
|
|
'label' => $field['field_label'],
|
|
];
|
|
|
|
if ( isset( $field['field_options'] ) ) {
|
|
$mapped_field['options'] = preg_split( '/(\r\n|\n|\r)/', $field['field_options'] );
|
|
}
|
|
|
|
if ( isset( $field['allow_multiple'] ) ) {
|
|
$mapped_field['is_multiple'] = 'true' === $field['allow_multiple'];
|
|
}
|
|
|
|
return $mapped_field;
|
|
}, $fields, array_keys( $fields ) ),
|
|
] );
|
|
}
|
|
|
|
/**
|
|
* It listen for all the form actions and log the result into the database.
|
|
*
|
|
* @param Action_Base $action Should be class based on ActionBase (do not type hint to support third party plugins)
|
|
* @param \Exception|null $exception
|
|
*/
|
|
private function save_action_log( $action, \Exception $exception = null ) {
|
|
if ( ! $this->submission_id || $action->get_name() === $this->get_name() ) {
|
|
return;
|
|
}
|
|
|
|
$query = Query::get_instance();
|
|
$error_message = null;
|
|
|
|
if ( $exception ) {
|
|
$error_message = $exception->getMessage();
|
|
|
|
$status = Query::ACTIONS_LOG_STATUS_FAILED;
|
|
} else {
|
|
$this->actions_succeeded_count += 1;
|
|
|
|
$query->update_submission( $this->submission_id, [
|
|
'actions_succeeded_count' => $this->actions_succeeded_count,
|
|
] );
|
|
|
|
$status = Query::ACTIONS_LOG_STATUS_SUCCESS;
|
|
}
|
|
|
|
$query->add_action_log(
|
|
$this->submission_id,
|
|
$action,
|
|
$status,
|
|
$error_message
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Save_To_Database constructor.
|
|
*/
|
|
public function __construct() {
|
|
add_action( 'elementor_pro/forms/actions/after_run', function ( Action_Base $action, \Exception $exception = null ) {
|
|
$this->save_action_log( $action, $exception );
|
|
}, 10, 2 );
|
|
}
|
|
}
|