Create WordPress gallery shortcode from Advanced Custom Fields - php

I am following the instructions set out in the ACF Gallery page at https://www.advancedcustomfields.com/resources/gallery/ in how to create a native Wordpress gallery using the shortcode and dynamically populating the item IDs from the data in the ACF Gallery field.
Example:
EDIT: I have slightly modified the code to include definition for $image_ids
<?php
// Load value (array of ids).
$images = get_field('product_images');
$image_ids = get_field('product_images', false, false);
if( $images ) {
// Generate string of ids ("123,456,789").
$images_string = implode( ',', $image_ids );
// Generate and do shortcode.
$shortcode = sprintf( '', $images_string );
echo do_shortcode( $shortcode );
}
Now my problem is that the an error returns saying that the value for $image_ids is undefined, and rightly so, can't see where that gets defined at all.
I've got some older code that I used to use:
<?php
// different product sizes (gallery)
if(get_field('product_images')) : ?>
<h3>Product Images</h3>
<?php
$image_ids = get_field('product_images', false, false);
$shortcode = '[' . 'gallery ids="' . implode(',', $image_ids) . '"]';
echo do_shortcode( $shortcode );
endif;
?>
This code does work but returns an error php notice array to string conversion in jetpack-carousel. Yes I am using the 'Tiled Galleries Carousel Without Jetpack' plugin.
https://wordpress.org/support/topic/php-notice-array-to-string-conversion-in-jetpack-carousel/page/2/
I really want to follow the recommended way set out in the ACF documentation but it does not work for me. What am I doing wrong?

I don't have ACF installed but after reading their manual, I see a few issues with your code.
Problem one: you are using both $images and $images_ids. Ultimately, both of them are doing the same job and that is to get back the ids array for you. Their data can be different from the last two arguments.
Nonetheless, when you check to see if there is something, you check and evaluation with $images, but then you use $images_ids for your short_code string composition. For the error, I think that is because the version without the optional arguments returned a value while the one($images_ids) that utilized the optional arguments did not return a value but was being utilized anyway by the if clause.
I think you kind of have to figure out, which get_field version you want to use. The one with 3 args or the one with 1 arg.
This was edited after I noticed something, for why you are not getting anything, you may want to contact ACF to update their manual. That sprintf() statement will not do anything. It just going to generate a blank string that all. You may need to alter that sprintf() like the below to follow your old statement, if it still shows array to string conversion error, you would need to debug that.
$image_ids = get_field('product_images', false, false);
if( $image_ids ) {
// Generate string of ids ("123,456,789").
$images_string = implode( ',', $image_ids );
// Generate and do shortcode.
$shortcode = sprintf( '[gallery ids="%s"]', $images_string );
echo do_shortcode( $shortcode );
}

As far as I've tried, the example on the ACF website (https://www.advancedcustomfields.com/resources/gallery/) isn't correct. Here's a less elegant method that worked for me.
<?php
// Get the Gallery Array created by ACF
$galleryarray = get_sub_field('gallery');
// Create an empty array to input the ID's in to
$galleryids = array();
// Loop through the Gallery array
foreach ( $galleryarray as $image ) {
// Grab the image ID
$imageid = $image['id'];
// Put the image ID in to the empty array
array_push($galleryids, $imageid);
}
// Convert the new array into a string, values separated by a comma
$images = implode(',', $galleryids);
// Run the default WordPress Gallery shortcode
echo do_shortcode( '[gallery ids="'.$images.'"]' );
?>

Related

How to use PHP variable with a Wordpress Shortcode of AAWP Plugin

