Completed
Push — develop ( 7bce7b...c273e7 )
by Zack
16:53
created

GravityView_Field_Sequence::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 8
ccs 0
cts 3
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * @file class-gravityview-field-sequence.php
4
 * @package GravityView
5
 * @subpackage includes\fields
6
 */
7
8
/**
9
 * Add a sequence field.
10
 * @since develop
11
 */
12
class GravityView_Field_Sequence extends GravityView_Field {
13
14
	var $name = 'sequence';
15
16
	var $contexts = array( 'single', 'multiple' );
17
18
	/**
19
	 * @var bool
20
	 */
21
	var $is_sortable = false;
22
23
	/**
24
	 * @var bool
25
	 */
26
	var $is_searchable = false;
27
28
	/**
29
	 * @var bool
30
	 */
31
	var $is_numeric = true;
32
33
	var $_custom_merge_tag = 'sequence';
34
35
	var $group = 'gravityview';
36
37
	public function __construct() {
38
39
		$this->label = esc_html__( 'Result Number', 'gravityview' );
40
41
		add_filter( 'gravityview/metaboxes/tooltips', array( $this, 'field_tooltips') );
42
43
		parent::__construct();
44
	}
45
46
	/**
47
	 * Add tooltips
48
	 * @param  array $tooltips Existing tooltips
49
	 * @return array           Modified tooltips
50
	 */
51
	public function field_tooltips( $tooltips ) {
52
53
		$return = $tooltips;
54
55
		$return['reverse_sequence'] = array(
56
			'title' => __('Reverse the order of the result numbers', 'gravityview'),
57
			'value' => __('Output row numbers in descending order. If enabled, numbers will go from high to low.', 'gravityview'),
58
		);
59
60
		return $return;
61
	}
62
63
	public function field_options( $field_options, $template_id, $field_id, $context, $input_type ) {
64 2
65 2
		unset ( $field_options['search_filter'] );
66
67 2
		$new_fields = array(
68
			'start' => array(
69 2
				'type' => 'number',
70 2
				'label' => __( 'First Row Number', 'gravityview' ),
71
				'value' => '1',
72
				'merge_tags' => false,
73
			),
74
			'reverse' => array(
75
				'type' => 'checkbox',
76
				'label' => __( 'Reverse the order of the result numbers', 'gravityview' ),
77 2
				'tooltip' => 'reverse_sequence',
78 1
				'value' => '',
79 1
			),
80 1
		);
81 1
82 1
		return $new_fields + $field_options;
83
	}
84
85
	/**
86
	 * Replace {sequence} Merge Tags inside Custom Content fields
87
	 *
88
	 * TODO:
89
	 * - Find a better way to infer current View data (without using legacy code)
90
	 * - Add tests
91
	 *
92
	 * @param array $matches
93
	 * @param string $text
94
	 * @param array $form
95
	 * @param array $entry
96
	 * @param bool $url_encode
97
	 * @param bool $esc_html
98
	 *
99
	 * @return string
100
	 */
101
	public function replace_merge_tag( $matches = array(), $text = '', $form = array(), $entry = array(), $url_encode = false, $esc_html = false ) {
102
103
104
		$view_data = gravityview_get_current_view_data(); // TODO: Don't use legacy code...
105
106
		if ( empty( $view_data ) ) {
107
			return '';
108
		}
109
110
		$return = $text;
111
112
		$context = new \GV\Template_Context();
113
		$context->view = \GV\View::by_id( $view_data['view_id'] );
114
		$context->entry = \GV\GF_Entry::from_entry( $entry );
115
116
		$gv_field = \GV\Internal_Field::by_id( 'sequence' );
117
118
		foreach ( $matches as $match ) {
119
120
			$full_tag = $match[0];
121
			$property = $match[1];
122
123
			$gv_field->reverse = false;
0 ignored issues
show
Bug introduced by
The property reverse does not seem to exist in GV\Internal_Field.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
124
			$gv_field->start = 1;
0 ignored issues
show
Bug introduced by
The property start does not seem to exist in GV\Internal_Field.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
125
126
			$modifiers = explode( ',', trim( $property ) );
127
128
			foreach ( $modifiers as $modifier ) {
129
130
				$modifier = trim( $modifier );
131
132
				if ( 'reverse' === $modifier ) {
133
					$gv_field->reverse = true;
134
				}
135
136
				$maybe_start = explode( ':', $modifier );
137
138
				if( 'start' === rgar( $maybe_start, 0 ) && is_numeric( rgar( $maybe_start, 1 ) ) ) {
139
					$gv_field->start = (int) rgar( $maybe_start, 1 );
140
				}
141
			}
142
143
			$context->field = $gv_field;
144
145
			$return = str_replace( $full_tag, $this->get_sequence( $context ), $return );
146
		}
147
148
		return $return;
149
	}
150
151
	/**
152
	 * Calculate the current sequence number for the context.
153
	 *
154
	 * @param  \GV\Template_Context $context The context.
155
	 *
156
	 * @return int The sequence number for the field/entry within the view results.
157
	 */
158
	public function get_sequence( $context ) {
159
		static $startlines = array();
160
161
		$context_key = md5( json_encode(
162
			array(
163
				$context->view->ID,
164
				\GV\Utils::get( $context, 'field/UID' ), //TODO: Generate UID when using Merge Tag
165
			)
166
		) );
167
168
		/**
169
		 * Figure out the starting number.
170
		 */
171
		if ( $context->request && $entry = $context->request->is_entry() ) {
172
			$sql_query = '';
173
			add_filter( 'gform_gf_query_sql', $callback = function( $sql ) use ( &$sql_query ) {
174
				$sql_query = $sql;
175
				return $sql;
176
			} );
177
178
			$total = $context->view->get_entries()->total();
179
			remove_filter( 'gform_gf_query_sql', $callback );
180
181
			unset( $sql_query['paginate'] );
182
183
			global $wpdb;
184
185
			foreach ( $wpdb->get_results( implode( ' ', $sql_query ), ARRAY_A ) as $n => $result ) {
186
				if ( in_array( $entry->ID, $result ) ) {
187
					return $context->field->reverse ? ( $total - $n ) : ( $n + 1 );
0 ignored issues
show
Documentation introduced by
The property reverse does not exist on object<GV\Field>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
188
				}
189
			}
190
191
			return 0;
192
		} elseif ( ! isset( $startlines[ $context_key ] ) ) {
193
			$pagenum  = max( 0, \GV\Utils::_GET( 'pagenum', 1 ) - 1 );
194
			$pagesize = $context->view->settings->get( 'page_size', 25 );
195
196
			if ( $context->field->reverse ) {
0 ignored issues
show
Documentation introduced by
The property reverse does not exist on object<GV\Field>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
197
				$startlines[ $context_key ] = $context->view->get_entries()->total() - ( $pagenum * $pagesize );
198
				$startlines[ $context_key ] += $context->field->start - 1;
0 ignored issues
show
Documentation introduced by
The property start does not exist on object<GV\Field>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
199
			} else {
200
				$startlines[ $context_key ] = ( $pagenum * $pagesize ) + $context->field->start;
0 ignored issues
show
Documentation introduced by
The property start does not exist on object<GV\Field>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
201
			}
202
		}
203
204
		return $context->field->reverse ? $startlines[ $context_key ]-- : $startlines[ $context_key ]++;
0 ignored issues
show
Documentation introduced by
The property reverse does not exist on object<GV\Field>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
205
	}
206
}
207
208
new GravityView_Field_Sequence;
209