I can't find a specific answer that has been helpful.
I have woocommerce products with 28 additional meta fields. Some that are simple text and some that are URLs.
I am trying to figure out how to display the Meta Key Name as well as the value individually rather than as a loop. This is so I can add appropriate HTML and CSS around each item as needed.
Example:
Meta Key Name : Meta Value
Batteries Included : No
Full Engineering Drawing : https://www.websiteaddress.com/drawings/1024-4.5.pdf
So if you do not want to loop trough the meta I think your best bet is doing it like this:
I use the if statements to only echo the field if the meta is added to that product.
//Add all meta keys here individually
$batteries = get_post_meta( get_the_ID(), "Batteries Included", true );
$drawing = get_post_meta( get_the_ID(), "Full Engineering Drawing", true );
//Check if meta value is empty and only display if not
if(!($batteries == null || $batteries == '')) {
echo '<div class="battery-div">' . '<span class="batteries">Batteries Included: </span>' . '<span class="battery-value">' . $batteries . '</span>' . '</div>';
}
if(!($drawing == null || $drawing == '')) {
echo '<div class="drawing-div">' . '<span class="engineering_drawing">Full Engineering Drawing: </span>' . '<span class="drawing-value">' . $drawing . '</span>' . '</div>';
}
But if you loop trough the meta you could do something like this instead:
//Get product meta
$meta_info = get_post_meta(get_the_ID());
//Loop trough meta
foreach($meta_info as $key=>$val){
//If meta key is this and not empty echo this
if ($key == 'Batteries Included' && !($val == null || $val == '')) {
echo '<div class="battery-div">' . '<span class="battery-name">' . $key . ' : ' . '</span>' . '<span class="battery-value">' . $val[0] . '</span>' . '</div>';
}
if ($key == 'Full Engineering Drawing' && !($val == null || $val == '')) {
echo '<div class="drawing-div">' . '<span class="drawing-name">' . $key . ' : ' . '</span>' . '<span class="drawing-value">' . $val[0] . '</span>' . '</div>';
}
}
Related
I'm new to coding and wordpress/woocommerce and am trying to find a simple way to edit the output of wc_get_rating_html.
At the moment it outputs the following:
function wc_get_rating_html( $rating ) {
if ( $rating > 0 ) {
$rating_html = '<div class="star-rating" title="' . sprintf( esc_attr__( 'Rated %s out of 5', 'woocommerce' ), $rating ) . '">';
$rating_html .= '<span style="width:' . ( ( $rating / 5 ) * 100 ) . '%"><strong class="rating">' . $rating . '</strong> ' . esc_html__( 'out of 5', 'woocommerce' ) . '</span>';
$rating_html .= '</div>';
} else {
$rating_html = '';
}
return apply_filters( 'woocommerce_product_get_rating_html', $rating_html, $rating );
}
I simply want to output the star rating and not the text that goes before and after. Any suggestions on how i can do this as i obv cant edit the template file. thanks
Wordpress utilizes filters which allow you to replace and/or modify the output of what the filter processes. Here is the full block for the wc_get_rating_html function:
function wc_get_rating_html( $rating, $count = 0 ) {
$html = '';
if ( 0 < $rating ) {
/* translators: %s: rating */
$label = sprintf( __( 'Rated %s out of 5', 'woocommerce' ), $rating );
$html = '<div class="star-rating" role="img" aria-label="' . esc_attr( $label ) . '">' . wc_get_star_rating_html( $rating, $count ) . '</div>';
}
return apply_filters( 'woocommerce_product_get_rating_html', $html, $rating, $count );
}
In your example, woocommerce_product_get_rating_html is the filter name and takes three arguments:
$rating_html which represents the output which the user sees
$rating which is the numerical rating
$count which is the total number of ratings.
If you wish to replace the output, you'll need to hook into the filter woocommerce_product_get_rating_html with a function that will return the modified content. You'll definitely need to review Hooks & Filters and how they work in Wordpress if you are not familiar with utilizing hooks and filters in Wordpress.
Currently it add nofollow at all products across website, how to make it at is_front_page() only?..
function woocommerce_template_loop_product_title() {
echo '<p class="name product-title ' . esc_attr( apply_filters( 'woocommerce_product_loop_title_classes', 'woocommerce-loop-product__title' ) ) . '">' . get_the_title() . '</p>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
Change the value of your rel attribute. So, when the user is at the frontpage, rel will have a value of nofollow. Otherwise, the value will be "" empty.
<?php
function woocommerce_template_loop_product_title() {
// Add the $nofollow
$nofollow = "";
if(is_front_page() ){
$nofollow = "nofollow";
}
echo '<p class="name product-title ' . esc_attr( apply_filters( 'woocommerce_product_loop_title_classes', 'woocommerce-loop-product__title' ) ) . '"><a href="' . get_the_permalink() . '" rel='.$nofollow.'>' . get_the_title() . '</a></p>';
?>
I displayed WPML language switcher in my menu, at the bottom as the last item. I want it at the second position of the secondary menu.
How to change my code to achieve that please?
Current code:
/*Display WPML language switcher in the menu */
function wpml144107($menu, $args){
if ( ! is_admin() ):
if( $args->theme_location == 'secondary' ):
if(function_exists('icl_get_languages')):
$languages = icl_get_languages('skip_missing=0&orderby=custom');
if(count($languages) >= 1):
$flags = '<li id="menu-item-lang"><div class="flags_top">';
//foreach((array)$languages as $language):
//echo print_r($languages);
$language = $languages['fr'];
$flags .= '
<span class="icl-'. $language['language_code'] . ( $language['active'] == 1 ? ' icl-current' : '' ) .'">
<a rel="alternate" hreflang="' . $language['language_code'] . '" href="' . $language['url']. '">' . $language['language_code'] . '</a>
</span> /';
$language = $languages['en'];
$flags .= '
<span class="icl-'. $language['language_code'] . ( $language['active'] == 1 ? ' icl-current' : '' ) .'">
<a rel="alternate" hreflang="' . $language['language_code'] . '" href="' . $language['url']. '">' . $language['language_code'] . '</a>
</span>';
//endforeach;
$flags .= '</div></li>';
endif;
return $menu . $flags;
endif;
endif;
endif;
return $menu;
}
add_action('wp_nav_menu_items', 'wpml144107', 50, 2);
At this point:
return $menu . $flags;
The language menu is appended to the menu.
If you change it to:
return $flags . $menu;
It would be at the first position...
But you want to have it at the second one, right? Then it is a little more complicated, you have to split the string containing the menu, I suppose that every element is within a <li>-element:
/* finds the position of the first occurrence of </li>,
so the end of the first element, add 4 because we want the position of
the end of the </li>-tag not the start... */
$splitpos = strpos($menu, '</li>') + 4;
// cut the string up to that position and you get the first element...
$firstelem = substr($menu, 0, $splitpos));
// cut after that position and you get the rest of the menu...
$rest = substr($menu, $splitpos));
// now return the menu with your language menu in between...
return $firstelem . $flags . $rest;
I guess this should work! :)
I have found a way to do it: I split the menu items in an array to be able to insert your language switcher in 2nd position.
I have revisited your code a bit:
// Display WPML language switcher in 2nd position of the menu
function wpml144107($items, $args){
if ( ! is_admin() && $args->theme_location == 'secondary' && function_exists('icl_get_languages') ):
$languages = icl_get_languages('skip_missing=0&orderby=custom');
if( count($languages) == 0 ) return $items; // If there is no languages we return defaults menu items
$html = 'id="menu-item-lang">
<div class="flags_top">
<span class="icl-'. $languages['fr']['language_code'] . ( $languages['fr']['active'] == 1 ? ' icl-current' : '' ) .'">
<a rel="alternate" hreflang="' . $languages['fr']['language_code'] . '" href="' . $languages['fr']['url']. '">' . $languages['fr']['language_code'] . '</a>
</span> /';
$html .= '
<span class="icl-'. $languages['en']['language_code'] . ( $languages['en']['active'] == 1 ? ' icl-current' : '' ) .'">
<a rel="alternate" hreflang="' . $languages['en']['language_code'] . '" href="' . $languages['en']['url']. '">' . $languages['en']['language_code'] . '</a>
</span>';
$html .= '</div>
';
// Html in between each items (to split the items in an array)
$glue = '</li>
<li ';
// Spliting menu items in an array
$items_array = explode( $glue, $items );
// Counter
$count = 0;
foreach($items_array as $key => $item){
// We insert in 2nd position the language switcher
if($key == 1)
$ordered_items[$count] = $html;
else
$ordered_items[$count] = $item;
$count++;
}
// We set back the array of menu items in a correct html string
$items = implode( $glue, $ordered_items );
endif;
return $items;
}
add_action('wp_nav_menu_items', 'wpml144107', 50, 2);
Code goes in function.php file of your active child theme (active theme or in any plugin file).
Tested and Works in WooCommerce 3+
I solved it using this answer
with this code:
/*Display WPML language switcher in the secondary menu at the second position*/
function add_custom_in_menu( $items, $args )
{
if( $args->theme_location == 'secondary' ):
if(function_exists('icl_get_languages')):
$languages = icl_get_languages('skip_missing=0&orderby=custom');
if(count($languages) >= 1):
$items_array = array();
while ( false !== ( $item_pos = strpos ( $items, '<li', 3 ) ) )
{
$items_array[] = substr($items, 0, $item_pos);
$items = substr($items, $item_pos);
}
$items_array[] = $items;
$customHtml = '<li>bla</li>';
$flags = '<li id="menu-item-lang"><div class="flags_top">';
//foreach((array)$languages as $language):
//echo print_r($languages);
$language = $languages['fr'];
$flags .= '
<span class="icl-'. $language['language_code'] . ( $language['active'] == 1 ? ' icl-current' : '' ) .'">
<a rel="alternate" hreflang="' . $language['language_code'] . '" href="' . $language['url']. '">' . $language['language_code'] . '</a>
</span> /';
$language = $languages['en'];
$flags .= '
<span class="icl-'. $language['language_code'] . ( $language['active'] == 1 ? ' icl-current' : '' ) .'">
<a rel="alternate" hreflang="' . $language['language_code'] . '" href="' . $language['url']. '">' . $language['language_code'] . '</a>
</span>';
//endforeach;
$flags .= '</div></li>';
// insert custom item after 2nd one
array_splice($items_array, 1, 0, $flags);
$items = implode('', $items_array);
endif;
endif;
endif;
return $items;
}
add_filter('wp_nav_menu_items','add_custom_in_menu', 10, 2);
I think it's the same approach you guys suggested. Thank you.
For ACF form plugin, I used field group function which contains 10 fields, and loop to display in post like below:
<?php $fields = get_field_objects($post_id);
if( $fields)
{
foreach( $fields as $field_name => $field )
{
if($field['type']=='text' || $field['type']=='textarea' ){
echo '<li>';
echo '<label>' . $field['label'] . '</label>';
echo '<span>' . $field['value'] . '</span>';
echo '<span>' . $field['order_no'] . '</span>';
echo '</li>';
}
}
}?>
Now I want to sort it by order_no, how can I do it?
You could try something like that before you print out:
function objectSort( $a, $b ) {
return $a->order_no == $b->order_no ? 0 : ( $a->order_no > $b->order_no ) ? 1 : -1;
}
usort( $fields, 'objectSort' );
Note: This is not meant to be a full correct code, I just want to give you an idea for the solution.
perhaps you have an idea how I can solve the following problem. I rewrite a field-collection-field in my template.php to change the output. Therefore I just added a new var ($my_classes) which contains a specific value. This value comes out of the field-collection. Everything works fine (my classes are added - yeah), besides the problem that I got the following error:
Notice: Undefined index: entity in template_field__field_fc_page_fields() (line 333 of ..
This error pops up four times, so every upcoming field(-collection) throws this error. Here is my code:
function template_field__field_fc_page_fields($variables) {
kpr($variables);
$output = '';
// Render the label, if it's not hidden.
if (!$variables['label_hidden']) {
$output .= '<div class="field-label"' . $variables['title_attributes'] . '>' . $variables['label'] . ': </div>';
}
// Render the items.
foreach ($variables['items'] as $delta => $item) {
// Custom class
$my_classes = $variables['items'][$delta]['entity']['field_collection_item'][$delta+1]['field_layout']['#items'][0]['value'];
$classes = 'field-item ' . ($delta % 2 ? 'odd' : 'even');
$output .= '<div class="' . $classes . ' ' . $my_classes .'"' . $variables['item_attributes'][$delta] . '>' . drupal_render($item) . '</div>';
}
// Render the top-level DIV.
$output = '<div class="' . $variables['classes'] . '"' . $variables['attributes'] . '>' . $output . '</div>';
return $output;
I am not a programmer, so I hope you can help me out! Thanks a lot!!!
Here is the solution:
The problem is, that when you try to alter the output of a field-collection you alter also the inherit fields in your field-collection which have no entity-id. so you just have to use the isset on the $classes (thanks to #Hans Nilson) AND extract the id of the entity to use it in your function. here is the solution in code:
function template_field__field_fc_page_fields($variables) {
// kpr($variables);
$output = '';
// Render the label, if it's not hidden.
if (!$variables['label_hidden']) {
$output .= '<div class="field-label"' . $variables['title_attributes'] . '>' . $variables['label'] . ': </div>';
}
// Render the items.
foreach ($variables['items'] as $delta => $item) {
if (isset($variables['items'][$delta]['entity']) && (isset($variables['element']['#items'][$delta]['value']))) {
$fc_id = ($variables['element']['#items'][$delta]['value']);
$my_classes = $variables['items'][$delta]['entity']['field_collection_item'][$fc_id]['field_layout']['#items'][0]['value'];
}
if (isset($variables['items'][$delta]['entity'])) {
$classes = 'field-item-custom ' . $my_classes . ' ' . ($delta % 2 ? 'odd' : 'even');
}
else {
$classes = 'field-item ' . ($delta % 2 ? 'odd' : 'even');
}
$output .= '<div class="' . $classes . '"' . $variables['item_attributes'][$delta] . '>' . drupal_render($item) . '</div>';
}
// Render the top-level DIV.
$output = '<div class="' . $variables['classes'] . '"' . $variables['attributes'] . '>' . $output . '</div>';
return $output;
}
It means that in this line:
$my_classes = $variables['items'][$delta]['entity']['field_collection_item'][$delta+1]['field_layout']['#items'][0]['value'];
key 'entity' does not exist in this $delta
You could add a check:
if (isset($variables['items'][$delta]['entity'])) { }
but it might make better sense to try and figure out why a particular delta doesn't have the entity key, if you believe it should be there.