File: /dom877180/wp-content/plugins/gravityview/includes/fields/class-gravityview-field-sequence.php
<?php
/**
* @file class-gravityview-field-sequence.php
* @package GravityView
* @subpackage includes\fields
*/
/**
* Add a sequence field.
* @since 2.3.3
*/
class GravityView_Field_Sequence extends GravityView_Field {
var $name = 'sequence';
var $contexts = array( 'single', 'multiple' );
/**
* @var bool
*/
var $is_sortable = false;
/**
* @var bool
*/
var $is_searchable = false;
/**
* @var bool
*/
var $is_numeric = true;
var $_custom_merge_tag = 'sequence';
var $group = 'gravityview';
var $icon = 'dashicons-editor-ol';
public function __construct() {
$this->label = esc_html__( 'Number Sequence', 'gk-gravityview' );
$this->description = esc_html__( 'Display a sequential result number for each entry.', 'gk-gravityview' );
add_filter( 'gravityview/metaboxes/tooltips', array( $this, 'field_tooltips') );
add_filter( 'gravityview_entry_default_fields', array( $this, 'add_default_field' ), 10, 3 );
parent::__construct();
}
/**
* Add as a default field, outside those set in the Gravity Form form
*
* @since 2.10 Moved here from GravityView_Admin_Views::get_entry_default_fields
*
* @param array $entry_default_fields Existing fields
* @param string|array $form form_ID or form object
* @param string $zone Either 'single', 'directory', 'edit', 'header', 'footer'
*
* @return array
*/
public function add_default_field( $entry_default_fields, $form = array(), $zone = '' ) {
if ( 'edit' === $zone ) {
return $entry_default_fields;
}
$entry_default_fields['sequence'] = array(
'label' => __( 'Result Number', 'gk-gravityview' ),
'type' => $this->name,
'desc' => $this->description,
'icon' => $this->icon,
'group' => 'gravityview',
);
return $entry_default_fields;
}
/**
* Add tooltips
* @param array $tooltips Existing tooltips
* @return array Modified tooltips
*/
public function field_tooltips( $tooltips ) {
$return = $tooltips;
$return['reverse_sequence'] = array(
'title' => __('Reverse the order of the result numbers', 'gk-gravityview'),
'value' => __('Output the number sequence in descending order. If enabled, numbers will count down from high to low.', 'gk-gravityview'),
);
return $return;
}
public function field_options( $field_options, $template_id, $field_id, $context, $input_type, $form_id ) {
unset ( $field_options['search_filter'] );
$new_fields = array(
'start' => array(
'type' => 'number',
'label' => __( 'First Number in the Sequence', 'gk-gravityview' ),
'desc' => __('For each entry, the displayed number will increase by one. When displaying ten entries, the first entry will display "1", and the last entry will show "10".', 'gk-gravityview'),
'value' => '1',
'merge_tags' => false,
),
'reverse' => array(
'type' => 'checkbox',
'label' => __( 'Reverse the order of the number sequence (high to low)', 'gk-gravityview' ),
'tooltip' => 'reverse_sequence',
'value' => '',
),
);
return $new_fields + $field_options;
}
/**
* Replace {sequence} Merge Tags inside Custom Content fields
*
* TODO:
* - Find a better way to infer current View data (without using legacy code)
*
* @param array $matches
* @param string $text
* @param array $form
* @param array $entry
* @param bool $url_encode
* @param bool $esc_html
*
* @return string
*/
public function replace_merge_tag( $matches = array(), $text = '', $form = array(), $entry = array(), $url_encode = false, $esc_html = false ) {
/**
* An internal cache for sequence tag reuse within one field.
* Avoids calling get_sequence over and over again, off-by-many increments, etc.
*/
static $merge_tag_sequences = array();
$view_data = gravityview_get_current_view_data(); // TODO: Don't use legacy code...
// If we're not in a View or embed, don't replace the merge tag
if ( empty( $view_data ) ) {
gravityview()->log->error( '{sequence} Merge Tag used outside of a GravityView View.', array( 'data' => $matches ) );
return $text;
}
$legacy_field = \GravityView_View::getInstance()->getCurrentField(); // TODO: Don't use legacy code...
// If we're outside field context (like a GV widget), don't replace the merge tag
if ( ! $legacy_field ) {
gravityview()->log->error( '{sequence} Merge Tag was used without outside of the GravityView entry loop.', array( 'data' => $matches ) );
return $text;
}
$return = $text;
$context = new \GV\Template_Context();
$context->view = \GV\View::by_id( $view_data['view_id'] );
$context->entry = \GV\GF_Entry::from_entry( $entry );
$gv_field = \GV\Internal_Field::by_id( 'sequence' );
$merge_tag_context = \GV\Utils::get( $legacy_field, 'UID' );
$merge_tag_context = $entry['id'] . "/{$merge_tag_context}";
foreach ( $matches as $match ) {
$full_tag = $match[0];
$property = $match[1];
$gv_field->reverse = false;
$gv_field->start = 1;
$modifiers = explode( ',', trim( $property ) );
foreach ( $modifiers as $modifier ) {
$modifier = trim( $modifier );
if ( 'reverse' === $modifier ) {
$gv_field->reverse = true;
}
$maybe_start = explode( ':', $modifier );
// If there is a field with the ID of the start number, the merge tag won't work.
// In that case, you can use "=" instead: `{sequence start=10}`
if( 1 === sizeof( $maybe_start ) ) {
$maybe_start = explode( '=', $modifier );
}
if ( 'start' === rgar( $maybe_start, 0 ) && is_numeric( rgar( $maybe_start, 1 ) ) ) {
$gv_field->start = (int) rgar( $maybe_start, 1 );
}
}
/**
* We make sure that distinct sequence modifiers have their own
* output counters.
*/
$merge_tag_context_modifiers = $merge_tag_context . '/' . var_export( $gv_field->reverse, true ) . '/' . $gv_field->start;
if ( ! isset( $merge_tag_sequences[ $merge_tag_context_modifiers ] ) ) {
$gv_field->UID = $legacy_field['UID'] . '/' . var_export( $gv_field->reverse, true ) . '/' . $gv_field->start;
$context->field = $gv_field;
$sequence = $merge_tag_sequences[ $merge_tag_context_modifiers ] = $this->get_sequence( $context );
} else {
$sequence = $merge_tag_sequences[ $merge_tag_context_modifiers ];
}
$return = str_replace( $full_tag, $sequence, $return );
}
return $return;
}
/**
* Calculate the current sequence number for the context.
*
* @param \GV\Template_Context $context The context.
*
* @return int The sequence number for the field/entry within the view results.
*/
public function get_sequence( $context ) {
static $startlines = array();
$context_key = md5( json_encode(
array(
$context->view->ID,
\GV\Utils::get( $context, 'field/UID' ),
)
) );
/**
* Figure out the starting number.
*/
if ( $context->request && $entry = $context->request->is_entry() ) {
$sql_query = array();
add_filter( 'gform_gf_query_sql', $callback = function( $sql ) use ( &$sql_query ) {
$sql_query = $sql;
return $sql;
} );
$total = $context->view->get_entries()->total();
remove_filter( 'gform_gf_query_sql', $callback );
unset( $sql_query['paginate'] );
global $wpdb;
foreach ( $wpdb->get_results( implode( ' ', $sql_query ), ARRAY_A ) as $n => $result ) {
if ( in_array( $entry->ID, $result ) ) {
return $context->field->reverse ? ( $total - $n ) : ( $n + 1 );
}
}
return 0;
} elseif ( ! isset( $startlines[ $context_key ] ) ) {
$pagenum = max( 0, \GV\Utils::_GET( 'pagenum', 1 ) - 1 );
$pagesize = $context->view->settings->get( 'page_size', 25 );
if ( $context->field->reverse ) {
$startlines[ $context_key ] = $context->view->get_entries()->total() - ( $pagenum * $pagesize );
$startlines[ $context_key ] += $context->field->start - 1;
} else {
$startlines[ $context_key ] = ( $pagenum * $pagesize ) + $context->field->start;
}
}
return $context->field->reverse ? $startlines[ $context_key ]-- : $startlines[ $context_key ]++;
}
}
new GravityView_Field_Sequence;