I want to change the value of a custom taxonomy in woocommerce.
function get_pw_by_email($email) {
$products = get_posts(array('post_type' =>'product', 'tax_query' =>array(array('taxonomy' =>'pa_e-mail', 'field' =>'name', 'terms' =>$email))));
$terms = wp_get_post_terms($products[0] ->ID, 'pa_pw', true);
if (empty($terms)) {
return '';
}
return $terms[0]->name;
}
Like this I can get the correct taxonomy value. But now I want to create a random number and update that value - without loosing all other other taxonomies of that product.
Update: I was able to solve it.
function get_pw_by_email($email) {
$products = get_posts(array('post_type' =>'product', 'tax_query' =>array(array('taxonomy' =>'pa_e-mail', 'field' =>'name', 'terms' =>$email))));
if (empty($products)) {
return '';
}
$random_number = rand(10000000, 99999999);
$attributes = get_post_meta($products[0] ->ID, '_product_attributes', true);
$terms = wp_get_post_terms($products[0]->ID, 'pa_pw', true);
if (isset($terms[0]->name)) {
// pa_pw attribute is already set for the product, set its value
wp_set_post_terms($products[0] ->ID, $random_number, 'pa_pw', false);
} else {
// pa_pw attribute is not set for the product, add it and set its value
$attributes['pa_pw'] = array('name' => 'pa_pw','value' => null,'is_visible' => '0','is_taxonomy' => '1',);
update_post_meta($products[0] ->ID, '_product_attributes', $attributes);
wp_set_post_terms($products[0] ->ID, $random_number, 'pa_pw', false);
}
$terms = wp_get_post_terms($products[0]->ID, 'pa_pw', true);
if (empty($terms)) {
return '';
}
return $terms[0]->name;
}
If you're doing this on a per-product basis, and not modifying the global taxonomies, one option could be getting the term you want to replace (as you're doing now), remove it with wp_remove_object_terms(), then use wp_set_post_terms() to append the new, modified term.
Related
When saving a product, I want to check if the product has a certain attribute. In my case pa_region. If not I want to add the attribute set and a attribute term to the product.
If the attribute pa_region is already set, I don't want to update/change it.
I saw that there is a function called wp_set_object_terms (Docs). I tried a few things with it but I think, that update_post_meta is the correct way to do it.
From this answer I know how to check if a product has an attribute. I will add that check later.
At the moment I try to add the attribute in the first place. For now it's not working.
I found a similar question here and I tried to use the code for my purpose. But it doesn't work. I guess the reason is that the function needs the attribute already in the product?!
Edit: I checked. Even if the attribute pa_region is set in the product, the code doesn't update the value of it.
Here's my current code:
add_action('woocommerce_update_product', 'save_product_region');
function save_product_region( $post )
{
if( in_array( $post->post_type, array( 'product' ) ) ){
$test = 'test';
$product_id = $post->ID;
$product_attributes = get_post_meta( $product_id ,'_product_attributes', true);
var_dump($product_attributes);
// Loop through product attributes
foreach( $product_attributes as $attribute => $attribute_data ) {
// Target specif attribute by its name
if( 'pa_region' === $attribute_data['name'] ) {
// Set the new value in the array
$product_attributes[$attribute]['value'] = $test;
break; // stop the loop
}
}
update_post_meta( $product_id ,'_product_attributes', $product_attributes );
}
}
First $post is not object. Will return ID which is fine.
add_action('woocommerce_update_product', 'save_product_region');
function save_product_region( $product_id ) {
//Get product object from the ID
$_product = wc_get_product($product_id);
$attributes = $_product->get_attributes();
$add_option = wp_set_object_terms( $product_id, 'canada', 'pa_region', true );
$curr_options = $attributes['pa_region']['options'];
//Check if we have this attribute set already
if(!in_array($add_option,$curr_options)):
$updated_options = array_push($curr_options,$add_option);
$data = array(
'pa_region' => array(
'name'=>'pa_region',
'options'=> $updated_options,
'is_visible' => '1',
'is_variation' => '0',
'is_taxonomy' => '1'
)
);
//First getting the Post Meta
$_product_attributes = get_post_meta($product_id, '_product_attributes', TRUE);
//Updating the Post Meta
update_post_meta($product_id, '_product_attributes', array_merge($_product_attributes, $data));
endif;
}
What i am trying to do is if the user selects a Taxonomy attribute then is should fetch the terms id and set it into the options but, while doing so it just sets the id in the attribute variation rather than the name of the term
public static function create_product_attribute($product,$attribute_data){
$id = [];
function matchTerms($attribute,$types,$isTaxonomy){
$term_id = [];
($isTaxonomy == true) ? $options = (array) $attribute : $options = (array) $attribute->get_options();
foreach($options as $option){
($isTaxonomy == true) ? $name = $option->name : $name = get_term($option)->name;
foreach($types as $type){
if(strtolower($type) == strtolower($name)){
array_push($term_id,($isTaxonomy == true) ? $option->term_id : $option);
}
}
}
return $term_id;
}
foreach($attribute_data as $input_attribute){
$attributes = (array) $product->get_attributes();
$attribute = new KKART_Product_Attribute();
$attribute->set_name($input_attribute['name']);
if(strpos($input_attribute['name'],'pa_') !== false){
$terms = get_terms([
'taxonomy' => $input_attribute['name'],
'hide_empty' => false,
]);
$term_id = matchTerms($terms,$input_attribute['types'],$isTaxonomy = true);
// $terms = [];
// foreach($term_id as $term){
// array_push($terms,get_term($term)->name);
// }
}
(!empty($term_id)) ? $options = $term_id : $options = $input_attribute['types'];
$attribute->set_options($options);
$attribute->set_position( 1 );
$attribute->set_visible( 1 );
$attribute->set_variation( 1 );
$attributes[$attribute->get_name()] = $attribute;
$product->set_attributes($attributes);
array_push($id,$product->save());
}
return $id;
}
The data in `$attribute_data is:
[
{"name":"Color","types":["red"]},
{"name":"pa_material","types":["Type"]}
]
It turns out that when the term_id gets passed in the backend it works fine, but when you check it on the attribute product section it just shows the term id not name for that you just need to save the attribute and let it reload, But even if you dont save it and keep it untouched, it will work fine for the end user.
I am trying to create wordpress snippet that run when post change status from 'draft' to 'publish'. When post change status, my snippet found words in title a replace them with synonymous. I found wordpress action 'draft_to_publish'. But i don't know how get wordpress title to string and how to save post with new title and slug.
Here is a idea
[https://pastebin.com/CBYAZRfr]
Any ideas? :(
Can you check with your code inside this hook
// define the draft_to_publish callback
function action_draft_to_publish( $array ) {
// make action magic happen here...
};
// add the action
add_action( 'draft_to_publish', 'action_draft_to_publish', 10, 1 );
Like this you can do it
function action_post_draft_to_publish($post){
if( $post->post_type == 'post' ) : //Check Post Type, You may update it accordingly for your need
$title = $post->post_title;
// Convert title to lowercase
$lowTitle = mb_convert_case($title, MB_CASE_LOWER, "UTF-8");
// Synonymous for replace
$synonymous = array(
'beautiful' => 'perect',
'vehicle' => 'car',
);
// Loop with word check and replace
foreach($synonymous as $key => $value) {
if( is_string($key) ) {
$stringKey = $key;
// Replace in title
if (strpos($lowTitle, $stringKey) !== false) {
$lowTitle = str_replace($stringKey, $value, $lowTitle);
}
}
}
wp_update_post( array(
'ID' => $post->ID,
'post_title' => $lowTitle //Use Your Updated Title Which You Want to Use
) );
endif; //Endif
}
add_action('draft_to_publish', 'action_post_draft_to_publish', 20);
You can use this code snippet:
function draft_to_publish( $post ) {
$title = $post['post_title'];
$lowTitle = mb_convert_case($title, MB_CASE_LOWER, "UTF-8");
// Synonymous for replace
$synonymous = array(
'beautiful' => 'perect',
'vehicle' => 'car',
);
// Loop with word check and replace
foreach ($synonymous as $key => $value) {
if(is_string($key)) {
$stringKey = $key;
// Replace in title
if (strpos($lowTitle, $stringKey) !== false) {
$lowTitle = str_replace($stringKey, $value, $lowTitle);
}
}
}
// Update post
$my_post = array(
'ID' => $post['ID'],
'post_title' => $lowTitle, // new title
);
// Update the post into the database
wp_update_post( $my_post );
}
add_action( 'draft_to_publish', 'draft_to_publish' );
I'm trying to not load some products on category page based on its name. Googling I found some examples with taxonomies, which doesn't help me at all. So, how can I edit the code below to fit in my needs? Thx!
function check_variations( $q ) {
if ( $outofstock_term = get_term_by( 'name', 'outofstock', 'product_visibility' ) ) {
$tax_query = (array) $q->get('tax_query');
$tax_query[] = array(
'taxonomy' => 'product_visibility',
'field' => 'term_taxonomy_id',
'terms' => array( $outofstock_term->term_taxonomy_id ),
'operator' => 'NOT IN'
);
$q->set( 'tax_query', $tax_query );
}
remove_action( 'pre_get_posts', 'check_variations' );
}
UPDATE
I am really new on Woocommerce. Although It's my first time working on it, I didn't had much difficulties along the way. But I have a problem: Since it's really painful working with products variations, I made a json file with the available variations depending on the category of the product (there are a tons of variations - 91 each product). On product page, I made with js and it's working just fine. Now, I just want to hide some products on the filter page category. Here is my php reading the json:
function check_variations( $q ) {
$page_url = $_SERVER['REQUEST_URI'];
if (strpos($page_url, '?filter_modelo=') !== false) {
$filter = explode('?filter_modelo=', $page_url)[1];
}
if($filter) {
$json_data = file_get_contents(get_template_directory_uri().'/release/json/variations-in-stock.json');
$json_decoded = json_decode($json_data, true);
foreach($json_decoded as $key => $value){
if (strpos(implode(",", $value[0]), $filter) !== false) {
//var_dump($key);
//Here I want to hide products with $key on its name
return;
}
}
}
}
add_action( 'woocommerce_shop_loop', 'check_variations' );
UPDATE 2
I made it by content-product.php file. It worked, but it bugs the pagination... I am trying to add this code to functions.php but I don't know how which action/filter I have to use to get the post/product name and also prevent the pagination bug.
$page_url = $_SERVER['REQUEST_URI'];
$product_name = $product->get_title();
if (strpos($page_url, 'filter_modelo=') !== false) {
$filter = explode('filter_modelo=', $page_url)[1];
$json_data = file_get_contents(get_template_directory_uri().'/release/json/variations-in-stock.json');
$json_decoded = json_decode($json_data, true);
foreach($json_decoded as $key => $value){
if (in_array($filter, explode(', ', $value[0]['modelos']))) {
if (strpos($product_name, $key) !== false) {
return;
}
}
}
}
I have a custom post type named "Designer" Each posts will be using different unique Advanced Custom Fields as each posts has unique templates.With the below code I am able to give rules for each posts in Designer post type and save but the custom fields are not displaying on post edit pages on backend.
Normally this code should ork but no idea what happend to the code
Please Help.
add_filter('acf/location/rule_types', 'acf_location_rules_types');
function acf_location_rules_types( $choices )
{
$choices['Custom Post types']['cpt_parent'] = 'Custom post type parent';
return $choices;
}
add_filter('acf/location/rule_values/cpt_parent', 'acf_location_rules_values_cpt_parent');
function acf_location_rules_values_cpt_parent( $choices )
{
$args = array(
'hierarchical' => true,
'_builtin' => false
);
$posttypes = get_post_types( $args );
if( $posttypes )
{
foreach( $posttypes as $posttype ):
if( $posttype != 'acf' ):
$args = array(
'post_type' => 'designer',
'posts_per_page' => -1,
'post_status' => 'publish'
);
$customposts = get_posts( $args );
if ( $customposts ) {
foreach( $customposts as $custompost ){
$choices[ $custompost->ID] = $custompost->post_title;
}
}
endif;
endforeach;
}
return $choices;
}
//MATCH THE RULE
add_filter('acf/location/rule_match/cpt_parent', 'acf_location_rules_match_cpt_parent', 10, 3);
function acf_location_rules_match_cpt_parent( $match, $rule, $options )
{
global $post;
$selected_post = (int) $rule['value'];
// post parent
$post_parent = $post->post_parent;
if( $options['page_parent'] ) {
$post_parent = $options['page_parent'];
}
if ($rule['operator'] == "=="){
$match = ( $post_parent == $selected_post );
}
elseif ($rule['operator'] != "!="){
$match = ( $post_parent != $selected_post );
}
return $match;
}
Your Artist Collection field group is set to only appear on one post, the post Designer Post 1 which is a Designer Post type.
I don't understand what all the code is for? Just create a different field group for each post that needs a different field group and a separate rule for each.
Ok sorry I understand the issue now and I have recreated the issue on my local install.
On the line of code below you are looking for the post_parent but I think you should be looking for the ID.
I changed this:
$post_parent = $post->post_parent;
to this:
$post_parent = $post->ID;
and it's working for me.
If I understand your problem correctly, in wp-admin post edit page click on screen options on the upper right corner. In the menu that appears make sure the Custom fields is selected. This will make the custom fields appear for edit.