Dynamically populate an ACF field (radio) on a multisite install - wordpress

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;

Related

Wordpress get_posts() shows only partially correct data of custom post inside user profile

I have a wordpress-based website where I'm trying to move some custom functionality that used to be just plain mysql table and some code to insert/update/show stuff from it. I'm trying to merge it in WP as custom posts so I can use filters, tags, pagination and such.
It supposed to show a few custom items inside the user profile (Ultimate Member). Like, user info, then 10 of user's top items of this kind, then on next tab 10 items of some other kind, etc.
But seems like things aren't as simple in WP, and you can't just toss things on top of each other and expect it to not overlap. >_> So when I'm trying to add a block with custom post type data, it returns only some of the data mixed with profile data mixed with nothingness.
Yeah, I get it, there's probably a profile loop and some data already inside variables, as far as I could understand from manuals. What I can't understand is how to fix it. Here's how it looks:
$args = array(
'author' => $uid,
'numberposts' => 10,
'post_type' => 'ff',
);
$ff = get_posts($args);
if($ff){
foreach($ff as $f){
setup_postdata($f);
the_content(); //shows what's needed, as well as ID, the_time() and some more
the_title(); //shows author's name instead of post title
the_tags(); //shows nothing, as well as excerpt, etc
get_the_excerpt(); //still nothing
$f->post_excerpt; //but this shows the excerpt, as well as print_r($f)
}
wp_reset_postdata();
}
Maybe someone could give a hint what am I missing? Thanks in advance!
Try using the post ID to get your data and echo it. A little more code but may work better.
// Set the global post up here
global $post;
$args = array(
'author' => $uid,
'numberposts' => 10,
'post_type' => 'ff',
);
$ff = get_posts($args);
if($ff){
foreach($ff as $f){
setup_postdata($f);
$id = $f->ID; // get post ID
$content = get_the_content($id); // get the content to echo later
$tags = get_the_tags($id); // use to get tags, these are not part of the get_posts return object
echo $content; // show the content
echo $f->post_title; // show the returned post title. can use get_the_title($id) and echo it if this does not work
// Display the tags after getting them above
foreach ($tags as $tag) {
echo $tag->name . ', ';
}
// You can get the excerpt this way too but you said your other worked okay
$excerpt = get_the_excerpt($id);
echo $excerpt;
}
wp_reset_postdata();
}
(Original) To elaborate. This sets up the global post object. Which is generally a requirement for your functions to work in the loop. Not always the case as I've found over the years, but a good practice if you're not using the post ID in the loop to get your data.

How to remove meta value in all WordPress posts?

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.

Woocommerce custom Product slug

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 );
}

Importing Product data doesn't show meta value

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.

Dynamic permalinks when creating a post in WordPress

I have a custom post type named houses. Inside my custom post type I have several custom fields which I created using ACF.
What I need to do is to change the permalink when I create a new post.
I would like to use the code and title fields to customize the permalink:
//code + post title
4563312-house-example-1
I'm developing a plugin which controls everything.
Is there a way to intermediate the creation of a post to update its permalink?
Thanks.
After some research, I found an answer related to wp_insert_post_data.
Using wp_insert_post_data, I couldn't get the custom field value, and to achieve that, I had to use another action, save_post instead.
function rci_custom_permalink($post_id) {
$post = get_post($post_id);
if($post->post_type !== 'houses') return;
$code = get_field('code', $post_id);
$post_name = sanitize_title($post->post_title);
$permalink = $code . '-' . $post_name;
// remove the action to not enter in a loop
remove_action('save_post', 'rci_custom_permalink');
// perform the update
wp_update_post(array('ID' => $post_id, 'post_name' => $permalink));
// add the action again
add_action('save_post', 'rci_custom_permalink');
}
add_action('save_post', 'rci_custom_permalink');
PS: Since all these fields are required, I didn't need to check if they are empty or not.
For reference about save_post action:
Plugin API/Action Reference/save post

Resources