add_list_dynamics( $apl_post_list );
$this->query_args_arr = $this->set_query_args_arr( $apl_post_list );
$this->query_args_arr = $this->query_arg_consolidate( $this->query_args_arr );
$this->query_args_arr = $this->query_args_accommodate( $this->query_args_arr );
}
/**
* Add Dynamic values to Post List
*
* Adds the current global post values for any dynamic settings checked.
*
* @ignore
* @since 0.3.b8
* @since 0.4.0 - Changed to use APL_Post_List object.
* @access private
*
* @param APL_Post_List $apl_post_list APL Post List object.
* @return APL_Post_List Modified post list object.
*/
private function add_list_dynamics( $apl_post_list ) {
$post_id = get_the_ID();
if ( ! $post_id ) {
return $apl_post_list;
}
// EXCLUDE CURRENT POST.
if ( $apl_post_list->pl_exclude_current ) {
$apl_post_list->post__not_in[] = $post_id;
}
$current_post_type = get_post_type( $post_id );
$current_taxonomies = get_post_taxonomies( $post_id );
$terms_args = array(
'orderby' => 'term_id',
'order' => 'ASC',
'fields' => 'ids',
);
foreach ( $apl_post_list->post_type as $k1_index => $v1_pt_arr ) {
if ( is_array( $v1_pt_arr ) ) {
// POST TYPES.
foreach ( $v1_pt_arr as $k2_index => $v2_pt_slug ) {
// Current Post Type.
// PAGE PARENT.
if ( $current_post_type === $v2_pt_slug ) {
if ( isset( $apl_post_list->post_parent_dynamic[ $v2_pt_slug ] ) ) {
if ( $apl_post_list->post_parent_dynamic[ $v2_pt_slug ] ) {
// Add current Page as Parent and prevent doubles.
$apl_post_list->post_parent__in[ $v2_pt_slug ][] = $post_id;
$apl_post_list->post_parent__in[ $v2_pt_slug ] = array_values( array_unique( $apl_post_list->post_parent__in[ $v2_pt_slug ] ) );
}
}
}
// TAXONOMIES.
if ( isset( $apl_post_list->tax_query[ $v2_pt_slug ] ) ) {
foreach ( $apl_post_list->tax_query[ $v2_pt_slug ] as $k3_tax_key => &$v3_tax_arr ) {
if ( 'relation' !== $k3_tax_key ) {
if ( in_array( $v3_tax_arr['taxonomy'], $current_taxonomies, true ) ) {
if ( $v3_tax_arr['apl_terms_dynamic'] ) {
// Add Terms.
$current_taxonomy_terms = wp_get_post_terms(
$post_id,
$v3_tax_arr['taxonomy'],
array(
'fields' => 'ids',
)
);
if ( is_wp_error( $current_taxonomy_terms ) ) {
echo '
' . esc_html( $current_taxonomy_terms->get_error_message() ) . '
';
return $apl_post_list;
}
foreach ( $current_taxonomy_terms as $current_term_id ) {
//$apl_post_list->tax_query[ $v2_pt_slug ]['terms'][] = $current_term_id;
$v3_tax_arr['terms'][] = $current_term_id;
}
$apl_post_list->tax_query[ $v2_pt_slug ][ $k3_tax_key ]['terms'] = array_values( array_unique( $v3_tax_arr['terms'] ) );
}
}
}
}
}
}// End Foreach( POST TYPE).
} else { // ANY / ALL.
// TAXONOMIES.
if ( isset( $apl_post_list->tax_query[ $v1_pt_arr ] ) ) {
foreach ( $apl_post_list->tax_query[ $v1_pt_arr ] as $k2_tax_key => &$v2_tax_arr ) {
if ( 'relation' !== $k2_tax_key ) {
if ( in_array( $v2_tax_arr['taxonomy'], $current_taxonomies, true ) ) {
if ( $v2_tax_arr['apl_terms_dynamic'] ) {
// Add Terms.
$current_taxonomy_terms = wp_get_post_terms(
$post_id,
$v2_tax_arr['taxonomy'],
array(
'fields' => 'ids',
)
);
if ( is_wp_error( $current_taxonomy_terms ) ) {
echo '' . esc_html( $current_taxonomy_terms->get_error_message() ) . '
';
}
foreach ( $current_taxonomy_terms as $current_term_id ) {
$v2_tax_arr['terms'][] = $current_term_id;
}
$apl_post_list->tax_query[ $v1_pt_arr ][ $k2_tax_key ]['terms'] = array_values( array_unique( $v2_tax_arr['terms'] ) );
}
}
}
}
}
// Break Post Type Loop (Just in case).
break;
}// End if().
}// End foreach().
return $apl_post_list;
}
/**
* Set Query Args
*
* Sets multiple query_args in query_args_arr.
*
* @ignore
* @since 0.3.b8
* @since 0.4.0 - Changed to use APL_Post_List structure.
* @access private
*
* @see $query_args for WP_Query.
* @link https://gist.github.com/luetkemj/2023628
*
* @param APL_Post_List $apl_post_list APL Post List object.
* @return array Multiple query_args
*/
private function set_query_args_arr( $apl_post_list ) {
$rtn_query_args_arr = array();
foreach ( $apl_post_list->post_type as $v1_pt_arr ) {
$tmp_query_args = array();
// If there is an array of post types, then loop through and add.
if ( is_array( $v1_pt_arr ) ) {
foreach ( $v1_pt_arr as $v2_pt_slug ) {
$tmp_query_args['post_type'] = array( $v2_pt_slug );
$tmp_tax_query = $apl_post_list->tax_query[ $v2_pt_slug ];
if ( ! empty( $tmp_tax_query ) ) {
$tmp_query_args['tax_query']['relation'] = $tmp_tax_query['relation'];
$tmp_query_args['tax_query'] = $tmp_tax_query;
}
// Page Parents.
if ( isset( $apl_post_list->post_parent__in[ $v2_pt_slug ] ) ) {
$tmp_query_args['post_parent__in'] = $apl_post_list->post_parent__in[ $v2_pt_slug ];
}
}
} else { // ANY.
$tmp_query_args['post_type'] = 'any';
if ( ! empty( $apl_post_list->tax_query[ $v1_pt_arr ] ) ) {
$tmp_tax_query = $apl_post_list->tax_query[ $v1_pt_arr ];
$tmp_query_args['tax_query']['relation'] = $tmp_tax_query['relation'];
$tmp_query_args['tax_query'] = $tmp_tax_query;
}
}// End if().
// General Filter.
$tmp_query_args['posts_per_page'] = $apl_post_list->posts_per_page;
$tmp_query_args['page'] = 1;
$tmp_query_args['offset'] = $apl_post_list->offset;
$tmp_query_args['orderby'] = $apl_post_list->order_by;
$tmp_query_args['order'] = $apl_post_list->order;
// Handle post_status in accommodate method.
$tmp_query_args['post_status'] = $apl_post_list->post_status;
if ( 'none' !== $apl_post_list->perm ) {
$tmp_query_args['perm'] = $apl_post_list->perm;
}
if ( 'none' !== $apl_post_list->author__bool && ! empty( $apl_post_list->author__in ) ) {
if ( 'in' === $apl_post_list->author__bool ) {
$tmp_query_args['author__in'] = $apl_post_list->author__in;
} elseif ( 'not_in' === $apl_post_list->author__bool ) {
$tmp_query_args['author__not_in'] = $apl_post_list->author__in;
}
}
$tmp_query_args['ignore_sticky_posts'] = $apl_post_list->ignore_sticky_posts;
$tmp_query_args['post__not_in'] = $apl_post_list->post__not_in;
$rtn_query_args_arr[] = $tmp_query_args;
}// End foreach().
return $rtn_query_args_arr;
}
/**
* Query Args Consolidation
*
* Merges any simular query strings.
*
* STEP 1: Go through string and match post parents with the same post status
* or tax query.
* STEP 2: Return (modified) query_str_array.
*
* @ignore
* @since 0.3.b8
* @access private
*
* @param array $arg_arr Multi-dimensional query_str array.
* @return array Multi-dimensional query_str array.
*/
public function query_arg_consolidate( $arg_arr ) {
$query_count = count( $arg_arr );
for ( $i = 0; $i < $query_count; $i++ ) {
if ( empty( $arg_arr[ $i ]['post_parent'] ) ) {
$query_count = count( $arg_arr );
for ( $j = $i + 1; $j < $query_count; $j++ ) {
// IF there is a post_parents; which would conflict.
// IF both query_arg's tax_query match.
$tax_query_match = $this->tax_query_match( $arg_arr[ $i ]['tax_query'], $arg_arr[ $j ]['tax_query'] );
if ( isset( $arg_arr[ $i ]['post_parent'] ) && empty( $arg_arr[ $i ]['post_parent'] ) && $tax_query_match ) {
$arg_arr[ $i ]['post_type'][] = $arg_arr['post_type'][0];
unset( $arg_arr[ $j ] );
$arg_arr = array_values( $arg_arr );
// Set $i back 1 to do next $j properly.
$i--;
} elseif ( ! isset( $arg_arr[ $i ]['post_parent'] ) && $tax_query_match ) {
$arg_arr[ $i ]['post_type'][] = $arg_arr['post_type'][0];
unset( $arg_arr[ $j ] );
$arg_arr = array_values( $arg_arr );
// Set $i back 1 to do next $j properly.
$i--;
}
}
}
}
return $arg_arr;
}
/**
* Match Tax Query Args
*
* Checks to see if there is a 100% relation.
*
* STEP 1: Check and return false if taxomonies do not have 100% relation.
* STEP 2: Return true if there is a 100% relation.
*
* @ignore
* @since 0.3.b8
* @access private
*
* @param array $tax_query1 The query string's tax query.
* @param array $tax_query2 The query string's tax query.
* @return boolean Similar Tax_Querys.
*/
private function tax_query_match( $tax_query1, $tax_query2 ) {
// STEP 1.
if ( $tax_query1['relation'] === $tax_query2['relation'] ) {
$tax_query_count1 = count( $tax_query1 ) - 1;
for ( $i = 0; $i < $tax_query_count1; $i++ ) {
$tax_match_found = false;
$tax_query_count2 = count( $tax_query2 ) - 1;
for ( $j = 0; $j < $tax_query_count2; $j++ ) {
// Would have included the next IF statement if the 2 weren't
// required to have and not have an else return false.
if ( $tax_query1[ $i ]['taxonomy'] === $tax_query2[ $j ]['taxonomy'] ) {
$tax_match_found = true;
if ( $tax_query1[ $i ]['operator'] === $tax_query2[ $j ]['operator'] ) {
foreach ( $tax_query1[ $i ]['terms'] as $key => $value ) {
if ( ! in_array( $value, $tax_query2[ $j ]['terms'], true ) ) {
return false;
}
}
} else {
return false;
}
}
}
if ( ! $tax_match_found ) {
return false;
}
}
} else {
return false;
}
// STEP 2.
return true;
}
/**
* Add/Change Query Args
*
* Modifications for certain enhancements after query array has been consolidated.
*
* @ignore
* @since 0.4.0
* @private
*
* @param array $query_args_arr Old query argument array.
* @return array
*/
private function query_args_accommodate( $query_args_arr ) {
$rtn_query_args_arr = array();
foreach ( $query_args_arr as $v1_query_args ) {
if ( is_array( $v1_query_args['post_status'] ) ) {
$public = array_search( 'public', $v1_query_args['post_status'], true );
$private = array_search( 'private', $v1_query_args['post_status'], true );
if ( $public && $private ) {
unset( $v1_query_args['post_status'][ $public ] );
$rtn_query_args_arr[] = $v1_query_args;
unset( $v1_query_args['post_status'][ $private ] );
$rtn_query_args_arr[] = $v1_query_args;
} elseif ( $public ) {
unset( $v1_query_args['post_status'][ $public ] );
$rtn_query_args_arr[] = $v1_query_args;
} else {
$rtn_query_args_arr[] = $v1_query_args;
}
} elseif ( 'none' === $v1_query_args['post_status'] ) {
// WP Default.
$v1_query_args['post_status'] = array( 'publish' );
$rtn_query_args_arr[] = $v1_query_args;
} elseif ( 'any' === $v1_query_args['post_status'] ) {
$v1_query_args['post_status'] = 'any';
$rtn_query_args_arr[] = $v1_query_args;
}
}
return $rtn_query_args_arr;
}
/**
* APL Query WP
*
* Queries multiple instances of this function if there is more than one
* query_str.
*
* STEP 1: If this is NOT the first and last instance of this function.
* Then repeat this function if more queries are present, and
* query/collect the posts IDs.
* STEP 2: FINAL Query and order the post IDs collected. Return results.
*
* @since 0.3.b8
*
* @see Function/method/class relied on
* @link https://gist.github.com/EkoJr/7352549
*
* @param array $query_str_array Multi-dimensional query_str array.
* @param boolean $repeated This function repeated.
* @return mixed WP_Query class if unrepeated, otherwise array of post_IDs.
*/
public function query_wp( $query_str_array, $repeated = false ) {
$post_in_ids = array();
$post_not_in_ids = array();
/*
* Normally a recursive function will have an exit statement setup first,
* however, it needs to check if it is a repeated instance first before
* moving on to the first/last instance.
*/
// TODO Create function for the repeated query_wp function.
if ( true === $repeated ) {
// Shift the args when repeating this method / function.
// If more args exist, then repeat this function.
// Merge returned post ids for pre-final query.
$query_str = array_shift( $query_str_array );
if ( ! empty( $query_str_array ) ) {
$post_in_ids = array_merge( $this->query_wp( $query_str_array, true ), $post_in_ids );
}
// Add Terms for Any/All ( value = 0 ).
if ( ! empty( $query_str['tax_query'] ) ) {
foreach ( $query_str['tax_query'] as $k1_index => $tax_arr ) {
if ( 'relation' === $k1_index ) {
continue;
}
if ( 0 === $tax_arr['terms'][0] && 1 === count( $tax_arr['terms'] ) ) {
$terms_args = array(
'taxonomy' => $tax_arr['taxonomy'],
'fields' => 'ids',
);
$tax_arr['terms'] = get_terms( $terms_args );
$query_str['tax_query'][ $k1_index ] = $tax_arr;
} else {
$query_str['tax_query'][ $k1_index ] = $tax_arr;
}
}
}
if ( isset( $query_str['page'] ) ) {
if ( 1 < $query_str['page'] ) {
$query_str['posts_per_page'] *= $query_str['page'];
}
unset( $query_str['page'] );
}
// Since post__in and post__not_in don't mix at all. The 2 variables
// are stored separately.
// TODO Create function for Post Include/Exclude.
if ( ! empty( $query_str['post__not_in'] ) && 0 < $query_str['posts_per_page'] ) {
// Removed at final.
//$post_not_in_ids = $query_str['post__not_in'];
$query_str['posts_per_page'] += count( $query_str['post__not_in'] );
}
unset( $query_str['post__not_in'] );
if ( ! empty( $query_str['post__in'] ) ) {
$post_in_ids = array_merge( $post_in_ids, $query_str['post__in'] );
}
unset( $query_str['post__in'] );
// If Posts Per Page is set to -1/Unlimited, then set nopaging to true.
if ( -1 === $query_str['posts_per_page'] ) {
$query_str['nopaging'] = true;
}
if ( isset( $query_str['offset'] ) ) {
$query_str['offset'] = 0;
}
// Sets the query string to just query IDs.
$query_str['fields'] = 'ids';
$query_obj = new WP_Query( $query_str );
// Collect an array of Post IDs.
$post_ids = array();
if ( ! empty( $query_obj->posts ) ) {
foreach ( $query_obj->posts as $i => $post_id ) {
$post_ids[] = intval( $post_id );
}
}
$post_ids = array_merge( $post_ids, $post_in_ids );
wp_reset_postdata();
return $post_ids;
} else {
/*
* This is the Initial and Final Query. This is used to collect IDs first
* with 1 or more query_str (that couldn't be consolidated/merged), and
* then do one last query here to return. This allows sorting with other
* custom post types that couldn't be queried together, and allows
* compatability with posts_in & posts_not_in.
*/
$post_in_ids = array_merge( $this->query_wp( $query_str_array, true ) );
$query_str = array_shift( $query_str_array );
// Filter out excluded posts.
foreach ( $query_str['post__not_in'] as $post_not_value ) {
foreach ( $post_in_ids as $key => $post_in_value ) {
if ( $post_in_value === $post_not_value ) {
unset( $post_in_ids[ $key ] );
}
}
}
$post_in_ids = array_merge( $post_in_ids );
// Prevent defaulting when there's no posts.
if ( empty( $post_in_ids ) ) {
$post_in_ids[] = 0;
}
$paginate_offset = 0;
if ( isset( $query_str['page'] ) ) {
$paginate_offset = $query_str['posts_per_page'] * ( $query_str['page'] - 1 );
}
// STEP.
// Set FINAL query_str with post IDs.
$final_query_str = array(
'post__in' => $post_in_ids,
'post_type' => 'any',
'posts_per_page' => $query_str['posts_per_page'],
'offset' => ( $query_str['offset'] + $paginate_offset ),
'nopaging' => ( -1 === $query_str['posts_per_page'] ) ? true : false,
'order' => $query_str['order'],
'orderby' => $query_str['orderby'],
'ignore_sticky_posts' => $query_str['ignore_sticky_posts'],
// Does not work. Uses offset instead.
//'page' => $query_str['page'],
//'paged' => $query_str['page'],
);
// Get FINAL Query Object.
$final_query_obj = new WP_Query( $final_query_str );
return $final_query_obj;
}// End if().
}
}