* Admin\API\Reports\SqlQuery class file.
namespace Automattic\WooCommerce\Admin\API\Reports;
if ( ! defined( 'ABSPATH' ) ) {
* Admin\API\Reports\SqlQuery: Common parent for manipulating SQL query clauses.
private $sql_clauses = array(
* SQL clause merge filters.
private $sql_filters = array(
* Data store context used to pass to filters.
* @param string $context Optional context passed to filters. Default empty string.
public function __construct( $context = '' ) {
$this->context = $context;
* Add a SQL clause to be included when get_data is called.
* @param string $type Clause type.
* @param string $clause SQL clause.
public function add_sql_clause( $type, $clause ) {
if ( isset( $this->sql_clauses[ $type ] ) && ! empty( $clause ) ) {
$this->sql_clauses[ $type ][] = $clause;
* Get SQL clause by type.
* @param string $type Clause type.
* @param string $handling Whether to filter the return value (filtered|unfiltered). Default unfiltered.
* @return string SQL clause.
protected function get_sql_clause( $type, $handling = 'unfiltered' ) {
if ( ! isset( $this->sql_clauses[ $type ] ) ) {
* Default to bypassing filters for clause retrieval internal to data stores.
* The filters are applied when the full SQL statement is retrieved.
if ( 'unfiltered' === $handling ) {
return implode( ' ', $this->sql_clauses[ $type ] );
if ( isset( $this->sql_filters[ $type ] ) ) {
foreach ( $this->sql_filters[ $type ] as $subset ) {
$clauses = array_merge( $clauses, $this->sql_clauses[ $subset ] );
$clauses = $this->sql_clauses[ $type ];
* Filter SQL clauses by type and context.
* @param array $clauses The original arguments for the request.
* @param string $context The data store context.
$clauses = apply_filters( "woocommerce_analytics_clauses_{$type}", $clauses, $this->context );
* Filter SQL clauses by type and context.
* @param array $clauses The original arguments for the request.
$clauses = apply_filters( "woocommerce_analytics_clauses_{$type}_{$this->context}", $clauses );
return implode( ' ', $clauses );
* Clear SQL clauses by type.
* @param string|array $types Clause type.
protected function clear_sql_clause( $types ) {
foreach ( (array) $types as $type ) {
if ( isset( $this->sql_clauses[ $type ] ) ) {
$this->sql_clauses[ $type ] = array();
* Replace strings within SQL clauses by type.
* @param string $type Clause type.
* @param string $search String to search for.
* @param string $replace Replacement string.
protected function str_replace_clause( $type, $search, $replace ) {
if ( isset( $this->sql_clauses[ $type ] ) ) {
foreach ( $this->sql_clauses[ $type ] as $key => $sql ) {
$this->sql_clauses[ $type ][ $key ] = str_replace( $search, $replace, $sql );
* Get the full SQL statement.
public function get_query_statement() {
$join = $this->get_sql_clause( 'join', 'filtered' );
$where = $this->get_sql_clause( 'where', 'filtered' );
$group_by = $this->get_sql_clause( 'group_by', 'filtered' );
$having = $this->get_sql_clause( 'having', 'filtered' );
$order_by = $this->get_sql_clause( 'order_by', 'filtered' );
$union = $this->get_sql_clause( 'union', 'filtered' );
{$this->get_sql_clause( 'select', 'filtered' )}
{$this->get_sql_clause( 'from', 'filtered' )}
if ( ! empty( $group_by ) ) {
if ( ! empty( $having ) ) {
if ( ! empty( $union ) ) {
if ( ! empty( $order_by ) ) {
return $statement . $this->get_sql_clause( 'limit', 'filtered' );
* Reinitialize the clause array.
public function clear_all_clauses() {
$this->sql_clauses = array(