I want my acf field "unique_field" in my custom post type "places" to be unique.
I used acf/validate_value documented here -> https://www.advancedcustomfields.com/resources/acf-validate_value/
https://support.advancedcustomfields.com/forums/topic/solved-check-if-value-already-exist-2/
I tried to put this on my functions.php but it doesn't work.
add_filter('acf/validate_value/name=unique_field', 'validate_unique_field_filter', 10, 4);
function validate_unique_field_filter($valid, $value, $field, $input) {
if (!$valid || $value == '') {
return $valid;
}
// query posts for the same value
global $post;
$args = array(
'post_type' => 'places',
'post__not_in' => array($post->ID),
'meta_query' => array(
array(
'key' => 'unique_field',
'value' => $value
)
)
);
$query = new WP_Query($args);
if (count($query->posts)) {
$valid = 'Place already exist';
}
return $valid;
}
Are there any mistakes? Please Advise. Thank you!
it is missing 'meta_key' => 'unique_field' in the meta_query array
the filter 'acf/validate_value/name=unique_field' should be 'acf/validate_value/key=field_unique_field'
Related
I have the following code:
function custom_meta_query( $meta_query ){
$rem_width = get_query_var('rem_width');
$rem_length = get_query_var('rem_length');
$meta_query[] = array( 'key'=>'remnant_width', 'value' => $rem_width, 'compare'=>'>=');
$meta_query[] = array( 'key'=>'remnant_length', 'value' => $rem_length, 'compare'=>'>=');
$meta_query['relation'] = 'AND';
return $meta_query;
}
// The main shop and archives meta query
add_filter( 'woocommerce_product_query_meta_query', 'custom_product_query_meta_query', 10, 2 );
function custom_product_query_meta_query( $meta_query, $query ) {
if( (! is_admin() ) && ((isset($_GET['rem_width'])) || (isset($_GET['rem_length']) ) ))
return custom_meta_query( $meta_query );
}
I want to order the products returned by width and currently it is showing alphabetical order.
'orderby' => 'meta_value_num',
'meta_key' => 'remnant_width',
'order' => 'ASC'
But I don't know how to incorporate it into what has gone before.
Thanks
I'm trying to get a list with all woocommerce attributes and values, but only those used for product variations (for example, I want to get "size" and "color" values, but not other attributes used only for information purposes like "fabric" or "weight").
I'm using this code:
$allAttributes = wc_get_attribute_taxonomies();
foreach ($allAttributes as $att) {
$wcAttribute = wc_get_attribute($att->attribute_id);
[...]
}
At this point, I want to check if this $wcAttribute is used for any product variation, to add it to my list or not, but I don't know how to proceed.
Any help?
I respond to myself, because I found a solution. Probably, it isn't the best solution, but it works (if someone has any better solution, I'll appreciate):
function getAllWCAttributes()
{
/* Format for attributes: ['attribute_id' => ['id', 'name', 'values'=>['id', 'name'] ] ]*/
$attributes = array();
$allAttributes = wc_get_attribute_taxonomies();
foreach ($allAttributes as $att) {
if (isAttributeUsedForVariations($att)) {
$wcAttTerms = get_terms('pa_' . $att->attribute_name);
$terms = array();
foreach ($wcAttTerms as $wcTerm) {
$terms[] = array(
'id' => $wcTerm->term_id,
'name' => $wcTerm->name
);
}
$attributes[$att->attribute_id] = array(
'id' => $att->attribute_id,
'name' => $att->attribute_label,
'values' => $terms
);
}
}
return $attributes;
}
function isAttributeUsedForVariations($attribute)
{
$terms = array();
$attTerms = get_terms('pa_' . $attribute->attribute_name);
foreach ($attTerms as $attTerm) {
$terms[] = $attTerm->slug;
}
$args = array(
'post_type' => 'product_variation',
'post_status' => 'publish',
'meta_query' => array(
array(
'key' => 'attribute_pa_' . $attribute->attribute_name,
'value' => $terms,
'compare' => 'IN'
)
)
);
$variationsQuery = new WP_Query($args);
return ($variationsQuery->post_count > 0)? true: false;
}
Documentation:
wc_get_attribute_taxonomies()
get_terms()
WP_Query
i use a Toolset plugin to make view on WP and they give us possibility to manipulate with API.
I try to add argument to my view but it doesn't work.
here is the function :
add_filter( 'wpv_filter_query', 'add_city_tax', 99, 3 );
function add_city_tax( $query_args, $view_settings, $view_id )
{
if($view_id == 7706)
{
$args = array(
'tax_query' => array
(
array
(
[taxonomy] => 'ville',
[field] => 'id',
[terms] => Array
(
[0] => 220
),
[operator] => 'IN'
),
[relation] => 'OR',
),
);
}
$query_args = new WP_Query( $args );
return $query_args;
}
the page make an error
The method you are declaring args is not correct. You should not create array like that. Please check following example.
function add_city_tax( $query_args, $view_settings, $view_id ) {
if($view_id == 7706) {
$args = array(
'tax_query' => array(
array(
'taxonomy' => 'ville',
'field' => 'id',
'terms' => array( 220 ),
'operator' => 'IN',
),
'relation' => 'OR',
),
);
}
$query_args = new WP_Query( $args );
return $query_args;
}
And here doc
Description
When displaying a View listing posts, this filter is applied to the arguments being generated by the View settings before they are passed to the WP_Query class.
Views filters - wpv_filter_query
Note that the filters that you can add to the View are also hooked here, each of them using a different priority that gets up to 100. To ensure that your filter runs after them, you would need to use a higher priority number.
Remember that the filter can take three parameters. If you pass more than one, you need to specify it in your code using the fourth argument:
1
add_filter( 'wpv_filter_query', 'my_callback_function', 99, 3 );
Arguments
array $query_args Τhe query arguments as in WP_Query.
array $view_settings The View settings.
int $view_id The View ID.
No it doesn't work like this.
i have tried like this :
function add_city_tax( $query_args, $view_settings, $view_id ) {
if($view_id == 7706) {
$args = array(
'tax_query' => array(
array(
'taxonomy' => 'ville',
'field' => 'id',
'terms' => array( 220 ),
'operator' => 'IN',
),
'relation' => 'AND',
),
);
}
$query_args[] = $args ;
$msg = '<pre>' . print_r($query_args, true) . '</pre>';
mail('franck#efficonex.fr', 'test', $msg);
return $query_args;
}
add_filter( 'wpv_filter_query', 'add_city_tax', 99, 3 );
But it is the same result without filter.
here is the example of api
//Return only posts from the current author when listing posts of type company:
add_filter( 'wpv_filter_query', 'prefix_show_only_current_author' );
function prefix_show_only_current_author( $query_args ) {
global $current_user;
$types = (array) $query_args['post_type'];
if ( !is_admin() && in_array( 'company', $types ) ) {
$query_args['author'] = empty( $current_user->ID ) ? -1 : $current_user->ID;
}
return $query_args;
}
EDIT: See the last (3rd) code snippet, it's the working one.
I have an "Actions" page (an archive for a custom post type called Actions), which is an equivalent to "events".
I used this tutorial to filter them with custom fields: ville (city), action (type of action) and date and it works perfectly.
Then I created another function to filter by "date range": past, future actions. And it also works. But they "accumulate". When I select "Past" actions and a city, it shows me ALL past actions + ALL actions that happened or will happen in a city.
So these two functions work, but I don't know how to set their relation to AND or something that makes them work together instead of "accumulating".
Can someone please help me figure this out ?
Thank you.
Function to filter by Type/City/Date custom fields:
// array of filters (field key => field name)
$GLOBALS['my_query_filters'] = array(
'action' => 'action',
'ville' => 'ville',
'date' => 'date',
);
// action
add_action('pre_get_posts', 'my_pre_get_posts', 10, 1);
function my_pre_get_posts( $query ) {
// bail early if is in admin
if( is_admin() ) return;
// bail early if not main query
// - allows custom code / plugins to continue working
if( !$query->is_main_query() ) return;
// get meta query
$meta_query = $query->get('meta_query');
// loop over filters
foreach( $GLOBALS['my_query_filters'] as $key => $name ) {
// continue if not found in url
if( empty($_GET[ $name ]) ) {
continue;
}
// get the value for this filter
// eg: http://www.website.com/events?city=melbourne,sydney
$value = explode(',', $_GET[ $name ]);
// append meta query
$meta_query[] = array(
'key' => $name,
'value' => $value,
'compare' => 'IN',
);
}
$query->set( 'orderby', array( 'date' => 'DESC' ) );
// update meta query
$query->set('meta_query', $meta_query);
return;
}
?>
Function for Future/Past actions:
<?php
add_action('pre_get_posts', 'future_past_actions', 10, 1);
function future_past_actions( $query ) {
// bail early if is in admin
if( is_admin() ) return;
// bail early if not main query
// - allows custom code / plugins to continue working
if( !$query->is_main_query() ) return;
// get meta query
$meta_query = $query->get('meta_query');
if( isset($_GET['range']) ) {
$range = explode(',', $_GET['range']);
$meta_query[] = array(
'key' => 'range',
'value' => $range,
'compare' => 'IN',
);
if( $query->get( 'range' ) == 'future' ) {
$meta_query[] = array(
'key' => 'date',
'value' => date("Ymd"),
'compare' => '>',
);
$meta_query['relation'] = 'OR';
}
elseif( $query->get( 'range' ) == 'past' ) {
$meta_query[] = array(
'key' => 'date',
'value' => date("Ymd"),
'compare' => '<',
);
$meta_query['relation'] = 'OR';
}
elseif( $query->get( 'range' ) == 'toutes' ) {
return;
}
}
$query->set( 'meta_key', 'date' );
$query->set( 'orderby', array( 'date' => 'DESC' ) );
$query->set('meta_query', $meta_query);
return;
}
?>
The final merged and working code:
<?php
// array of filters (field key => field name)
$GLOBALS['my_query_filters'] = array(
'action' => 'action',
'ville' => 'ville',
'date' => 'date'
);
add_action('pre_get_posts', 'my_pre_get_posts', 10, 1);
function my_pre_get_posts( $query ) {
// bail early if is in admin
if( is_admin() ) return;
// bail early if not main query
// - allows custom code / plugins to continue working
if( !$query->is_main_query() ) return;
if( ! is_post_type_archive( 'actions' ) ) return;
// CITY/TYPE/DATE filters
// loop over filters
foreach( $GLOBALS['my_query_filters'] as $key => $name ) {
// continue if not found in url
if( empty($_GET[ $name ]) ) { continue; }
// get the value for this filter
// eg: http://www.website.com/events?city=melbourne,sydney
$value = explode(',', $_GET[ $name ]);
// append meta query
$meta_query[] = array(
'key' => $name,
'value' => $value,
'compare' => 'IN',
);
}
// FUTURE/PAST/ALL filters
if( isset($_GET['range']) ) {
$range = $_GET['range'];
if($range != "toutes") {
// Select what kind of compare you need
if($range == "past") {
$comparer = '<';
} else if($range == "future") {
$comparer = '>=';
}
// If you need to filter by date add this to meta_query array
$meta_query[] = array(
'key' => 'date',
'value' => date("Ymd"),
'compare' => $comparer,
);
}
}
// update meta query
$query->set('meta_query', $meta_query);
$query->set( 'meta_key', 'date' );
$query->set( 'orderby', array( 'date' => 'DESC' ) );
$query->set('posts_per_page', '20');
}
?>
In this case best solution in my opinion is to have one action and check query arguments inside of it and then decide what kind of logic you want to do.
$query variable has all the arguments you assign, so your code might look something like this:
Editing considering the comments on situation, you have to use AND relation between two meta fields. Code inside action should look like this:
add_action('pre_get_posts', 'my_pre_get_posts', 10, 1);
function my_pre_get_posts( $query ) {
$meta_query = array(
'relation' => 'AND',
array(
'key' => 'ville',
'value' => '$value',
'compare' => '=',
)
);
// Select what kind of compare you need
if($range == "past") {
$compare = ">";
} else if($range == "future") {
$compare = "<";
}
if($range != "all") {
// If you need to filter by date add this to meta_query array
$date_query = array(
'key' => 'date',
'value' => 'date(\"Ymd\"),',
'compare' => $compare,
);
$meta_query[] = $date_query;
}
$query->set( 'orderby', array( 'date' => 'DESC' ) );
// update meta query
$query->set('meta_query', $meta_query);
}
Because what you do now, you set query arguments multiple times.
If you need more parameters to filter out you can add them conditionally to $meta_query variable considering what kind of parameters you get.
I think if I understand correctly this kind of meta query should return needed results.
I am working on a project where I need to list all hidden products in a page. I have created a shortcode for that and I have used following meta query, but it's not working.
$meta_query = array(
'key' => '_visibility',
'value' => array('hidden'),
'compare' => 'IN'
);
Any idea why this is not working? Thank you in advance for your help.
$args = array(
'post_type' => 'product',
'meta_key' => '_visibility',
'meta_value' => 'hidden'
);
$query = new WP_Query($args);
Then your usual loop worked for me :)
WooCommerce 3+ visibility has been changed to a taxonomy instead of post meta and if you're using WC()->query->get_tax_query() function call for building the args, you can just remove that call from setting tax_query.
IF you don't have access to the args or how they are built and it is ran through get_tax_query you can use the filter to remove the NOT IN tax query for visibility:
add_filter( 'woocommerce_product_query_tax_query', 'smyles_show_all_products' );
// do something that calls some fn that makes product query
remove_filter( 'woocommerce_product_query_tax_query', 'smyles_show_all_products' );
function smyles_show_all_products( $tax_query ) {
foreach( (array) $tax_query as $t_index => $t_query ){
if( isset( $t_query['taxonomy'], $t_query['operator'] ) && $t_query['taxonomy'] === 'product_visibility' && $t_query['operator'] === 'NOT IN' ){
unset( $tax_query[ $t_index ] );
break;
}
}
return $tax_query;
}
Use this
'meta_query' => array(
array(
'key' => '_visibility',
'value' => array( 'catalog', 'visible' ),
'compare' => 'IN'
)
)