I use Wordpress with the GeneratePress Theme. A feature of this theme called "Elements" let you write php code which will be executed on a specific hook. These Hooks can be found here: https://docs.generatepress.com/article/hooks-visual-guide/
I use the AAWP plugin to show an amazon bestseller list. I want to get the Wordpress category and place it into the bestseller parameter of the aawp shortcode to get Products for the respective categories.
I already read posts here about using php variables in wordpress shortcodes but it seems that something other than the syntax is the problem.
I have this code
<?php
$categories = get_the_category();
if ( ! empty($categories ) ) {
$category = $categories[0];
$name = $category->name;
$bestseller = 'bestseller="'.$name.'"';
$shortCode = '[aawp grid="3" '.$bestseller.' items="3" filter_items="20" orderby="percentage_saved" order="desc"]';
echo do_shortcode($shortCode);
}
?>
The amazon list doesnt appear on my page. It seems that the "bestseller" parameter is neccesarry in order to get shown.
The variable doesnt really get recognized.
When I remove the variable and replace it with a hardcoded bestseller parameter its working fine.
When I use this code:
<?php
$categories = get_the_category();
if ( ! empty($categories ) ) {
$category = $categories[0];
$name = $category->name;
$bestseller = 'bestseller="'.$name.'"';
$shortCode = '[aawp template="angebot-vertical" grid="3" bestseller="'.$name.'" items="3" filter_items="20" orderby="percentage_saved" order="desc"]';
echo do_shortcode($shortCode);
}
?>
It seems that the bestseller value doesnt get read but the "empty" bestseller parameter is enough to show the amazon list, so it just shows random products.
How can I make this work? I just want to place a variable as a value into the "bestseller" parameter. Should be the easiest thing but it doesnt work in the scope of this GeneratePress Elements Hook whith the AAWP shortcode
You're possibly not getting what you believe you need back from get_the_category(). Assuming you're able to get the category id you can use get_cat_name() function to return the category name.
<?php
$cat_name = get_cat_name($category_id);
if ( ! empty($cat_name) ) {
$shortCode = '[aawp template="angebot-vertical" grid="3" bestseller="'.$cat_name.'" items="3" filter_items="20" orderby="percentage_saved" order="desc"]';
echo do_shortcode($shortCode);
}
?>

WordPress/PHP get all navigation links

