AdCommander::posttype_ad(), 'post_status' => $post_status, 'posts_per_page' => $limit, 'orderby' => $orderby, 'order' => $order, 'no_found_rows' => true, 'ignore_sticky_posts' => true, ); if ( $fields !== 'all' ) { $args['fields'] = $fields; } if ( $meta_query ) { // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- meta_query needed in some cases. $args['meta_query'] = $meta_query; } if ( $tax_query ) { // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query -- tax_query needed in some cases. $args['tax_query'] = $tax_query; } if ( ! empty( $ad_ids ) ) { $args['post__in'] = $ad_ids; } $ad_query = new \WP_Query( $args ); if ( $ad_query->have_posts() ) { $ads = $ad_query->posts; } return $ads; } /** * Query posts with post_title matching. * * @param string $search_term The term to search for in the title. * @param string|array $post_status The post status to query. * @param string $post_type The post type to query. * * @return array */ public static function by_title( $search_term, $post_status = 'publish', $post_type = null ) { if ( $post_type === null ) { $post_type = AdCommander::posttype_ad(); } add_filter( 'posts_where', array( static::class, 'post_title_where' ), 10, 2 ); $post_query = new \WP_Query( array( 'search_title' => $search_term, 'post_type' => $post_type, 'post_status' => $post_status, 'posts_per_page' => -1, 'orderby' => 'title', 'order' => 'asc', 'no_found_rows' => true, 'ignore_sticky_posts' => true, ) ); remove_filter( 'posts_where', array( static::class, 'post_title_where' ), 10, 2 ); if ( $post_query->have_posts() ) { return $post_query->posts; } return array(); } /** * Add like matching to post_title via posts_where filter. Implemented by Query::by_title(). * * @param string $where The current where string. * @param \WP_Query $wp_query The current WP_Query instance. * * @return string */ public static function post_title_where( $where, $wp_query ) { global $wpdb; $title = $wp_query->get( 'search_title' ); $like_sql = ' AND ' . $wpdb->posts . ".post_title LIKE '%" . esc_sql( $wpdb->esc_like( $title ) ) . "%'"; if ( $title && stripos( $where, $like_sql ) === false ) { $where .= $like_sql; } return $where; } /** * Query an individual post by Id. * * @param int $post_id The post ID to query. * @param string|array $post_status The post status to query. * @param string $post_type The post type to query. * * @return bool|\WP_Post */ public static function by_id( $post_id, $post_status = 'publish', $post_type = null ) { if ( $post_type === null ) { $post_type = AdCommander::posttype_ad(); } $result = false; $post_id = absint( $post_id ); $args = array( 'post_type' => $post_type, 'post_status' => $post_status, 'posts_per_page' => 1, 'no_found_rows' => true, ); if ( $post_type === 'page' ) { $args['page_id'] = $post_id; } else { $args['p'] = $post_id; } $post_query = new \WP_Query( $args ); if ( $post_query->have_posts() ) { $result = $post_query->posts[0]; } return $result; } /** * Query an individual ad using WP_Query. * * @param int $ad_id The post ID to query. * @param string $post_status The post_status for the query. * * @return \WP_Post|bool */ public static function ad( $ad_id, $post_status = 'publish' ) { return self::by_id( $ad_id, $post_status ); } /** * Query ads that have an expire key and have expired. * Interfaces with self::ads using a meta_query. * * @return array */ public static function expiring_ads() { $wo_meta = new WOMeta( AdCommander::ns() ); $expire_key = $wo_meta->make_key( 'expire_gmt' ); $meta_query = array( 'relation' => 'AND', 'exists_clause' => array( 'key' => $expire_key, 'compare' => 'EXISTS', ), 'not_empty_clause' => array( 'key' => $expire_key, 'compare' => '!=', 'value' => '', ), 'value_clause' => array( 'key' => $expire_key, 'compare' => '<=', 'value' => time(), 'type' => 'NUMERIC', ), ); return self::ads( 'post_id', 'asc', 'publish', $meta_query ); } /** * Query ads that are in a particular group. * Interfaces with self::ads using a tax_query. * * @param mixed $group_id The term_id of the group to query. * @param string $post_status The status of the ads to query. * * @return array */ public static function ads_by_group( $group_id, $post_status = 'publish', $sync_campaigns = false ) { $tax_query = array( 'relation' => 'AND', array( 'taxonomy' => AdCommander::tax_group(), 'field' => 'term_id', 'terms' => absint( $group_id ), ), ); if ( $sync_campaigns && ! empty( $sync_campaigns ) && ( is_array( $sync_campaigns ) || is_integer( $sync_campaigns ) ) ) { $tax_query[] = array( 'taxonomy' => AdCommander::tax_campaign(), 'field' => 'term_id', 'terms' => is_array( $sync_campaigns ) ? $sync_campaigns : array( $sync_campaigns ), 'operator' => 'IN', ); } return self::ads( 'post_title', 'asc', $post_status, array(), $tax_query ); } /** * Query groups using get_terms() * * @param bool $hide_empty Whether to hide empty groups or not. * @param array $meta_query Optional meta_query to include in get_terms(). * * @return array */ public static function groups( $hide_empty = false, $meta_query = array() ) { $args = array( 'taxonomy' => AdCommander::tax_group(), 'hide_empty' => $hide_empty, ); if ( $meta_query ) { // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- meta_query needed in some cases. $args['meta_query'] = $meta_query; } $groups = get_terms( $args ); if ( ! $groups || is_wp_error( $groups ) ) { $groups = array(); } return $groups; } /** * Query campaigns using get_terms() * * @param bool $hide_empty Whether to hide empty campaigns or not. * @param array $meta_query Optional meta_query to include in get_terms(). * * @return array */ public static function campaigns( $hide_empty = false, $meta_query = array() ) { $args = array( 'taxonomy' => AdCommander::tax_campaign(), 'hide_empty' => $hide_empty, ); if ( $meta_query ) { // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- meta_query needed in some cases. $args['meta_query'] = $meta_query; } $campaigns = get_terms( $args ); if ( ! $campaigns || is_wp_error( $campaigns ) ) { $campaigns = array(); } return $campaigns; } /** * Query advertisers using get_terms() * * @param bool $hide_empty Whether to hide empty advertisers or not. * @param array $meta_query Optional meta_query to include in get_terms(). * * @return array */ public static function advertisers( $hide_empty = false, $meta_query = array() ) { $args = array( 'taxonomy' => AdCommander::tax_advertiser(), 'hide_empty' => $hide_empty, ); if ( $meta_query ) { // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- meta_query needed in some cases. $args['meta_query'] = $meta_query; } $advertisers = get_terms( $args ); if ( ! $advertisers || is_wp_error( $advertisers ) ) { $advertisers = array(); } return $advertisers; } /** * Query the campaigns associated with a specific ad ID. * * @param int $ad_id The ad ID to query campaigns for. * @param string|false $pluck Optional parameter to pluck a specific field from the returned terms. Defaults to 'term_id'. Set to false to return full term objects. */ public static function campaigns_by_ad_id( $ad_id, $pluck = 'term_id' ) { $terms = get_the_terms( $ad_id, AdCommander::tax_campaign() ); if ( ! $terms || is_wp_error( $terms ) ) { return array(); } if ( $pluck ) { return wp_list_pluck( $terms, $pluck ); } return $terms; } /** * Query specific group. * * @param int $term_id The term ID to query. * * @return WP_Term|bool */ public static function group( $term_id ) { $group = get_term( $term_id, AdCommander::tax_group() ); if ( ! $group || is_wp_error( $group ) ) { return false; } return $group; } /** * Check if any groups exist that use a specific mode. * * @param string $mode The name of the mode. * * @return bool */ public static function group_mode_exists( $mode ) { global $wpdb; $wo_meta = new WOMeta( AdCommander::ns() ); $mode_key = $wo_meta->make_key( 'mode' ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- TODO: Test implicatoins of caching this query in future versions. $results = $wpdb->get_results( $wpdb->prepare( 'SELECT meta_id FROM ' . $wpdb->prefix . 'termmeta WHERE meta_key = %s AND meta_value = %s LIMIT 1', $mode_key, $mode ) ); return count( $results ) > 0; } /** * Query inserts using WP_Query * * @param string $post_status The post_status to query. * @param array $meta_query Optional meta_query. * @param array $include_ids Post IDs to include. * * @return array */ public static function placements( $post_status = 'publish', $meta_query = array(), $include_ids = array(), $limit = -1, $fields = 'all' ) { $placements = array(); $args = array( 'post_type' => AdCommander::posttype_placement(), 'post_status' => $post_status, 'posts_per_page' => $limit, 'no_found_rows' => true, 'ignore_sticky_posts' => true, ); if ( $fields !== 'all' ) { $args['fields'] = $fields; } if ( $meta_query ) { // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- meta_query needed in some cases. $args['meta_query'] = $meta_query; } if ( ! empty( $include_ids ) ) { $args['post__in'] = array_map( 'absint', $include_ids ); } $placement_query = new \WP_Query( $args ); if ( $placement_query->have_posts() ) { $placements = $placement_query->posts; } return $placements; } /** * Query an individual insert using WP_Query. * * @param int $placement_id The post ID to query. * @param string $post_status The post_status for the query. * * @return \WP_Post|bool */ public static function placement( $placement_id, $post_status = 'publish' ) { return self::by_id( $placement_id, $post_status, AdCommander::posttype_placement() ); } /** * Determine if the site has ads of any post status. * * @return bool */ public static function has_ads() { $ads = self::ads( 'ID', 'asc', Util::any_post_status(), array(), array(), array(), 1, 'ids' ); return count( $ads ) > 0; } /** * Determine if the site has inserts of any post status. * * @return bool */ public static function has_placements() { $placements = self::placements( Util::any_post_status(), array(), array(), 1, 'ids' ); return count( $placements ) > 0; } }