904 lines
23 KiB
PHP
904 lines
23 KiB
PHP
<?php
|
|
namespace ElementorPro\Modules\Forms\Submissions\Database;
|
|
|
|
use Elementor\Core\Base\Base_Object;
|
|
use ElementorPro\Plugin;
|
|
use Elementor\Core\Utils\Collection;
|
|
use Exception;
|
|
use ElementorPro\Modules\Forms\Classes\Action_Base;
|
|
use ElementorPro\Modules\Forms\Submissions\Database\Repositories\Form_Snapshot_Repository;
|
|
|
|
class Query extends Base_Object {
|
|
const STATUS_NEW = 'new';
|
|
const STATUS_TRASH = 'trash';
|
|
|
|
const ACTIONS_LOG_STATUS_SUCCESS = 'success';
|
|
const ACTIONS_LOG_STATUS_FAILED = 'failed';
|
|
|
|
const TYPE_SUBMISSION = 'submission';
|
|
|
|
/**
|
|
* @var Query
|
|
*/
|
|
private static $instance = null;
|
|
|
|
const E_SUBMISSIONS_ACTIONS_LOG = 'e_submissions_actions_log';
|
|
const E_SUBMISSIONS_VALUES = 'e_submissions_values';
|
|
const E_SUBMISSIONS = 'e_submissions';
|
|
|
|
/**
|
|
* @var \wpdb
|
|
*/
|
|
private $wpdb;
|
|
|
|
/**
|
|
* @var string
|
|
*/
|
|
private $table_submissions;
|
|
|
|
/**
|
|
* @var string
|
|
*/
|
|
private $table_submissions_values;
|
|
|
|
/**
|
|
* @var string
|
|
*/
|
|
private $table_submissions_actions_log;
|
|
|
|
public static function get_instance() {
|
|
if ( ! self::$instance ) {
|
|
self::$instance = new Query();
|
|
}
|
|
|
|
return self::$instance;
|
|
}
|
|
|
|
public function get_submissions( $args = [] ) {
|
|
$args = wp_parse_args( $args, [
|
|
'page' => 1,
|
|
'per_page' => 10,
|
|
'filters' => [],
|
|
'order' => [],
|
|
'with_meta' => false,
|
|
'with_form_fields' => false,
|
|
] );
|
|
|
|
$page = $args['page'];
|
|
$per_page = $args['per_page'];
|
|
$filters = $args['filters'];
|
|
$order = $args['order'];
|
|
$with_meta = $args['with_meta'];
|
|
$with_form_fields = $args['with_form_fields'];
|
|
|
|
$result = [
|
|
'data' => [],
|
|
'meta' => [],
|
|
];
|
|
|
|
$where_sql = $this->apply_filter( $filters );
|
|
$order_sql = '';
|
|
|
|
$total = (int) $this->wpdb->get_var("SELECT COUNT(*) FROM `{$this->get_table_submissions()}` t_submissions {$where_sql}" );// phpcs:ignore
|
|
|
|
$last_page = 0 < $total && 0 < $per_page ? (int) ceil( $total / $per_page ) : 1;
|
|
|
|
if ( $page > $last_page ) {
|
|
$page = $last_page;
|
|
}
|
|
|
|
$offset = (int) ceil( ( $page - 1 ) * $per_page );
|
|
|
|
$result['meta']['pagination'] = [
|
|
'current_page' => $page,
|
|
'per_page' => $per_page,
|
|
'total' => $total,
|
|
'last_page' => $last_page,
|
|
];
|
|
|
|
$this->handle_order( $order, $order_sql );
|
|
|
|
$per_page = (int) $per_page;
|
|
|
|
$q = "SELECT t_submissions.* FROM `{$this->get_table_submissions()}` t_submissions {$where_sql} {$order_sql} LIMIT {$per_page} OFFSET {$offset}";
|
|
|
|
$submissions = $this->wpdb->get_results( $q );// phpcs:ignore
|
|
|
|
$data = new Collection( [] );
|
|
|
|
foreach ( $submissions as $current_submission ) {
|
|
$data[] = $this->get_submission_body( $current_submission, $with_form_fields );
|
|
}
|
|
|
|
$submissions_meta = $this
|
|
->get_submissions_meta( $data, ! $with_meta )
|
|
->group_by( 'submission_id' );
|
|
|
|
$result['data'] = $data
|
|
->map( function ( $submission ) use ( $submissions_meta ) {
|
|
$current_submission_meta = $submissions_meta->get( $submission['id'], [] );
|
|
|
|
foreach ( $current_submission_meta as $meta ) {
|
|
$extract_meta = $this->extract( $meta, [ 'id', 'key', 'value' ], [ 'id:int' ] );
|
|
|
|
if ( $meta->id === $submission['main_meta_id'] ) {
|
|
$submission['main'] = $extract_meta;
|
|
}
|
|
|
|
$submission['values'][] = $extract_meta;
|
|
}
|
|
|
|
return $submission;
|
|
} )
|
|
->all();
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Get count by status.
|
|
*
|
|
* @param $filter
|
|
*
|
|
* @return Collection
|
|
*/
|
|
public function count_submissions_by_status( $filter = [] ) {
|
|
// Should not filter by status.
|
|
unset( $filter['status'] );
|
|
|
|
$where_sql = $this->apply_filter( $filter );
|
|
|
|
$trash_status = '"' . static::STATUS_TRASH . '"';
|
|
|
|
$sql = "
|
|
SELECT
|
|
SUM(IF(`status` != {$trash_status}, 1, 0)) AS `all`,
|
|
SUM(IF(`status` = {$trash_status}, 1, 0)) AS `trash`,
|
|
SUM(IF(is_read = 1 AND `status` != {$trash_status}, 1, 0)) AS `read`,
|
|
SUM(IF(is_read = 0 AND `status` != {$trash_status}, 1, 0)) AS `unread`
|
|
FROM {$this->get_table_submissions()} AS `t_submissions` {$where_sql};
|
|
";
|
|
|
|
$sql_result = $this->wpdb->get_row( $sql, ARRAY_A ); // phpcs:ignore
|
|
|
|
$result = new Collection( [
|
|
'all' => 0,
|
|
'trash' => 0,
|
|
'read' => 0,
|
|
'unread' => 0,
|
|
] );
|
|
|
|
if ( ! $sql_result ) {
|
|
return $result;
|
|
}
|
|
|
|
return $result->map( function ( $count, $key ) use ( $sql_result ) {
|
|
if ( ! isset( $sql_result[ $key ] ) ) {
|
|
return $count;
|
|
}
|
|
|
|
return intval( $sql_result[ $key ] );
|
|
} );
|
|
}
|
|
|
|
public function get_submissions_by_email( $email, $include_submission_values = false ) {
|
|
$user = get_user_by( 'email', $email );
|
|
$user_filter = '';
|
|
|
|
if ( $user ) {
|
|
$user_filter = $this->wpdb->prepare( 't_submissions.user_id = %s OR', $user->ID );
|
|
}
|
|
|
|
$query = "
|
|
SELECT DISTINCT(t_submissions.id), t_submissions.*
|
|
FROM `{$this->get_table_submissions()}` t_submissions
|
|
INNER JOIN {$this->get_table_submissions_values()} t_submissions_meta
|
|
ON t_submissions.id = t_submissions_meta.submission_id
|
|
WHERE
|
|
{$user_filter}
|
|
t_submissions_meta.value = %s
|
|
;
|
|
";
|
|
|
|
$data = $this->wpdb->get_results(
|
|
$this->wpdb->prepare( $query, $email ) // phpcs:ignore
|
|
);
|
|
|
|
if ( ! $data ) {
|
|
return new Collection( [] );
|
|
}
|
|
|
|
$data = new Collection( $data );
|
|
|
|
if ( $include_submission_values ) {
|
|
$submissions_meta = $this->get_submissions_meta( $data )
|
|
->group_by( 'submission_id' );
|
|
|
|
$data->map( function ( $submission ) use ( $submissions_meta ) {
|
|
$submission->values = $submissions_meta->get( $submission->id, [] );
|
|
|
|
return $submission;
|
|
} );
|
|
}
|
|
|
|
return $data;
|
|
}
|
|
|
|
/**
|
|
* @param int $delete_timestamp
|
|
*
|
|
* @return array
|
|
*/
|
|
public function get_trashed_submission_ids_to_delete( $delete_timestamp ) {
|
|
$date = gmdate( 'Y-m-d H:i:s', $delete_timestamp );
|
|
|
|
$sql = "
|
|
SELECT s.id FROM `{$this->get_table_submissions()}` s
|
|
WHERE s.status = %s AND s.updated_at_gmt < %s;
|
|
";
|
|
|
|
return $this->wpdb->get_col(
|
|
$this->wpdb->prepare( $sql, static::STATUS_TRASH, $date ) // phpcs:ignore
|
|
);
|
|
}
|
|
|
|
public function get_submission( $id ) {
|
|
$result = [
|
|
'data' => [],
|
|
'meta' => [],
|
|
];
|
|
|
|
$q = "SELECT * FROM `{$this->get_table_submissions()}` WHERE id=%d";
|
|
$submission = $this->wpdb->get_row( $this->wpdb->prepare( $q, [ $id ] ) );// phpcs:ignore
|
|
|
|
if ( ! $submission ) {
|
|
return null;
|
|
}
|
|
|
|
$result['data'] = $this->get_submission_body( $submission, true );
|
|
|
|
$current_submission_meta = $this->get_submissions_meta( $submission, false )->all();
|
|
|
|
foreach ( $current_submission_meta as $meta ) {
|
|
$extract_meta = $this->extract( $meta, [ 'id', 'key', 'value' ], [ 'id:int' ] );
|
|
|
|
if ( $meta->id === $result['data']['main_meta_id'] ) {
|
|
$result['data']['main'] = $extract_meta;
|
|
}
|
|
|
|
$result['data']['values'][] = $extract_meta;
|
|
}
|
|
|
|
$result['data']['form_actions_log'] = ( new Collection( $this->get_submissions_actions_log( $id ) ) )
|
|
->map( function ( $value ) {
|
|
return $this->extract(
|
|
$value,
|
|
[ 'id', 'action_name', 'action_label', 'status', 'log', 'created_at', 'updated_at' ],
|
|
[ 'id:int', 'name', 'label' ]
|
|
);
|
|
} )
|
|
->all();
|
|
|
|
return $result;
|
|
}
|
|
|
|
public function get_referrers( $search = '', $value = '' ) {
|
|
$where = '';
|
|
|
|
if ( $search ) {
|
|
$search = '%' . $this->wpdb->esc_like( $search ) . '%';
|
|
|
|
$where = $this->wpdb->prepare( ' AND s.referer_title LIKE %s', $search );
|
|
}
|
|
|
|
if ( $value ) {
|
|
$where = $this->wpdb->prepare( ' AND s.referer = %s', $value ); // phpcs:ignore
|
|
}
|
|
|
|
$where = 'WHERE 1=1' . $where;
|
|
|
|
$query = "
|
|
SELECT DISTINCT (s.referer), s.referer_title
|
|
FROM {$this->get_table_submissions()} s
|
|
{$where};
|
|
";
|
|
|
|
$result = $this->wpdb->get_results( $query, ARRAY_A ); // phpcs:ignore
|
|
|
|
if ( ! $result ) {
|
|
return new Collection( [] );
|
|
}
|
|
|
|
return new Collection( $result );
|
|
}
|
|
|
|
/**
|
|
* @param $submissions
|
|
* @param false $only_main
|
|
*
|
|
* @return Collection
|
|
*/
|
|
public function get_submissions_meta( $submissions, $only_main = false ) {
|
|
if ( ! ( $submissions instanceof Collection ) ) {
|
|
$submissions = new Collection(
|
|
is_array( $submissions ) ? $submissions : [ $submissions ]
|
|
);
|
|
}
|
|
|
|
if ( $submissions->is_empty() ) {
|
|
return new Collection( [] );
|
|
}
|
|
|
|
if ( $only_main ) {
|
|
$column = 'id';
|
|
$ids = $submissions->pluck( 'main_meta_id' );
|
|
} else {
|
|
$column = 'submission_id';
|
|
$ids = $submissions->pluck( 'id' );
|
|
}
|
|
|
|
$placeholders = $ids->map( function () {
|
|
return '%d';
|
|
} )->implode( ',' );
|
|
|
|
$q = "SELECT * FROM `{$this->get_table_submissions_values()}` WHERE `{$column}` IN ({$placeholders})";
|
|
|
|
$result = $this->wpdb->get_results( $this->wpdb->prepare( $q, $ids->all() ) ); // phpcs:ignore
|
|
|
|
if ( ! $result ) {
|
|
return new Collection( [] );
|
|
}
|
|
|
|
return new Collection( $result );
|
|
}
|
|
|
|
/**
|
|
* @param $post_id
|
|
* @param $element_id
|
|
*
|
|
* @return Collection
|
|
*/
|
|
public function get_submissions_value_keys( $post_id, $element_id ) {
|
|
$sql = "
|
|
SELECT DISTINCT(wesv.`key`)
|
|
FROM {$this->get_table_submissions_values()} wesv
|
|
INNER JOIN {$this->get_table_submissions()} wes
|
|
ON wes.id = wesv.submission_id
|
|
WHERE wes.post_id = %s AND wes.element_id = %s;
|
|
";
|
|
|
|
$result = $this->wpdb->get_col( $this->wpdb->prepare( $sql, $post_id, $element_id ) ); // phpcs:ignore
|
|
|
|
$form = Form_Snapshot_Repository::instance()->find( $post_id, $element_id );
|
|
if ( $form ) {
|
|
$ordered_keys = array_map( function( $field ) {
|
|
return $field['id'];
|
|
}, $form->fields );
|
|
|
|
$result = array_merge( array_intersect( $ordered_keys, $result ), array_diff( $result, $ordered_keys ) );
|
|
}
|
|
|
|
if ( ! $result ) {
|
|
return new Collection( [] );
|
|
}
|
|
|
|
return new Collection( $result );
|
|
}
|
|
|
|
/**
|
|
* @param $submission_id
|
|
*
|
|
* @return array|null
|
|
*/
|
|
public function get_submissions_actions_log( $submission_id ) {
|
|
$query = "SELECT * FROM `{$this->get_table_form_actions_log()}` WHERE `submission_id` = %d;";
|
|
|
|
return $this->wpdb->get_results(
|
|
$this->wpdb->prepare( $query, (int) $submission_id ), // phpcs:ignore
|
|
ARRAY_A
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Add submission.
|
|
*
|
|
* @param array $submission_data
|
|
* @param array $fields_data
|
|
*
|
|
* @return int id or 0
|
|
*/
|
|
public function add_submission( array $submission_data, array $fields_data ) {
|
|
global $wpdb;
|
|
|
|
$result = 0;
|
|
|
|
$submission_data = $this->get_new_submission_initial_data( $submission_data );
|
|
|
|
try {
|
|
$wpdb->query( 'START TRANSACTION' );
|
|
|
|
$submission_success = $wpdb->insert( $this->get_table_submissions(), $submission_data );
|
|
|
|
if ( ! $submission_success ) {
|
|
throw new Exception( $wpdb->last_error );
|
|
}
|
|
|
|
$submission_id = $wpdb->insert_id;
|
|
|
|
// Meta's keys/values.
|
|
$main_meta_id = 0;
|
|
$first_submissions_meta_id = 0;
|
|
foreach ( $fields_data as $field ) {
|
|
$wpdb->insert( $this->get_table_submissions_values(), [
|
|
'submission_id' => $submission_id,
|
|
'key' => $field['id'],
|
|
'value' => $field['value'],
|
|
] );
|
|
|
|
if ( ! $first_submissions_meta_id ) {
|
|
$first_submissions_meta_id = $wpdb->insert_id;
|
|
}
|
|
|
|
if ( 0 === $main_meta_id && 'email' === $field['type'] ) {
|
|
$main_meta_id = $wpdb->insert_id;
|
|
}
|
|
}
|
|
|
|
// If `$main_meta_id` not determined.
|
|
if ( ! $main_meta_id ) {
|
|
$main_meta_id = $first_submissions_meta_id;
|
|
}
|
|
|
|
// Update main_meta_id.
|
|
$wpdb->update( $this->get_table_submissions(),
|
|
[
|
|
'main_meta_id' => $main_meta_id,
|
|
],
|
|
[
|
|
'id' => $submission_id,
|
|
]
|
|
);
|
|
|
|
$wpdb->query( 'COMMIT' );
|
|
|
|
$result = $submission_id;
|
|
} catch ( Exception $e ) {
|
|
$wpdb->query( 'ROLLBACK' );
|
|
|
|
Plugin::elementor()->logger->get_logger()->error( 'Save submission failed, db error: ' . $e->getMessage() );
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* @param $submission_id
|
|
* @param array $data
|
|
* @param array $values
|
|
*
|
|
* @return bool|int affected rows
|
|
*/
|
|
public function update_submission( $submission_id, array $data, $values = [] ) {
|
|
if ( $values ) {
|
|
foreach ( $values as $key => $value ) {
|
|
$this->wpdb->update(
|
|
$this->get_table_submissions_values(),
|
|
[ 'value' => $value ],
|
|
[
|
|
'submission_id' => $submission_id,
|
|
'key' => $key,
|
|
]
|
|
);
|
|
}
|
|
}
|
|
|
|
$data['updated_at_gmt'] = current_time( 'mysql', true );
|
|
$data['updated_at'] = get_date_from_gmt( $data['updated_at_gmt'] );
|
|
|
|
return $this->wpdb->update(
|
|
$this->get_table_submissions(),
|
|
$data,
|
|
[ 'id' => $submission_id ]
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Move single submission to trash
|
|
*
|
|
* @param $id
|
|
*
|
|
* @return bool|int number of affected rows or false if failed
|
|
*/
|
|
public function move_to_trash_submission( $id ) {
|
|
return $this->update_submission(
|
|
$id,
|
|
[ 'status' => static::STATUS_TRASH ]
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Delete a single submission.
|
|
*
|
|
* @param $id
|
|
*
|
|
* @return bool|int number of affected rows or false if failed
|
|
*/
|
|
public function delete_submission( $id ) {
|
|
$this->wpdb->delete(
|
|
$this->get_table_submissions_values(),
|
|
[ 'submission_id' => $id ]
|
|
);
|
|
|
|
$this->wpdb->delete(
|
|
$this->get_table_form_actions_log(),
|
|
[ 'submission_id' => $id ]
|
|
);
|
|
|
|
return $this->wpdb->delete(
|
|
$this->get_table_submissions(),
|
|
[ 'id' => $id ]
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Restore a single submission.
|
|
*
|
|
* @param $id
|
|
*
|
|
* @return bool|int number of affected rows or false if failed
|
|
*/
|
|
public function restore( $id ) {
|
|
return $this->wpdb->update(
|
|
$this->get_table_submissions(),
|
|
[ 'status' => self::STATUS_NEW ],
|
|
[ 'id' => $id ]
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @param $submission_id
|
|
* @param Action_Base $action Should be class based on ActionBase (do not type hint to support third party plugins)
|
|
* @param $status
|
|
* @param null $log_message
|
|
*
|
|
* @return bool|int
|
|
*/
|
|
public function add_action_log( $submission_id, $action, $status, $log_message = null ) {
|
|
$current_datetime_gmt = current_time( 'mysql', true );
|
|
$current_datetime = get_date_from_gmt( $current_datetime_gmt );
|
|
|
|
return $this->wpdb->insert(
|
|
$this->get_table_form_actions_log(),
|
|
[
|
|
'submission_id' => $submission_id,
|
|
'action_name' => $action->get_name(),
|
|
'action_label' => $action->get_label(),
|
|
'status' => $status,
|
|
'log' => $log_message,
|
|
'created_at_gmt' => $current_datetime_gmt,
|
|
'updated_at_gmt' => $current_datetime_gmt,
|
|
'created_at' => $current_datetime,
|
|
'updated_at' => $current_datetime,
|
|
]
|
|
);
|
|
}
|
|
|
|
public function get_last_error() {
|
|
$this->wpdb->last_error;
|
|
}
|
|
|
|
public function get_table_submissions() {
|
|
return $this->table_submissions;
|
|
}
|
|
|
|
public function get_table_submissions_values() {
|
|
return $this->table_submissions_values;
|
|
}
|
|
|
|
public function get_table_form_actions_log() {
|
|
return $this->table_submissions_actions_log;
|
|
}
|
|
|
|
/**
|
|
* Extract data from `$target` by selected `$keys`.
|
|
* `$as` used to convert extracted data with different keys.
|
|
* `$as` support converting to types. using ':' after the key name.
|
|
*
|
|
* Example: `$target = [ 'someId' => '5' ];`
|
|
* `$keys = [ 'someId' ]`
|
|
* `$as = [ 'id:int' ]`
|
|
* Output will be `[ 'id' => 5 ];`
|
|
*
|
|
* @param array|\stdClass $target
|
|
* @param array $keys
|
|
* @param array $as
|
|
*
|
|
* @return array
|
|
*/
|
|
private function extract( $target, $keys, $as = [] ) {
|
|
$result = [];
|
|
|
|
$as_types = [];
|
|
$as_count = 0;
|
|
|
|
if ( is_object( $target ) ) {
|
|
$target = (array) $target;
|
|
}
|
|
|
|
foreach ( $as as $key => $as_item ) {
|
|
$exploded = explode( ':', $as_item );
|
|
|
|
if ( count( $exploded ) > 1 ) {
|
|
$as_types [] = $exploded[1];
|
|
$as[ $key ] = $exploded[0];
|
|
}
|
|
}
|
|
|
|
foreach ( $keys as $key ) {
|
|
if ( isset( $target[ $key ] ) ) {
|
|
if ( isset( $as[ $as_count ] ) ) {
|
|
$value = $target[ $key ];
|
|
if ( isset( $as_types[ $as_count ] ) ) {
|
|
settype( $value, $as_types[ $as_count ] );
|
|
}
|
|
$result[ $as[ $as_count ] ] = $value;
|
|
} else {
|
|
$result[ $key ] = $target[ $key ];
|
|
}
|
|
}
|
|
++$as_count;
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
private function handle_and_for_where_query( &$target_where_query ) {
|
|
if ( $target_where_query ) {
|
|
$target_where_query .= ' AND ';
|
|
}
|
|
}
|
|
|
|
private function filter_after_and_before( $filters, &$target_where_query ) {
|
|
// Filters 'after' & 'before' known in advance, and could handled systematically.
|
|
if ( isset( $filters['after'] ) || isset( $filters['before'] ) ) {
|
|
$this->handle_and_for_where_query( $target_where_query );
|
|
|
|
// TODO: This logic applies only for 'date' format not 'date-time' format.
|
|
$after = '0000-01-01 00:00:00';
|
|
$before = '9999-12-31 23:59:59';
|
|
|
|
if ( isset( $filters['after'] ) ) {
|
|
$after = $filters['after']['value'] . ' 00:00:00';
|
|
}
|
|
|
|
if ( isset( $filters['before'] ) ) {
|
|
$before = $filters['before']['value'] . ' 23:59:59';
|
|
}
|
|
|
|
$after = get_gmt_from_date( $after );
|
|
$before = get_gmt_from_date( $before );
|
|
|
|
$target_where_query .= $this->wpdb->prepare( 'created_at_gmt BETWEEN %s and %s', [ $after, $before ] );
|
|
}
|
|
}
|
|
|
|
private function filter_status( $filters, &$target_where_query ) {
|
|
if ( isset( $filters['status'] ) ) {
|
|
$this->handle_and_for_where_query( $target_where_query );
|
|
|
|
switch ( $filters['status']['value'] ) {
|
|
case 'all':
|
|
$target_where_query .= 'status != \'' . self::STATUS_TRASH . '\'';
|
|
break;
|
|
case 'unread':
|
|
$target_where_query .= 'status = \'' . self::STATUS_NEW . '\' AND is_read = 0';
|
|
break;
|
|
case 'read':
|
|
$target_where_query .= 'status = \'' . self::STATUS_NEW . '\' AND is_read > 0';
|
|
break;
|
|
case 'trash':
|
|
$target_where_query .= 'status = \'' . self::STATUS_TRASH . '\'';
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
private function filter_ids( $filters, &$target_where_query ) {
|
|
if ( ! isset( $filters['ids'] ) || empty( $filters['ids'] ) ) {
|
|
return;
|
|
}
|
|
|
|
$this->handle_and_for_where_query( $target_where_query );
|
|
|
|
$ids_collection = new Collection( $filters['ids']['value'] );
|
|
|
|
$placeholder = $ids_collection->map( function () {
|
|
return '%d';
|
|
} )->implode( ', ' );
|
|
|
|
$target_where_query .= $this->wpdb->prepare( "`id` IN ({$placeholder})", $ids_collection->all() ); // phpcs:ignore
|
|
}
|
|
|
|
private function filter_search( $filters, &$target_where_query ) {
|
|
if ( isset( $filters['search'] ) ) {
|
|
$this->handle_and_for_where_query( $target_where_query );
|
|
|
|
$like = '%' . $this->wpdb->esc_like( $filters['search']['value'] ) . '%';
|
|
$meta_table_name = $this->get_table_submissions_values();
|
|
|
|
$search = $this->wpdb->prepare( 'LIKE %s OR t_submissions.id LIKE %s', [ $like, $like ] );
|
|
|
|
$target_where_query .= "(
|
|
(
|
|
SELECT GROUP_CONCAT({$meta_table_name}.value)
|
|
FROM `{$meta_table_name}`
|
|
WHERE {$meta_table_name}.submission_id = t_submissions.id
|
|
GROUP BY {$meta_table_name}.submission_id
|
|
) {$search}
|
|
)";
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Filter bu element_id and post_id
|
|
*
|
|
* @param $filters
|
|
* @param $target_where_query
|
|
*/
|
|
private function filter_by_form( $filters, &$target_where_query ) {
|
|
if ( ! isset( $filters['form']['value'] ) ) {
|
|
return;
|
|
}
|
|
|
|
$this->handle_and_for_where_query( $target_where_query );
|
|
|
|
list( $post_id, $form_id ) = explode( '_', $filters['form']['value'] );
|
|
|
|
$target_where_query .= $this->wpdb->prepare(
|
|
'post_id = %d AND element_id = %s',
|
|
$post_id,
|
|
$form_id
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @param $filters
|
|
* @param $target_where_query
|
|
*/
|
|
private function filter_by_referer( $filters, &$target_where_query ) {
|
|
if ( ! isset( $filters['referer']['value'] ) ) {
|
|
return;
|
|
}
|
|
|
|
$this->handle_and_for_where_query( $target_where_query );
|
|
|
|
$target_where_query .= $this->wpdb->prepare(
|
|
'referer = %s',
|
|
$filters['referer']['value']
|
|
);
|
|
}
|
|
|
|
private function handle_order( $order, &$target_order_query ) {
|
|
if ( ! empty( $order ) ) {
|
|
$order['by'] = esc_sql( $order['by'] );
|
|
$order['order'] = strtoupper( $order['order'] );
|
|
|
|
if ( ! in_array( $order['order'], [ 'ASC', 'DESC' ], true ) ) {
|
|
$order['order'] = 'ASC';
|
|
}
|
|
|
|
$target_order_query = 'ORDER BY ' . $order['by'] . ' ' . $order['order'];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param \stdClass $submission
|
|
* @param bool $with_form_fields
|
|
*
|
|
* @return array
|
|
*/
|
|
private function get_submission_body( $submission, $with_form_fields = false ) {
|
|
$id = (int) $submission->id;
|
|
|
|
$result = [
|
|
'id' => $id,
|
|
];
|
|
|
|
$result['post'] = $this->extract( $submission, [ 'post_id' ], [ 'id:int' ] );
|
|
$result['form'] = $this->extract( $submission, [ 'form_name', 'element_id' ], [ 'name' ] );
|
|
|
|
$edit_post_id = $submission->post_id;
|
|
|
|
// TODO: Should be removed if there is an ability to edit "global widgets"
|
|
$meta = json_decode( $submission->meta ?? '', true );
|
|
|
|
if ( isset( $meta['edit_post_id'] ) ) {
|
|
$edit_post_id = $meta['edit_post_id'];
|
|
}
|
|
|
|
$document = Plugin::elementor()->documents->get( $edit_post_id );
|
|
|
|
if ( $document ) {
|
|
$result['post']['edit_url'] = $document->get_edit_url();
|
|
}
|
|
|
|
if ( $with_form_fields ) {
|
|
$form = Form_Snapshot_Repository::instance()
|
|
->find( $submission->post_id, $submission->element_id );
|
|
|
|
if ( $form ) {
|
|
$result['form']['fields'] = $form->fields;
|
|
}
|
|
}
|
|
|
|
$user = get_user_by( 'id', $submission->user_id );
|
|
|
|
$result['actions_count'] = (int) $submission->actions_count;
|
|
$result['actions_succeeded_count'] = (int) $submission->actions_succeeded_count;
|
|
$result['referer'] = $submission->referer;
|
|
$result['referer_title'] = $submission->referer_title;
|
|
$result['element_id'] = $submission->element_id;
|
|
$result['main_meta_id'] = $submission->main_meta_id;
|
|
$result['user_id'] = $submission->user_id;
|
|
$result['user_agent'] = $submission->user_agent;
|
|
$result['user_ip'] = $submission->user_ip;
|
|
$result['user_name'] = $user ? $user->display_name : null;
|
|
|
|
$result['created_at_gmt'] = $submission->created_at_gmt;
|
|
$result['updated_at_gmt'] = $submission->updated_at_gmt;
|
|
|
|
// Return the the dates according to WP current selected timezone.
|
|
$result['created_at'] = get_date_from_gmt( $submission->created_at_gmt );
|
|
$result['updated_at'] = get_date_from_gmt( $submission->updated_at_gmt );
|
|
|
|
$result['status'] = $submission->status;
|
|
$result['is_read'] = (bool) $submission->is_read;
|
|
|
|
return $result;
|
|
}
|
|
|
|
private function get_new_submission_initial_data( array $submission_data ) {
|
|
$current_datetime_gmt = current_time( 'mysql', true );
|
|
$current_datetime = get_date_from_gmt( $current_datetime_gmt );
|
|
|
|
$submission_data['hash_id'] = wp_generate_uuid4();
|
|
|
|
$submission_data = array_merge( [
|
|
'created_at_gmt' => $current_datetime_gmt,
|
|
'updated_at_gmt' => $current_datetime_gmt,
|
|
'created_at' => $current_datetime,
|
|
'updated_at' => $current_datetime,
|
|
'type' => self::TYPE_SUBMISSION,
|
|
'status' => self::STATUS_NEW,
|
|
], $submission_data );
|
|
|
|
return $submission_data;
|
|
}
|
|
|
|
private function apply_filter( array $filter ) {
|
|
$where_sql = '';
|
|
|
|
$this->filter_after_and_before( $filter, $where_sql );
|
|
$this->filter_status( $filter, $where_sql );
|
|
$this->filter_search( $filter, $where_sql );
|
|
$this->filter_by_form( $filter, $where_sql );
|
|
$this->filter_ids( $filter, $where_sql );
|
|
$this->filter_by_referer( $filter, $where_sql );
|
|
|
|
if ( ! $where_sql ) {
|
|
return '';
|
|
}
|
|
|
|
return 'WHERE ' . $where_sql;
|
|
}
|
|
|
|
public function __construct() {
|
|
global $wpdb;
|
|
|
|
$this->wpdb = $wpdb;
|
|
|
|
$this->table_submissions = $wpdb->prefix . self::E_SUBMISSIONS;
|
|
$this->table_submissions_values = $wpdb->prefix . self::E_SUBMISSIONS_VALUES;
|
|
$this->table_submissions_actions_log = $wpdb->prefix . self::E_SUBMISSIONS_ACTIONS_LOG;
|
|
}
|
|
}
|