Reputation: 53
Each form submission in Elementor gets assinged a unique ID that gets iterated by one for each new submission. I want to reference this ID in the Actions after submit - E-Mail as a way of letting the user know the ID of their request. Is there any way of including this ID as a shortcode in the email that gets sent to the user, to create some sort of ticketing system?
I tried to add the following but it didn't work: [field id="submission_id"]
I also read [these]https://elementor.com/help/customizing-form-emails/) Elementor Docs, but they are not very helpful with what I'm trying to achieve.
I think that this requries some custom coding, but I'm unsure where to start.
Upvotes: 1
Views: 1902
Reputation: 550
Thanks to @oscar's response, but trying to avoid hacking the plugin (upgrading will get complicated) I built the code below. Basically the idea is to have a hidden field in the form with a unique id, then I retrieve that and I store in a static array the submission value, obtained in after_run
where that value is available. Then you can use get_submission_id with the hidden field value as parameter. This is to avoid possible conflicts, else you can store directly in a static variable. Reflection is necessary because submission_id is not even public..
class Elementor
{
private static $submissions = [];
/**
* Store the submission ID in the static submissions array
*/
public static function store_submission_id($key, $id)
{
if ($key && $id) {
self::$submissions[$key] = $id;
}
}
/**
* Retrieve a stored submission ID
*/
public static function get_submission_id($key)
{
return self::$submissions[$key] ?? null;
}
/**
* After run hook to capture the submission ID.
* hook: elementor_pro/forms/actions/after_run
*/
public function after_run($action, $exception = null)
{
if ($action instanceof \ElementorPro\Modules\Forms\Submissions\Actions\Save_To_Database && !$exception) {
$reflection = new \ReflectionClass($action);
if ($reflection->hasProperty('submission_id')) {
$property = $reflection->getProperty('submission_id');
$property->setAccessible(true);
$submission_id = $property->getValue($action);
if ($submission_id) {
// record not available here
$form_fields = $_POST['form_fields'] ?? [];
$unique_form_key = $form_fields['unique_form_key'] ?? null;
if ($unique_form_key) {
self::store_submission_id($unique_form_key, $submission_id);
Main::log("Stored Submission ID: {$submission_id} with key: {$unique_form_key}");
} else {
Main::log("Unique form key not found in POST data.");
}
} else {
Main::log("Submission ID not found in Save_To_Database.");
}
}
}
}
}
Upvotes: 0
Reputation: 129
A more structured way (wordpress way) of doing the web hook basing on @oscar's amazing answer, would be to utilize a plug that can help manage web hooks such as Bit Integrations.
First a modification need to be done to the following path as @oscar mentioned.
plugins/elementor-pro/modules/forms/submissions/actions/save-to-database.php
the modification is by simply adding the following line
$record->set('submission_id', $this->submission_id);
exactly after
$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' => $meta['remote_ip']['value'],
'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 ) );
now instead of calling the hook customly through function.php n the theme which could risk in breaking the theme if was edited incorrectly. We shall use the bit integration plugin. After installing the plugin, we go to the plugin code files to allow it to read the added piece of data which is the submission id.
First we go to this file
plugins/bit-integrations/includes/Triggers/Elementor/t ElementorHelper.php
we modify the following functions :
public static function extractRecordData($record)
{
return [
'id' => $record->get_form_settings('id'),
'form_post_id' => $record->get_form_settings('form_post_id'),
'edit_post_id' => $record->get_form_settings('edit_post_id'),
'submission_id' => $record->get('submission_id'),
'fields' => $record->get('fields'),
'files' => $record->get('files'),
];
}
and scroll down a bit to modify the second function that handles the retrieved data and passes it to the UI to be seen by the user while setting up the hook in bit integrations plugin.
public static function setFields($formData)
{
$allFields = [
['name' => 'id', 'type' => 'text', 'label' => wp_sprintf(__('Form Id (%s)', 'bit-integrations'), $formData['id']), 'value' => $formData['id']],
['name' => 'form_post_id', 'type' => 'text', 'label' => wp_sprintf(__('Form Post Id (%s)', 'bit-integrations'), $formData['form_post_id']), 'value' => $formData['form_post_id']],
['name' => 'edit_post_id', 'type' => 'text', 'label' => wp_sprintf(__('Edit Post Id (%s)', 'bit-integrations'), $formData['edit_post_id']), 'value' => $formData['edit_post_id']],
['name' => 'submission_id', 'type' => 'text', 'label' => wp_sprintf(__('Submission Id (%s)', 'bit-integrations'), $formData['submission_id']), 'value' => $formData['submission_id']],
];
//... rest of the code
To understand where those functions are called we can check the controller PHP file as follows:
plugins/bit-integrations/includes/Triggers/Elementor/t ElementorController.php
public static function handle_elementor_submit($record)
{
$recordData = ElementorHelper::extractRecordData($record);
$formData = ElementorHelper::setFields($recordData);
$reOrganizeId = $recordData['id'] . $recordData['form_post_id'];
if (get_option('btcbi_elementor_test') !== false) {
update_option('btcbi_elementor_test', [
'formData' => $formData,
'primaryKey' => [(object) ['key' => 'id', 'value' => $recordData['id']]]
]);
}
$flows = ElementorHelper::fetchFlows($recordData['id'], $reOrganizeId);
if (!$flows) {
return;
}
foreach ($flows as $flow) {
$flowDetails = static::parseFlowDetails($flow->flow_details);
if (!isset($flowDetails->primaryKey) && ($flow->triggered_entity_id == $recordData['id'] || $flow->triggered_entity_id == $reOrganizeId)) {
$data = ElementorHelper::prepareDataForFlow($record);
Flow::execute('Elementor', $flow->triggered_entity_id, $data, [$flow]);
continue;
}
if (\is_array($flowDetails->primaryKey) && ElementorHelper::isPrimaryKeysMatch($recordData, $flowDetails)) {
$data = array_column($formData, 'value', 'name');
Flow::execute('Elementor', $flow->triggered_entity_id, $data, [$flow]);
}
}
return ['type' => 'success'];
}
voilla, works like a charm.
special thanks to @oscar for his insight and ope it saved someone's time.
Upvotes: 0
Reputation: 11
as I had the same problem with retrieving the submission ID I found a workaround. It's not simple, but depending on your needs this may be sufficient.
You can create a new Action after submitting the form just like explained on this Elementor Page. There you make a query for the last Submission, which is basically the submission that has just been created.
If you then want to use the submission ID in a mail, you can use the wp_mail function to send the mail with the ID. Here is an example:
public function run( $record, $ajax_handler ) {
global $wpdb;
$table_name = $wpdb->prefix . 'e_submissions_values';
$ID = $wpdb->get_var($wpdb->prepare("SELECT submission_id FROM $table_name ORDER BY submission_id DESC",));
wp_mail('[email protected]', 'Your Submission: ' . $ID, 'Example Message', 'headers');
return;
}
I didn't try this exact function out, but I got the correct submission ID by using the query.
Upvotes: 1
Reputation: 153
Another method is to obtain the information directly from Elementor itself, if you are comfortable with hacking the plugin core code; adding one line in plugins/elementor-pro/modules/forms/submissions/actions/save-to-database.php
In a nutshell; the hack feeds the submission id back to elementor's $record
object right after the form is saved into the submissions table; during which the id is produced.
class Save_To_Database extends Action_Base {
private $submission_id;
...
public function run( $record, $ajax_handler ) {
...
$this->submission_id = Query::get_instance()->add_submission( [
...
], $record->get_field( null ) );
// following line does the magic
$record->set('submission_id', $this->submission_id);
...
}
...
}
Now, the submission id can be consumed in an Elementor hook with $record->get('submission_id')
- provided the hook is executed after Save_To_Database action; i.e. in elementor_pro/forms/new_record
hook.
Do note that, the hack will probably not survive an Elementor Pro update!
Upvotes: 3
Reputation: 53
I found an easy solution for this. I created a short code, that queries the DB table where the submission IDs are stored, extracts the highest value, adds one and returns the value. I then use this short code in the email template that gets sent to the user, and it displays the corresponding submission ID in the E-Mail.
Here is the shortcode:
// Register a function to run on the init hook
add_action( 'init', 'register_get_submission_id_shortcode' );
function register_get_submission_id_shortcode() {
// Register the get submission id shortcode
add_shortcode( 'get_submission_id', 'get_submission_id' );
}
function get_submission_id() {
global $wpdb;
// Get the highest value from the database table
$sql = "SELECT MAX(ID) as max_id FROM `hleKsJ9_e_submissions`;";
$result = $wpdb->get_var( $sql );
// Add 1 to the highest value and return it
if ( $result ) {
return $result;
} else {
return 'No results found';
}
}
Upvotes: 3