Show all terms excluding the current page - wordpress

The following lists all of the terms, can I get help revising it so that it shows all terms except the the active/current page? Thank you.
$terms = get_terms( 'topics', array(
'orderby' => 'name',
'order' => 'ASC',
));
if ( ! empty( $terms ) ){
foreach ( $terms as $term ) {
$term_thumb = get_field('image', $term);
echo '<li><img src="' .$term_thumb['url']. '"><span class="model">'.$term->name .'</span></li>';
}
}

You can do something like this:
// create an empty array holder
$current_tax_ids = array();
// get the post terms
$current_tax = get_the_terms( $post->ID, 'topics' );
// creating loop to insert ids
foreach( $current_tax as $tax ) {
$current_tax_ids[] = $tax->term_id;
}
$args = array(
'taxonomy' => 'topics',
'hide_empty' => 0,
'exclude' => $current_tax_ids // exclude the terms
);
// get all the terms
$all_terms = get_terms($args);
// now do whatever you want
so if you follow my comments it should be clear, but basically you want to get the current post terms and store the id in an array, then simply exclude the ids when you do get_terms .

Related

Bulk update all taxonomy terms in wordpress

My custom post type "references" has a custom field called "references_count". It has a numeric value.
I have an custom taxonomy called "country" with a custom field called "country_count" for the terms.
Background:
The custom post type "references" saves cities with a number of clients in this city. This value is saved in the field "references_count". In the custom taxonomy there are countries. For each country, there is a total number of references.
Example:
In the city of "Berlin" there are 3 clients. In the city of "Munich" there are 2 clients. The taxonomy term "Germany" includes the sum of all cities in this country. So the value of "country_count" in this example for the taxonomy term "Germany" is 5, being the sum of the references of each city.
I wrote this code which is working, if I'm saving each individual taxonomy term.
add_action( 'edited_country', 'update_counter_for_countries', 10, 2 );
function update_counter_for_countries( $term_id ) {
// Get posts with term
$args = array(
'post_type' => 'reference',
'posts_per_page' => -1,
'tax_query' => array(
array(
'taxonomy' => 'country',
'field' => 'term_id',
'terms' => $term_id
)
)
);
$the_query = new WP_Query( $args );
// sum values in posts
$sumTerm = 0;
if ( $the_query->have_posts() ) {
while ( $the_query->have_posts() ) {
$the_query->the_post();
$number = get_field( 'references_count', get_the_ID() );
$sumTerm = $sumTerm + $number;
}
}
wp_reset_postdata();
// update field in term
update_field( 'country_count', $sumTerm, 'country'.'_'.$term_id );
}
Problem:
I have more than 100 countries (taxonomy terms), so I have to save each term individually to get things going.
What I am looking for: Is there a way to update / save all custom taxonomy terms at once, so I don't have to update each term seperately? I checked out a lot of plugins, but couldn't find any plugin which gives the possibility of "bulk edit" or "bulk save" taxonomy terms. I would prefer a solution without plugin if possible. I am very grateful for any hint, thank you very much.
You can use this code to update all terms in one go.
Just make sure to backup your database in case needed.
This code will loop through all the terms and will only run once. after that you can remove this code.
Just to make this code run only on your IP, change 111.111.111.111 to your IP ADDRESS.
if($_SERVER["REMOTE_ADDR"]=='111.111.111.111'){
//run only my ip
add_action("init","update_all_terms_in_one_go");
}
function update_all_terms_in_one_go(){
session_start();
if(isset($_SESSION['all_terms_updated']) && $_SESSION['all_terms_updated'] == "done"){
return;
}
$taxonomy = "country";
$terms = get_terms([
'taxonomy' => $taxonomy,
'hide_empty' => false,
]);
foreach ($terms as $term) {
update_counter_for_countries( $term->term_id );
}
$_SESSION['all_terms_updated'] = "done";
echo "ALL TAXONOMY TERMS UPDATED";
die();
}
function update_counter_for_countries( $term_id ) {
// Get posts with term
$args = array(
'post_type' => 'reference',
'posts_per_page' => -1,
'tax_query' => array(
array(
'taxonomy' => 'country',
'field' => 'term_id',
'terms' => $term_id
)
)
);
$the_query = new WP_Query( $args );
// sum values in posts
$sumTerm = 0;
if ( $the_query->have_posts() ) {
while ( $the_query->have_posts() ) {
$the_query->the_post();
$number = get_field( 'references_count', get_the_ID() );
$sumTerm = $sumTerm + $number;
}
}
wp_reset_postdata();
// update field in term
update_field( 'country_count', $sumTerm, 'country'.'_'.$term_id );
}
I wanted to have a neat admin page with a button to bulk update all my taxonomy terms. The process should work using AJAX so it can take a while without confusing the user. There should be status messages.
So in the first step I added a new admin page to the wordpress backend.
add_action( 'admin_menu', array( $this, 'my_admin_page' ) );
function my_admin_page() {
add_menu_page(
__('Bulk Terms'), // page title
__('Bulk Terms'), // menu title
'manage_options', // user capabilities
'options-page', // menu slug
'my_output_function', // output function
'dashicons-admin-generic', // menu icon
77 // menu position
);
}
In the output function I put a form with a button to bulk update terms. And some status messages.
function my_output_function() {
echo '<div class="wrap">';
echo '<form action="admin.php?page=options-page" method="post">';
wp_nonce_field( 'ajax_validation', 'nonce' ); // security feature
submit_button('Update Terms', 'primary', 'submitOptions', false);
echo '</form>';
echo '<div id="processing" style="display:none;">Please wait</div>';
echo '<div id="error" style="display:none;">Something went wrong</div>';
echo '<div id="success" style="display:none;">Done!</div>';
echo '</div>';
}
In the second step I had to enqueue script file for ajax calls:
add_action( 'admin_enqueue_scripts', 'my_ajax_scripts' );
function my_ajax_scripts() {
// Check if on specific admin page
global $pagenow;
if (( $pagenow == 'admin.php' ) && ($_GET['page'] == 'options-page')):
wp_enqueue_script( 'ajaxcalls', plugin_dir_url( __FILE__ ).'/js/ajax-calls.js', array('jquery'), '1.0.0', true );
wp_localize_script( 'ajaxcalls', 'ajax_object', array(
'ajaxurl' => admin_url( 'admin-ajax.php' ),
'ajaxnonce' => wp_create_nonce( 'ajax_validation' )
) );
endif;
}
And create the function to bulk update all my taxnomy terms:
function options_page_action() {
$taxonomy = "country";
$terms = get_terms([
'taxonomy' => $taxonomy,
'hide_empty' => false,
]);
foreach ($terms as $term) {
$term_id = $term->term_id;
// Get posts with term
$args = array(
'post_type' => 'reference',
'posts_per_page' => -1,
'tax_query' => array(
array(
'taxonomy' => 'country',
'field' => 'term_id',
'terms' => $term_id
)
)
);
$the_query = new WP_Query( $args );
// sum values in posts
$sumTerm = 0;
if ( $the_query->have_posts() ) {
while ( $the_query->have_posts() ) {
$the_query->the_post();
$number = get_field( 'references_count', get_the_ID() );
$sumTerm = $sumTerm + $number;
}
}
wp_reset_postdata();
// update field in term
update_field( 'country_count', $sumTerm, 'country'.'_'.$term_id );
}
$result = array( 'status' => 'success' ); // create response
wp_send_json_success( $result ); // send response
wp_die(); // close ajax request
}
As the third step, in my ajax_calls.js file I take the click event to call the function for updating the taxonomy terms using ajax.
$( '#submitOptions' ).click( function(event) {
event.preventDefault();
$('#submitOptions').css('cssText','display:none;');
$('#processing').css('cssText','display: block;');
$.ajax({
type: 'POST',
url: ajax_object.ajaxurl,
data: {
action: 'options_page_action',
nonce: ajax_object.ajaxnonce
},
success: function( response ) {
if( response['data']['status'] == 'success' ) {
$('#processing').css('cssText','display:none;');
$('#success').css('cssText','display:block;');
}
},
error: function() {
$('#processing').css('cssText','display:none;');
$('#error').css('cssText','display:block;');
}
});
});
There are messages indicating that the function is running and it show messages when it's done or has an error. This way the user will always know what's going on when bulk updating terms.

