I am facing very strange issue. I am working on woocomerce based wordpress site, in which I have imported about more than 1 lack product form XML programatically, My problem is product meta data named Related Product saved in database, Displayed in back-end, But not displayed on single product page on front-end. But when I manually update post from back-end then after it displayed. It is not possible for me to manually update more than 1 lack post. So I decided to create function that will update post.
add_action( 'wp_loaded', 'my_update_posts' );
if ( $_REQUEST['test'] == 1 ) {
function my_update_posts() {
$args = array(
'post_type' => 'product',
'numberposts' => -1
);
$myposts = get_posts($args);
//echo "<pre>"; print_r($myposts); die;
foreach ( $myposts as $mypost ) {
if ( $mypost->ID == 17 ) {
//$mypost->title = "test";
wp_update_post( $mypost );
}
}
}
}
So I created this function and tested but it will update/save post data like content and title, and not updating/saving meta data.
I want create function that can save post programatically, including meta data.
The best way to save post data is using the update_post_meta function.
I have no idea how Woocommerce saves the related products. Keep in mind that it might make more then one meta field, maybe even create meta in the other related post.
Hope this helps, your question is a bit vague.
Related
Am working on a blog and I want to add a banner which is a featured post.
But am not sure how can I make only one post to be marked as the "Featured" so if another post is marked as "Featured" it removes the old post from showing as featured.
I've tried using ACF (Advance Custom Field) checkbox to mark featured posts but my approach is incorrect.
Here is my code.
<?php
global $post;
$myposts = get_posts( array(
'posts_per_page' => 1,
'order' => 'DESC',
'numberposts' => 1,
) );
if ( $myposts ) {
foreach ( $myposts as $post ) :
setup_postdata( $post );
if(get_field('featured_post')):
?>
Once I marked the other posts featured nothing shows up.
Planning to follow this approach but I have no idea on how to remove the old featured posts.
An ACF checkbox / True/False field is a good starting point. A solution from there on would be to...
hook onto the acf/save_post action
check whether the currently saved post has featured_post enabled
if enabled, unset the 'featured' flag on the previously featured post
if enabled, store the post's ID as a global option for the featured post ('mysites_featured_post')
upon rendering the banner, get the featured post's ID from this option
For the option, you can do two things: use WP's own update_option, or create an ACF options page with a Post field that contains just one (featured) post. The ACF options page has the advantage that you can manually edit the featured post in wp-admin by navigating to the options page.
However, I'll demonstrate it using WP's update_option:
function hookACFSavePost($post_id) {
$marked_featured = get_field('featured_post', $post_id);
if ($marked_featured) {
// get previously featured post
$prev_featured_post = get_option('mysites_featured_post', false);
if (is_numeric($prev_featured_post)) {
// disable featured flag on the previously featured post, for consistency:
update_field('featured_post', false, $prev_featured_post);
}
// store this as the current featured post
update_option('mysites_featured_post', $post_id, true);
}
}
add_action('acf/save_post', 'hookACFSavePost', 20);
By this, we have achieved to disable the 'featured' checkbox on the previously selected post (if it existed), and stored the new featured post's ID in the 'mysites_featured_post' option.
To then get the featured post for rendering the banner, you can retrieve the $post_id from the option:
$featured_post_id = get_option('mysites_featured_post', false);
if ($featured_post_id) {
$post = get_post( $featured_post_id );
// render the post('s ID)
// ...
}
This solution is simple and efficient in the sense that it does not have to iterate over / query all posts' meta entries to find the currently featured post.
Is there a way to create custom product URL based on the product attributes, I have a product sunglasses which has a couple of attributes tied to it: metal, blue and round, so the current URL is:
website.com/glasses/sunglasses/abram-widana-629/
What I am trying to get is a URL which has those attributes included:
website.com/glasses/sunglasses/abram-widana-meta-blue-round-629/
I would really appreciate if someone would even just point me to the right direction on how to tackle this.
There are two ways to do this, either Manually or Programmatically.
Manually adjusting permalinks:
In your example, you are simply adjusting the product URL to include attributes. This can be achieved manually by editing the permalink on the product itself.
Once the product has been added/saved, you will see the permalink showing directly under the title field like this:
Simply click the Edit button next to it and change it from abram-widana-629 to abram-widana-meta-blue-round-629
Programmatically adding attributes to permalinks:
If you want to try to achieve this permanently for all products you will have to work through the "save_post" filter/hook to add all the attributes to the permalink. The only downfall from this is that you will no longer be able to adjust your individual permalinks for your products as they will simply revert back once you click save.
Below is a code example of how to achieve that:
add_action( 'save_post', 'add_custom_attributes_to_permalink', 10, 3 );
function add_custom_attributes_to_permalink( $post_id, $post, $update ) {
//make sure we are only working with Products
if ($post->post_type != 'product' || $post->post_status == 'auto-draft') {
return;
}
//get the product
$_product = wc_get_product($post_id);
//get the "clean" permalink based on the post title
$clean_permalink = sanitize_title( $post->post_title, $post_id );
//next we get all of the attribute slugs, and separate them with a "-"
$attribute_slugs = array(); //we will be added all the attribute slugs to this array
foreach ($_product->get_attributes(); as $attribute_slug => $attribute_value) {
$attribute_slugs[] = $attribute_value;
}
$attribute_suffix = implode('-', $attribute_slugs);
//then add the attributes to the clean permalink
$full_permalink = $clean_permalink.$attribute_suffix;
// unhook the save post action to avoid a broken loop
remove_action( 'save_post', 'add_custom_attributes_to_permalink', 10, 3 );
// update the post_name (which becomes the permalink)
wp_update_post( array(
'ID' => $post_id,
'post_name' => $full_permalink
));
// re-hook the save_post action
add_action( 'save_post', 'add_custom_attributes_to_permalink', 10, 3 );
}
I'm trying to populate an Advanced Custom Fields' radio field pulling out the data from a custom post type located in the main blog of a multisite install.
For a better understanding I made this simple flow graphic.
So I created a function in order to pull out the data from Main Blog and show as radio items on child site.
The function looks like this and I used this as reference
function getctas($field) {
$field['choices'] = array();
switch_to_blog(1);
$args = array(
'post_type' => 'location_icons',
'posts_per_page' => '-1',
);
$ctas = new WP_Query( $args );
while ( $ctas->have_posts()) {
$ctas->the_post();
$choices = get_field('icon',false);
$choices = explode("\n", $choices);
foreach( $choices as $choice ):
$field['choices'][ $choice ] = '<img src="'.$choice.'"/>';
endforeach;
}
restore_current_blog();
return $field;
}
add_filter('acf/load_field/name=call_to_action_icon', 'getctas');
I get the options listed correctly (options are images), I successfully pulled out the field icon from main blog and put as radio label and value.
The issue I'm having is that once the post is saved when I query it on the child's page template I get the correct images but the title of the post on blog 1 repeated. The ideal would be to have:
Image
Child Blog Post's Title
Child Blog Post's Desc
And what I'm, instead getting is:
Correct Image
CTP Title that contains the image on blog 1
No description
Correct Image
Same title as previous one
No description
And so on.
If any of you need more clarifications to help me solve this I'd be pleased to explain further.
Please declare global $switched; before switching to the main blog , it seems wp is not switching it back to the current blog if it does not work after declaring the global variable, Please try this
get current blog id before switching to main blog $current_site =get_current_blog_id();
once you are done. switch it back using
switch_to_blog( $current_site );
$GLOBALS['_wp_switched_stack'] = array();
$GLOBALS['switched'] = FALSE;
I'm trying to get a plugin to read the post metadata of an attachment, and use it to update the content of the post it is attached to. I'm using the following in my themes function.php:
add_action( 'afip_created_post', 'get_desc', 10, 2 );
function get_desc( $post_id, $attachment_id ) {
$postmeta = get_post_meta ($attachment_id, '_wp_attachment_metadata', true);
$meta = $postmeta['image_meta'];
$mmwwdesc = $meta['description'];
wp_update_post( array( 'ID' => $post_id, 'post_content' => $mmwwdesc ) );
}
and then using this line in the plugin to hook the function
do_action( 'afip_created_post', $new_post_id, $post_id );
If I fill in the varibale "$attachment_id" with a number from another post i.e "15," I get the description inserted into the published post. If I change the output to wp_update_post( array( 'ID' => $post_id, 'post_content' => $attachment_id ) ); I get the id number echoed in the body of the published post. I'm don't understand why the original code does not work, since $attachment_id seems to be properly defined. I'm just a beginner with php. Is there something obvious that I'm doing wrong? Is the variable $attachment_id being echoed when it should be returned, or something technical like that?
Background: I'm using two wordpress plugins, one called Media Metadata Workflow Wizard (MMWW), and the other called Automatic Featured Image Post (AFIP). MMWW extracts the image metadata and writes it to the database as post meta. AFIP creates new posts using uploaded media, and attaches each image to a post, setting it as the post thumbnail. I don't think its an issue of the metadata not being ready when the function is called, because AFIP creates the post after the media has been uploaded, and had its meta written to the database. I'm also hooking my function as an update to the post, after it has already been created.
I've done extensive searching, and trial and error with no success. Can anybody help me out?
Thanks!
I think your issue here is that the get_post_meta function is returning blank in functions.php. The way to deal with this issue is to use a MYSQL query with wordpress to return the data in your psot meta.
First you need the global $wpdb object so at the start of your function write: global $wpdb;
Then you need to do the get_post_meta action using mysql and the $wpdb object:
$postmeta = $wpdb->get_var("SELECT meta_value FROM $wpdb->postmeta" WHERE meta_key = '_wp_attachment_metadata' AND post_id = $attachment_id");
Replace your get_post_meta line with the wpdb query and you should be fine.
I have a taxonomy.php file to display taxonomy terms. I added a filter in functions.php to include post types for the taxonomy page query. This filter:
add_filter( 'pre_get_posts' , 'ucc_include_custom_post_types' );
function ucc_include_custom_post_types( $query ) {
global $wp_query;
/* Don't break admin or preview pages. */
if ( !is_preview() && !is_admin() && !is_page() && !is_single() ) {
$args = array(
'public' => true ,
'_builtin' => false
);
$output = 'names';
$operator = 'and';
$post_types = get_post_types( $args , $output , $operator );
$post_types = array_merge( $post_types , array( 'post' ) );
if ($query->is_feed) {
// Do feed processing here.
} else {
$my_post_type = get_query_var( 'post_type' );
if ( empty( $my_post_type ) )
$query->set( 'post_type' , $post_types );
}
}
return $query;
}
Returns any and all post types you want. But I am trying to find a way to separate them. I tried to use a normal loop but I don't know how to fetch the current taxonomy tag from the page.
I have 2 questions which are all related but seeing what is the best way to go about this. Pretend I have 3 posts types ('post' 'post2' 'post3')
Is there a loop that can be used in taxonomy.php that will display a particular post type? So it can be possible to have one loop for each post type? So when I click on a taxonomy term, the taxonomy.php will return:
--Taxonomy Page --
Loop for custom type post 1 (show post with current taxonomy tag in this specific post type)
Loop for custom type post 2
Loop for custom type post 3
If there are multiple loops, will this affect the pagination? Or will pagination only work for posts?
I have used many single loops in the taxonomy.php page to no avail. I feel I have to echo the current taxonomy term variable to a new variable:
$term = $wp_taxonomies??
Any way for multiple loops in the taxonomy.php pages?
Probably the easiest way to do this is ignore the existing $wp_query and create three new queries in your taxonomy template. So don't start "The Loop" in your template, just create a new query and loop with that one. Repeat this for the other post types. This also means you don't need to hook into the pre_get_posts filter, you create a custom query just for you.
You will have to think about the UI for the next pages, indeed. This depends on the reason you want the post types separated. If it is enough that you see the three together on the first page, you could go with three separate "next page" links, so one per post type.