im trying to put icons in front of every menu item with ACF. I used this tutorial here https://www.advancedcustomfields.com/resources/adding-fields-menu-items/
It works perfectly but it always add icon AFTER the menu item but I need it to put it IN FRONT of it. I believe it is just some minor code edit I cant see.
Here is my code:
add_filter('wp_nav_menu_objects', 'my_wp_nav_menu_objects', 10, 2);
function my_wp_nav_menu_objects( $items, $args ) {
// loop
foreach( $items as &$item ) {
// vars
$icon = get_field('icon', $item);
// append icon
if( $icon ) {
$item->title .= ''.$icon.'';
}
}
// return
return $items;
}
Thank you for any help.
ms
what you do there is that you add it after the title,
so insted of: $item->title .'' . $icon . '';
It should look like this: $item->title = $icon . $item->title;
Related
I'm trying to display some attributes directly on the shop page. The attributes are all collected in the database. To make it easier to show, I made a screenshot so you can get a better idea. the thing is now, with which code I can do that. the attributes, there are always 4, should be display centered under the block with the pictures and the buy button. I would be very happy if we could find a way to do this. Thanks very much
Ok, i've found some code here on stackoverflow... the good news are, i get the results/attributes i want, the bad news are, on the wrong page (shop page instead of shop page single).
this is the code:
add_action('woocommerce_after_shop_loop_item_title', 'display_custom_product_attributes_on_loop', 5 );
function display_custom_product_attributes_on_loop() {
global $product;
// Settings: Here below set your product attribute label names
$attributes_names = array('alter', 'bausteine', 'publicationdate', 'sku');
$attributes_data = array(); // Initializing
// Loop through product attribute settings array
foreach ( $attributes_names as $attribute_name ) {
if ( $value = $product->get_attribute($attribute_name) ) {
$attributes_data[] = $attribute_name . ': ' . $value;
}
}
if ( ! empty($attributes_data) ) {
echo '<div class="items" style="color: red;"><p>' . implode( '<br>', $attributes_data ) . '</p></div>';
}
}
this code shows me the attributes and the results on the shoppage, but i need it on the single shop page/product page.
Thank you!
Change the hook name and then check
add_action('woocommerce_single_product_summary', 'display_custom_product_attributes_on_loop', 5 );
function display_custom_product_attributes_on_loop() {
global $product;
// Settings: Here below set your product attribute label names
$attributes_names = array('alter', 'bausteine', 'publicationdate', 'sku');
$attributes_data = array(); // Initializing
// Loop through product attribute settings array
foreach ( $attributes_names as $attribute_name ) {
if ( $value = $product->get_attribute($attribute_name) ) {
$attributes_data[] = $attribute_name . ': ' . $value;
}
}
if ( ! empty($attributes_data) ) {
echo '<div class="items" style="color: red;"><p>' . implode( '<br>', $attributes_data ) . '</p></div>';
}
}
I have a wordpress website where customers make an image with text and icons, once processed thru woocommerce and payed for that image name 12345.png is saved as Customer_product_image
function add_order_item_meta($item_id, $values) {
$key = 'customer_product_image'; // Define your key here
$value = $values['user_img']; // Get your value here
woocommerce_add_order_item_meta($item_id, $key, $value);
}
And i works great, but now i'm banning my head against the wall! When the purchased image is displayed on the Order admin detail page, it shows up as CUSTOMER_PRODUCT_IMAGE: 1234.png how on earth would i go about wrapping that within an image tag so the image is displayed there?
I've searched high and low on google but haven't been able to find anything, its probably that i dont know what do actually search for....
This did the trick for me!
First i added this snippet for removing the custom meta item on order detail render:
add_filter( 'woocommerce_hidden_order_itemmeta', 'hide_order_item_meta_fields' );
function hide_order_item_meta_fields( $fields ) {
$fields[] = 'current_view';
$fields[] = 'custom_image';//Add all meta keys to this array,so that it will not be displayed in order meta box
return $fields;
}
second i added it back with this, and with the desired text and image tag:
add_action( 'woocommerce_after_order_itemmeta', 'order_meta_customized_display',10, 3 );
function order_meta_customized_display( $item_id, $item, $product ){
$all_meta_data=get_metadata( 'order_item', $item_id, "", "");
$useless = array(
"_qty","_tax_class","_variation_id","_product_id","_line_subtotal","_line_total","_line_subtotal_tax","_line_tax","_line_tax_data"
);// Add key values that you want to ignore
$customized_array= array();
foreach($all_meta_data as $data_meta_key => $value) {
if(!in_array($data_meta_key,$useless)){
$newKey = ucwords(str_replace('_'," ",$data_meta_key ));//To remove underscrore and capitalize
$customized_array[$newKey]=ucwords(str_replace('_'," ",$value[0])); // Pushing each value to the new array
}
}
if (!empty($customized_array)) {
foreach($customized_array as $data_meta_key => $value){
echo "<div class='product_container'><span>Produkt Billede: </span><img src='".wp_upload_dir()['baseurl'].'/flapper/'. $value ."' /> </div>";
}
}
}
i found the answer to this question on this page
You can use the filter woocommerce_order_item_display_meta_value to output the image. Place this code in your functions.php file, you'll need to modify the src attribute of the img tag to include the appropriate URL before the filename value. You can also modify the display label with the filter woocommerce_order_item_display_meta_key
add_filter( 'woocommerce_order_item_display_meta_value', 'modify_order_item_display_value' , 10, 3 );
function modify_order_item_display_value( $display_value, $meta, $wc_order_item ) {
$meta_data = $meta->get_data();
if( $meta_data['key'] === 'customer_product_image' ) {
return '<img src="' . $meta_data['value'] . '">';
}
return $display_value;
}
add_filter('woocommerce_order_item_display_meta_key', 'modify_order_item_display_key', 10, 3);
function modify_order_item_display_key( $display_key, $meta, $wc_order_item ) {
$meta_data = $meta->get_data();
if( $meta_data['key'] === 'customer_product_image' ) {
return 'Customer Image';
}
return $display_key;
}
This is a self Q&A.
How do you modify the text/html that appears in the output of a wp_nav_menu? For example, I wanted to add the featured image for pages and categories.
You see examples of doing this with a custom walker, but the code is very complex to do for small changes. Surely there is a way to do it with a filter?
This is the code I came up with thanks to some help from a Wordpress StackOverflow answer that I can't find anymore (please comment with a link if you find it).
First you need to add the filter to the specific menu (you could add it to all menus if you want - just use the add_filter line by itself).
// Add filter to specific menus
add_filter('wp_nav_menu_args', 'add_filter_to_menus');
function add_filter_to_menus($args) {
// You can test agasint things like $args['menu'], $args['menu_id'] or $args['theme_location']
if( $args['theme_location'] == 'header_menu') {
add_filter( 'wp_setup_nav_menu_item', 'filter_menu_items' );
}
return $args;
}
Then you need to build out the code to get the post or category ID from the $item object passed to the filter. It's not as easy as you'd expect, as $item doesn't contain the underlying post/category ID, just the menu item ID. So I use the URL's to do a reverse lookup of the IDs.
This won't work for tags used in a menu, or custom taxonomys. I only needed it for categories, so this is all I built.
// Filter menu
function filter_menu_items($item) {
if( $item->type == 'taxonomy') {
// For category menu items
$cat_base = get_option('category_base');
if( empty($cat_base) ) {
$cat_base = 'category';
}
// Get the path to the category (excluding the home and category base parts of the URL)
$cat_path = str_replace(home_url().'/'.$cat_base, '', $item->url);
// Get category and image ID
$cat = get_category_by_path($cat_path, true);
$thumb_id = get_term_meta($cat->term_id, '_term_image_id', true); // I'm using the 'Simple Term Meta' plugin to store an attachment ID as the featured image
} else {
// Get post and image ID
$post_id = url_to_postid( $item->url );
$thumb_id = get_post_thumbnail_id( $post_id );
}
if( !empty($thumb_id) ) {
// Make the title just be the featured image.
$item->title = wp_get_attachment_image( $thumb_id, 'poster');
}
return $item;
}
And then you want to remove the filter that you applied at the beginning, so that the next menu processed doesn't use the same HTML as defined above in filter_menu_items().
// Remove filters
add_filter('wp_nav_menu_items','remove_filter_from_menus', 10, 2);
function remove_filter_from_menus( $nav, $args ) {
remove_filter( 'wp_setup_nav_menu_item', 'filter_menu_items' );
return $nav;
}
Modified Drew Baker answer. It works without plugins, also if there is no category with current slug it checks for woocommerce product category ('product_cat').
functions.php
// Add filter to specific menus
add_filter('wp_nav_menu_args', 'add_filter_to_menus');
function add_filter_to_menus($args) {
// You can test agasint things like $args['menu'], $args['menu_id'] or $args['theme_location']
if( $args['theme_location'] == 'menu-header') {
add_filter( 'wp_setup_nav_menu_item', 'filter_menu_items' );
}
return $args;
}
// Filter menu
function filter_menu_items($item) {
if( $item->type == 'taxonomy') {
// Get category and image ID
$slug = pathinfo( $item->url, PATHINFO_BASENAME );
$cat = get_term_by( 'slug', $slug, 'category' );
// If there is no standard category try getting product category
if( !$cat ) {
$cat = get_term_by( 'slug', $slug, 'product_cat' );
}
$thumb_id = get_term_meta($cat->term_id, 'thumbnail_id', true);
} else {
// Get post and image ID
$post_id = url_to_postid( $item->url );
$thumb_id = get_post_thumbnail_id( $post_id );
}
if( !empty($thumb_id) ) {
// Make the title just be the featured image.
$item->title = wp_get_attachment_image( $thumb_id, 'poster');
// Display image + title example
// $item->title = wp_get_attachment_image( $thumb_id, 'poster').$item->title;
}
return $item;
}
// Remove filters
add_filter('wp_nav_menu_items','remove_filter_from_menus', 10, 2);
function remove_filter_from_menus( $nav, $args ) {
remove_filter( 'wp_setup_nav_menu_item', 'filter_menu_items' );
return $nav;
}
Entirely Revised Please Reread
Hello,
The theme I am using displays the page's title as opposed to it's menu label in the breadcrumbs. I am trying to get the breadcrumbs to instead display the associated menu label if it is available and if not then default to the page_title.
I have come up with some code that I think is close. Line 4/// $menu_items = wp_get_nav_menu_items( $slug ); returns null and it should return the nav item that contains $slug of the current post. Obviously, there is something I do not understand.
What I am attempting to do is get the slug of the current post, then using the slug get the nav item post. Then extract the title of the nav item and use that in place of the page title in the breadcrumbs. If the page was not in the nav system then it should default to the page title, as might be the case for a ppc campaign landing page.
if ( is_page() && !$post->post_parent ) {
$title = null;
$slug = mpactMEDIA_get_the_slug( get_the_ID() );
$menu_items = wp_get_nav_menu_items( $slug );
//var_dump((array)$menu_items);
foreach ( (array)$menu_items as $key => $menu_item ) {
$title = $menu_item->post_title;
}
if ( $title ) { echo $delimiter . ' ' . $before . $title . $after; }
else { echo $delimiter . ' ' . $before . get_the_title() . $after; }
}
I'm my functions.php file I have the following function
function mpactMEDIA_get_the_slug( $id=null ){
if( empty($id) ) global $post;
if( empty($post) ) return '';
$id = $post->ID;
endif;
$slug = basename( get_permalink($id) );
return $slug;
}
Thank you in advance,
Tim
I read the question a few times, I got here searching for an answer, ended up making my own.
function get_menu_label_by_post_id($post_id, $menu) {
$menu_title = '';
$nav = wp_get_nav_menu_items($menu);
foreach ( $nav as $item ) {
if ( $post_id == $item->object_id ) {
$menu_title = $item->post_title;
break;
}
}
return ($menu_title !== '') ? $menu_title : get_the_title($post_id);
}
Example usage:
echo get_menu_label_by_post_id($post->ID, 'Primary Nav');
This will return what the menu label is if it finds it, otherwise just the title of the post ID.
Check the documentation for wp_get_nav_menu_items. It doesn't take a page slug as a parameter at all.
If you want to list child pages of a given page, use wp_list_pages and pass a child_of parameter to it.
Also, as a side note, if you know the $post and want the slug, it's just $post->post_name
Been searching for a while on this subject without any success. All I can find are solutions which involve using the Walker property of the wp_nav_menu, which I don't think is the right approach. I want to create a menu with the following structure:
Link that is a category
X numbers of submenu items which are posts belonging to the parent
category
And so on...
Do I need to manually run a loop for each menu item to retrieve the posts?
Try this in your functions.php:
add_filter('wp_nav_menu_items', 'add_productions', 10, 2);
function add_productions($items, $args) {
$cat = '28'; // define category
$productions = array();
$productions = get_posts("cat=$cat");
if ($productions[0] != '') {
$items .= '<li>Productions<ul class="sub-menu">';
foreach ( $productions as $production ) {
$permalink = get_permalink( $production->ID );
$items .= '<li>'.$production->post_title.'</li>';
}
$items .= '</ul>';
}
return $items;
}
This question and answer was very helpful to me, so thought I would add an additional solution that provides an option to insert the menu at any point in the existing core menu.
Most of the examples on the web show how to add an item to the end of a menu, this will help you add the new menu anywhere in the menu.
Here is the code to place the new menu after my "Home" menu:
add_filter('wp_nav_menu_items', 'add_gallery', 10, 2);
function add_gallery($items, $args) {
$cat = '1'; // define category
$pattern = 'Home</a></li>';
$productions = array();
$productions = get_posts("cat=$cat");
$temp_items = '';
if ($productions[0] != '') {
$temp_items .= '<li>Galleries<ul class="sub-menu">';
foreach ( $productions as $production ) {
$permalink = get_permalink( $production->ID );
$temp_items .= '<li>'.$production->post_title.'</li>';
}
$temp_items .= '</ul>';
}
$replacement = $pattern .$temp_items;
$temp_menu = str_replace($pattern, $replacement, $items);
return $temp_menu;
}
Hopefully this helps someone else...