I am working on a small plugin and am wondering how can I get all links in primary navigation? Wondering if it's possible without knowing the name or slug of the menu in a particular theme.
Below I was trying to get all menu links and return them in a script tag but it didn't work out too well. It ended up returning a bunch of metadata and on one site it broke the site completely.
For now, the script tag is only for testing purposes, where I am going to use the navigation links in an unordered list later on.
function get_nav_menu_items_by_location( $location, $args = [] ) {
?>
<script type = "application/ld+json" alt="hejtest" >
<?
// Get all locations
$locations = get_nav_menu_locations();
// Get object id by location
$object = wp_get_nav_menu_object( $locations[$location] );
// Get menu items by menu name
$menu_items = wp_get_nav_menu_items( $object->name, $args );
// Return menu post objects
return $menu_items;
?>
</script>
<?
}
add_action('wp_head', 'get_nav_menu_items_by_location');
```
You can't "return" data from PHP to JS. The return keyword tells PHP that you've finished the get_nav_menu_items_by_location function, and to give that value to the calling PHP code.
To run JavaScript, you need to output some code that the browser will then execute when it receives the HTML.
If you want to output some data in a way that's easy for JS to read, you can abuse the fact that JSON format is valid JS code, and write echo json_encode($menu_items);. You also need to output code to assign it to a variable, or pass it to a function.
If the function you're writing is expected to return some HTML, you don't want to use echo, and also don't want to use ?>. Instead, you want to build up a PHP string containing the HTML and return that.
So you might end up with this:
function get_nav_menu_items_by_location( $location, $args = [] ) {
$html = '<script type="application/ld+json" alt="hejtest">';
// Get all locations
$locations = get_nav_menu_locations();
// Get object id by location
$object = wp_get_nav_menu_object( $locations[$location] );
// Get menu items by menu name
$menu_items = wp_get_nav_menu_items( $object->name, $args );
$html .= "var my_menu_items = " . json_encode($menu_items) . ";";
$html .= "</script>";
return $html;
}
add_action('wp_head', 'get_nav_menu_items_by_location');

How to limit the number of list elements when displaying the tags for a post type

I get the all tags for my post type, and they are all being displayed. I need to limit this to show only five. Since I do not work with php, I need help on how to implement this correctly. I tried using array_slice method but I got an error.
<div class="menu_grid__tags">
<?php $tags = get_all_tags_from_post_type( "news" );
foreach ( $tags as $tag ) {?>
<?php print $tag ?>
<a class="menu_grid__tag" href="<?= get_category_link( $tag ) ?>"><?= $tag->name ?></a>
<?php }; ?>
</div>
And the get_all_tags_from_post_type function is:
function get_all_tags_from_post_type( $type ) {
$type_ids = get_post_type_ids( $type );
return wp_get_object_terms( $type_ids, 'post_tag' );
}
If you only want to loop five elements, instead of all elements, use a for() loop, and not a foreach() loop.
Change foreach ( $tags as $tag ) {...} to...
for($i = 0; $i < min(5, count($tags)); $i++) {
$tag = $tags[$i];
// (the rest of the code you have
}
Then it will only go over 5 tags, or, if there are fewer than 5 tags, just that many, because we are using min(5, count($tags)).
You can change your get_all_tags_from_post_type function to return only the number of objects you want - this is more efficient than getting all WP_Term objects and then processing the list then to limit the number.
You just need these few changes:
Add a parameter to specify how many tags to get to the get_all_tags_from_post_type function. We also give it a default of 9999 so it will return all if no value is passed in
Limit the list to only include that number of tags, if a value was passed in.
That's it! Step 2 means we only get the Term objects for the ids in our new limited list, and returns just those
/* 1. Add a parameter to the function to specify how many tags to get
Default value = 9999 so it will get all if no values is passed in */
function get_all_tags_from_post_type( $type, $numberOfTags=9999) {
$type_ids = get_post_type_ids( $type );
/* 2. if numberOfTags was passed in, limit the list to only include that number of elements */
if ($numberOfTags < 9999)
$type_ids= array_slice($type_ids, 0, $numberOfTags, true);
/* 3. Now only return the Term objects for those ids */
return wp_get_object_terms( $type_ids, 'post_tag' );
}
Using this version of your function, you just need to tell it how many elements you want to get, e.g. to get 5 elements change this:
$tags = get_all_tags_from_post_type( "news" );
...to this:
$tags = get_all_tags_from_post_type( "news", 5 );

Wordpress | Bulk move content from main editor to custom field

I've used the Advanced Custom Fields plugin to create a new Custom Field in Wordpress. My aim now is to move all Download Links from "the_content", to the newly created Custom Field "the_field('download_link')". The issue is that I have over 10,000 posts to modify. I was wondering if there is a quick way of doing this, rather than manually moving the download link for each post?
Please see the images below for an idea of what I am trying to achieve.
Before | After
One hurdle is that all content is saved in the "wp_posts" table, where the custom field content is saved in the "wp_postmeta" table.
The content saved in the "download_link" custom field, looks like this in the "wp_postmeta" table:
(8214, 2282, 'download_link', '<div class=\"source\"><img src=\"https://www.google.com/image.png\"></div>'),
(8215, 2282, '_download_link', 'field_5cffd35335ce3'),
(8220, 2280, 'download_link', '<div class=\"source\"><img src=\"https://www.google.com/image.png\"></div>'),
(8221, 2280, '_download_link', 'field_5cffd35335ce3'),
(8226, 2278, 'download_link', '<div class=\"source\"><img src=\"https://www.google.com/image.png\"></div>'),
(8227, 2278, '_download_link', 'field_5cffd35335ce3'),
Can this be done at all? Or is the only real way to achieve this is by moving the download links manually?
Thanks in advance for your help.
It can be done automatically if the format of your download link is always the same.
Backup your database
Create a php file named my-cleanup.php.
Loop over all products, grab the link from the description and move it to a post_meta.
Launch the file with WP-CLI:
wp eval-file my-cleanup.php
Sample code
// Select the posts you want
$args = array(
'post_type' => 'post',
'post_status' => 'any',
// -1 means all posts
// For debug, set this to a small number
'posts_per_page' => 3,
);
// Retrieve posts
$query = new WP_Query( $args );
$posts = $query->posts;
// Pattern to match
// [wpdm_package id='90228']
$pattern = "/(\[wpdm_package id='\d+'\])/";
// Process posts one by one
foreach ( $posts as $post ) {
echo "Processing " . $post->post_title . "\n";
$post_args['ID'] = $post->ID;
// Get the shortcode from the post content
preg_match( $pattern, $post->post_content, $matches );
// Do we have a match?
if ( count( $matches) > 0 ) {
// Retrieve shortcode
$shortcode = $matches[0];
// Convert shortcode, maybe add some HTML
$link = do_shortcode( $shortcode );
// remove shortcode from description
$post_args['post_content'] = preg_replace( $pattern, '', $post->post_content );
// Update post
wp_update_post( $post_args );
// Create the post_metas
add_post_meta( $post->ID, '_download_link', 'field_5cffd35335ce3', true );
add_post_meta( $post->ID, 'download_link', $link, true );
}
}
Notes
Backup your database
Test on a few posts to get confidence in your code. You can restore the previous revision in the editor.
Then try on 100, then 1000. You will often find small differences in the way posts are entered.
This might take hours to run on 10.000 posts, which is why you need a WP-CLI command.

How to unserialize() data string when an url inside it has to be changed?

In WordPress you can save post custom information in the form of post meta.
SO I have saved to input fields value in one meta field in the form of serialized array like this.
a:2:{i:0;s:81:"http://sme.sabidoclick.com/sme/wp-content/uploads/2014/05/L-Mini-Instructions.pdf";i:1;s:85:"http://sme.sabidoclick.com/sme/test/wp-content/uploads/2014/05/L-Mini-Graphic-Template.pdf";
So as you can see in the string "i:0;s:81:" this "81" is the length of the next url.
and before transferring the site to new domain I have replaced the url in the database file now the url is changed and the new array is.
a:2:{i:0;s:81:"http://smedisplays.com/test/wp-content/uploads/2014/05/L-Mini-Instructions.pdf";i:1;s:85:"http://smedisplays.com/test/wp-content/uploads/2014/05/L-Mini-Graphic-Template.pdf";
So the url is changed but the length number "81" remains the same due to which the unserialize() function is not working properly.
Is there a quick way to solve it by code because I am having around 450 posts and every single post have this meta field.
So I have worked out a bit on #TiMESPLiNTER suggested solution and solved my problem in such a way though I was not able to understand what #EliasVanOotegem trying to suggest.
May be a working example by him will explain his solution.
And thanks to all for participating in this question.
<?php
$args = array(
'post_type' => 'product',
'meta_key' => '_uploaded_document',
'posts_per_page' => -1
);
// Fetch All posts
$the_query = new WP_Query( $args );
// The Loop
if ( $the_query->have_posts() ) {
while ( $the_query->have_posts() ) {
$the_query->the_post();
$postid = get_the_ID();
// Get the meta value
$meta = get_post_meta( $postid, '_uploaded_document', false );
f(!empty($meta)){
$instruction_sheet = $meta[0][0];
$graphic_template = $meta[0][1];
get_the_title();
if( !empty($instruction_sheet) || !empty($graphic_template)){
$new_array = array();
if(!empty($instruction_sheet)){
// Break the URL in to an array
$iexplode = explode('/', $instruction_sheet);
// Replace a particular element with you string
$iexplode[2]="your_string.com";
// Remove a url sting which you dont need
array_splice($iexplode, 3, 1);
// Combine the array to make new URL again
$iurl = implode('/', $iexplode);
$new_array[] = $iurl;
}
if(!empty($graphic_template)){
$gexplode = explode('/', $graphic_template);
$gexplode[2]="your_string.com";
array_splice($gexplode, 3, 1);
$gurl = implode('/', $gexplode);
$new_array[] = $gurl;
}
// Generate a new serialised string
$new_array = serialize ( $new_array);
// Update the meta value
update_post_meta($postid, '_uploaded_document', $new_array);
}
}
}
} else {
// no posts found
}
/* Restore original Post Data */
wp_reset_postdata();
?>
Its a very old issue but I recently faced similar issue. I was using the multi image upload plugin https://wordpress.org/plugins/multi-image-upload/ and I had Godaddy backups setup. I recently needed to restore my website from godaddy using its backup. and all of a sudden the serialized images data that multi image upload stored in post meta, the unserialize wasn't working on that.
After banging my head around it for almost 2 days, I found that instead of using the "Restore" function to restore db, i needed to downloaded the sql backup, and through phpmyadmin import it and all went well.
Seems like the restore function was corrupting the serialized data.
May help someone.

Categories