plugin install
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Gravity_Forms\Gravity_Forms\Query\Batch_Processing;
|
||||
|
||||
|
||||
use Gravity_Forms\Gravity_Forms\GF_Service_Provider;
|
||||
use Gravity_Forms\Gravity_Forms\GF_Service_Container;
|
||||
|
||||
class GF_Batch_Operations_Service_Provider extends GF_Service_Provider {
|
||||
|
||||
const ENTRY_META_BATCH_PROCESSOR = 'entry_meta_batch_processor';
|
||||
/**
|
||||
* Register new services to the Service Container.
|
||||
*
|
||||
* @param GF_Service_Container $container
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register( GF_Service_Container $container ) {
|
||||
require_once( plugin_dir_path( __FILE__ ) . 'class-gf-entry-meta-batch-processor.php' );
|
||||
$container->add(
|
||||
self::ENTRY_META_BATCH_PROCESSOR,
|
||||
function() {
|
||||
return new GF_Entry_Meta_Batch_Processor();
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
<?php
|
||||
|
||||
namespace Gravity_Forms\Gravity_Forms\Query\Batch_Processing;
|
||||
|
||||
class GF_Entry_Meta_Batch_Processor {
|
||||
|
||||
/**
|
||||
* Stores the entry meta information for batch processing.
|
||||
*
|
||||
* begin_batch_entry_meta_operations() should be called before adding anything to this array
|
||||
* then commit_batch_entry_meta_operations() to save it.
|
||||
*
|
||||
* @since 2.5.16
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private static $_batch_entry_meta_updates = array();
|
||||
|
||||
/**
|
||||
* Checks if any entry meta updates have been registered for entry meta batch processing.
|
||||
*
|
||||
* @since 2.5.16
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function has_batch_entry_meta_operations() {
|
||||
return ! empty( self::$_batch_entry_meta_updates );
|
||||
}
|
||||
|
||||
/**
|
||||
* Flushes the contents of the entry meta batch data to begin a new batch operation.
|
||||
*
|
||||
* @since 2.5.16
|
||||
*/
|
||||
public static function begin_batch_entry_meta_operations() {
|
||||
self::$_batch_entry_meta_updates = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Queues an item into the batch entry meta operations array.
|
||||
*
|
||||
* @since 2.5.16
|
||||
*
|
||||
* @param array $form The current form being processed.
|
||||
* @param array $entry The current entry being processed.
|
||||
* @param string $entry_meta_key The entry meta key.
|
||||
* @param mixed $entry_meta_value The entry meta value.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function queue_batch_entry_meta_operation( $form, $entry, $entry_meta_key, $entry_meta_value ) {
|
||||
|
||||
$entry_id = rgar( $entry, 'id' );
|
||||
$form_id = rgar( $form, 'id' );
|
||||
|
||||
if ( ! $entry_id || ! $form_id || ! $entry_meta_key ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
self::$_batch_entry_meta_updates[] = array(
|
||||
'meta_value' => $entry_meta_value,
|
||||
'meta_key' => $entry_meta_key,
|
||||
'form_id' => $form_id,
|
||||
'entry_id' => $entry_id,
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Commits the contents of the entry meta batch data to the database.
|
||||
*
|
||||
* @since 2.5.16
|
||||
*
|
||||
* @return array An associative array that contains the results of the operation as the value and the operation as the key.
|
||||
*/
|
||||
public static function commit_batch_entry_meta_operations() {
|
||||
|
||||
global $wpdb;
|
||||
$meta_table = \GFFormsModel::get_entry_meta_table_name();
|
||||
|
||||
$results['updates'] = array();
|
||||
|
||||
if ( empty( self::$_batch_entry_meta_updates ) ) {
|
||||
return $results;
|
||||
}
|
||||
|
||||
$meta_keys = array_column( self::$_batch_entry_meta_updates, 'meta_key' );
|
||||
$prepare_statement_placeholders = '(' . implode( ',', array_fill( 0, count( $meta_keys ), '%s' ) ) . ')';
|
||||
$sql = call_user_func_array(
|
||||
array( $wpdb, 'prepare' ),
|
||||
array_merge(
|
||||
array( "SELECT id, meta_key FROM {$meta_table} WHERE meta_key in " . $prepare_statement_placeholders ),
|
||||
$meta_keys
|
||||
)
|
||||
);
|
||||
$existing_rows = $wpdb->get_results( $sql, ARRAY_A );
|
||||
$update_rows = array();
|
||||
foreach ( $existing_rows as $row ) {
|
||||
$update_rows[ $row['meta_key'] ] = $row['id'];
|
||||
}
|
||||
|
||||
$values = array();
|
||||
foreach ( self::$_batch_entry_meta_updates as $update ) {
|
||||
$update['meta_value'] = maybe_serialize( $update['meta_value'] );
|
||||
$values[] = $wpdb->prepare( '(%s,%s,%s,%s,%s)', rgar( $update_rows, $update['meta_key'] ), $update['meta_key'], $update['meta_value'], $update['form_id'], $update['entry_id'] );
|
||||
}
|
||||
$values_str = join( ',', $values );
|
||||
|
||||
$update_sql = "INSERT INTO {$meta_table} (id,meta_key,meta_value,form_id,entry_id)
|
||||
VALUES {$values_str}
|
||||
ON DUPLICATE KEY UPDATE meta_value=VALUES(meta_value);";
|
||||
|
||||
$result = $wpdb->query( $update_sql );
|
||||
|
||||
if ( $result === false ) {
|
||||
$result = new \WP_Error( 'update_error', $wpdb->last_error );
|
||||
}
|
||||
|
||||
$results['updates'] = $result;
|
||||
self::$_batch_entry_meta_updates = array();
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the count of pending update operations.
|
||||
*
|
||||
* @since 2.5.16
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function get_pending_operations_count() {
|
||||
return count( self::$_batch_entry_meta_updates );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* The Gravity Forms Query Call class.
|
||||
*/
|
||||
class GF_Query_Call {
|
||||
/**
|
||||
* @var string The function name.
|
||||
*/
|
||||
private $_function_name = null;
|
||||
|
||||
/**
|
||||
* @var array The parameters.
|
||||
*/
|
||||
private $_parameters = array();
|
||||
|
||||
/**
|
||||
* A function call.
|
||||
*
|
||||
* @param string $function_name The function to call.
|
||||
* @param array $parameters The function parameters. Default: []
|
||||
*/
|
||||
public function __construct( $function_name, $parameters = array() ) {
|
||||
$this->_function_name = $function_name;
|
||||
$this->_parameters = $parameters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the SQL.
|
||||
*
|
||||
* The default behavior is to just plop function_name( implode( ', ', $parameters ) ).
|
||||
* For other cases, like CAST, check the derived classes.
|
||||
*
|
||||
* @param GF_Query $query The query.
|
||||
*
|
||||
* @return string The generated SQL.
|
||||
*/
|
||||
public function sql( $query ) {
|
||||
if ( method_exists( $this, strtolower( $this->function_name ) . '_sql' ) ) {
|
||||
return call_user_func( array( $this, strtolower( $this->function_name ) . '_sql' ), $query );
|
||||
}
|
||||
return sprintf( "{$this->function_name}(%s)", implode( ', ', $this->parameters ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* A cast call.
|
||||
*
|
||||
* @param GF_Query_Column $column The column to cast.
|
||||
* @param string $type The type to cast to.
|
||||
*
|
||||
* @return GF_Query_Call|null instance or null.
|
||||
*/
|
||||
public static function CAST( $column, $type ) {
|
||||
if ( ! $column instanceof GF_Query_Column ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new self( 'CAST', array( $column, $type ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* A RAND call.
|
||||
*
|
||||
* @return GF_Query_Call|null instance or null.
|
||||
*/
|
||||
public static function RAND( ) {
|
||||
return new self( 'RAND' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the RAND call SQL.
|
||||
*
|
||||
* @return string The generated SQL.
|
||||
*/
|
||||
private function rand_sql() {
|
||||
return 'RAND()';
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the CAST call SQL.
|
||||
*
|
||||
* @param GF_Query $query The query.
|
||||
*
|
||||
* @return string The generated SQL.
|
||||
*/
|
||||
private function cast_sql( $query ) {
|
||||
if ( ! $this->parameters || count( $this->parameters ) != 2 ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
list( $column, $type ) = $this->parameters;
|
||||
|
||||
if ( ! in_array( $type, array( GF_Query::TYPE_SIGNED, GF_Query::TYPE_UNSIGNED, GF_Query::TYPE_DECIMAL ) ) ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if ( ! $column->field_id || ! $column->source ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if ( GF_Query::TYPE_DECIMAL === $type ) {
|
||||
$type = 'DECIMAL(65, 6)'; // @todo make the decimal point configurable one day
|
||||
}
|
||||
|
||||
$id = $column->is_entry_column() ? $column->field_id : 'meta_value';
|
||||
return sprintf( 'CAST(`%s`.`%s` AS %s)', $query->_alias( $column->field_id, $column->source, 'c' ), $id, $type );
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve all the columns from the parameters of this call.
|
||||
*
|
||||
* @return array The columns.
|
||||
*/
|
||||
private function get_columns() {
|
||||
$columns = array();
|
||||
foreach ( $this->parameters as $p ) {
|
||||
if ( $p instanceof GF_Query_Column ) {
|
||||
$columns[] = $p;
|
||||
}
|
||||
}
|
||||
return $columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Proxy read-only values.
|
||||
*/
|
||||
public function __get( $key ) {
|
||||
switch ( $key ):
|
||||
case 'parameters':
|
||||
return $this->_parameters;
|
||||
case 'function_name':
|
||||
return $this->_function_name;
|
||||
case 'columns':
|
||||
return $this->get_columns();
|
||||
endswitch;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* The Gravity Forms Query Column class.
|
||||
*/
|
||||
class GF_Query_Column {
|
||||
|
||||
/**
|
||||
* @const Identifier for searching across any meta field.
|
||||
*/
|
||||
const META = '{{ANY META FIELD}}';
|
||||
|
||||
/**
|
||||
* @var string The field ID.
|
||||
*/
|
||||
private $_field_id;
|
||||
|
||||
/**
|
||||
* @var int|array The source.
|
||||
*/
|
||||
private $_source;
|
||||
|
||||
/**
|
||||
* @var string|false The alias override (for meta rows)
|
||||
*/
|
||||
private $_alias = false;
|
||||
|
||||
/**
|
||||
* Represents a column.
|
||||
*
|
||||
* @param string $field_id The field ID (meta key or column name).
|
||||
* @param int|array $source The source this field is referencing.
|
||||
* @param string|bool $alias An alias override. Default: false.
|
||||
*/
|
||||
public function __construct( $field_id, $source = 0, $alias = false ) {
|
||||
if ( ! ( is_int( $source ) || is_array( $source ) ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->_field_id = $field_id;
|
||||
$this->_source = $source;
|
||||
$this->_alias = $alias;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get some SQL for this column.
|
||||
*
|
||||
* @param $query GF_Query The query.
|
||||
*
|
||||
* @return string The SQL.
|
||||
*/
|
||||
public function sql( $query ) {
|
||||
if ( ! $query instanceof GF_Query ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if ( ! $this->field_id ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if ( $this->is_entry_column() ) {
|
||||
return sprintf( '`%s`.`%s`', $this->alias ? $this->alias : $query->_alias( null, $this->source ), $this->field_id );
|
||||
} else if ( $this->is_meta_column() ) {
|
||||
return sprintf( '`%s`.`%s`', $this->alias ? $this->alias : $query->_alias( $this->field_id, $this->source, 'm' ), $this->field_id );
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this field is an entry column.
|
||||
*
|
||||
* @return boolean An entry column or not.
|
||||
*/
|
||||
public function is_entry_column() {
|
||||
if ( ! $this->field_id ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static $entry_columns = array();
|
||||
if ( empty( $entry_columns ) ) {
|
||||
global $wpdb;
|
||||
$entry_columns = wp_list_pluck( $wpdb->get_results( 'SHOW COLUMNS FROM ' . GFFormsModel::get_entry_table_name(), ARRAY_A ), 'Field' );
|
||||
}
|
||||
return in_array( $this->field_id, $entry_columns );
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this field is a nullable entry column.
|
||||
*
|
||||
* @since 2.3.1.10
|
||||
*
|
||||
* @return boolean An entry column or not.
|
||||
*/
|
||||
public function is_nullable_entry_column() {
|
||||
if ( ! $this->field_id ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static $nullable_entry_columns = array();
|
||||
if ( empty( $nullable_entry_columns ) ) {
|
||||
global $wpdb;
|
||||
$nullable_entry_columns = wp_list_pluck( $wpdb->get_results( 'SHOW COLUMNS FROM ' . GFFormsModel::get_entry_table_name() . " WHERE `Null` = 'YES'", ARRAY_A ), 'Field' );
|
||||
}
|
||||
return in_array( $this->field_id, $nullable_entry_columns );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Whether this field is a meta column.
|
||||
*
|
||||
* @return boolean A meta column or not.
|
||||
*/
|
||||
public function is_meta_column() {
|
||||
if ( ! $this->field_id ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return in_array( $this->field_id, array( 'meta_key', 'meta_value' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Proxy read-only values.
|
||||
*/
|
||||
public function __get( $key ) {
|
||||
switch ( $key ):
|
||||
case 'field_id':
|
||||
return $this->_field_id;
|
||||
case 'source':
|
||||
return $this->_source;
|
||||
case 'alias':
|
||||
return $this->_alias;
|
||||
endswitch;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,551 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* The Gravity Forms Query Condition class.
|
||||
*/
|
||||
class GF_Query_Condition {
|
||||
/**
|
||||
* @var string The chosen operator.
|
||||
*/
|
||||
private $_operator = null;
|
||||
|
||||
/**
|
||||
* @var array Boolean combined expressions.
|
||||
*/
|
||||
private $_expressions = array();
|
||||
|
||||
/**
|
||||
* @var mixed The left-hand expression.
|
||||
*/
|
||||
private $_left = null;
|
||||
|
||||
/**
|
||||
* @var mixed The right-hand expression.
|
||||
*/
|
||||
private $_right = null;
|
||||
|
||||
/**
|
||||
* @const string The AND operator.
|
||||
*/
|
||||
const _AND = 'AND';
|
||||
|
||||
/**
|
||||
* @const string The AND operator.
|
||||
*/
|
||||
const _OR = 'OR';
|
||||
|
||||
/**
|
||||
* @const string The less than operator.
|
||||
*/
|
||||
const LT = '<';
|
||||
|
||||
/**
|
||||
* @const string The less than or equal to operator.
|
||||
*/
|
||||
const LTE = '<=';
|
||||
|
||||
/**
|
||||
* @const string The greater than operator.
|
||||
*/
|
||||
const GT = '>';
|
||||
|
||||
/**
|
||||
* @const string The greater than or equal to operator.
|
||||
*/
|
||||
const GTE = '>=';
|
||||
|
||||
/**
|
||||
* @const string The equal to operator.
|
||||
*/
|
||||
const EQ = '=';
|
||||
|
||||
/**
|
||||
* @const string The not equal to operator.
|
||||
*/
|
||||
const NEQ = '!=';
|
||||
|
||||
/**
|
||||
* @const string The IN operator.
|
||||
*/
|
||||
const IN = 'IN';
|
||||
|
||||
/**
|
||||
* @const string The NOT IN operator.
|
||||
*/
|
||||
const NIN = 'NOT IN';
|
||||
|
||||
/**
|
||||
* @const string The LIKE operator.
|
||||
*/
|
||||
const LIKE = 'LIKE';
|
||||
|
||||
/**
|
||||
* @const string The NOT LIKE operator.
|
||||
*/
|
||||
const NLIKE = 'NOT LIKE';
|
||||
|
||||
/**
|
||||
* @const string The BETWEEN operator.
|
||||
*/
|
||||
const BETWEEN = 'BETWEEN';
|
||||
|
||||
/**
|
||||
* @const string The NOT BETWEEN operator.
|
||||
*/
|
||||
const NBETWEEN = 'NOT BETWEEN';
|
||||
|
||||
/**
|
||||
* @const string The inverse IN operator.
|
||||
*/
|
||||
const CONTAINS = 'CONTAINS';
|
||||
|
||||
/**
|
||||
* @const string The inverse NIN operator.
|
||||
*/
|
||||
const NCONTAINS = 'NCONTAINS';
|
||||
|
||||
/**
|
||||
* @const string The IS operator.
|
||||
*/
|
||||
const IS = 'IS';
|
||||
|
||||
/**
|
||||
* @const string The IS NOT operator.
|
||||
*/
|
||||
const ISNOT = 'IS NOT';
|
||||
|
||||
/**
|
||||
* @const string NULL.
|
||||
*/
|
||||
const NULL = 'NULL';
|
||||
|
||||
/**
|
||||
* A condition.
|
||||
*
|
||||
* @param GF_Query_Column|GF_Query_Call|GF_Query_Literal|null $left The left-hand expression.
|
||||
* @param string|null $operator The operator.
|
||||
* @param GF_Query_Column|GF_Query_Call|GF_Query_Literal|GF_Query_Series|null $right The right-hand expression.
|
||||
*
|
||||
* @return GF_Query_Condition $this This condition.
|
||||
*/
|
||||
public function __construct( $left = null, $operator = null, $right = null ) {
|
||||
|
||||
$allowed_ops = array( self::LT, self::LTE, self::GT, self::GTE, self::EQ, self::NEQ, self::IN, self::NIN, self::LIKE, self::NLIKE, self::BETWEEN, self::NBETWEEN, self::CONTAINS, self::NCONTAINS, self::IS, self::ISNOT );
|
||||
|
||||
/**
|
||||
* Left-hand expression, non Series.
|
||||
*/
|
||||
if ( self::is_valid_expression_type( $left ) && ! $left instanceof GF_Query_Series ) {
|
||||
$this->_left = $left;
|
||||
}
|
||||
|
||||
/**
|
||||
* The operator.
|
||||
*/
|
||||
if ( in_array( $operator, $allowed_ops ) ) {
|
||||
$this->_operator = $operator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Right-hand expression, non Series.
|
||||
*/
|
||||
if ( self::is_valid_expression_type( $right ) ) {
|
||||
$this->_right = $right;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tie several conditions together with an AND relationship.
|
||||
*
|
||||
* Accepts any number of GF_Query_Condition objects.
|
||||
*
|
||||
* @return GF_Query_Condition The condition.
|
||||
*/
|
||||
public static function _and() {
|
||||
$conditions = array();
|
||||
|
||||
foreach ( func_get_args() as $arg ) {
|
||||
if ( $arg instanceof GF_Query_Condition ) {
|
||||
$conditions[] = $arg;
|
||||
}
|
||||
}
|
||||
|
||||
$_this = new self();
|
||||
$_this->_operator = self::_AND;
|
||||
$_this->_expressions = $conditions;
|
||||
return $_this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tie several conditions together with an OR relationship.
|
||||
*
|
||||
* Accepts any number of GF_Query_Condition objects.
|
||||
*
|
||||
* @return GF_Query_Condition The condition.
|
||||
*/
|
||||
public static function _or() {
|
||||
|
||||
$conditions = array();
|
||||
|
||||
foreach ( func_get_args() as $arg ) {
|
||||
if ( $arg instanceof GF_Query_Condition ) {
|
||||
$conditions[] = $arg;
|
||||
}
|
||||
}
|
||||
|
||||
$_this = new self();
|
||||
$_this->_operator = self::_OR;
|
||||
$_this->_expressions = $conditions;
|
||||
return $_this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the expressions into a SQL string.
|
||||
*
|
||||
* @param GF_Query $query The query.
|
||||
*
|
||||
* @return string The SQL string.
|
||||
*/
|
||||
public function sql( $query ) {
|
||||
global $wpdb;
|
||||
|
||||
/**
|
||||
* Both expressions are given.
|
||||
*/
|
||||
if ( $this->operator && $this->left && $this->right ) {
|
||||
|
||||
/**
|
||||
* Meta field.
|
||||
*/
|
||||
if ( $this->left instanceof GF_Query_Column && ( ! $this->left->is_entry_column() && ! $this->left->is_meta_column() ) && $this->left->field_id ) {
|
||||
/**
|
||||
* A meta field needs some extra conditions: "meta_key", "meta_value", and sometimes EXISTS.
|
||||
*/
|
||||
$alias = $query->_alias( $this->left->field_id, $this->left->source, 'm' );
|
||||
|
||||
if ( $this->left->field_id == GF_Query_Column::META ) {
|
||||
|
||||
// Global meta search doesn't require a meta_key clause.
|
||||
$compare_condition = new self(
|
||||
new GF_Query_Column( 'meta_value', $this->left->source, $alias ),
|
||||
$this->operator,
|
||||
$this->right
|
||||
);
|
||||
|
||||
return $query->_where_unwrap( $compare_condition );
|
||||
}
|
||||
|
||||
/**
|
||||
* Multi-input fields are processed in a more complex way.
|
||||
*
|
||||
* If a non-specific input is requested (radio, checkboxes, usually)
|
||||
* we have to include all the input ids in the query.
|
||||
*/
|
||||
if ( is_numeric( $this->left->field_id ) && intval( $this->left->field_id ) == $this->left->field_id ) {
|
||||
if ( ( $field = GFFormsModel::get_field( GFAPI::get_form( $this->left->source ), $this->left->field_id ) ) && $field->get_entry_inputs() ) {
|
||||
|
||||
/**
|
||||
* EQ and NEQ require an unordered comparison of all the values for the entry.
|
||||
*/
|
||||
if ( in_array( $this->operator, array( self::EQ, self::NEQ ) ) && $this->right instanceof GF_Query_Series ) {
|
||||
$compare_conditions = array();
|
||||
foreach ( $this->right->values as $literal ) {
|
||||
$subquery = $wpdb->prepare( sprintf( "SELECT 1 FROM `%s` WHERE `meta_key` LIKE %%s AND `meta_value` = %s AND `entry_id` = `%s`.`id`",
|
||||
GFFormsModel::get_entry_meta_table_name(), $literal->sql( $query ), $query->_alias( null, $this->left->source ) ),
|
||||
sprintf( '%d.%%', $this->left->field_id ) );
|
||||
$compare_condition = new self( new GF_Query_Call( sprintf( '%sEXISTS', $this->operator == self::NEQ ? 'NOT ' : '' ), array( $subquery ) ) );
|
||||
$compare_conditions []= $compare_condition->sql( $query );
|
||||
}
|
||||
|
||||
$subquery = $wpdb->prepare( sprintf( "SELECT COUNT(1) FROM `%s` WHERE `meta_key` LIKE %%s AND `entry_id` = `%s`.`id`",
|
||||
GFFormsModel::get_entry_meta_table_name(), $query->_alias( null, $this->left->source ) ),
|
||||
sprintf( '%d.%%', $this->left->field_id ) );
|
||||
|
||||
/**
|
||||
* Add length comparison to make sure all the needed values are found
|
||||
* and no extra ones exist.
|
||||
*/
|
||||
$compare_conditions []= sprintf( "(%s) %s %d", $subquery, $this->operator == self::NEQ ? '!=' : '=', count( $compare_conditions ) );
|
||||
return sprintf( "(%s)", implode( $this->operator == self::NEQ ? ' OR ' : ' AND ', $compare_conditions ) );
|
||||
|
||||
/**
|
||||
* Inverse contains.
|
||||
*/
|
||||
} elseif ( in_array( $this->operator, array( self::CONTAINS, self::NCONTAINS ) ) ) {
|
||||
$subquery = $wpdb->prepare( sprintf( "SELECT 1 FROM `%s` WHERE `meta_key` LIKE %%s AND `meta_value` = %s AND `entry_id` = `%s`.`id`",
|
||||
GFFormsModel::get_entry_meta_table_name(), $this->right->sql( $query ), $query->_alias( null, $this->left->source ) ),
|
||||
sprintf( '%d.%%', $this->left->field_id ) );
|
||||
$compare_condition = new self( new GF_Query_Call( sprintf( '%sEXISTS', $this->operator == self::NCONTAINS ? 'NOT ' : '' ), array( $subquery ) ) );
|
||||
return $compare_condition->sql( $query );
|
||||
|
||||
/**
|
||||
* One of.
|
||||
*/
|
||||
} elseif ( in_array( $this->operator, array( self::IN, self::NIN ) ) && $this->right instanceof GF_Query_Series ) {
|
||||
$subquery = $wpdb->prepare( sprintf( "SELECT 1 FROM `%s` WHERE `meta_key` LIKE %%s AND `meta_value` IN (%s) AND `entry_id` = `%s`.`id`",
|
||||
GFFormsModel::get_entry_meta_table_name(), str_replace( '%', '%%', $this->right->sql( $query, ', ' ) ), $query->_alias( null, $this->left->source ) ),
|
||||
sprintf( '%d.%%', $this->left->field_id ) );
|
||||
$compare_condition = new self( new GF_Query_Call( sprintf( '%sEXISTS', $this->operator == self::NIN ? 'NOT ' : '' ), array( $subquery ) ) );
|
||||
return $compare_condition->sql( $query );
|
||||
|
||||
/**
|
||||
* Everything else.
|
||||
*/
|
||||
} else {
|
||||
$operator = $this->operator;
|
||||
$is_negative = in_array( $operator, array( self::NLIKE, self::NBETWEEN, self::NEQ ) );
|
||||
if ( $is_negative ) {
|
||||
/**
|
||||
* Convert operator to positive, since we're doing it the NOT EXISTS way.
|
||||
*/
|
||||
switch ( $operator ) {
|
||||
case self::NLIKE:
|
||||
$operator = self::LIKE;
|
||||
break;
|
||||
case self::NBETWEEN:
|
||||
$operator = self::BETWEEN;
|
||||
break;
|
||||
case self::NEQ:
|
||||
$operator = self::EQ;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$subquery = $wpdb->prepare( sprintf( "SELECT 1 FROM `%s` WHERE `meta_key` LIKE %%s AND `meta_value` %s %s AND `entry_id` = `%s`.`id`",
|
||||
GFFormsModel::get_entry_meta_table_name(), $operator, str_replace( '%', '%%', $this->right->sql( $query ) ), $query->_alias( null, $this->left->source ) ),
|
||||
sprintf( '%d.%%', $this->left->field_id ) );
|
||||
$compare_condition = new self( new GF_Query_Call( sprintf( '%sEXISTS', $is_negative ? 'NOT ' : '' ), array( $subquery ) ) );
|
||||
return $compare_condition->sql( $query );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$compare_condition = self::_and(
|
||||
new self(
|
||||
new GF_Query_Column( 'meta_key', $this->left->source, $alias ),
|
||||
self::EQ,
|
||||
new GF_Query_Literal( $this->left->field_id )
|
||||
),
|
||||
new self(
|
||||
new GF_Query_Column( 'meta_value', $this->left->source, $alias ),
|
||||
$this->operator,
|
||||
$this->right
|
||||
)
|
||||
);
|
||||
|
||||
if ( ( in_array( $this->operator, array( self::NIN, self::NBETWEEN ) ) && ! in_array( new GF_Query_Literal(''), $this->right->values ) )
|
||||
|| ( $this->operator == self::NEQ && ! $this->right->value == '')
|
||||
|| ( $this->operator == self::EQ && $this->right->value == '' )
|
||||
) {
|
||||
/**
|
||||
* Empty string comparisons and negative comparisons need a NOT EXISTS clause to grab entries that
|
||||
* don't have the value set in the first place.
|
||||
*/
|
||||
$subquery = $wpdb->prepare( sprintf( "SELECT 1 FROM `%s` WHERE `meta_key` = %%s AND `entry_id` = `%s`.`id`",
|
||||
GFFormsModel::get_entry_meta_table_name(), $query->_alias( null, $this->left->source ) ), $this->left->field_id );
|
||||
$not_exists = new self( new GF_Query_Call( 'NOT EXISTS', array( $subquery ) ) );
|
||||
return $query->_where_unwrap( self::_or( $not_exists, $compare_condition ) );
|
||||
}
|
||||
|
||||
return $query->_where_unwrap( $compare_condition );
|
||||
}
|
||||
|
||||
if ( ( $left = $this->left_sql( $query ) ) && ( $right = $this->right_sql( $query ) ) ) {
|
||||
if ( in_array( $this->operator, array( self::NBETWEEN, self::BETWEEN ) ) ) {
|
||||
return "($left {$this->operator} $right)";
|
||||
}
|
||||
|
||||
if ( $this->left instanceof GF_Query_Column && $this->left->is_nullable_entry_column() ) {
|
||||
if ( ( $this->operator == self::EQ && empty ( $this->right->value ) ) || ( $this->operator == self::NEQ && ! empty ( $this->right->value ) ) ) {
|
||||
$right .= ' OR ' . $left . ' IS NULL)';
|
||||
$left = "($left";
|
||||
}
|
||||
}
|
||||
|
||||
if ( $this->left instanceof GF_Query_Column && $this->left->is_entry_column() && $this->left->source ) {
|
||||
if ( $query->is_multisource() && $this->left->field_id != 'form_id' ) {
|
||||
$alias = $query->_alias( null, $this->left->source );
|
||||
$left = "(`$alias`.`form_id` = {$this->left->source} AND $left";
|
||||
$right .= ')';
|
||||
}
|
||||
}
|
||||
|
||||
return "$left {$this->operator} $right";
|
||||
}
|
||||
}
|
||||
|
||||
if ( $this->left && ( $this->left instanceof GF_Query_Call || $this->left instanceof GF_Query_Column ) ) {
|
||||
return $this->left_sql( $query );
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the expression is of a valid type.
|
||||
*
|
||||
* @param mixed $expression The expression to check.
|
||||
*
|
||||
* @return boolean Valid or not.
|
||||
*/
|
||||
public static function is_valid_expression_type( $expression ) {
|
||||
return (
|
||||
( $expression instanceof GF_Query_Literal ) ||
|
||||
( $expression instanceof GF_Query_Column ) ||
|
||||
( $expression instanceof GF_Query_Series ) ||
|
||||
( $expression instanceof GF_Query_Call ) ||
|
||||
( $expression === self::NULL )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* The right expression.
|
||||
*
|
||||
* @return string The SQL string or null for the right expression.
|
||||
*/
|
||||
private function right_sql( $query ) {
|
||||
/**
|
||||
* (NOT) IN
|
||||
*
|
||||
* Only works with literal arrays, which can be made
|
||||
* up of a Literal, Column or Call.
|
||||
*/
|
||||
if ( in_array( $this->operator, array( self::IN, self::NIN ) ) ) {
|
||||
if ( ! $this->right instanceof GF_Query_Series ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return sprintf( '(%s)', $this->right->sql( $query, ', ' ) );
|
||||
|
||||
/**
|
||||
* BETWEEN
|
||||
*/
|
||||
} elseif ( in_array( $this->operator, array( self::BETWEEN, self::NBETWEEN ) ) ) {
|
||||
if ( ! $this->right instanceof GF_Query_Series ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $this->right->sql( $query, ' AND ' );
|
||||
} elseif ( in_array( $this->operator, array( self::IS, self::ISNOT ) ) ) {
|
||||
if ( $this->right !== self::NULL ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return self::NULL;
|
||||
}
|
||||
|
||||
return $this->right->sql( $query );
|
||||
}
|
||||
|
||||
/**
|
||||
* The left expression.
|
||||
*
|
||||
* @return string The SQL string or null for the left expression.
|
||||
*/
|
||||
private function left_sql( $query ) {
|
||||
if ( $this->left instanceof GF_Query_Call ) {
|
||||
|
||||
$columns = array();
|
||||
|
||||
foreach ( $this->left->parameters as $c ) {
|
||||
if ( $c instanceof GF_Query_Column ) {
|
||||
$columns[] = $c;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a meta_key condition to a calls.
|
||||
*/
|
||||
if ( $columns ) {
|
||||
$meta_key_conditions = array();
|
||||
foreach ( $columns as $column ) {
|
||||
$alias = $column->alias ? $column->alias : $query->_alias( $column->field_id, $column->source, 'm' );
|
||||
$condition = new GF_Query_Condition(
|
||||
new GF_Query_Column( 'meta_key', $column->source, $alias ),
|
||||
GF_Query_Condition::EQ,
|
||||
new GF_Query_Literal( $column->field_id )
|
||||
);
|
||||
|
||||
$meta_key_conditions []= $condition->sql( $query );
|
||||
}
|
||||
|
||||
return implode( ' AND ',
|
||||
array_merge(
|
||||
$meta_key_conditions,
|
||||
array( $this->left->sql( $query ) )
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
return $this->left->sql( $query );
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve all the columns present in the left, right clauses.
|
||||
*
|
||||
* @return array The columns.
|
||||
*/
|
||||
public function get_columns() {
|
||||
$columns = array();
|
||||
|
||||
if ( $this->left instanceof GF_Query_Column ) {
|
||||
$columns[] = $this->left;
|
||||
}
|
||||
|
||||
if ( $this->right instanceof GF_Query_Column ) {
|
||||
$columns[] = $this->right;
|
||||
}
|
||||
|
||||
/**
|
||||
* Support Calls
|
||||
*/
|
||||
if ( $this->left instanceof GF_Query_Call) {
|
||||
|
||||
$left_columns = array();
|
||||
|
||||
foreach ( $this->left->parameters as $c ) {
|
||||
if ( $c instanceof GF_Query_Column ) {
|
||||
$left_columns[] = $c;
|
||||
}
|
||||
}
|
||||
|
||||
$columns = array_merge( $columns, $left_columns );
|
||||
}
|
||||
|
||||
/**
|
||||
* Support series of columns.
|
||||
*/
|
||||
if ( $this->right instanceof GF_Query_Series ) {
|
||||
|
||||
$right_columns = array();
|
||||
|
||||
foreach ( $this->right->values as $c ) {
|
||||
if ( $c instanceof GF_Query_Column ) {
|
||||
$right_columns[] = $c;
|
||||
}
|
||||
}
|
||||
|
||||
$columns = array_merge( $columns, $right_columns );
|
||||
}
|
||||
|
||||
return $columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Proxy read-only values.
|
||||
*/
|
||||
public function __get( $key ) {
|
||||
switch ( $key ) :
|
||||
case 'operator':
|
||||
return $this->_operator;
|
||||
case 'expressions':
|
||||
return $this->_expressions;
|
||||
case 'left':
|
||||
return $this->_left;
|
||||
case 'right':
|
||||
return $this->_right;
|
||||
case 'columns':
|
||||
return $this->get_columns();
|
||||
endswitch;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* The Gravity Forms Query JSON Literal class.
|
||||
*/
|
||||
class GF_Query_JSON_Literal extends GF_Query_Literal{
|
||||
/**
|
||||
* @var int|string|float The value.
|
||||
*/
|
||||
private $_value;
|
||||
|
||||
/**
|
||||
* A literal value.
|
||||
*
|
||||
* @param string $value
|
||||
*/
|
||||
public function __construct( $value ) {
|
||||
if ( is_string( $value ) ) {
|
||||
$this->_value = $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get SQL for this.
|
||||
*
|
||||
* @param GF_Query $query The query.
|
||||
* @param string $delimiter The delimiter for arrays.
|
||||
*
|
||||
* @return string The SQL.
|
||||
*/
|
||||
public function sql( $query, $delimiter = '' ) {
|
||||
global $wpdb;
|
||||
|
||||
if ( is_string( $this->value ) ) {
|
||||
$value = trim( json_encode( $this->value ), '"' );
|
||||
$value = str_replace( '\\', '\\\\', $value );
|
||||
|
||||
return $wpdb->prepare( '%s', $value );
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Proxy read-only values.
|
||||
*/
|
||||
public function __get( $key ) {
|
||||
switch ( $key ) :
|
||||
case 'value':
|
||||
return $this->_value;
|
||||
endswitch;
|
||||
}
|
||||
|
||||
public function __isset( $key ) {
|
||||
return in_array( $key, array( 'value' ) );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* The Gravity Forms Query Literal class.
|
||||
*/
|
||||
class GF_Query_Literal {
|
||||
/**
|
||||
* @var int|string|float The value.
|
||||
*/
|
||||
private $_value;
|
||||
|
||||
/**
|
||||
* A literal value.
|
||||
*
|
||||
* @param int|string|float $value
|
||||
*/
|
||||
public function __construct( $value ) {
|
||||
if ( is_int( $value ) || is_string( $value ) || is_float( $value ) ) {
|
||||
$this->_value = $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get SQL for this.
|
||||
*
|
||||
* @param GF_Query $query The query.
|
||||
* @param string $delimiter The delimiter for arrays.
|
||||
*
|
||||
* @return string The SQL.
|
||||
*/
|
||||
public function sql( $query, $delimiter = '' ) {
|
||||
global $wpdb;
|
||||
|
||||
if ( is_int( $this->value ) ) {
|
||||
return $wpdb->prepare( '%d', $this->value );
|
||||
} elseif ( is_double( $this->value ) ) {
|
||||
return $this->value;
|
||||
} elseif ( is_string( $this->value ) || is_float( $this->value ) ) {
|
||||
return $wpdb->prepare( '%s', $this->value );
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo Add support for Column, Call
|
||||
*/
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Proxy read-only values.
|
||||
*/
|
||||
public function __get( $key ) {
|
||||
switch ( $key ) :
|
||||
case 'value':
|
||||
return $this->_value;
|
||||
endswitch;
|
||||
}
|
||||
|
||||
public function __isset( $key ) {
|
||||
return in_array( $key, array( 'value' ) );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* The Gravity Forms Query Series class.
|
||||
*
|
||||
* A list of arguments. Would have named "List" but it's a reserved keyword.
|
||||
*/
|
||||
class GF_Query_Series {
|
||||
/**
|
||||
* @var array A series of values.
|
||||
*/
|
||||
private $_values = array();
|
||||
|
||||
/**
|
||||
* A series of expressions.
|
||||
*
|
||||
* @param mixed[] $values With a valid expression type (GF_Query_Literal, GF_Query_Column, GF_Query_Call)
|
||||
*/
|
||||
public function __construct( $values ) {
|
||||
if ( is_array( $values ) ) {
|
||||
$this->_values = array_filter( $values, array( 'GF_Query_Condition', 'is_valid_expression_type' ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get SQL for this.
|
||||
*
|
||||
* @param GF_Query $query The query.
|
||||
* @param string $delimiter The delimiter to stick the series values with.
|
||||
*
|
||||
* @return string The SQL.
|
||||
*/
|
||||
public function sql( $query, $delimiter = '' ) {
|
||||
$values = array();
|
||||
|
||||
foreach( $this->_values as $value ) {
|
||||
$values[] = $value->sql( $query );
|
||||
}
|
||||
|
||||
$chunks = array_filter( $values, 'strlen' );
|
||||
|
||||
return implode( $delimiter, $chunks);
|
||||
}
|
||||
|
||||
/**
|
||||
* Proxy read-only values.
|
||||
*/
|
||||
public function __get( $key ) {
|
||||
switch ( $key ):
|
||||
case 'values':
|
||||
return $this->_values;
|
||||
endswitch;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace Gravity_Forms\Gravity_Forms\Query;
|
||||
|
||||
use Gravity_Forms\Gravity_Forms\GF_Service_Container;
|
||||
use Gravity_Forms\Gravity_Forms\GF_Service_Provider;
|
||||
|
||||
use Gravity_Forms\Gravity_Forms\Query\JSON_Handlers\GF_String_JSON_Handler;
|
||||
use Gravity_Forms\Gravity_Forms\Query\JSON_Handlers\GF_Query_JSON_Handler;
|
||||
|
||||
/**
|
||||
* Class GF_Query_Service_Provider
|
||||
*
|
||||
* Service provider for the Query Service.
|
||||
*
|
||||
* @package Gravity_Forms\Gravity_Forms\Query;
|
||||
*/
|
||||
class GF_Query_Service_Provider extends GF_Service_Provider {
|
||||
const JSON_STRING_HANDLER = 'json_string_handler';
|
||||
const JSON_QUERY_HANDLER = 'json_query_handler';
|
||||
|
||||
/**
|
||||
* Register services to the container.
|
||||
*
|
||||
* @since
|
||||
*
|
||||
* @param GF_Service_Container $container
|
||||
*/
|
||||
public function register( GF_Service_Container $container ) {
|
||||
require_once( plugin_dir_path( __FILE__ ) . '/json-handlers/class-gf-json-handler.php' );
|
||||
require_once( plugin_dir_path( __FILE__ ) . '/json-handlers/class-gf-query-json-handler.php' );
|
||||
require_once( plugin_dir_path( __FILE__ ) . '/json-handlers/class-gf-string-json-handler.php' );
|
||||
|
||||
$container->add( self::JSON_STRING_HANDLER, function() {
|
||||
return new GF_String_JSON_Handler();
|
||||
});
|
||||
|
||||
$container->add( self::JSON_QUERY_HANDLER, function() {
|
||||
return new GF_Query_JSON_Handler();
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
1609
wp/wp-content/plugins/gravityforms/includes/query/class-gf-query.php
Normal file
1609
wp/wp-content/plugins/gravityforms/includes/query/class-gf-query.php
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
namespace Gravity_Forms\Gravity_Forms\Query\JSON_Handlers;
|
||||
|
||||
/**
|
||||
* Abstract class to provide contract for JSON Handlers used to query against JSON values in the database.
|
||||
*
|
||||
* @since 2.7
|
||||
*/
|
||||
abstract class GF_JSON_Handler {
|
||||
|
||||
const SETTING_NAME = 'form_full_screen_slug';
|
||||
const SECTION_NAME = 'gf_theme_layers';
|
||||
|
||||
/**
|
||||
* Get the correct setting name to check to enable full screen for a slug.
|
||||
*
|
||||
* @since 2.7
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function get_setting_name() {
|
||||
/**
|
||||
* Filter to allow third-party code to modify the setting name being queried against in the JSON.
|
||||
*
|
||||
* @since 2.7
|
||||
*
|
||||
* @param string $setting_name The current setting name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
return apply_filters( 'gform_full_screen_display_setting_name', self::SETTING_NAME );
|
||||
}
|
||||
|
||||
protected function get_section_name() {
|
||||
/**
|
||||
* Filter to allow third-party code to modify the setting section to query against in the JSON.
|
||||
*
|
||||
* @since 2.7
|
||||
*
|
||||
* @param string $section_name The current section name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
return apply_filters( 'gform_full_screen_display_setting_group', self::SECTION_NAME );
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the DB query to get data.
|
||||
*
|
||||
* @param string $slug The slug against which to query.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract public function query( $slug );
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace Gravity_Forms\Gravity_Forms\Query\JSON_Handlers;
|
||||
|
||||
/**
|
||||
* GF_JSON_Handler implementation which uses a MySQL JSON query to gather data. More performant that string-based
|
||||
* queries, but only available in MySQL 5.7+.
|
||||
*
|
||||
* @since 2.7
|
||||
*/
|
||||
class GF_Query_JSON_Handler extends GF_JSON_Handler {
|
||||
|
||||
/**
|
||||
* Perform the query against the DB.
|
||||
*
|
||||
* @param string $slug
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function query( $slug ) {
|
||||
global $wpdb;
|
||||
|
||||
$setting_name = $this->get_setting_name();
|
||||
$section = $this->get_section_name();
|
||||
|
||||
// JSON Selector is formatted as `{"setting_name": "value"}`
|
||||
$json_selector = sprintf( '{"%s": "%s"}', $setting_name, $slug );
|
||||
$query = "SELECT form_id FROM {$wpdb->prefix}gf_form_meta AS meta LEFT JOIN {$wpdb->prefix}gf_form AS form ON form.id = meta.form_id WHERE is_trash = 0 AND is_active = 1 AND JSON_CONTAINS(display_meta, %s, %s)";
|
||||
|
||||
// To define a "section" to query against, we pass it as `$.section` as the third argument to JSON_CONTAINS.
|
||||
$prepared_query = $wpdb->prepare( $query, $json_selector, sprintf( '$.%s', $section ) );
|
||||
|
||||
return $wpdb->get_var( $prepared_query );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Gravity_Forms\Gravity_Forms\Query\JSON_Handlers;
|
||||
|
||||
/**
|
||||
* GF_JSON_Handler implementation which uses a MySQL "LIKE" query. Not as performant as JSON_CONTAINS, but
|
||||
* available on older (pre-5.7) versions of MySQL.
|
||||
*
|
||||
* @since 2.7
|
||||
*/
|
||||
class GF_String_JSON_Handler extends GF_JSON_Handler {
|
||||
|
||||
public function query( $slug ) {
|
||||
global $wpdb;
|
||||
|
||||
$setting_name = $this->get_setting_name();
|
||||
$like_statement = sprintf( '%%"%s":"%s"%%', $setting_name, $slug );
|
||||
$query = "SELECT form_id FROM {$wpdb->prefix}gf_form_meta AS meta LEFT JOIN {$wpdb->prefix}gf_form AS form ON form.id = meta.form_id WHERE is_trash = 0 AND is_active = 1 AND display_meta LIKE %s";
|
||||
$prepared_query = $wpdb->prepare( $query, $like_statement );
|
||||
|
||||
return $wpdb->get_var( $prepared_query );
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user