query_filter = &$query_filter; } /** * Attempts to guess the correct URL based on query vars * * @since 3.2.3 * * @param string $name * @param WP_Query $query * * @return array containing most likely name, type and whether or not a match was found */ public function guess_cpt_by_name( $name, $query ) { $type = $query->get( 'post_type' ); $ret = array( $name, $type, false ); $types = (bool) $type === false ? $this->sitepress->get_wp_api()->get_post_types( array( 'public' => true ) ) : (array) $type; if ( (bool) $types === true ) { $date_snippet = $this->by_date_snippet( $query ); $cache = new WPML_WP_Cache( 'WPML_404_Guess' ); $cache_key = 'guess_cpt' . $name . wp_json_encode( $types ) . $date_snippet; $found = false; $ret = $cache->get( $cache_key, $found ); if ( ! $found ) { $ret = $this->find_post_type( $name, $type, $types, $date_snippet ); $cache->set( $cache_key, $ret ); } } return $ret; } /** * Query the database to find the post type * * @param string $name * @param string $type * @param array $types * @param string $date_snippet * * @return array */ private function find_post_type( $name, $type, $types, $date_snippet ) { $ret = array( $name, $type, false ); $where = $this->wpdb->prepare( "post_name = %s ", $name ); $where .= " AND post_type IN ('" . implode( "', '", $types ) . "')"; $where .= $date_snippet; $res = $this->wpdb->get_row( " SELECT post_type, post_name FROM {$this->wpdb->posts} p LEFT JOIN {$this->wpdb->prefix}icl_translations t ON t.element_id = p.ID AND CONCAT('post_', p.post_type) = t.element_type AND " . $this->query_filter->in_translated_types_snippet( false, 'p' ) . " WHERE $where AND ( post_status = 'publish' OR ( post_type = 'attachment' AND post_status = 'inherit' ) ) " . $this->order_by_language_snippet( (bool) $date_snippet ) . " LIMIT 1" ); if ( (bool) $res === true ) { $ret = array( $res->post_name, $res->post_type, true ); } return $ret; } /** * Retrieves year, month and day parameters from the query if they are set and builds the appropriate sql * snippet to filter for them. * * @param WP_Query $query * * @return string */ private function by_date_snippet( $query ) { $snippet = ''; foreach ( array( 'year' => 'YEAR', 'monthnum' => 'MONTH', 'day' => 'DAY' ) as $index => $time_unit ) { if ( (bool) ( $value = $query->get( $index ) ) === true ) { $snippet .= $this->wpdb->prepare( " AND {$time_unit}(post_date) = %d ", $value ); } } return $snippet; } /** * @param bool $has_date * * @return string */ private function order_by_language_snippet( $has_date ) { $lang_order = $this->get_ordered_langs(); $current_lang = array_shift( $lang_order ); $best_score = count( $lang_order ) + 2; $order_by = ''; if ( $best_score > 2 ) { $order_by .= $this->wpdb->prepare( 'ORDER BY CASE t.language_code WHEN %s THEN %d ', $current_lang, $best_score ); $score = $best_score - 2; foreach ( $lang_order as $lang_code ) { $order_by .= $this->wpdb->prepare( ' WHEN %s THEN %d ', $lang_code, $score ); $score -= 1; } $order_by .= ' ELSE 0 END DESC '; if ( $has_date ) { $order_by .= ", CASE p.post_type WHEN 'post' THEN 0 ELSE 1 END "; } $order_by .= ' , ' . $this->order_by_post_type_snippet(); } return $order_by; } /** * * @return string */ private function order_by_post_type_snippet() { $post_types = array( 'page' => 2, 'post' => 1 ); $order_by = ' CASE p.post_type '; foreach ( $post_types as $type => $score ) { $order_by .= $this->wpdb->prepare( ' WHEN %s THEN %d ', $type, $score ); } $order_by .= ' ELSE 0 END DESC '; return $order_by; } }