2092 lines
61 KiB
PHP
2092 lines
61 KiB
PHP
<?php
|
|
/**
|
|
* Gravity Flow Status
|
|
*
|
|
* @package GravityFlow
|
|
* @subpackage Classes/Gravity_Flow_Status
|
|
* @copyright Copyright (c) 2015-2018, Steven Henty S.L.
|
|
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
|
|
* @since 1.0
|
|
*/
|
|
|
|
if ( ! class_exists( 'GFForms' ) ) {
|
|
die();
|
|
}
|
|
|
|
/**
|
|
* Class Gravity_Flow_Status
|
|
*/
|
|
class Gravity_Flow_Status {
|
|
|
|
/**
|
|
* Triggers display of the status page or processing of the export.
|
|
*
|
|
* @param array $args The status page arguments.
|
|
*
|
|
* @return array|WP_Error
|
|
*/
|
|
public static function render( $args = array() ) {
|
|
wp_enqueue_script( 'gform_field_filter' );
|
|
|
|
$args = array_merge( self::get_defaults(), $args );
|
|
$args = self::maybe_add_constraint_filters( $args );
|
|
|
|
if ( empty( $args['filter_hidden_fields'] ) ) {
|
|
$args['filter_hidden_fields'] = array( 'page' => 'gravityflow-status' );
|
|
}
|
|
|
|
/**
|
|
* Allow the status page/export arguments to be overridden.
|
|
*
|
|
* @param array $args The status page and export arguments.
|
|
*/
|
|
$args = apply_filters( 'gravityflow_status_args', $args );
|
|
|
|
if ( $args['format'] == 'table' ) {
|
|
self::status_page( $args );
|
|
} else {
|
|
return self::process_export( $args );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* The default arguments to use when rendering the status page or processing the export.
|
|
*
|
|
* @return array
|
|
*/
|
|
public static function get_defaults() {
|
|
return array(
|
|
'action_url' => admin_url( 'admin.php?page=gravityflow-status' ),
|
|
'constraint_filters' => array(),
|
|
'field_ids' => apply_filters( 'gravityflow_status_fields', array() ),
|
|
'format' => 'table', // The output format: table or csv.
|
|
'file_name' => 'export.csv',
|
|
'id_column' => true,
|
|
'submitter_column' => true,
|
|
'step_column' => true,
|
|
'status_column' => true,
|
|
'last_updated' => false,
|
|
'filter_hidden_fields' => array(),
|
|
);
|
|
}
|
|
|
|
/**
|
|
* If not already configured define the default constraint filters.
|
|
*
|
|
* @param array $args The status page and export arguments.
|
|
*
|
|
* @return array
|
|
*/
|
|
public static function maybe_add_constraint_filters( $args ) {
|
|
|
|
if ( empty( $args['constraint_filters'] ) ) {
|
|
$args['constraint_filters'] = array(
|
|
'form_id' => 0,
|
|
'start_date' => '',
|
|
'end_date' => '',
|
|
);
|
|
}
|
|
|
|
$args['constraint_filters'] = apply_filters( 'gravityflow_status_filter', $args['constraint_filters'] );
|
|
|
|
if ( ! isset( $args['constraint_filters']['form_id'] ) ) {
|
|
$args['constraint_filters']['form_id'] = 0;
|
|
}
|
|
if ( ! isset( $args['constraint_filters']['start_date'] ) ) {
|
|
$args['constraint_filters']['start_date'] = '';
|
|
}
|
|
if ( ! isset( $args['constraint_filters']['end_date'] ) ) {
|
|
$args['constraint_filters']['end_date'] = '';
|
|
}
|
|
|
|
return $args;
|
|
}
|
|
|
|
/**
|
|
* Display the status page.
|
|
*
|
|
* @param array $args The status page arguments.
|
|
*/
|
|
public static function status_page( $args ) {
|
|
$table = new Gravity_Flow_Status_Table( $args );
|
|
|
|
?>
|
|
<form id="gravityflow-status-filter" method="GET" action="">
|
|
<?php
|
|
foreach ( $args['filter_hidden_fields'] as $hidden_field => $hidden_field_value ) {
|
|
printf( '<input type="hidden" name="%s" value="%s"/>', $hidden_field, $hidden_field_value );
|
|
}
|
|
|
|
$table->views();
|
|
$table->filters();
|
|
$table->prepare_items();
|
|
?>
|
|
</form>
|
|
<form id="gravityflow-status-list" method="POST" action="">
|
|
<?php
|
|
$table->display();
|
|
?>
|
|
</form>
|
|
|
|
<?php
|
|
if ( is_admin() ) {
|
|
$str = $_SERVER['QUERY_STRING'];
|
|
parse_str( $str, $query_args );
|
|
|
|
$remove_args = array( 'paged', '_wpnonce', '_wp_http_referer', 'action', 'action2' );
|
|
foreach ( $remove_args as $remove_arg_key ) {
|
|
unset( $query_args[ $remove_arg_key ] );
|
|
}
|
|
$query_args['gravityflow_export_nonce'] = wp_create_nonce( 'gravityflow_export_nonce' );
|
|
$filter_args_str = '&' . http_build_query( $query_args );
|
|
echo sprintf( '<br /><a class="gravityflow-export-status-button button" data-filter_args="%s">%s</a>', $filter_args_str, esc_html__( 'Export', 'gravityflow' ) );
|
|
echo sprintf( '<img class="gravityflow-spinner" src="%s" style="display:none;margin:5px"/>', GFCommon::get_base_url() . '/images/spinner.gif' );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Process the status export.
|
|
*
|
|
* @param array $args The status export arguments.
|
|
*
|
|
* @return array|WP_Error
|
|
*/
|
|
public static function process_export( $args ) {
|
|
$upload_dir = wp_upload_dir();
|
|
if ( ! is_writeable( $upload_dir['basedir'] ) ) {
|
|
return new WP_Error( 'export_destination_not_writeable', esc_html__( 'The destination file is not writeable', 'gravityflow' ) );
|
|
}
|
|
|
|
$file_path = trailingslashit( $upload_dir['basedir'] ) . $args['file_name'] . '.csv';
|
|
$export = '';
|
|
|
|
$table = new Gravity_Flow_Status_Table( $args );
|
|
$table->prepare_items();
|
|
$page = (int) $table->get_pagination_arg( 'page' );
|
|
|
|
if ( $page < 2 ) {
|
|
@unlink( $file_path );
|
|
$export .= $table->export_column_names();
|
|
}
|
|
$export .= $table->export();
|
|
|
|
@file_put_contents( $file_path, $export, FILE_APPEND );
|
|
|
|
$per_page = (int) $table->get_pagination_arg( 'per_page' );
|
|
$total_items = (int) $table->get_pagination_arg( 'total_items' );
|
|
$total_pages = (int) $table->get_pagination_arg( 'total_pages' );
|
|
|
|
$status = $page == $total_pages ? 'complete' : 'incomplete';
|
|
$percent = $page * $per_page / $total_items * 100;
|
|
$response = array( 'status' => $status, 'percent' => (int) $percent );
|
|
|
|
if ( $status == 'complete' ) {
|
|
$download_args = array(
|
|
'nonce' => wp_create_nonce( 'gravityflow_download_export' ),
|
|
'action' => 'gravityflow_download_export',
|
|
'file_name' => $args['file_name'],
|
|
);
|
|
$download_url = add_query_arg( $download_args, admin_url( 'admin-ajax.php' ) );
|
|
$response['url'] = esc_url_raw( $download_url );
|
|
}
|
|
|
|
return $response;
|
|
}
|
|
}
|
|
|
|
|
|
if ( ! class_exists( 'WP_List_Table' ) ) {
|
|
require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
|
|
}
|
|
|
|
/**
|
|
* Class Gravity_Flow_Status_Table
|
|
*/
|
|
class Gravity_Flow_Status_Table extends WP_List_Table {
|
|
|
|
/**
|
|
* The pagination arguments.
|
|
*
|
|
* @var array
|
|
*/
|
|
public $pagination_args;
|
|
|
|
/**
|
|
* URL of this page
|
|
*
|
|
* @var string
|
|
*/
|
|
public $base_url;
|
|
|
|
/**
|
|
* Base url of the detail page
|
|
*
|
|
* @var string
|
|
*/
|
|
public $detail_base_url;
|
|
|
|
/**
|
|
* Total number of entries
|
|
*
|
|
* @var int
|
|
*/
|
|
public $total_count;
|
|
/**
|
|
* Total number of pending entries
|
|
*
|
|
* @var int
|
|
*/
|
|
public $pending_count;
|
|
/**
|
|
* Total number of complete entries
|
|
*
|
|
* @var int
|
|
*/
|
|
public $complete_count;
|
|
/**
|
|
* Total number of cancelled entries
|
|
*
|
|
* @var int
|
|
*/
|
|
public $cancelled_count;
|
|
|
|
/**
|
|
* The fields to be displayed.
|
|
*
|
|
* @var array
|
|
*/
|
|
public $field_ids = array();
|
|
|
|
/**
|
|
* The filter arguments used to limit the displayed entries.
|
|
*
|
|
* @var array
|
|
*/
|
|
public $constraint_filters = array();
|
|
|
|
/**
|
|
* Indicates if the table should include entries from all users.
|
|
*
|
|
* @var bool
|
|
*/
|
|
public $display_all;
|
|
|
|
/**
|
|
* The bulk action properties.
|
|
*
|
|
* @var array
|
|
*/
|
|
public $bulk_actions;
|
|
|
|
/**
|
|
* The number of entries to include on each page.
|
|
*
|
|
* @var int
|
|
*/
|
|
public $per_page;
|
|
|
|
/**
|
|
* The steps for the specified form.
|
|
*
|
|
* @var Gravity_Flow_Step[]
|
|
*/
|
|
private $_steps;
|
|
|
|
/**
|
|
* The filter arguments.
|
|
*
|
|
* @var array
|
|
*/
|
|
private $_filter_args;
|
|
|
|
/**
|
|
* Should the ID column be displayed?
|
|
*
|
|
* @var bool
|
|
*/
|
|
public $id_column;
|
|
|
|
/**
|
|
* Should the submitter column be displayed?
|
|
*
|
|
* @var bool
|
|
*/
|
|
public $submitter_column;
|
|
|
|
/**
|
|
* Should the step column be displayed?
|
|
*
|
|
* @var bool
|
|
*/
|
|
public $step_column;
|
|
|
|
/**
|
|
* Should the status column be displayed?
|
|
*
|
|
* @var bool
|
|
*/
|
|
public $status_column;
|
|
|
|
/**
|
|
* Should the last updated column be displayed?
|
|
*
|
|
* @var bool
|
|
*/
|
|
public $last_updated;
|
|
|
|
/**
|
|
* A cache of previously retrieved forms.
|
|
*
|
|
* @var array
|
|
*/
|
|
private $_forms = array();
|
|
|
|
/**
|
|
* All the args for the table.
|
|
*
|
|
* @var array $args
|
|
*/
|
|
public $args;
|
|
|
|
/**
|
|
* Gravity_Flow_Status_Table constructor.
|
|
*
|
|
* @param array $args The status page arguments.
|
|
*/
|
|
public function __construct( $args = array() ) {
|
|
|
|
|
|
$default_args = array(
|
|
'singular' => 'entry', // Not translated - only used in class names
|
|
'plural' => 'entries', // Not translated - only used in class names
|
|
'ajax' => false,
|
|
'base_url' => admin_url( 'admin.php?page=gravityflow-status' ),
|
|
'detail_base_url' => admin_url( 'admin.php?page=gravityflow-inbox&view=entry' ),
|
|
'constraint_filters' => array(),
|
|
'field_ids' => array(),
|
|
'screen' => 'gravityflow-status',
|
|
'display_all' => GFAPI::current_user_can_any( 'gravityflow_status_view_all' ),
|
|
'per_page' => 20,
|
|
'id_column' => true,
|
|
'submitter_column' => true,
|
|
'step_column' => true,
|
|
'status_column' => true,
|
|
'last_updated' => false,
|
|
);
|
|
|
|
$args = wp_parse_args( $args, $default_args );
|
|
|
|
$default_bulk_actions = array( 'print' => esc_html__( 'Print', 'gravityflow' ) );
|
|
|
|
if ( GFAPI::current_user_can_any( 'gravityflow_admin_actions' ) ) {
|
|
$default_bulk_actions['restart_workflow'] = esc_html__( 'Restart Workflow', 'gravityflow' );
|
|
}
|
|
|
|
$args['bulk_actions'] = isset ( $args['bulk_actions'] ) ? array_merge( $default_bulk_actions, $args['bulk_actions'] ) : $default_bulk_actions;
|
|
|
|
require_once( ABSPATH .'wp-admin/includes/template.php' );
|
|
if ( ! class_exists( 'WP_Screen' ) ) {
|
|
require_once( ABSPATH . 'wp-admin/includes/class-wp-screen.php' );
|
|
}
|
|
|
|
parent::__construct( $args );
|
|
|
|
$this->base_url = $args['base_url'];
|
|
$this->detail_base_url = $args['detail_base_url'];
|
|
$this->constraint_filters = $args['constraint_filters'];
|
|
if ( ! is_array( $args['field_ids'] ) ) {
|
|
$args['field_ids'] = empty( $args['field_ids'] ) ? array() : explode( ',', $args['field_ids'] );
|
|
}
|
|
$this->field_ids = $args['field_ids'];
|
|
$this->display_all = $args['display_all'];
|
|
$this->bulk_actions = $args['bulk_actions'];
|
|
$this->set_counts();
|
|
$this->per_page = $args['per_page'];
|
|
$this->id_column = $args['id_column'];
|
|
$this->step_column = $args['step_column'];
|
|
$this->submitter_column = $args['submitter_column'];
|
|
$this->status_column = $args['status_column'];
|
|
$this->last_updated = $args['last_updated'];
|
|
}
|
|
|
|
/**
|
|
* The text to be displayed if there are no workflow entries.
|
|
*/
|
|
public function no_items() {
|
|
esc_html_e( "You haven't submitted any workflow forms yet.", 'gravityflow' );
|
|
}
|
|
|
|
/**
|
|
* Get the views.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function get_views() {
|
|
$current = isset( $_REQUEST['status'] ) ? $_REQUEST['status'] : '';
|
|
$total_count = ' <span class="count">(' . $this->total_count . ')</span>';
|
|
$complete_count = ' <span class="count">(' . $this->complete_count . ')</span>';
|
|
$pending_count = ' <span class="count">(' . $this->pending_count . ')</span>';
|
|
$cancelled_count = ' <span class="count">(' . $this->cancelled_count . ')</span>';
|
|
|
|
$pending_label = gravity_flow()->translate_status_label( 'pending' );
|
|
$complete_label = gravity_flow()->translate_status_label( 'complete' );
|
|
$cancelled_label = gravity_flow()->translate_status_label( 'cancelled' );
|
|
|
|
$views = array(
|
|
'all' => sprintf( '<a href="%s"%s>%s</a>', esc_url( remove_query_arg( array(
|
|
'status',
|
|
'paged',
|
|
) ) ), $current === 'all' || $current == '' ? ' class="current"' : '', esc_html__( 'All', 'gravityflow' ) . $total_count ),
|
|
'pending' => sprintf( '<a href="%s"%s>%s</a>', esc_url( add_query_arg( array(
|
|
'status' => 'pending',
|
|
'paged' => false,
|
|
) ) ), $current === 'pending' ? ' class="current"' : '', esc_html( $pending_label ) . $pending_count ),
|
|
'complete' => sprintf( '<a href="%s"%s>%s</a>', esc_url( add_query_arg( array(
|
|
'status' => 'complete',
|
|
'paged' => false,
|
|
) ) ), $current === 'complete' ? ' class="current"' : '',esc_html( $complete_label ) . $complete_count ),
|
|
'cancelled' => sprintf( '<a href="%s"%s>%s</a>', esc_url( add_query_arg( array(
|
|
'status' => 'cancelled',
|
|
'paged' => false,
|
|
) ) ), $current === 'cancelled' ? ' class="current"' : '', esc_html( $cancelled_label ) . $cancelled_count ),
|
|
);
|
|
|
|
return $views;
|
|
}
|
|
|
|
/**
|
|
* Output the status filters.
|
|
*/
|
|
public function filters() {
|
|
wp_print_styles( array( 'thickbox' ) );
|
|
add_thickbox();
|
|
?>
|
|
<div id="gravityflow-status-filters">
|
|
|
|
<div id="gravityflow-status-date-filters">
|
|
<?php
|
|
$filter_entry_id = $this->entry_id_input();
|
|
$start_date = $this->date_input( esc_html__( 'Start:', 'gravityflow' ), 'start_date' );
|
|
$end_date = $this->date_input( esc_html__( 'End:', 'gravityflow' ), 'end_date' );
|
|
$filter_form_id = $this->form_select();
|
|
$this->status_input();
|
|
?>
|
|
|
|
<div id="entry_filters" style="display:inline-block;"></div>
|
|
<input type="submit" class="button-secondary" value="<?php esc_html_e( 'Apply', 'gravityflow' ); ?>"/>
|
|
|
|
<?php if ( ! empty( $start_date ) || ! empty( $end_date ) || ! empty( $filter_form_id ) | ! empty( $filter_entry_id ) ) : ?>
|
|
<a href="<?php echo esc_url( $this->base_url ); ?>"
|
|
class="button-secondary"><?php esc_html_e( 'Clear Filter', 'gravityflow' ); ?></a>
|
|
<?php endif; ?>
|
|
</div>
|
|
<?php $this->search_box( esc_html__( 'Search', 'gravityflow' ), 'gravityflow-search' ); ?>
|
|
</div>
|
|
|
|
<?php
|
|
$this->output_filter_scripts();
|
|
$this->output_print_modal();
|
|
$this->process_bulk_action();
|
|
}
|
|
|
|
/**
|
|
* Output an input for the entry id filter.
|
|
*
|
|
* @return int|string The entry ID to filter the entries by.
|
|
*/
|
|
public function entry_id_input() {
|
|
$filter_entry_id = empty( $_REQUEST['entry-id'] ) ? '' : absint( $_REQUEST['entry-id'] );
|
|
|
|
printf( '<input placeholder="ID" type="text" name="entry-id" id="entry-id" class="small-text" value="%s"/> ', $filter_entry_id );
|
|
|
|
return $filter_entry_id;
|
|
}
|
|
|
|
/**
|
|
* Output a datepicker input for the specified filter if it is not defined in the constraint filters.
|
|
*
|
|
* @param string $label The label to be displayed for this input.
|
|
* @param string $filter The filter key as used in the constraint filters (start_date or end_date).
|
|
*
|
|
* @return null|string The date to filter the entries by.
|
|
*/
|
|
public function date_input( $label, $filter ) {
|
|
if ( ! empty( $this->constraint_filters[ $filter ] ) ) {
|
|
return null;
|
|
}
|
|
|
|
$id = str_replace( '_', '-', $filter );
|
|
$date = isset( $_REQUEST[ $id ] ) ? $this->sanitize_date( $_REQUEST[ $id ] ) : null;
|
|
|
|
printf( '<label for="%s">%s</label> <input type="text" id="%s" name="%s" class="datepicker medium-text ymd_dash" value="%s" placeholder="%s"/> ', $id, $label, $id, $id, $date, esc_attr__( 'yyyy-mm-dd', 'gravityflow' ) );
|
|
|
|
return $date;
|
|
}
|
|
|
|
/**
|
|
* Output the forms drop down or a hidden input if a form was specified in the constraint filters.
|
|
*
|
|
* @return string|int $filter_form_id The form ID to filter the entries by.
|
|
*/
|
|
public function form_select() {
|
|
if ( ! empty( $this->constraint_filters['form_id'] ) ) {
|
|
|
|
printf( '<input type="hidden" name="form-id" id="gravityflow-form-select" value="%s">', esc_attr( $this->constraint_filters['form_id'] ) );
|
|
|
|
return '';
|
|
|
|
} else {
|
|
|
|
$filter_form_id = empty( $_REQUEST['form-id'] ) ? '' : absint( $_REQUEST['form-id'] );
|
|
$selected = selected( '', $filter_form_id, false );
|
|
$options = sprintf( '<option value="" %s >%s</option>', $selected, esc_html__( 'Workflow Form', 'gravityflow' ) );
|
|
$forms = GFAPI::get_forms();
|
|
|
|
foreach ( $forms as $form ) {
|
|
$form_id = absint( $form['id'] );
|
|
$steps = gravity_flow()->get_steps( $form_id );
|
|
if ( ! empty( $steps ) ) {
|
|
$selected = selected( $filter_form_id, $form_id, false );
|
|
$options .= sprintf( '<option value="%d" %s>%s</option>', $form_id, $selected, esc_html( $form['title'] ) );
|
|
}
|
|
}
|
|
|
|
printf( '<select id="gravityflow-form-select" name="form-id">%s</select>', $options );
|
|
|
|
return $filter_form_id;
|
|
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Output the hidden input for the status filter.
|
|
*/
|
|
public function status_input() {
|
|
$status = isset( $_REQUEST['status'] ) ? $_REQUEST['status'] : '';
|
|
|
|
if ( ! empty( $status ) ) {
|
|
printf( '<input type="hidden" name="status" value="%s"/>', esc_attr( $status ) );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get the field filters to be output with the filter scripts.
|
|
*
|
|
* @return null|array
|
|
*/
|
|
public function get_field_filters() {
|
|
$field_filters = null;
|
|
|
|
$forms = GFAPI::get_forms();
|
|
foreach ( $forms as $form ) {
|
|
$form_filters = GFCommon::get_field_filter_settings( $form );
|
|
|
|
$empty_filter = array(
|
|
'key' => '',
|
|
'text' => esc_html__( 'Fields', 'gravityflow' ),
|
|
'operators' => array(),
|
|
);
|
|
array_unshift( $form_filters, $empty_filter );
|
|
$field_filters[ $form['id'] ] = $form_filters;
|
|
}
|
|
|
|
/**
|
|
* Allows modification of the field filters in the status table.
|
|
*
|
|
* @param array $field_filters An associative array of filters by Form ID.
|
|
*/
|
|
$field_filters = apply_filters( 'gravityflow_field_filters_status_table', $field_filters );
|
|
|
|
return $field_filters;
|
|
}
|
|
|
|
/**
|
|
* Get the field id for use with the filter scripts.
|
|
*
|
|
* @return string
|
|
*/
|
|
public function get_init_filter_field_id() {
|
|
$search_field_ids = isset( $_REQUEST['f'] ) ? $_REQUEST['f'] : '';
|
|
|
|
return ( $search_field_ids && is_array( $search_field_ids ) ) ? $search_field_ids[0] : '';
|
|
}
|
|
|
|
/**
|
|
* Get the operator for use with the filter scripts.
|
|
*
|
|
* @return bool|string
|
|
*/
|
|
public function get_init_filter_operator() {
|
|
$search_operators = isset( $_REQUEST['o'] ) ? $_REQUEST['o'] : '';
|
|
$search_operator = ( $search_operators && is_array( $search_operators ) ) ? $search_operators[0] : false;
|
|
|
|
return empty( $search_operator ) ? 'contains' : $search_operator;
|
|
}
|
|
|
|
/**
|
|
* Get the value for use with the filter scripts.
|
|
*
|
|
* @return int|string
|
|
*/
|
|
public function get_init_filter_value() {
|
|
$values = isset( $_REQUEST['v'] ) ? $_REQUEST['v'] : '';
|
|
|
|
return ( $values && is_array( $values ) ) ? $values[0] : 0;
|
|
}
|
|
|
|
/**
|
|
* Get the init filters to be output with the filter scripts.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function get_init_filter_vars() {
|
|
return array(
|
|
'mode' => 'off',
|
|
'filters' => array(
|
|
array(
|
|
'field' => $this->get_init_filter_field_id(),
|
|
'operator' => $this->get_init_filter_operator(),
|
|
'value' => $this->get_init_filter_value(),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Output the filter scripts to the page.
|
|
*/
|
|
public function output_filter_scripts() {
|
|
?>
|
|
<script>
|
|
(function ($) {
|
|
$(document).ready(function () {
|
|
var gformFieldFilters = <?php echo json_encode( $this->get_field_filters() ) ?>,
|
|
gformInitFilter = <?php echo json_encode( $this->get_init_filter_vars() ) ?>;
|
|
var $form_select = $('#gravityflow-form-select');
|
|
var filterFormId = $form_select.val();
|
|
var $entry_filters = $('#entry_filters');
|
|
if (filterFormId) {
|
|
$entry_filters.gfFilterUI(gformFieldFilters[filterFormId], gformInitFilter, false);
|
|
if ($('.gform-filter-field').val() === '') {
|
|
$('.gform-filter-operator').hide();
|
|
$('.gform-filter-value').hide();
|
|
}
|
|
}
|
|
$form_select.change(function () {
|
|
filterFormId = $form_select.val();
|
|
if (filterFormId) {
|
|
$entry_filters.gfFilterUI(gformFieldFilters[filterFormId], gformInitFilter, false);
|
|
$('.gform-filter-field').val('');
|
|
$('.gform-filter-operator').hide();
|
|
$('.gform-filter-value').hide();
|
|
} else {
|
|
$entry_filters.html('');
|
|
}
|
|
|
|
});
|
|
$('#entry_filters').on('change', '.gform-filter-field', function () {
|
|
if ($('.gform-filter-field').val() === '') {
|
|
$('.gform-filter-operator').hide();
|
|
$('.gform-filter-value').hide();
|
|
}
|
|
});
|
|
});
|
|
|
|
})(jQuery);
|
|
</script>
|
|
<?php
|
|
}
|
|
|
|
/**
|
|
* Output the markup for the print modal.
|
|
*/
|
|
public function output_print_modal() {
|
|
?>
|
|
<div id="print_modal_container" style="display:none;">
|
|
<div id="print_container">
|
|
|
|
<div class="tagsdiv">
|
|
<div id="print_options">
|
|
|
|
<p class="description"><?php esc_html_e( 'Print all of the selected entries at once.', 'gravityflow' ); ?></p>
|
|
|
|
<input type="checkbox" name="gravityflow-print-timelines" value="print_timelines" checked="checked" id="gravityflow-print-timelines"/>
|
|
<label for="gravityflow-print-timelines"><?php esc_html_e( 'Include timelines', 'gravityflow' ); ?></label>
|
|
<br/><br/>
|
|
|
|
<input type="checkbox" name="gravityflow-print-page-break" value="print_page_break" checked="checked" id="gravityflow-print-page-break"/>
|
|
<label for="gravityflow-print-page-break"><?php esc_html_e( 'Add page break between entries', 'gravityflow' ); ?></label>
|
|
<br/><br/>
|
|
|
|
<input id="gravityflow-bulk-print-button" type="button" value="<?php esc_attr_e( 'Print', 'gravityflow' ); ?>" class="button"/>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
<?php
|
|
}
|
|
|
|
/**
|
|
* Output the row checkbox.
|
|
*
|
|
* @param array $item The current entry.
|
|
*
|
|
* @return string
|
|
*/
|
|
public function column_cb( $item ) {
|
|
$feed_id = rgar( $item, 'id' );
|
|
|
|
return sprintf( '<input type="checkbox" class="gravityflow-cb-entry-id" name="entry_ids[]" value="%s" />', esc_attr( $feed_id ) );
|
|
}
|
|
|
|
/**
|
|
* Output the entry ID.
|
|
*
|
|
* @param array $item The current entry.
|
|
*/
|
|
public function column_id( $item ) {
|
|
$url_entry = $this->detail_base_url . sprintf( '&id=%d&lid=%d', $item['form_id'], $item['id'] );
|
|
$url_entry = esc_url( $url_entry );
|
|
$label = absint( $item['id'] );
|
|
|
|
/**
|
|
* Allows the field value to be filtered in the status table.
|
|
*
|
|
* @since 1.7.1
|
|
*
|
|
* @param string $label The value to be displayed.
|
|
* @param int $item ['form_id'] The Form ID.
|
|
* @param string 'id' The column name.
|
|
* @param array $item The entry array.
|
|
*/
|
|
$label = apply_filters( 'gravityflow_field_value_status_table', $label, $item['form_id'], 'id', $item );
|
|
|
|
$link = "<a href='{$url_entry}'>$label</a>";
|
|
echo $link;
|
|
}
|
|
|
|
/**
|
|
* Output the column value.
|
|
*
|
|
* @param array $item The current entry.
|
|
* @param string $column_name The column name.
|
|
*/
|
|
public function column_default( $item, $column_name ) {
|
|
$url_entry = $this->detail_base_url . sprintf( '&id=%d&lid=%d', $item['form_id'], $item['id'] );
|
|
$url_entry = esc_url( $url_entry );
|
|
$form_id = rgar( $item, 'form_id' );
|
|
$form = GFAPI::get_form( $form_id );
|
|
|
|
/* @var GF_Field $field */
|
|
$field = GFFormsModel::get_field( $form, $column_name );
|
|
$value = rgar( $item, $column_name );
|
|
if ( $field ) {
|
|
$columns = RGFormsModel::get_grid_columns( $form_id, true );
|
|
$value = $field->get_value_entry_list( $value, $item, $column_name, $columns, $form );
|
|
}
|
|
|
|
$label = esc_html( $value );
|
|
|
|
/**
|
|
* Allows the field value to be filtered in the status table.
|
|
*
|
|
* @since 1.7.1
|
|
*
|
|
* @param string $label The value to be displayed.
|
|
* @param int $item ['form_id'] The Form ID.
|
|
* @param string $column_name The column name.
|
|
* @param array $item The entry array.
|
|
*/
|
|
$label = apply_filters( 'gravityflow_field_value_status_table', $label, $item['form_id'], $column_name, $item );
|
|
|
|
$link = "<a href='{$url_entry}'>$label</a>";
|
|
echo $link;
|
|
}
|
|
|
|
/**
|
|
* Outputs the workflow final status.
|
|
*
|
|
* @param array $item The current entry.
|
|
*/
|
|
public function column_workflow_final_status( $item ) {
|
|
$url_entry = $this->detail_base_url . sprintf( '&id=%d&lid=%d', $item['form_id'], $item['id'] );
|
|
$final_status = rgar( $item, 'workflow_final_status' );
|
|
$label = empty( $final_status ) ? '' : gravity_flow()->translate_status_label( $final_status );
|
|
$label = esc_html( $label );
|
|
|
|
/**
|
|
* Allows the field value to be filtered in the status table.
|
|
*
|
|
* @since 1.7.1
|
|
*
|
|
* @param string $label The value to be displayed.
|
|
* @param int $item ['form_id'] The Form ID.
|
|
* @param string 'final_status'.
|
|
* @param array $item The entry array.
|
|
*/
|
|
$label = apply_filters( 'gravityflow_field_value_status_table', $label, $item['form_id'], 'final_status', $item );
|
|
$url_entry = esc_url( $url_entry );
|
|
$link = "<a href='{$url_entry}'>$label</a>";
|
|
|
|
echo $link;
|
|
|
|
$args = $this->get_filter_args();
|
|
|
|
if ( empty( $item['workflow_step'] ) ) {
|
|
return;
|
|
}
|
|
|
|
if ( ! isset( $args['form-id'] ) ) {
|
|
$duration = time() - strtotime( $item['date_created'] );
|
|
$duration_str = ' ' . $this->format_duration( $duration );
|
|
echo $duration_str;
|
|
|
|
return;
|
|
}
|
|
|
|
$step_id = $this->get_filter_step_id();
|
|
|
|
if ( $step_id ) {
|
|
return;
|
|
}
|
|
|
|
$steps = $this->get_steps( $item['form_id'] );
|
|
if ( $steps ) {
|
|
$pending = $rejected = $green = 0;
|
|
$id = 'gravityflow-status-assignees-' . absint( $item['id'] );
|
|
$m[] = '<ul id="' . $id . '" style="display:none;">';
|
|
$step = gravity_flow()->get_step( $item['workflow_step'], $item );
|
|
|
|
$meta_key = '';
|
|
$assignee = false;
|
|
|
|
if ( $step ) {
|
|
$step_type = $step->get_type();
|
|
if ( ( $step_type == 'approval' && ! $step->unanimous_approval ) || $step->assignee_policy == 'any' ) {
|
|
$duration = time() - strtotime( $item['date_created'] );
|
|
$duration_str = ' (' . $this->format_duration( $duration ) . ') ';
|
|
echo $duration_str;
|
|
|
|
return;
|
|
}
|
|
|
|
$assignees = $step->get_assignees();
|
|
foreach ( $assignees as $assignee ) {
|
|
$duration_str = '';
|
|
$meta_key = sprintf( 'workflow_%s_%s', $assignee->get_type(), $assignee->get_id() );
|
|
if ( isset( $item[ $meta_key ] ) ) {
|
|
if ( $item[ $meta_key ] == 'pending' ) {
|
|
$pending ++;
|
|
if ( $item[ $meta_key . '_timestamp' ] ) {
|
|
$duration = time() - $item[ $meta_key . '_timestamp' ];
|
|
$duration_str = ' (' . $this->format_duration( $duration ) . ') ';
|
|
} else {
|
|
$duration_str = '';
|
|
}
|
|
} elseif ( $item[ $meta_key ] == 'rejected' ) {
|
|
$rejected ++;
|
|
} else {
|
|
$green ++;
|
|
}
|
|
$m[] = '<li>' . $assignee->get_display_name() . ': ' . $item[ $meta_key ] . $duration_str . '</li>';
|
|
}
|
|
}
|
|
}
|
|
$m[] = '</ul>';
|
|
|
|
if ( $green == 0 && $rejected == 0 && $pending == 1 && $assignee ) {
|
|
if ( $item[ $meta_key . '_timestamp' ] ) {
|
|
$duration = time() - $item[ $meta_key . '_timestamp' ];
|
|
$duration_str = ' (' . $this->format_duration( $duration ) . ') ';
|
|
echo ': ' . $assignee->get_display_name() . $duration_str;
|
|
}
|
|
} else {
|
|
$assignee_icons = array();
|
|
for ( $i = 0; $i < $green; $i ++ ) {
|
|
$assignee_icons[] = "<i class='fa fa-male' style='color:green;'></i>";
|
|
}
|
|
for ( $i = 0; $i < $rejected; $i ++ ) {
|
|
$assignee_icons[] = "<i class='fa fa-male' style='color:red;'></i>";
|
|
}
|
|
for ( $i = 0; $i < $pending; $i ++ ) {
|
|
$assignee_icons[] = "<i class='fa fa-male' style='color:silver;'></i>";
|
|
}
|
|
echo sprintf( ": <span style='cursor:pointer;' onclick=\"jQuery('#$id').slideToggle()\">%s</span>", join( "\n", $assignee_icons ) );
|
|
echo join( "\n", $m );
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* Outputs the entry submitter details.
|
|
*
|
|
* @param array $item The current entry.
|
|
*/
|
|
public function column_created_by( $item ) {
|
|
$url_entry = $this->detail_base_url . sprintf( '&id=%d&lid=%d', $item['form_id'], $item['id'] );
|
|
|
|
$user_id = $item['created_by'];
|
|
if ( $user_id ) {
|
|
$user = get_user_by( 'id', $user_id );
|
|
if ( empty( $user ) || is_wp_error( $user ) ) {
|
|
$display_name = $user_id . ' ' . esc_html__( '(deleted)', 'gravityflow' );
|
|
} else {
|
|
$display_name = $user->display_name;
|
|
}
|
|
} else {
|
|
$display_name = $item['ip'];
|
|
}
|
|
$label = esc_html( $display_name );
|
|
|
|
$form_id = rgar( $item, 'form_id' );
|
|
$form = $this->get_form( $form_id );
|
|
|
|
/**
|
|
* Allow the value displayed in the Submitter column to be overridden.
|
|
*
|
|
* @param string $label The display_name of the logged-in user who submitted the form or the guest ip address.
|
|
* @param array $item The entry object for the row currently being processed.
|
|
* @param array $form The form object for the current entry.
|
|
*/
|
|
$label = apply_filters( 'gravityflow_status_submitter_name', $label, $item, $form );
|
|
|
|
/**
|
|
* Allows the field value to be filtered in the status table.
|
|
*
|
|
* @since 1.7.1
|
|
*
|
|
* @param string $label The value to be displayed.
|
|
* @param int $item ['form_id'] The Form ID.
|
|
* @param string 'created_by'.
|
|
* @param array $item The entry array.
|
|
*/
|
|
$label = apply_filters( 'gravityflow_field_value_status_table', $label, $item['form_id'], 'created_by', $item );
|
|
|
|
$url_entry = esc_url( $url_entry );
|
|
|
|
$link = "<a href='{$url_entry}'>$label</a>";
|
|
echo $link;
|
|
}
|
|
|
|
/**
|
|
* Outputs the form title.
|
|
*
|
|
* @param array $item The current entry.
|
|
*/
|
|
public function column_form_id( $item ) {
|
|
$url_entry = $this->detail_base_url . sprintf( '&id=%d&lid=%d', $item['form_id'], $item['id'] );
|
|
|
|
$form_id = $item['form_id'];
|
|
$form = $this->get_form( $form_id );
|
|
|
|
$label = esc_html( $form['title'] );
|
|
|
|
/**
|
|
* Allows the field value to be filtered in the status table.
|
|
*
|
|
* @since 1.7.1
|
|
*
|
|
* @param string $label The value to be displayed
|
|
* @param int $item['form_id'] The Form ID
|
|
* @param string 'form_id'
|
|
* @param array $item The entry array.
|
|
*/
|
|
$label = apply_filters( 'gravityflow_field_value_status_table', $label, $item['form_id'], 'form_id', $item );
|
|
|
|
$url_entry = esc_url( $url_entry );
|
|
|
|
$link = "<a href='{$url_entry}'>$label</a>";
|
|
echo $link;
|
|
}
|
|
|
|
/**
|
|
* Outputs the current step name.
|
|
*
|
|
* @param array $item The current entry.
|
|
*/
|
|
public function column_workflow_step( $item ) {
|
|
$step_id = rgar( $item, 'workflow_step' );
|
|
if ( $step_id > 0 ) {
|
|
$step = gravity_flow()->get_step( $step_id );
|
|
$url_entry = $this->detail_base_url . sprintf( '&id=%d&lid=%d', $item['form_id'], $item['id'] );
|
|
|
|
$url_entry = esc_url( $url_entry );
|
|
|
|
$label = $step ? esc_html( $step->get_name() ) : '';
|
|
|
|
/**
|
|
* Allows the field value to be filtered in the status table.
|
|
*
|
|
* @since 1.7.1
|
|
*
|
|
* @param string $label The value to be displayed.
|
|
* @param int $item ['form_id'] The Form ID.
|
|
* @param string 'workflow_step'.
|
|
* @param array $item The entry array.
|
|
*/
|
|
$label = apply_filters( 'gravityflow_field_value_status_table', $label, $item['form_id'], 'workflow_step', $item );
|
|
$link = "<a href='{$url_entry}'>$label</a>";
|
|
$output = $link;
|
|
} else {
|
|
$output = '<span class="gravityflow-empty">‐</span>';
|
|
}
|
|
|
|
/**
|
|
* Allow the value in the step column on the status page to be modified.
|
|
*
|
|
* @param string $output The column value to be output.
|
|
* @param array $item The Entry.
|
|
*/
|
|
$output = apply_filters( 'gravityflow_step_column_status_page', $output, $item );
|
|
echo $output;
|
|
}
|
|
|
|
/**
|
|
* Outputs the entry creation date.
|
|
*
|
|
* @param array $item The current entry.
|
|
*/
|
|
public function column_date_created( $item ) {
|
|
$url_entry = $this->detail_base_url . sprintf( '&id=%d&lid=%d', $item['form_id'], $item['id'] );
|
|
$url_entry = esc_url( $url_entry );
|
|
$label = GFCommon::format_date( $item['date_created'] );
|
|
|
|
/**
|
|
* Allows the field value to be filtered in the status table.
|
|
*
|
|
* @since 1.7.1
|
|
*
|
|
* @param string $label The value to be displayed.
|
|
* @param int $item ['form_id'] The Form ID.
|
|
* @param string 'date_created'.
|
|
* @param array $item The entry array.
|
|
*/
|
|
$label = apply_filters( 'gravityflow_field_value_status_table', $label, $item['form_id'], 'date_created', $item );
|
|
$link = "<a href='{$url_entry}'>$label</a>";
|
|
echo $link;
|
|
}
|
|
|
|
/**
|
|
* Outputs the workflow timestamp.
|
|
*
|
|
* @param array $item The current entry.
|
|
*/
|
|
public function column_workflow_timestamp( $item ) {
|
|
$label = '-';
|
|
|
|
if ( ! empty( $item['workflow_timestamp'] ) ) {
|
|
$last_updated = date( 'Y-m-d H:i:s', $item['workflow_timestamp'] );
|
|
$url_entry = $this->detail_base_url . sprintf( '&id=%d&lid=%d', $item['form_id'], $item['id'] );
|
|
$last_updated = esc_html( GFCommon::format_date( $last_updated, true, 'Y/m/d' ) );
|
|
|
|
/**
|
|
* Allows the field value to be filtered in the status table.
|
|
*
|
|
* @since 1.7.1
|
|
*
|
|
* @param string $label The value to be displayed.
|
|
* @param int $item ['form_id'] The Form ID.
|
|
* @param string 'workflow_timestamp'.
|
|
* @param array $item The entry array.
|
|
*/
|
|
$last_updated = apply_filters( 'gravityflow_field_value_status_table', $last_updated, $item['form_id'], 'workflow_timestamp', $item );
|
|
$url_entry = esc_url( $url_entry );
|
|
$label = "<a href='{$url_entry}'>$last_updated</a>";
|
|
}
|
|
|
|
echo $label;
|
|
}
|
|
|
|
/**
|
|
* Get an associative array ( option_name => option_title ) with the list
|
|
* of bulk actions available on this table.
|
|
*
|
|
* @since 1.0
|
|
* @access protected
|
|
*
|
|
* @return array
|
|
*/
|
|
public function get_bulk_actions() {
|
|
$bulk_actions = $this->bulk_actions;
|
|
|
|
return $bulk_actions;
|
|
}
|
|
|
|
/**
|
|
* Get a list of sortable columns. The format is:
|
|
* 'internal-name' => 'orderby'
|
|
* or
|
|
* 'internal-name' => array( 'orderby', true )
|
|
*
|
|
* The second format will make the initial sorting order be descending
|
|
*
|
|
* @since 1.3.3
|
|
* @access protected
|
|
*
|
|
* @return array
|
|
*/
|
|
public function get_sortable_columns() {
|
|
$sortable_columns = array(
|
|
'id' => array( 'id', false ),
|
|
'created_by' => array( 'created_by', false ),
|
|
'workflow_final_status' => array( 'workflow_final_status', false ),
|
|
'date_created' => array( 'date_created', false ),
|
|
);
|
|
|
|
if ( $this->last_updated ) {
|
|
$sortable_columns['workflow_timestamp'] = array( 'workflow_timestamp', false );
|
|
}
|
|
|
|
$args = $this->get_filter_args();
|
|
|
|
if ( ! empty( $args['form-id'] ) && ! empty( $this->field_ids ) ) {
|
|
$form = $this->get_form( $args['form-id'] );
|
|
|
|
foreach ( $this->field_ids as $field_id ) {
|
|
$field_id = trim( $field_id );
|
|
$field = GFFormsModel::get_field( $form, $field_id );
|
|
if ( is_object( $field ) && in_array( $field->get_input_type(), array( 'workflow_user', 'workflow_assignee_select', 'workflow_role' ) ) ) {
|
|
continue;
|
|
}
|
|
$sortable_columns[ $field_id ] = array( $field_id, false );
|
|
}
|
|
}
|
|
|
|
return $sortable_columns;
|
|
}
|
|
|
|
/**
|
|
* Get the columns to be displayed in the table.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function get_columns() {
|
|
|
|
$args = $this->get_filter_args();
|
|
|
|
$columns['cb'] = esc_html__( 'Checkbox', 'gravityflow' );
|
|
if ( $this->id_column ) {
|
|
$columns['id'] = esc_html__( 'ID', 'gravityflow' );
|
|
}
|
|
$columns['date_created'] = esc_html__( 'Date', 'gravityflow' );
|
|
if ( ! isset( $args['form-id'] ) ) {
|
|
$columns['form_id'] = esc_html__( 'Form', 'gravityflow' );
|
|
}
|
|
if ( $this->submitter_column ) {
|
|
$columns['created_by'] = esc_html__( 'Submitter', 'gravityflow' );
|
|
}
|
|
|
|
if ( $this->step_column ) {
|
|
$columns['workflow_step'] = esc_html__( 'Step', 'gravityflow' );
|
|
}
|
|
|
|
if ( $this->status_column ) {
|
|
$columns['workflow_final_status'] = esc_html__( 'Status', 'gravityflow' );
|
|
}
|
|
|
|
$columns = Gravity_Flow_Common::get_field_columns( $columns, rgar( $args, 'form-id' ), $this->field_ids );
|
|
|
|
if ( $step_id = $this->get_filter_step_id() ) {
|
|
unset( $columns['workflow_step'] );
|
|
$step = gravity_flow()->get_step( $step_id );
|
|
$assignees = $step->get_assignees();
|
|
foreach ( $assignees as $assignee ) {
|
|
$meta_key = sprintf( 'workflow_%s_%s', $assignee->get_type(), $assignee->get_id() );
|
|
$columns[ $meta_key ] = $assignee->get_display_name();
|
|
}
|
|
}
|
|
|
|
if ( $this->last_updated ) {
|
|
$columns['workflow_timestamp'] = esc_html__( 'Last Updated', 'gravityflow' );
|
|
}
|
|
|
|
/**
|
|
* Allows the columns to be filtered for the status table.
|
|
*
|
|
* @since 1.7.1
|
|
*
|
|
* @param array $columns The columns to be filtered
|
|
* @param array $args The array of args for this status table.
|
|
* @param WP_List_Table $this The current WP_List_Table object.
|
|
*/
|
|
$columns = apply_filters( 'gravityflow_columns_status_table', $columns, $args, $this );
|
|
|
|
return $columns;
|
|
}
|
|
|
|
/**
|
|
* Get the step to filter by, if applicable.
|
|
*
|
|
* @return bool|int
|
|
*/
|
|
public function get_filter_step_id() {
|
|
$step_id = false;
|
|
$args = $this->get_filter_args();
|
|
if ( isset( $args['form-id'] ) && isset( $args['field_filters'] ) ) {
|
|
unset( $args['field_filters']['mode'] );
|
|
$criteria = array( 'key' => 'workflow_step' );
|
|
$step_filters = wp_list_filter( $args['field_filters'], $criteria );
|
|
$step_id = count( $step_filters ) > 0 ? $step_filters[0]['value'] : false;
|
|
}
|
|
|
|
return $step_id;
|
|
}
|
|
|
|
/**
|
|
* Get the filter arguments.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function get_filter_args() {
|
|
|
|
if ( isset( $this->_filter_args ) ) {
|
|
return $this->_filter_args;
|
|
}
|
|
|
|
$args = array();
|
|
|
|
if ( ! empty( $this->constraint_filters['form_id'] ) ) {
|
|
$args['form-id'] = absint( $this->constraint_filters['form_id'] );
|
|
} elseif ( ! empty( $_REQUEST['form-id'] ) ) {
|
|
$args['form-id'] = absint( $_REQUEST['form-id'] );
|
|
}
|
|
$f = isset( $_REQUEST['f'] ) ? $_REQUEST['f'] : '';
|
|
if ( ! empty( $args['form-id'] ) && $f !== '' ) {
|
|
$form = $this->get_form( absint( $args['form-id'] ) );
|
|
$field_filters = $this->get_field_filters_from_request( $form );
|
|
$args['field_filters'] = $field_filters;
|
|
}
|
|
|
|
if ( ! empty( $this->constraint_filters['start_date'] ) ) {
|
|
$start_date = $this->constraint_filters['start_date'];
|
|
$start_date_gmt = $this->prepare_start_date_gmt( $start_date );
|
|
$args['start-date'] = $start_date_gmt;
|
|
} elseif ( ! empty( $_REQUEST['start-date'] ) ) {
|
|
$start_date = urldecode( $_REQUEST['start-date'] );
|
|
$start_date = $this->sanitize_date( $start_date );
|
|
$start_date_gmt = $this->prepare_start_date_gmt( $start_date );
|
|
$args['start-date'] = $start_date_gmt;
|
|
}
|
|
|
|
if ( ! empty( $this->constraint_filters['end_date'] ) ) {
|
|
$end_date = $this->constraint_filters['end_date'];
|
|
$end_date_gmt = $this->prepare_end_date_gmt( $end_date );
|
|
$args['end-date'] = $end_date_gmt;
|
|
} elseif ( ! empty( $_REQUEST['end-date'] ) ) {
|
|
$end_date = urldecode( $_REQUEST['end-date'] );
|
|
$end_date = $this->sanitize_date( $end_date );
|
|
$end_date_gmt = $this->prepare_end_date_gmt( $end_date );
|
|
$args['end-date'] = $end_date_gmt;
|
|
}
|
|
|
|
if ( ! empty( $this->constraint_filters['field_filters'] ) ) {
|
|
$constraint_field_filters = $this->constraint_filters['field_filters'];
|
|
if ( ! empty( $constraint_field_filters ) ) {
|
|
$filters = ! empty( $args['field_filters'] ) ? $args['field_filters'] : array();
|
|
$args['field_filters'] = array_merge( $filters, $constraint_field_filters );
|
|
}
|
|
}
|
|
|
|
$this->_filter_args = $args;
|
|
|
|
return $args;
|
|
}
|
|
|
|
/**
|
|
* Sets the filter counts.
|
|
*/
|
|
public function set_counts() {
|
|
|
|
$args = $this->get_filter_args();
|
|
$counts = $this->get_counts( $args );
|
|
$this->total_count = $counts->total;
|
|
$this->pending_count = $counts->pending;
|
|
$this->complete_count = $counts->complete;
|
|
$this->cancelled_count = $counts->cancelled;
|
|
}
|
|
|
|
/**
|
|
* Get the filter counts.
|
|
*
|
|
* @param array $args The filter arguments.
|
|
*
|
|
* @return stdClass|string
|
|
*/
|
|
public function get_counts( $args ) {
|
|
|
|
if ( ! empty( $args['field_filters'] ) ) {
|
|
return $this->get_field_filter_counts( $args );
|
|
}
|
|
|
|
$form_clause = $this->get_form_clause( $args );
|
|
|
|
if ( is_object( $form_clause ) ) {
|
|
return $form_clause;
|
|
}
|
|
|
|
global $wpdb;
|
|
|
|
$start_clause = $this->get_start_clause( $args );
|
|
$end_clause = $this->get_end_clause( $args );
|
|
$user_id_clause = $this->get_user_id_clause();
|
|
|
|
if ( version_compare( $this->get_gravityforms_db_version(), '2.3-dev-1', '<' ) ) {
|
|
$lead_table = GFFormsModel::get_lead_table_name();
|
|
$meta_table = GFFormsModel::get_lead_meta_table_name();
|
|
|
|
$sql = "SELECT
|
|
(SELECT count(distinct(l.id)) FROM $lead_table l WHERE l.status='active' $form_clause $start_clause $end_clause $user_id_clause) as total,
|
|
(SELECT count(distinct(l.id)) FROM $lead_table l INNER JOIN $meta_table m ON l.id = m.lead_id WHERE l.status='active' AND meta_key='workflow_final_status' AND meta_value='pending' $form_clause $start_clause $end_clause $user_id_clause) as pending,
|
|
(SELECT count(distinct(l.id)) FROM $lead_table l INNER JOIN $meta_table m ON l.id = m.lead_id WHERE l.status='active' AND meta_key='workflow_final_status' AND meta_value NOT IN('pending', 'cancelled') $form_clause $start_clause $end_clause $user_id_clause) as complete,
|
|
(SELECT count(distinct(l.id)) FROM $lead_table l INNER JOIN $meta_table m ON l.id = m.lead_id WHERE l.status='active' AND meta_key='workflow_final_status' AND meta_value='cancelled' $form_clause $start_clause $end_clause $user_id_clause) as cancelled
|
|
";
|
|
} else {
|
|
$entry_table = GFFormsModel::get_entry_table_name();
|
|
$meta_table = GFFormsModel::get_entry_meta_table_name();
|
|
|
|
$sql = "SELECT
|
|
(SELECT count(distinct(l.id)) FROM $entry_table l WHERE l.status='active' $form_clause $start_clause $end_clause $user_id_clause) as total,
|
|
(SELECT count(distinct(l.id)) FROM $entry_table l INNER JOIN $meta_table m ON l.id = m.entry_id WHERE l.status='active' AND meta_key='workflow_final_status' AND meta_value='pending' $form_clause $start_clause $end_clause $user_id_clause) as pending,
|
|
(SELECT count(distinct(l.id)) FROM $entry_table l INNER JOIN $meta_table m ON l.id = m.entry_id WHERE l.status='active' AND meta_key='workflow_final_status' AND meta_value NOT IN('pending', 'cancelled') $form_clause $start_clause $end_clause $user_id_clause) as complete,
|
|
(SELECT count(distinct(l.id)) FROM $entry_table l INNER JOIN $meta_table m ON l.id = m.entry_id WHERE l.status='active' AND meta_key='workflow_final_status' AND meta_value='cancelled' $form_clause $start_clause $end_clause $user_id_clause) as cancelled
|
|
";
|
|
}
|
|
|
|
$results = $wpdb->get_results( $sql );
|
|
|
|
return $results[0];
|
|
}
|
|
|
|
/**
|
|
* Get the status counts based on the field filters.
|
|
*
|
|
* @param array $args The status page arguments.
|
|
*
|
|
* @return stdClass
|
|
*/
|
|
public function get_field_filter_counts( $args ) {
|
|
if ( isset( $args['form-id'] ) ) {
|
|
$form_ids = absint( $args['form-id'] );
|
|
} else {
|
|
$form_ids = $this->get_workflow_form_ids();
|
|
}
|
|
|
|
$results = new stdClass();
|
|
$results->total = 0;
|
|
$results->pending = 0;
|
|
$results->complete = 0;
|
|
$results->cancelled = 0;
|
|
|
|
if ( empty( $form_ids ) ) {
|
|
$this->items = array();
|
|
|
|
return $results;
|
|
}
|
|
|
|
$base_search_criteria = $pending_search_criteria = $complete_search_criteria = $cancelled_search_criteria = $this->get_search_criteria();
|
|
|
|
$pending_search_criteria['field_filters'][] = array(
|
|
'key' => 'workflow_final_status',
|
|
'value' => 'pending',
|
|
);
|
|
$complete_search_criteria['field_filters'][] = array(
|
|
'key' => 'workflow_final_status',
|
|
'operator' => 'not in',
|
|
'value' => array( 'pending', 'cancelled' ),
|
|
);
|
|
$cancelled_search_criteria['field_filters'][] = array(
|
|
'key' => 'workflow_final_status',
|
|
'value' => 'cancelled',
|
|
);
|
|
|
|
$results->total = GFAPI::count_entries( $form_ids, $base_search_criteria );
|
|
$results->pending = GFAPI::count_entries( $form_ids, $pending_search_criteria );
|
|
$results->complete = GFAPI::count_entries( $form_ids, $complete_search_criteria );
|
|
$results->cancelled = GFAPI::count_entries( $form_ids, $cancelled_search_criteria );
|
|
|
|
return $results;
|
|
}
|
|
|
|
/**
|
|
* Prepare the form part of the where clause or a basic results object if there are no forms to query.
|
|
*
|
|
* @param array $args The status page arguments.
|
|
*
|
|
* @return stdClass|string
|
|
*/
|
|
public function get_form_clause( $args ) {
|
|
if ( ! empty( $args['form-id'] ) ) {
|
|
$form_clause = ' AND l.form_id=' . absint( $args['form-id'] );
|
|
} else {
|
|
$form_ids = $this->get_workflow_form_ids();
|
|
|
|
if ( empty( $form_ids ) ) {
|
|
$results = new stdClass();
|
|
$results->total = 0;
|
|
$results->pending = 0;
|
|
$results->complete = 0;
|
|
$results->cancelled = 0;
|
|
|
|
return $results;
|
|
}
|
|
$form_clause = ' AND l.form_id IN(' . join( ',', $form_ids ) . ')';
|
|
}
|
|
|
|
return $form_clause;
|
|
}
|
|
|
|
/**
|
|
* If a start-date was specified in the page arguments prepare that part of the where clause.
|
|
*
|
|
* @param array $args The status page arguments.
|
|
*
|
|
* @return string
|
|
*/
|
|
public function get_start_clause( $args ) {
|
|
$start_clause = '';
|
|
|
|
if ( ! empty( $args['start-date'] ) ) {
|
|
global $wpdb;
|
|
$start_clause = $wpdb->prepare( ' AND l.date_created >= %s', $args['start-date'] );
|
|
}
|
|
|
|
return $start_clause;
|
|
}
|
|
|
|
/**
|
|
* If an end-date was specified in the page arguments prepare that part of the where clause.
|
|
*
|
|
* @param array $args The status page arguments.
|
|
*
|
|
* @return string
|
|
*/
|
|
public function get_end_clause( $args ) {
|
|
$end_clause = '';
|
|
|
|
if ( ! empty( $args['end-date'] ) ) {
|
|
global $wpdb;
|
|
$end_clause = $wpdb->prepare( ' AND l.date_created <= %s', $args['end-date'] );
|
|
}
|
|
|
|
return $end_clause;
|
|
}
|
|
|
|
/**
|
|
* If the page is not configured to display entries for all users prepare the created_by part of the where clause.
|
|
*
|
|
* @return string
|
|
*/
|
|
public function get_user_id_clause() {
|
|
$user_id_clause = '';
|
|
|
|
if ( ! $this->display_all ) {
|
|
global $wpdb;
|
|
$user_id_clause = $wpdb->prepare( ' AND created_by=%d', get_current_user_id() );
|
|
}
|
|
|
|
return $user_id_clause;
|
|
}
|
|
|
|
/**
|
|
* Format the start date to be used in the entry search.
|
|
*
|
|
* @param string $start_date The submitted date.
|
|
*
|
|
* @return string
|
|
*/
|
|
public function prepare_start_date_gmt( $start_date ) {
|
|
|
|
try {
|
|
$start_date = new DateTime( $start_date );
|
|
} catch (Exception $e) {
|
|
return '';
|
|
}
|
|
|
|
$start_date_str = $start_date->format( 'Y-m-d H:i:s' );
|
|
$start_date_gmt = get_gmt_from_date( $start_date_str );
|
|
|
|
return $start_date_gmt;
|
|
}
|
|
|
|
/**
|
|
* Format the end date to be used in the entry search.
|
|
*
|
|
* @param string $end_date The submitted date.
|
|
*
|
|
* @return string
|
|
*/
|
|
public function prepare_end_date_gmt( $end_date ) {
|
|
|
|
try {
|
|
$end_date = new DateTime( $end_date );
|
|
} catch (Exception $e) {
|
|
return '';
|
|
}
|
|
|
|
$end_datetime_str = $end_date->format( 'Y-m-d H:i:s' );
|
|
$end_date_str = $end_date->format( 'Y-m-d' );
|
|
|
|
// Extend end date till the end of the day unless a time was specified. 00:00:00 is ignored.
|
|
if ( $end_datetime_str == $end_date_str . ' 00:00:00' ) {
|
|
$end_date = $end_date->format( 'Y-m-d' ) . ' 23:59:59';
|
|
} else {
|
|
$end_date = $end_date->format( 'Y-m-d H:i:s' );
|
|
}
|
|
$end_date_gmt = get_gmt_from_date( $end_date );
|
|
|
|
return $end_date_gmt;
|
|
}
|
|
|
|
/**
|
|
* Get an array of form IDs which have workflows.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function get_workflow_form_ids() {
|
|
return gravity_flow()->get_workflow_form_ids();
|
|
}
|
|
|
|
/**
|
|
* Output the columns for a single row.
|
|
*
|
|
* @param array $item The entry.
|
|
*/
|
|
protected function single_row_columns( $item ) {
|
|
list( $columns, $hidden ) = $this->get_column_info();
|
|
|
|
foreach ( $columns as $column_name => $column_display_name ) {
|
|
$class = "class='$column_name column-$column_name'";
|
|
|
|
$style = '';
|
|
if ( in_array( $column_name, $hidden ) ) {
|
|
$style = ' style="display:none;"';
|
|
}
|
|
|
|
$data_label = ( ! empty( $column_display_name ) ) ? " data-label='$column_display_name'" : '';
|
|
|
|
$attributes = "$class$style$data_label";
|
|
|
|
if ( 'cb' == $column_name ) {
|
|
echo '<th data-label="' . esc_html__( 'Select', 'gravityflow' ) . '" scope="row" class="check-column">';
|
|
echo $this->column_cb( $item );
|
|
echo '</th>';
|
|
} elseif ( method_exists( $this, 'column_' . $column_name ) ) {
|
|
echo "<td $attributes>";
|
|
echo call_user_func( array( $this, 'column_' . $column_name ), $item );
|
|
echo '</td>';
|
|
} else {
|
|
echo "<td $attributes>";
|
|
echo $this->column_default( $item, $column_name );
|
|
echo '</td>';
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Gets the entries to be included in the table.
|
|
*/
|
|
public function prepare_items() {
|
|
|
|
$filter_args = $this->get_filter_args();
|
|
|
|
if ( isset( $filter_args['form-id'] ) ) {
|
|
$form_ids = absint( $filter_args['form-id'] );
|
|
$this->apply_entry_meta( $form_ids );
|
|
} else {
|
|
$form_ids = $this->get_workflow_form_ids();
|
|
|
|
if ( empty( $form_ids ) ) {
|
|
$this->items = array();
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
$columns = $this->get_columns();
|
|
$hidden = array();
|
|
$sortable = $this->get_sortable_columns();
|
|
$this->_column_headers = array( $columns, $hidden, $sortable );
|
|
|
|
$search_criteria = $this->get_search_criteria();
|
|
|
|
$orderby = ( ! empty( $_REQUEST['orderby'] ) ) ? $_REQUEST['orderby'] : 'date_created';
|
|
|
|
$order = ( ! empty( $_REQUEST['order'] ) ) ? $_REQUEST['order'] : 'desc';
|
|
|
|
$user = get_current_user_id();
|
|
if ( function_exists( 'get_current_screen' ) ) {
|
|
$screen = get_current_screen();
|
|
if ( $screen ) {
|
|
$option = $screen->get_option( 'per_page', 'option' );
|
|
}
|
|
}
|
|
|
|
$per_page_setting = ! empty( $option ) ? get_user_meta( $user, $option, true ) : false;
|
|
$per_page = empty( $per_page_setting ) ? $this->per_page : $per_page_setting;
|
|
|
|
$page_size = $per_page;
|
|
$current_page = $this->get_pagenum();
|
|
$offset = $page_size * ( $current_page - 1 );
|
|
|
|
$paging = array( 'page_size' => $page_size, 'offset' => $offset );
|
|
|
|
$total_count = 0;
|
|
|
|
$sorting = array( 'key' => $orderby, 'direction' => $order );
|
|
|
|
/**
|
|
* Allows form id(s) to be adjusted to define which forms' entries are displayed in status table.
|
|
*
|
|
* Return an array of form ids for use with GFAPI.
|
|
*
|
|
* @since 2.2.2-dev
|
|
*
|
|
* @param array $form_ids The form ids
|
|
* @param array $search_criteria The search criteria
|
|
*/
|
|
$form_ids = apply_filters( 'gravityflow_form_ids_status', $form_ids, $search_criteria );
|
|
|
|
gravity_flow()->log_debug( __METHOD__ . '(): search criteria: ' . print_r( $search_criteria, true ) );
|
|
|
|
$entries = GFAPI::get_entries( $form_ids, $search_criteria, $sorting, $paging, $total_count );
|
|
|
|
gravity_flow()->log_debug( __METHOD__ . '(): count entries: ' . count( $entries ) );
|
|
gravity_flow()->log_debug( __METHOD__ . '(): total count: ' . $total_count );
|
|
|
|
$this->pagination_args = array(
|
|
'total_items' => $total_count,
|
|
'per_page' => $page_size,
|
|
);
|
|
|
|
$this->set_pagination_args( $this->pagination_args );
|
|
|
|
$this->items = $entries;
|
|
}
|
|
|
|
/**
|
|
* Get the search criteria array for use with the GFAPI.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function get_search_criteria() {
|
|
$filter_args = $this->get_filter_args();
|
|
|
|
global $current_user;
|
|
$search_criteria['status'] = 'active';
|
|
|
|
if ( ! empty( $filter_args['start-date'] ) ) {
|
|
$search_criteria['start_date'] = $filter_args['start-date'];
|
|
}
|
|
if ( ! empty( $filter_args['end-date'] ) ) {
|
|
$search_criteria['end_date'] = $filter_args['end-date'];
|
|
}
|
|
|
|
if ( ! empty( $_REQUEST['entry-id'] ) ) {
|
|
$search_criteria['field_filters'][] = array(
|
|
'key' => 'id',
|
|
'value' => absint( $_REQUEST['entry-id'] ),
|
|
);
|
|
}
|
|
|
|
if ( ! empty( $_REQUEST['status'] ) ) {
|
|
if ( $_REQUEST['status'] == 'complete' ) {
|
|
$search_criteria['field_filters'][] = array(
|
|
'key' => 'workflow_final_status',
|
|
'operator' => 'not in',
|
|
'value' => array( 'pending', 'cancelled' ),
|
|
);
|
|
} else {
|
|
$search_criteria['field_filters'][] = array(
|
|
'key' => 'workflow_final_status',
|
|
'value' => sanitize_text_field( $_REQUEST['status'] ),
|
|
);
|
|
}
|
|
}
|
|
|
|
if ( ! $this->display_all ) {
|
|
$search_criteria['field_filters'][] = array(
|
|
'key' => 'created_by',
|
|
'value' => $current_user->ID,
|
|
);
|
|
}
|
|
|
|
if ( ! empty( $filter_args['field_filters'] ) ) {
|
|
$filters = ! empty( $search_criteria['field_filters'] ) ? $search_criteria['field_filters'] : array();
|
|
$search_criteria['field_filters'] = array_merge( $filters, $filter_args['field_filters'] );
|
|
$search_criteria['field_filters']['mode'] = 'all';
|
|
}
|
|
|
|
return $search_criteria;
|
|
}
|
|
|
|
/**
|
|
* Get an array of submitted field filters.
|
|
*
|
|
* @param array $form The current form.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function get_field_filters_from_request( $form ) {
|
|
$field_filters = array();
|
|
$filter_fields = isset( $_REQUEST['f'] ) ? $_REQUEST['f'] : '';
|
|
if ( is_array( $filter_fields ) && $filter_fields[0] !== '' ) {
|
|
$filter_operators = $_REQUEST['o'];
|
|
$filter_values = $_REQUEST['v'];
|
|
for ( $i = 0; $i < count( $filter_fields ); $i ++ ) {
|
|
$field_filter = array();
|
|
$key = $filter_fields[ $i ];
|
|
if ( 'entry_id' == $key ) {
|
|
$key = 'id';
|
|
}
|
|
$operator = $filter_operators[ $i ];
|
|
$val = $filter_values[ $i ];
|
|
$strpos_row_key = strpos( $key, '|' );
|
|
if ( $strpos_row_key !== false ) { // Multi-row likert.
|
|
$key_array = explode( '|', $key );
|
|
$key = $key_array[0];
|
|
$val = $key_array[1] . ':' . $val;
|
|
}
|
|
$field_filter['key'] = $key;
|
|
|
|
$field = GFFormsModel::get_field( $form, $key );
|
|
if ( $field ) {
|
|
$input_type = GFFormsModel::get_input_type( $field );
|
|
if ( $field->type == 'product' && in_array( $input_type, array( 'radio', 'select' ) ) ) {
|
|
$operator = 'contains';
|
|
}
|
|
}
|
|
|
|
$field_filter['operator'] = $operator;
|
|
$field_filter['value'] = $val;
|
|
$field_filters[] = $field_filter;
|
|
}
|
|
}
|
|
$field_filters['mode'] = isset( $_REQUEST['mode'] ) ? $_REQUEST['mode'] : '';
|
|
|
|
return $field_filters;
|
|
}
|
|
|
|
/**
|
|
* Get the steps for the specified form.
|
|
*
|
|
* @param int $form_id The form ID.
|
|
*
|
|
* @return Gravity_Flow_Step[]
|
|
*/
|
|
public function get_steps( $form_id ) {
|
|
if ( ! isset( $this->_steps ) ) {
|
|
$this->_steps = gravity_flow()->get_steps( $form_id );
|
|
|
|
}
|
|
|
|
return $this->_steps;
|
|
}
|
|
|
|
/**
|
|
* Add the assignee status and timestamp of each step to the entry meta.
|
|
*
|
|
* @param int $form_id The form ID.
|
|
*/
|
|
public function apply_entry_meta( $form_id ) {
|
|
global $_entry_meta;
|
|
|
|
$_entry_meta[ $form_id ] = apply_filters( 'gform_entry_meta', array(), $form_id );
|
|
|
|
$steps = $this->get_steps( $form_id );
|
|
|
|
$entry_meta = array();
|
|
|
|
foreach ( $steps as $step ) {
|
|
$assignees = $step->get_assignees();
|
|
foreach ( $assignees as $assignee ) {
|
|
$meta_key = sprintf( 'workflow_%s_%s', $assignee->get_type(), $assignee->get_id() );
|
|
$entry_meta[ $meta_key ] = array(
|
|
'label' => __( 'Status:', 'gravityflow' ) . ' ' . $assignee->get_id(),
|
|
'is_numeric' => false,
|
|
'is_default_column' => false,
|
|
);
|
|
$entry_meta[ $meta_key . '_timestamp' ] = array(
|
|
'label' => __( 'Status:', 'gravityflow' ) . ' ' . $assignee->get_id(),
|
|
'is_numeric' => false,
|
|
'is_default_column' => false,
|
|
);
|
|
}
|
|
}
|
|
|
|
$_entry_meta[ $form_id ] = array_merge( $_entry_meta[ $form_id ], $entry_meta );
|
|
}
|
|
|
|
/**
|
|
* Format the duration for output.
|
|
*
|
|
* @param int $seconds The duration in seconds.
|
|
*
|
|
* @return string
|
|
*/
|
|
public function format_duration( $seconds ) {
|
|
return gravity_flow()->format_duration( $seconds );
|
|
}
|
|
|
|
/**
|
|
* Prepare the column headers to be included in the export.
|
|
*
|
|
* @param bool $echo Indicates if the content should be echoed.
|
|
*
|
|
* @return string
|
|
*/
|
|
public function export_column_names( $echo = true ) {
|
|
$columns = $this->get_columns();
|
|
|
|
if ( isset( $columns['workflow_final_status'] ) ) {
|
|
$final_status_offset = array_search('workflow_final_status',array_keys($columns)) + 1;
|
|
$columns = array_slice($columns, 0, $final_status_offset, true) + array('duration' => esc_html__( 'Duration', 'gravityflow' )) + array_slice($columns, $final_status_offset, NULL, true);
|
|
}
|
|
|
|
$export_arr = array();
|
|
|
|
foreach ( $columns as $key => $column_title ) {
|
|
if ( $key == 'cb' ) {
|
|
continue;
|
|
}
|
|
$export_arr[] = '"' . $column_title . '"';
|
|
}
|
|
|
|
return join( ',', $export_arr ) . "\r\n";
|
|
}
|
|
|
|
/**
|
|
* Process the selected bulk action.
|
|
*/
|
|
public function process_bulk_action() {
|
|
|
|
$bulk_action = $this->current_action();
|
|
|
|
if ( empty( $bulk_action ) ) {
|
|
return;
|
|
}
|
|
|
|
if ( isset( $_POST['_wpnonce'] ) && ! empty( $_POST['_wpnonce'] ) ) {
|
|
|
|
$nonce = filter_input( INPUT_POST, '_wpnonce', FILTER_SANITIZE_STRING );
|
|
$nonce_action = 'bulk-' . $this->_args['plural'];
|
|
|
|
if ( ! wp_verify_nonce( $nonce, $nonce_action ) ) {
|
|
wp_die();
|
|
}
|
|
}
|
|
|
|
$entry_ids = rgpost( 'entry_ids' );
|
|
if ( empty( $entry_ids ) || ! is_array( $entry_ids ) ) {
|
|
return;
|
|
}
|
|
|
|
$entry_ids = wp_parse_id_list( $entry_ids );
|
|
|
|
$feedback = '';
|
|
|
|
/**
|
|
* Allows custom bulk actions to be processed in the status table.
|
|
*
|
|
* Return a string for a standard admin message. Return an instance of WP_Error to display an error.
|
|
*
|
|
* @param string|WP_Error $feedback The admin message.
|
|
* @param string $bulk_action The action.
|
|
* @param array $entry_ids The entry IDs to be processed.
|
|
* @param array $this ->args The args for this table.
|
|
*/
|
|
$feedback = apply_filters( 'gravityflow_bulk_action_status_table', $feedback, $bulk_action, $entry_ids, $this->args );
|
|
|
|
if ( ! empty( $feedback ) ) {
|
|
if ( is_wp_error( $feedback ) ) {
|
|
$this->display_message( $feedback->get_error_message(), true );
|
|
} else {
|
|
$this->display_message( $feedback );
|
|
}
|
|
return;
|
|
}
|
|
|
|
if ( $bulk_action !== 'restart_workflow' ) {
|
|
return;
|
|
}
|
|
|
|
$forms = array();
|
|
foreach ( $entry_ids as $entry_id ) {
|
|
$entry = GFAPI::get_entry( $entry_id );
|
|
$form_id = absint( $entry['form_id'] );
|
|
if ( ! isset( $forms[ $form_id ] ) ) {
|
|
$forms[ $form_id ] = $this->get_form( $form_id );
|
|
}
|
|
$form = $forms[ $form_id ];
|
|
$current_step = gravity_flow()->get_current_step( $form, $entry );
|
|
if ( $current_step ) {
|
|
$assignees = $current_step->get_assignees();
|
|
foreach ( $assignees as $assignee ) {
|
|
$assignee->remove();
|
|
}
|
|
}
|
|
$feedback = esc_html__( 'Workflow restarted.', 'gravityflow' );
|
|
gravity_flow()->add_timeline_note( $entry_id, $feedback );
|
|
gform_update_meta( $entry_id, 'workflow_final_status', 'pending' );
|
|
gform_update_meta( $entry_id, 'workflow_step', false );
|
|
gravity_flow()->log_event( 'workflow', 'restarted', $form_id, $entry_id );
|
|
gravity_flow()->process_workflow( $form, $entry_id );
|
|
|
|
}
|
|
|
|
$message = esc_html__( 'Workflows restarted.', 'gravityflow' );
|
|
$this->display_message( $message );
|
|
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* Displays an error or updated type message.
|
|
*
|
|
* @since 1.8.1-dev
|
|
*
|
|
* @param string $message The message to be displayed.
|
|
* @param bool $is_error Is this an error message? Default false.
|
|
*/
|
|
public function display_message( $message, $is_error = false ) {
|
|
$class = $is_error ? 'error' : 'updated';
|
|
|
|
echo '<div class="' . $class . ' below-h2"><p><strong>' . esc_html( $message ) . '</strong></p></div>';
|
|
}
|
|
|
|
/**
|
|
* Prepare the data to be included in the export.
|
|
*
|
|
* @return string
|
|
*/
|
|
public function export() {
|
|
|
|
$export = '';
|
|
$rows = array();
|
|
$columns = $this->get_columns();
|
|
if ( isset( $columns['workflow_final_status'] ) ) {
|
|
$final_status_offset = array_search('workflow_final_status',array_keys($columns)) + 1;
|
|
$columns = array_slice($columns, 0, $final_status_offset, true) + array('duration' => esc_html__( 'Duration', 'gravityflow' )) + array_slice($columns, $final_status_offset, NULL, true);
|
|
}
|
|
$column_keys = array_keys( $columns );
|
|
|
|
if ( ( $cb = array_search( 'cb', $column_keys ) ) !== false ) {
|
|
unset( $column_keys[ $cb ] );
|
|
}
|
|
|
|
foreach ( $this->items as $item ) {
|
|
$row_values = array();
|
|
foreach ( $column_keys as $column_key ) {
|
|
$col_val = null;
|
|
if ( array_key_exists( $column_key, $item ) ) {
|
|
switch ( $column_key ) {
|
|
case 'form_id' :
|
|
$form_id = rgar( $item, 'form_id' );
|
|
$form = $this->get_form( $form_id );
|
|
$col_val = $form['title'];
|
|
break;
|
|
case 'created_by' :
|
|
$user_id = $item['created_by'];
|
|
if ( $user_id ) {
|
|
$user = get_user_by( 'id', $user_id );
|
|
if ( empty( $user ) || is_wp_error( $user ) ) {
|
|
$col_val = $user_id . ' ' . esc_html__( '(deleted)', 'gravityflow' );
|
|
} else {
|
|
$col_val = $user->display_name;
|
|
}
|
|
} else {
|
|
$col_val = $item['ip'];
|
|
}
|
|
break;
|
|
case 'workflow_step' :
|
|
$step_id = rgar( $item, 'workflow_step' );
|
|
if ( $step_id > 0 ) {
|
|
$step = gravity_flow()->get_step( $step_id );
|
|
$col_val = $step ? $step->get_name() : $step_id;
|
|
} else {
|
|
$col_val = $step_id;
|
|
}
|
|
break;
|
|
default :
|
|
$col_val = $item[ $column_key ];
|
|
}
|
|
} else {
|
|
switch ( $column_key ) {
|
|
case 'duration':
|
|
if( $item[ 'workflow_final_status' ] == 'pending' ) {
|
|
$duration = time() - strtotime( $item['date_created'] );
|
|
$duration_str = $this->format_duration( $duration );
|
|
$col_val = $duration_str;
|
|
} else {
|
|
$col_val = '';
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Allows the field value to be filtered in the status table.
|
|
*
|
|
* @since 1.7.1
|
|
*
|
|
* @param string $label The value to be displayed
|
|
* @param int $item['form_id'] The Form ID
|
|
* @param string 'id'
|
|
* @param array $item The entry array.
|
|
*/
|
|
$col_val = apply_filters( 'gravityflow_field_value_status_table', $col_val, $item['form_id'], $column_key, $item );
|
|
|
|
if ( null !== $col_val ) {
|
|
$row_values[] = '"' . addslashes( $col_val ) . '"';
|
|
}
|
|
}
|
|
$rows[] = join( ',', $row_values );
|
|
}
|
|
|
|
$export .= join( "\r\n", $rows );
|
|
|
|
return $export . "\r\n";
|
|
}
|
|
|
|
/**
|
|
* Removes all characters except numbers and hyphens.
|
|
*
|
|
* @param string $unsafe_date The date to be sanitized.
|
|
*
|
|
* @return string
|
|
*/
|
|
public function sanitize_date( $unsafe_date ) {
|
|
$safe_date = preg_replace( '([^0-9-])', '', $unsafe_date );
|
|
|
|
return (string) $safe_date;
|
|
}
|
|
|
|
/**
|
|
* Get the specified form.
|
|
*
|
|
* @param int $form_id The form ID.
|
|
*
|
|
* @return array
|
|
*/
|
|
private function get_form( $form_id ) {
|
|
if ( isset( $this->_forms[ $form_id ] ) ) {
|
|
return $this->_forms[ $form_id ];
|
|
}
|
|
|
|
$this->_forms[ $form_id ] = GFAPI::get_form( $form_id );
|
|
|
|
return $this->_forms[ $form_id ];
|
|
}
|
|
|
|
/**
|
|
* Get the Gravity Forms database version number.
|
|
*
|
|
* @return string
|
|
*/
|
|
private function get_gravityforms_db_version() {
|
|
return Gravity_Flow_Common::get_gravityforms_db_version();
|
|
}
|
|
}
|