add_post_meta for all custom posts that dont have the metakey yet

For custom post type "bedrijf", i created a possibility where visitors can leave a rating. If they do, the meta key and value is added and saved. If there is more than one, the average is calculated and the value field is updated.
However, most custom posts don't have a meta key and value yet and i want them to have one with value "0".
The code I got so far:
function create_metadata(){
$args = array(
'post_type' => 'bedrijf',
'posts_per_page' => -1,
);
$posts = get_posts($args);
foreach ( $posts as $post ) {
$av = get_post_meta($post->ID, 'averagerating', true);
if (!isset($av)){
add_post_meta( $post->ID, 'averagerating', '0' );
}
}
}
add_action('init','create_metadata');
But so far this didn't work.
I found the problem, i had to use "new query" like this:
function create_metadata(){
$query = new WP_Query(array(
'post_type' => 'bedrijf',
'posts_per_page' => -1,
));
while ($query->have_posts()) {
$query->the_post();
if(!null == get_post_meta( get_the_ID(), 'averagerating', true )){
add_post_meta( get_the_ID(), 'averagerating', '0' );
}
}

Query to get Attributes based on Product Category selected in WooCommerce?

I need to implement custom functionality like "Product filter by Attributes" widget works in woocommerce.
For example in Product category page:
In Parent Category like Clothing, it loads all the attributes filter (pa_color , pa_size).
Now, when you check sub-category of that parent category i.e., Hoodies. It gets filtered and loads only related attributes (pa_color).
Please suggest the query to achieve this requirement.
This is how I am getting the data as per my requirement :
$filter_raw = array();
$attrs_raw = wc_get_attribute_taxonomy_names(); // Getting data of attributes assign in backend.
$cat_name = get_term($request['category'], 'product_cat', ARRAY_A ); //Category data by category ID.
$args = array(
'category' => array($cat_name['slug'] )
);
foreach( wc_get_products($args) as $product ){
foreach( $product->get_attributes() as $attr_name => $attr ){
$filter_raw[] = $attr_name;
if(is_array($attr->get_terms())){
foreach( $attr->get_terms() as $term ){
$terms_raw[] = $term->name;
}
}
}
}
$filters = array_unique(array_intersect((array)$filter_raw,(array)$attrs_raw)); //Filtering the attributes used by products in particular category
if(is_array($filters)){
foreach ( $filters as $filter ){
$terms = get_terms( $filter );
if ( ! empty( $terms ) ) {
$return['items'][ $filter ] = array(
'id' => $filter,
'type' => 'checkbox',
'label' => $this->decode_html( wc_attribute_label( $filter ) ),
);
foreach ( $terms as $term ) {
if(in_array($term->name,$terms_raw)){ //Filtering the terms from attribute used by the products in a category and showing required result.
$return['items'][ $filter ]['values'][] = array(
'label' => $this->decode_html( $term->name ),
'value' => $term->slug,
);
}
}
}
}
}
print_r($return);

Show posts of a specific category first in WordPress loop

I'd like to show posts from a category first in the homepage and then continue the default order of WordPress posts.
Is it even possible?
I've tried using 2 loops and filter the first one with the category that I want however I don't think that the pagination will work as expected.
Try this (untested code, though).
$total_posts_to_display = 10; // Change accordingly
$id_of_category_1 = 4; // Change accordingly
$filtered_posts = array(); // Array to be filled in with all posts, ordered by "category 1" first
$posts_in_category_1 = get_posts( array(
'numberposts' => $total_posts_to_display,
'category' => $id_of_category_1
) );
$ramaining_posts_number = $total_posts_to_display - count( $posts_in_category_1 );
if ( $ramaining_posts_number > 1 ) {
$excluded_post_ids = array();
foreach( $posts_in_category_1 as $ep ) {
array_push( $excluded_post_ids, $ep->ID );
}
$remaining_posts = get_posts( array(
'numberposts' => $ramaining_posts_number,
'exclude' => $excluded_post_ids
) );
} else {
$remaining_posts = array();
}
$filtered_posts = array_merge( $posts_in_category_1, $remaining_posts );
I have a more sophisticated solution that will support pagination too! You will need to place it in functions.php:
add_action( 'pre_get_posts', 'my_custom_home_post_ordering' );
function my_custom_home_post_ordering( $query ) {
if ( ! is_home() ) {
return;
}
if ( ! $query->is_main_query() ) {
return;
}
$posts_in_category_1 = get_posts( array(
'posts_per_page' => -1,
'category' => 4 // Change accordingly. You may also use 'category_name', instead.
'fields' => 'ids'
) );
$query->set( 'post__in', $posts_in_category_1 );
$query->set( 'orderby', 'post__in' );
}

Exclude children of custom post type from search

I have a custom post type of 'location'. I then have children pages for each of the pages for that cpt. so it looks something like this, "www.example.com/location/location-name/child-page/", each child page is using a post template of "location-product-services.php". So what I am trying to do is exclude from the search results the children of this cpt.
I am trying to do it by checking the meta data to see if it is using that template. I just cant seem to get it working. Any help would be great.
This is what I currently have -
// Exclude local product and services pages from search result.
function location_subpages_exclude_search( $query ) {
if ( is_search() && !is_admin()) {
$query->set('meta_query',
array(
'key' => '_wp_page_template',
'value' => 'location-product-services.php',
'compare' => '!='
)
);
}
}
add_action('pre_get_posts', 'location_subpages_exclude_search');
Thanks in advance.
First, I pretty much exclusively use the Relevanssi plugin any time I want to modify search. But to search programmatically, I think this is what you're after:
$taxonomy = 'location';
$terms = get_terms($taxonomy, array( 'parent' => 0, 'search' => $query ) );
if ( $terms && !is_wp_error( $terms ) ) :
?>
<ul>
<?php foreach ( $terms as $term ) { ?>
<li><?php echo $term->name; ?></li>
<?php } ?>
</ul>
<?php endif;?>
Use the function get_terms to search your CPT, the 'search' is your $query (you might consider wrapping the search string with the SQL wildcard '%') and 'parent'=>0 returns only the top level.
I figured it out.
First I got all parent pages of my post type, used get_pages() grab them all.
Looped through each of the parent pages and ran another get_pages() for children of that parent.
function SearchFilter($query) {
if ($query->is_search) {
$args = array(
'hierarchical' => 0,
'post_type' => 'location',
'parent' => 0, //returns all top level pages
'post_per_page' => -1
);
$parents = get_pages($args);
$excludes = array();
foreach($parents as $parent) :
$args = array(
'post_type' => 'location',
'child_of' => $parent->ID,
'post_per_page' => -1
);
$children = get_pages($args);
foreach($children as $child):
array_push($excludes, $child->ID);
endforeach;
endforeach;
$query->set('post__not_in', $excludes);
}
return $query;
}
add_filter('pre_get_posts','SearchFilter');

Resources