setAccessible( true ); $cache->setValue( null, array( 'post' => 'aeav_only', 'user' => 'disabled', 'term' => 'disabled', 'comment' => 'disabled' ) ); } public static function tearDownAfterClass(): void { $cache = new ReflectionProperty( WPDO_Mode_Manager::class, 'cache' ); $cache->setAccessible( true ); $cache->setValue( null, null ); WPDO_Entity_Registry::init(); } /** * @param array $vars Query vars (post_type defaults to product). * @return array{query:WP_Query, join:string, where:string, orderby:string} */ private function route( array $vars ): array { $query = new WP_Query(); foreach ( $vars + array( 'post_type' => 'product' ) as $k => $v ) { $query->set( $k, $v ); } $router = new TMDO_Post_Query_Router(); $router->pre_get_posts( $query ); return array( 'query' => $query, 'join' => $router->posts_join( '', $query ), 'where' => $router->posts_where( '', $query ), 'orderby' => $router->posts_orderby( 'wp_posts.post_date DESC', $query ), ); } /** * @param string $type Clause type. * @return array */ private function sort_shape( string $type ): array { return array( array( 'relation' => 'OR', 'price__order' => array( 'key' => '_price', 'type' => $type, 'compare' => 'NOT EXISTS' ), array( 'key' => '_price', 'type' => $type, 'compare' => 'EXISTS' ), ), ); } public function test_sort_shape_left_joins_and_orders_by_the_flat_column_without_filtering(): void { $sql = $this->route( array( 'meta_query' => $this->sort_shape( 'DECIMAL' ), 'orderby' => 'price__order', 'order' => 'ASC' ) ); $this->assertSame( array(), $sql['query']->get( 'meta_query' ), 'sort group removed from the native meta_query' ); $this->assertStringContainsString( 'LEFT JOIN `wp_itest_wpdo_post_wc_product` AS ' . self::ALIAS, $sql['join'] ); $this->assertStringNotContainsString( '_price', $sql['where'], 'every post matches: no condition' ); $this->assertStringStartsWith( self::ALIAS . '.`_price` ASC', $sql['orderby'] ); } public function test_sort_shape_with_char_type_on_a_numeric_column_stays_native(): void { $vars = array( 'meta_query' => $this->sort_shape( 'CHAR' ), 'orderby' => 'price__order', 'order' => 'ASC' ); $sql = $this->route( $vars ); $this->assertSame( $vars['meta_query'], $sql['query']->get( 'meta_query' ) ); $this->assertSame( 'wp_posts.post_date DESC', $sql['orderby'] ); } public function test_orderby_on_a_named_routed_clause_orders_by_its_column(): void { $sql = $this->route( array( 'meta_query' => array( 'price' => array( 'key' => '_price', 'compare' => 'EXISTS', 'type' => 'NUMERIC' ) ), 'orderby' => array( 'price' => 'DESC' ), ) ); $this->assertStringContainsString( self::ALIAS . '.`_price` IS NOT NULL', $sql['where'] ); $this->assertStringStartsWith( self::ALIAS . '.`_price` DESC', $sql['orderby'] ); } public function test_orderby_naming_a_routed_clause_among_other_keys_stays_native(): void { $vars = array( 'meta_query' => array( 'price' => array( 'key' => '_price', 'compare' => 'EXISTS', 'type' => 'NUMERIC' ) ), 'orderby' => array( 'price' => 'DESC', 'title' => 'ASC' ), ); $sql = $this->route( $vars ); $this->assertSame( $vars['meta_query'], $sql['query']->get( 'meta_query' ) ); $this->assertSame( 'wp_posts.post_date DESC', $sql['orderby'] ); } public function test_meta_value_num_on_a_numeric_key_requires_the_key_and_orders_by_its_column(): void { $sql = $this->route( array( 'meta_key' => '_price', 'orderby' => 'meta_value_num', 'order' => 'DESC' ) ); $this->assertSame( '', $sql['query']->get( 'meta_key' ), 'primary meta clause taken over' ); $this->assertStringContainsString( self::ALIAS . '.`_price` IS NOT NULL', $sql['where'], 'native INNER JOIN drops posts without the key' ); $this->assertStringStartsWith( self::ALIAS . '.`_price` DESC', $sql['orderby'] ); } public function test_meta_value_on_a_string_key_is_routed(): void { $sql = $this->route( array( 'meta_key' => '_sku', 'orderby' => 'meta_value', 'order' => 'ASC' ) ); $this->assertStringStartsWith( self::ALIAS . '.`_sku` ASC', $sql['orderby'] ); } public function test_meta_value_on_a_numeric_key_stays_native(): void { $sql = $this->route( array( 'meta_key' => '_price', 'orderby' => 'meta_value', 'order' => 'ASC' ) ); $this->assertSame( '_price', $sql['query']->get( 'meta_key' ), 'native string order' ); $this->assertSame( 'wp_posts.post_date DESC', $sql['orderby'] ); } public function test_meta_key_with_a_meta_value_filter_stays_native(): void { $sql = $this->route( array( 'meta_key' => '_price', 'meta_value' => '5', 'orderby' => 'meta_value_num' ) ); $this->assertSame( '_price', $sql['query']->get( 'meta_key' ) ); $this->assertSame( 'wp_posts.post_date DESC', $sql['orderby'] ); } }