158 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			158 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| /**
 | |
|  * Base Custom Database Table Compare Query Class.
 | |
|  *
 | |
|  * @package     Database
 | |
|  * @subpackage  Compare
 | |
|  * @copyright   Copyright (c) 2020
 | |
|  * @license     https://opensource.org/licenses/gpl-2.0.php GNU Public License
 | |
|  * @since       1.0.0
 | |
|  */
 | |
| namespace EDD\Database\Queries;
 | |
| 
 | |
| // Exit if accessed directly
 | |
| defined( 'ABSPATH' ) || exit;
 | |
| 
 | |
| /**
 | |
|  * Class used for generating SQL for compare clauses.
 | |
|  *
 | |
|  * This class is used to generate the SQL when a `compare` argument is passed to
 | |
|  * the `Base` query class. It extends `Meta` so the `compare` key accepts
 | |
|  * the same parameters as the ones passed to `Meta`.
 | |
|  *
 | |
|  * @since 1.0.0
 | |
|  */
 | |
| class Compare extends Meta {
 | |
| 
 | |
| 	/**
 | |
| 	 * Generate SQL WHERE clauses for a first-order query clause.
 | |
| 	 *
 | |
| 	 * "First-order" means that it's an array with a 'key' or 'value'.
 | |
| 	 *
 | |
| 	 * @since 1.0.0
 | |
| 	 *
 | |
| 	 * @param array  $clause       Query clause (passed by reference).
 | |
| 	 * @param array  $parent_query Parent query array.
 | |
| 	 * @param string $clause_key   Optional. The array key used to name the clause in the original `$meta_query`
 | |
| 	 *                             parameters. If not provided, a key will be generated automatically.
 | |
| 	 * @return array {
 | |
| 	 *     Array containing WHERE SQL clauses to append to a first-order query.
 | |
| 	 *
 | |
| 	 *     @type string $where SQL fragment to append to the main WHERE clause.
 | |
| 	 * }
 | |
| 	 */
 | |
| 	public function get_sql_for_clause( &$clause, $parent_query, $clause_key = '' ) {
 | |
| 		global $wpdb;
 | |
| 
 | |
| 		$sql_chunks = array(
 | |
| 			'where' => array(),
 | |
| 			'join'  => array(),
 | |
| 		);
 | |
| 
 | |
| 		if ( isset( $clause['compare'] ) ) {
 | |
| 			$clause['compare'] = strtoupper( $clause['compare'] );
 | |
| 		} else {
 | |
| 			$clause['compare'] = isset( $clause['value'] ) && is_array( $clause['value'] ) ? 'IN' : '=';
 | |
| 		}
 | |
| 
 | |
| 		if ( ! in_array(
 | |
| 			$clause['compare'], array(
 | |
| 				'=',
 | |
| 				'!=',
 | |
| 				'>',
 | |
| 				'>=',
 | |
| 				'<',
 | |
| 				'<=',
 | |
| 				'LIKE',
 | |
| 				'NOT LIKE',
 | |
| 				'IN',
 | |
| 				'NOT IN',
 | |
| 				'BETWEEN',
 | |
| 				'NOT BETWEEN',
 | |
| 				'EXISTS',
 | |
| 				'NOT EXISTS',
 | |
| 				'REGEXP',
 | |
| 				'NOT REGEXP',
 | |
| 				'RLIKE',
 | |
| 			), true
 | |
| 		) ) {
 | |
| 			$clause['compare'] = '=';
 | |
| 		}
 | |
| 
 | |
| 		if ( isset( $clause['compare_key'] ) && 'LIKE' === strtoupper( $clause['compare_key'] ) ) {
 | |
| 			$clause['compare_key'] = strtoupper( $clause['compare_key'] );
 | |
| 		} else {
 | |
| 			$clause['compare_key'] = '=';
 | |
| 		}
 | |
| 
 | |
| 		$compare     = $clause['compare'];
 | |
| 		$compare_key = $clause['compare_key'];
 | |
| 
 | |
| 		// Build the WHERE clause.
 | |
| 
 | |
| 		// Column name and value.
 | |
| 		if ( array_key_exists( 'key', $clause ) && array_key_exists( 'value', $clause ) ) {
 | |
| 			$column = sanitize_key( $clause['key'] );
 | |
| 			$value  = $clause['value'];
 | |
| 
 | |
| 			if ( in_array( $compare, array( 'IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN' ), true ) ) {
 | |
| 				if ( ! is_array( $value ) ) {
 | |
| 					$value = preg_split( '/[,\s]+/', $value );
 | |
| 				}
 | |
| 			} else {
 | |
| 				$value = trim( $value );
 | |
| 			}
 | |
| 
 | |
| 			switch ( $compare ) {
 | |
| 				case 'IN':
 | |
| 				case 'NOT IN':
 | |
| 					$compare_string = '(' . substr( str_repeat( ',%s', count( $value ) ), 1 ) . ')';
 | |
| 					$where          = $wpdb->prepare( $compare_string, $value );
 | |
| 					break;
 | |
| 
 | |
| 				case 'BETWEEN':
 | |
| 				case 'NOT BETWEEN':
 | |
| 					$value = array_slice( $value, 0, 2 );
 | |
| 					$where = $wpdb->prepare( '%s AND %s', $value );
 | |
| 					break;
 | |
| 
 | |
| 				case 'LIKE':
 | |
| 				case 'NOT LIKE':
 | |
| 					$value = '%' . $wpdb->esc_like( $value ) . '%';
 | |
| 					$where = $wpdb->prepare( '%s', $value );
 | |
| 					break;
 | |
| 
 | |
| 				// EXISTS with a value is interpreted as '='.
 | |
| 				case 'EXISTS':
 | |
| 					$compare = '=';
 | |
| 					$where   = $wpdb->prepare( '%s', $value );
 | |
| 					break;
 | |
| 
 | |
| 				// 'value' is ignored for NOT EXISTS.
 | |
| 				case 'NOT EXISTS':
 | |
| 					$where = '';
 | |
| 					break;
 | |
| 
 | |
| 				default:
 | |
| 					$where = $wpdb->prepare( '%s', $value );
 | |
| 					break;
 | |
| 
 | |
| 			}
 | |
| 
 | |
| 			if ( $where ) {
 | |
| 				$sql_chunks['where'][] = "{$column} {$compare} {$where}";
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		/*
 | |
| 		 * Multiple WHERE clauses (for meta_key and meta_value) should
 | |
| 		 * be joined in parentheses.
 | |
| 		 */
 | |
| 		if ( 1 < count( $sql_chunks['where'] ) ) {
 | |
| 			$sql_chunks['where'] = array( '( ' . implode( ' AND ', $sql_chunks['where'] ) . ' )' );
 | |
| 		}
 | |
| 
 | |
| 		return $sql_chunks;
 | |
| 	}
 | |
| }
 |