First I would like to analyze my problem. Using Wordpress/Woocommerce I need to add videos beside images in the gallery of the product. Woocommerce does not support videos at all.
So, I thought to install an extra gallery plugin that supports both images and videos.
Now, I want to map a specific image/video gallery collection to a specific product. I want also to view this gallery collection in a new region that is not belong to the standard text fields like description or short description. Lets say above of the main product image. The php code that represent the gallery collection id=1 looks like below :
<?php echo do_shortcode('[wonderplugin_gallery id="1"]'); ?>
The problem is that I need the gallery collection id to be variable, something like this :
<?php echo do_shortcode('[wonderplugin_gallery id="X"]'); ?>
where X represnt the specific gallery collection. How the heck can I connect the gallery collection ID XXXX to my Product page XXXXX?
I have programming skills but I am new to the wordpress code logic.
Any other suggestions to my problem like plugins that may replace the default product gallery with better one ?
Regards,
I'd either use the product custom fields as Anand suggested, or create a metabox with the necessary input fields (or dropdowns depending on how you use the gallery plugin).
First I'd create a metabox, and in that metabox I'd pull the info from the plugin (gallery id's and names). Out of that you can create a dropdown. You should be able to select the id from that metabox for each product like you suggested. For instance something like this could work:
<?php
if ( ! function_exists( 'product_add_meta' ) ){
function product_add_meta(){
add_meta_box("gallery_dropdown", "Select Gallery", "product_gallery_meta_box", "product");
}
}
add_action("admin_init", "product_add_meta");
if ( ! function_exists( 'product_gallery_meta_box' ) ){
function product_gallery_meta_box( $post ){
$post_types = array('product'); //limit meta box to certain post types
global $post;
$product = get_product( $post->ID );
$values = get_post_custom( $post->ID );
$gallery = (isset($values['gallery'][0])) ? $values['gallery'][0] : '';
wp_nonce_field( 'my_meta_box_nonce', 'meta_box_nonce' );
?>
<p>
<select name="gallery" id="gallery">
//example of how the option should look
<option value="<?php echo $gallery_id; ?>" <?php selected( $gallery, $gallery_id ); ?>><?php echo $gallery_name; ?></option>
<?php
//pull options from plugin here and create an option dropdown with foreach
?>
</select>
</p>
<?php
}
}
if ( ! function_exists( 'product_gallery_save_meta_box' ) ){
function product_gallery_save_meta_box( $post_id ){
if( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ){
return;
}
if( !isset( $_POST['gallery'] ) || !wp_verify_nonce( $_POST['meta_box_nonce'], 'my_meta_box_nonce' ) ) {
return;
}
if( !current_user_can( 'edit_pages' ) ) {
return;
}
if( isset( $_POST['gallery'] ) ){
update_post_meta( $post_id, 'gallery', wp_kses( $_POST['gallery'] ,'') );
}
}
}
add_action( 'save_post', 'product_gallery_save_meta_box' );
If you put this in the functions.php, it should show a metabox called 'Select Gallery' with an empty dropdown on your woocommerce product page.
I haven't filled the options that you get from the plugin with which you create your galleries, but it shouldn't be too hard.
One way is to bind the product page id and gallery id. If you can change the id of a gallery then change it to match the id of the product page. Now you can create shortcode with any of these two examples.
// outside the loop use global ( uncomment appropriate statement )
// global $product;
// global $post;
do_shortcode( sprintf( '[wonderplugin_gallery id="%d"]', $product->id ) );
do_shortcode( sprintf( '[wonderplugin_gallery id="%d"]', $post->ID ) );
HERE is a link for plugin that reveals most of the IDs on admin pages.
Another is to create Custom Field ( post meta ) in edit product admin page ( named gallery_id for example ), and to save there id of the gallery to use. To create shortcode use get_post_meta() function that retrieves the saved post meta.
do_shortcode( sprintf( '[wonderplugin_gallery id="%d"]', get_post_meta( $post->ID, 'gallery_id', true ) ) );
To get the gallery id meta use $post->ID, $product->id, or get_the_ID() function, the latter only inside the loop.
Related
I have created a super simple theme. What i want to have is the ability to define an array of 3 fields for each post and page.
For example having the fields: Name, Link and a Dropdown for Type
Additionally i want to add multiple items of these "field sets" per post/page. I couldn't find any documentation on this but always results in Google which led me to WP Plugins. In general this is ood, cause in this case this seems to be possible programmatically, but bad cause i couldn't find any kind of information on this.
Hopefully someone can help me.
You are looking for custom meta boxes, with the add_meta_box() function:
Adds a meta box to one or more screens.
Source # https://developer.wordpress.org/reference/functions/add_meta_box/
And the add_meta_boxes action hook.
Fires after all built-in meta boxes have been added:
Source # https://developer.wordpress.org/reference/hooks/add_meta_boxes/
A simple example would be if we wanted to add a "Listening to..." custom meta box, to share our mood while writing a post.
<?php
add_action( 'add_meta_boxes', 'add_meta_listening_to' );
function add_meta_listening_to() {
add_meta_box(
'meta_listening_to', //id
'Listening to ...', //title
'listeningto', //callback
'post', //screen &/or post type
'normal', //context
'high', //priority
null //callback_args
);
};
function listeningto( $post ) { //function handle same as callback
$ListeningToInput = get_post_meta( $post->ID, 'ListeningToInput', true );
echo '<input name="listening_to_input" type="text" placeholder="Listening to ..." value="'. $ListeningToInput .'" style="width:100%;">';
};
add_action( 'save_post', 'save_meta_listening_to' );
function save_meta_listening_to( $post_ID ) {
if ( isset( $_POST[ 'listening_to_input' ] ) ) {
update_post_meta( $post_ID, 'ListeningToInput', esc_html( $_POST[ 'listening_to_input' ] ) );
};
}; ?>
Then to display on the front end, we would use the following:
<?php echo get_post_meta( $post->ID, 'ListeningToInput', true ); ?>
Learn more
Learn more about the Custom Meta Boxes # https://developer.wordpress.org/plugins/metadata/custom-meta-boxes/
I need to translate 3 value in a checkbox acf option.
The problem is i have already create my 200 woocommerce products and if i translate in backoffice (acf), i have to change the translate value in each product.
I'm looking for a solution with php.
<?php // gout_interne ( value )
$gout_interne_array = get_field( 'gout_interne' );
if ( $gout_interne_array ):
foreach ( $gout_interne_array as $gout_interne_item ):
echo $gout_interne_item;
endforeach;
endif; ?>
Values for example are : red, white, blue.
Try using the wpml_translate_single_string filter (documentation):
foreach ( $gout_interne_array as $gout_interne_item ) {
$translated_value = apply_filters( 'wpml_translate_single_string',
$gout_interne_item,
'custom_fields_user',
'[custom_fields_user]gout_interne' );
echo $translated_value;
}
Anyone knows how to hide the product dimensions from the additional tabs on Single Product page but still show the Weight value?
I search and see this filter but it hides both weight and dimensions.
add_filter( 'woocommerce_product_get_dimensions', '__return_false' );
To hide only dimensions (but not weight), there is 2 ways to make it work.
1) using hooks (here composite filter hooks):
Looking at the template that displays dimension in single products, you can see this line:
<?php if ( $display_dimensions && $product->has_dimensions() ) : ?>
Then if you look at WC_Product has_dimensions() method, you will see this line (where $this is the WC_Product Object instance):
return ( $this->get_length() || $this->get_height() || $this->get_width() ) && ! $this->get_virtual();
So when the length, the height and the with are empty (or false), the method returns falseā¦
The following code that use composite hooks, will hide dimensions from "Additional information" tab in single product pages only:
add_filter( 'woocommerce_product_get_width', 'hide_single_product_dimentions', 25, 2 );
add_filter( 'woocommerce_product_get_height', 'hide_single_product_dimentions', 25, 2 );
add_filter( 'woocommerce_product_get_length', 'hide_single_product_dimentions', 25, 2 );
function hide_single_product_dimentions( $value, $product ){
// Only on single product pages
if( is_product() )
$value = '';
return $value;
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
To hide weight (just for info) use this composite hook code:
add_filter( 'woocommerce_product_get_weight', 'hide_single_product_weight', 25, 2 );
function hide_single_product_weight( $value, $product ){
// Only on single product pages
if( is_product() )
$value = '';
return $value;
}
2) Overriding Woocommerce templates via your active theme:
First read: Overriding Woocommerce template via the theme.
It explain how to copy the template to your theme before editing it.
Here the related template is single-product/product-attributes.php.
You will have to remove this block from the template code (from line 33 to line 38):
<?php if ( $display_dimensions && $product->has_dimensions() ) : ?>
<tr>
<th><?php _e( 'Dimensions', 'woocommerce' ) ?></th>
<td class="product_dimensions"><?php echo esc_html( wc_format_dimensions( $product->get_dimensions( false ) ) ); ?></td>
</tr>
<?php endif; ?>
You can also use the css property display:none if everything else fails.
I have created custom user taxonomy for user and its working good for single taxonomy.
From Bellow reference guide i have created custom user taxonomy.
Reference guide:- http://justintadlock.com/archives/2011/10/20/custom-user-taxonomies-in-wordpress
Bellow is structure of taxonomy
(registered taxonomy) profession
Dietitian (under the profession )
(registered taxonomy) city
NewYork(under the city)
my slug name name expert
Here i want to display filter result which user is Dietitian in NewYork city.so it will display all user which have selected above option in profile.
Now i want the url something like www.test.com/expert/dietitian/newyork
with user which have selected Dietitian , NewYork in user profile. And is there any solution to combine Dietitian,NewYork
The url with single terms works like:- www.test.com/expert/dietitian/
I am assuming that you have spend a great deal of time on the tutorial of justintadlock, so I will get involved only with the parts of it that are needed for the multiple taxonomy filtering and display on the front-end.
Before your read the long text, you can have a taste at http://playground.georgemanousarides.com/
So, first thing's first.
The logical base is the same for both SINGLE TAXONOMY and MULTIPLE TAXONOMIES.
After having registered the taxonomies and their terms and have done all the work needed wp-admin wise, we will need:
A) A page (lets call it TAX-QUERY PAGE) in which visitors can select the taxonomy query.
B) Another page (lets call it TAX-RESULTS PAGE) in which the results of TAX-QUERY PAGE will be displayed.
Let's dive in
SINGLE TAXONOMY
TAX-QUERY PAGE
After following the tutorial, the page that you display the taxonomies links should look, on its primal form, like this:
single taxonomy tax-query page
Visitors "Select" which taxonomy they want to see by simply clicking on the links provided.
Note that:
A) The links for:
Proffession will be like:
www.example.com/user/profession/developer/
City will be like:
www.example.com/user/city/gotham/
B) The slugs "user/city" and "user/profession" are defined at the function: my_register_user_taxonomy >> register_taxonomy >> rewrite >> slug
TAX-RESULTS PAGE
Clicking on the links mentioned above takes you to a page ( which needs to be defined by you of course ) that displays all the users under the same taxonomy-term.
This is achieved by creating custom taxonomy templates.
You can create the taxonomy-profession-developer.php file to handle a single taxonomy and term, or the taxonomy-profession.php to handle a single taxonomy and all its' terms, or the taxonomy.php for all taxonomies and their terms.
In my opinion, if you don't want your server to be flooded with template files which are manually created by you, you should use the taxonomy.php and make a general teplate for all taxonomies which descriminates the results you want to display automatically.
Note that:
A) To itterate through users and fetch only those under the desired taxonomy-term, a custom query is needed ( in the taxonomy.php file ), as mentioned and explained in the tutorial.
B) Permalinks should be on Post Name option from the wp-admin >> settings >> permalinks so that wordpress can find your taxonomies, fetch the file taxonomy.php and provide usefull info about the selected taxonomy that can be used in the taxonomy.php file.
MULTIPLE TAXONOMIES
TAX-QUERY PAGE
We need to create a page where visitors will select terms from the custom taxonomies. This page will provide the TAX-RESULTS PAGE ( taxonomy.php ) with the needed terms through a link (as get variables**) so as to make a query.
**In order to have pretty permalinks in the TAX-RESULTS PAGE we need to add the following rewrite function (found it here) to the function.php, and refresh the permalinks in wp-admin:
function eg_add_rewrite_rules() {
global $wp_rewrite;
$new_rules = array(
'user/(profession|city)/(.+?)/(profession|city)/(.+?)/?$' => 'index.php?post_type=eg_event&' . $wp_rewrite->preg_index(1) . '=' . $wp_rewrite->preg_index(2) . '&' . $wp_rewrite->preg_index(3) . '=' . $wp_rewrite->preg_index(4),
'user/(profession|city)/(.+)/?$' => 'index.php?post_type=eg_event&' . $wp_rewrite->preg_index(1) . '=' . $wp_rewrite->preg_index(2)
);
$wp_rewrite->rules = $new_rules + $wp_rewrite->rules;
}
add_action( 'generate_rewrite_rules', 'eg_add_rewrite_rules' );
Note that
If you register more taxonomies the "profession|city" in the function should become "profession|city|tax1|tax2|tax3".
So the TAX-QUERY PAGE will be:
HTML
<div id="taxonomies">
<h1>Find your professional</h1>
<form>
<?php if ( $taxonomies = get_object_taxonomies( 'user' ) ) : //get all taxonomies under the object_type "user" ( The second parameter given to the function my_register_user_taxonomy of the tutorial )
foreach ( $taxonomies as $taxonomy ) : ?>
<p>
<ul>
<fieldset id="<?php echo esc_attr( $taxonomy ); ?>"> <!-- group the form by taxonomies -->
<legend><h2>Choose <?php echo $taxonomy; ?></h2></legend>
<?php if ( $terms = get_terms( $taxonomy ) ) : //get taxonomy's terms
foreach ( $terms as $term ) : ?>
<li><input type="checkbox" value="<?php echo esc_attr( $term -> slug ); ?>"> <?php echo $term -> name; ?></li>
<?php endforeach;
endif; ?>
</fieldset>
</ul>
</p>
<?php endforeach;
endif; ?>
</form>
<a id="multiTaxSubmit" href="<?php echo esc_attr( get_home_url() . '/user' ); ?>">SUBMIT</a> <!-- this link is processed by jQuery to provide the taxonomy.php with the proper values. The href attribute is the base url needed by the taxonomy.php -->
</div>
JQUERY ( Can be put in an external file )
$( document ).ready( function() {
$( '#multiTaxSubmit' ).click( function ( event ){
event.preventDefault(); //prevent default link url from loading
var taxQuerySubmit = $( this ),
hasChecked = 0;
querySlug = taxQuerySubmit.attr( 'href' ); //get multitax url base from link href attr
$( '#taxonomies fieldset' ).each( function() { //iterate each taxonomy
var checkedTerms = $( this ).find( 'input:checked' ),
checkedLength = checkedTerms.length; //how many terms has the user selected
if ( checkedLength ) {
hasChecked += checkedLength;
querySlug += '/' + $( this ).attr( 'id' ) + '/'; //add taxonomy slug to query url
checkedTerms.each( function( index, value ) {
var comma = ( index == checkedLength-1 ? '' : ',' );
querySlug += $( this ).val() + comma;
} );
}
} );
if ( hasChecked ) {
window.location = querySlug;
} else {
alert( 'Please enter some criteria.' );
}
} );
} );
TAX-RESULTS PAGE ( taxonomy.php )
<?php
$USERS_BY_TAX = array();
if ( $taxonomies = get_object_taxonomies( 'user' ) ) { //get all taxonomies under the object_type "user" ( The second parameter given to the function my_register_user_taxonomy of the tutorial )
foreach ( $taxonomies as $tax_key => $taxonomy ) {
eval( '$check = $' . $taxonomy . ';' ); // Check if the taxonomy exists in the url. eval outputs $check = $profession, $check = $city etc.
if ( !$check ){
unset( $taxonomies[ $tax_key ] );
continue;
}
eval( '$term_names = explode( ",", $' . $taxonomy . ' );' ); // get terms array from $$taxonomy which gives $profession,$city, the values of which are given through the url as such: $profession="designer,developer"
$USERS_BY_TAX[ $taxonomy ] = array();
foreach ( $term_names as $term_name ) {
$term_obj = get_term_by( 'name', $term_name, $taxonomy ); //get term object for each given term
$users_in_term = get_objects_in_term( $term_obj -> term_id, $taxonomy ); // find users with term
if ( !empty( $users_in_term ) ) {
$USERS_BY_TAX[ $taxonomy ] = $USERS_BY_TAX[ $taxonomy ] + array_fill_keys( $users_in_term, $term_name ) ;
}
}
}
}
/* $USERS_BY_TAX array has all the users for each taxonomy but we only need those who exist in all taxonomies */
if ( $taxonomies ) {
$RESULTS = $USERS_BY_TAX; // keep the initiate array intact
$matched = array_pop( $USERS_BY_TAX ); // first array to compare
$TAXS = $taxonomies;
array_pop( $taxonomies );
if ( !empty( $USERS_BY_TAX ) ) {
foreach ( $taxonomies as $taxonomy ) {
if ( !empty( $USERS_BY_TAX ) ) $matched = array_intersect_key( $matched, $USERS_BY_TAX[ $taxonomy ] );
}
}
}
?>
/* DISPLAY */
<?php if ( $matched ) :
foreach ( array_keys( $matched ) as $user_id ): ?>
<div class="user-entry">
<?php echo get_avatar( get_the_author_meta( 'email', $user_id ), '96' ); ?>
<h2><?php the_author_meta( 'display_name', $user_id ); ?></h2>
<?php if ( in_array( 'profession', $TAXS ) ) : ?><h3>Profession: <?php echo $RESULTS[ 'profession' ][ $user_id ]; ?></h3><?php endif;?>
<?php if ( in_array( 'city', $TAXS ) ) : ?><h3>City: <?php echo $RESULTS[ 'city' ][ $user_id ]; ?></h3><?php endif;?>
<?php echo wpautop( get_the_author_meta( 'description', $user_id ) ); ?>
</div>
<?php endforeach;
else: ?>
<div class="user-entry">
<h2>We are sorry. No results match your criteria.</h2>
<h3>Please go back and search again!</h3>
</div>
<?php endif; ?>
This rewrite rule should work (assuming "profession" and "city" are the taxonomy registered names):
Code:
function custom_rewrite_rules() {
add_rewrite_rule('^profession/(.*)/city/(.*)?', 'index.php?profession=$matches[1]&city=$matches[2]', 'top');
}
add_action('init', 'custom_rewrite_rules');
Remember to flush the rewirte rules after saving this code in your site.
URL :
http://yourdomain.com/profession/dietitian/city/newyork/
To flush the permalinks or rewrite rules from your theme or plugin you need to use the flush_rewrite_rules() function.
<?php
function custom_rewrite_rules() {
flush_rewrite_rules();
add_rewrite_rule( '^products/([^/]*)/([^/]*)/(\d*)?',
'index.php?product_type=$matches[1]&product_brand=$matches[2]&p=$matches[3]',
'top' );
//Post Type: products
//Taxonomy: product_type
//Taxonomy: product_brand
}
add_action('init', 'custom_rewrite_rules');
?>
Is there a way to change the WooCommerce add-to-cart form through functions.php?
The goal is to add a checkbox for an additional product. When the checkbox is checked this product will also be added to the cart after a click on the add to cart button.
I am looking for a solution which doesn't rely on javascript.
A better title would be "WooCommerce up-sells as checkboxes".
A lot of research and several strategies to tackle this problem lead me to a solution which I thought was not even possible in the beginning.
The solution is now exactly what I wanted. A non-JavaScript, no-template-override, but a simple and pure addition to functions.php. It works for simple and variable products (and probably with grouped and external products too).
It misses some nice features still. It won't work yet if an up-sell is a variable product. Quantity selection and limiting up-sells per item or order would be nice additions too. Based on the code below adding those features should not be a big deal anymore.
// create the checkbox form fields and add them before the cart button
add_action( 'woocommerce_before_add_to_cart_button', 'action_woocommerce_before_add_to_cart_form', 10, 0 );
function action_woocommerce_before_add_to_cart_form(){
global $woocommerce, $product;
// get the product up-sells
$upsells = $product->get_upsells();
// store the number of up-sells and pass it on to the add-to-cart hook
?>
<input type="hidden" name="upsells_size" value="<?php echo(sizeof($upsells)); ?>">
<div id="wb-upsell-div">
<?php
// iterate through all upsells and add an input field for each
$i = 1;
foreach( $upsells as $value ){
$product_id = $value;
?>
<input id="wb-upsell-checkboxes" type="checkbox" name="upsell_<?php echo($i) ?>" value="<?php echo($product_id); ?>"><?php echo( '' . get_the_title( $product_id ) . "". " ($" . get_post_meta( $product_id, '_regular_price', true) . ")"); ?><br>
<?php
$i++;
}
?>
</div>
<?php
}
// function to add all up-sells, where the checkbox have been checked, to the cart
add_action('woocommerce_add_to_cart', 'custom_add_to_cart', 10, 3);
function custom_add_to_cart() {
global $woocommerce;
// get the number of up-sells to iterate through
$upsell_size = $_POST['upsells_size'];
// iterate through up-sell fields
for ($i=1; $i<=$upsell_size; $i++){
// get the product id of the up-sell
$product_id = $_POST['upsell_' . $i];
$found = false;
//check if product already in cart
if ( sizeof( WC()->cart->get_cart() ) > 0 ) {
foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
$_product = $values['data'];
if ( $_product->id == $product_id )
$found = true;
}
// if product not found, add it
if ( ! $found )
WC()->cart->add_to_cart( $product_id );
} else {
// if no products in cart, add it
WC()->cart->add_to_cart( $product_id );
}
}
}
And here is the CSS for formatting the <div>and the checkboxes. It goes into the style.css file:
#wb-upsell-div {
margin-top: 10px;
margin-bottom: 20px;
}
#wb-upsell-checkboxes{
}
So there's an actual answer to this question, you can add whatever you want inside the add to cart <form> using hooks. For example:
add_action( 'woocommerce_before_add_to_cart_button', 'so_34115452_add_input' );
function so_34115452_add_input(){
echo '<input type="checkbox" name="something"/>' . __( 'Some Checkbox', 'text-domain' );
}