Changing Woocommerce Product Image thumbnail size - php

I want to make the gallery thumbnails on the Woocommerce single product page the same size as my main product image. I know I can set the size with this
add_filter( 'woocommerce_get_image_size_gallery_thumbnail', function($size ) {
return array(
'width' => 487,
'height' => 487,
'crop' => 0,
);
});
But I would like to keep small 100x100x Woo thumbnails for the cart page. I read in the Woo docs that you can change which image sized is being used, so I tried
add_filter( 'woocommerce_gallery_thumbnail_size', function( $size ) {
return 'woocommerce_single';
});
but this is not working. Any thoughts why?

There are some hooks available. If you want to change the size using below hook
add_filter( 'wp_get_attachment_image_src', 'your function name', 50, 4 );
Source:
https://docs.woocommerce.com/wc-apidocs/hook-docs.html
https://businessbloomer.com/woocommerce-visual-hook-guide-single-product-page/

I would do it using CSS, setting a specific size for the cart page:
table.shop_table img {
width: 100px;
height: 100px;
}

The correct snippet:
add_filter( 'woocommerce_get_image_size_gallery_thumbnail', function( $size ) {
return 'thumbnail'; //replace 'thumbnail' with required size name or array()
} );

Related

Getting the contents of a WooCommerce basket with JQuery

I've been working with WooCommerce recently and I was wondering if it was possible to get cart items via JavaScript or JQuery
I know you can use PHP functions to retrieve the contents of the cart but currently I do not have access to the backend of the site.
I've found a similar question here: WooCommerce cookies and sessions - Get the current products in cart
In the session there is a wc_fragment that contains the HTML of the cart.
{"div.widget_shopping_cart_content":"<div class=\"widget_shopping_cart_content\">\n\n\t<ul class=\"woocommerce-mini-cart cart_list product_list_widget \">\n\t\t\t\t\t\t<li class=\"woocommerce-mini-cart-item mini_cart_item\">\n\t\t\t\t\t×\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t<img width=\"800\" height=\"450\" src=\"https://cdn2.co.uk/app/uploads/Overlapped-800x450.jpg\" class=\"attachment-woocommerce_thumbnail size-woocommerce_thumbnail\" alt=\"\" />Raspberry Drinking Yogurt - 1 drink\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<span class=\"quantity\">1 × <span class=\"woocommerce-Price-amount amount\"><span class=\"woocommerce-Price-currencySymbol\">£</span>1.50</span></span>\t\t\t\t</li>\n\t\t\t\t\t</ul>\n\n\t<p class=\"woocommerce-mini-cart__total total\">\n\t\t<strong>Subtotal:</strong> <span class=\"woocommerce-Price-amount amount\"><span class=\"woocommerce-Price-currencySymbol\">£</span>1.50</span>\t</p>\n\n\t\n\t<p class=\"woocommerce-mini-cart__buttons buttons\">View basketCheckout</p>\n\n\t\n\n</div>"}
Would it be possible to extract the elements from this?
I've found a solution for you. Maybe there is a better one but's how I would do it.
First create a custom JS file and register it. Also add a custom ajaxurl (in case you don't did this already):
add_action( 'wp_enqueue_scripts', 'wp_enqueue_scripts_action' );
function wp_enqueue_scripts_action() {
wp_register_script( 'child-theme', get_stylesheet_directory_uri() . '/assets/child.js', [ 'jquery' ] );
wp_enqueue_script( 'child-theme' );
wp_localize_script( 'child-theme', 'child_theme', [
'ajaxurl' => admin_url( 'admin-ajax.php' )
]
);
}
Now add an AJAX endpoint:
add_action( 'wp_ajax_get_cart_items', 'wp_ajax_get_cart_items_action' );
add_action( 'wp_ajax_nopriv_get_cart_items', 'wp_ajax_get_cart_items_action' );
function wp_ajax_get_cart_items_action() {
$cart = WC()->cart;
if ( $cart ) {
wp_send_json_success( $cart->get_cart_contents() );
/** #noinspection ForgottenDebugOutputInspection */
wp_die();
}
}
This will return the content of the cart in case a cart is available. Now call it inside your JS function. In my case for testing directly in the document.ready method:
(function ( $ ) {
$( document ).ready( function () {
let data = {
action: 'get_cart_items'
};
$.post( child_theme.ajaxurl, data, function () {
} ).done( function ( response ) {
console.log( response );
} ).fail( function ( response ) {
console.log( 'Fail' );
} );
} );
})( jQuery );
This will return for example:
077e29b11be80ab57e1a2ecabb7da330: {key:
"077e29b11be80ab57e1a2ecabb7da330", product_id: 249, variation_id: 0,
variation: Array(0), quantity: 1, …}
I think you need to add some null checks but all in all its a working solution.

Hide COD payment based on chosen select field options in WooCommerce checkout

I am using WooCommerce and I have a custom checkout field in form of a selection list. I am trying to remove COD gateway, when customer select on a custom checkout field a specific option ("newyork" in this case).
Here below is my actual code where I don't know how to make the IF statement condition part working:
add_filter('woocommerce_available_payment_gateways', 'woocs_filter_gateways', 1);
function woocs_filter_gateways($gateway_list)
{
if ( order_meta key="wc_billing_field_7378" value = newyork )
{
unset($gateway_list['cod']);
}
return $gateway_list;
}
How can I get the selected value of my custom checkout field In my code, to get my IF statement working?
Edit:
The custom checkout field id is wc_billing_field_7789 generated by a plugin...
Updated - Handling multiple not allowed destinations…
First, for testing I here is a hooked function that displays a custom checkout select field with few options:
// Just for testing
add_action( 'woocommerce_after_checkout_billing_form', 'custom_select_field_after_checkout_billing_form', 10, 1 );
function custom_select_field_after_checkout_billing_form ( $checkout ) {
woocommerce_form_field( 'wc_billing_field_7378', array(
'type' => 'select',
'label' => __( "Destinations (custom select field)"),
'class' => array( 'form-row-wide' ),
'options' => array(
'' => __("Choose a destination"),
'naeem' => __("Naeem"),
'saad-al-abdullah' => __("Saad Al Abdullah"),
'other-one' => __("Other one"),
'last-one' => __("Last one"),
),
'required' => true,
), $checkout->get_value( 'wc_billing_field_7378' ) );
}
See below the display:
Now to get this working jQuery and Ajax are required, to be able to make "Cod" payment enabled or disabled depending on the selected option value from this custom checkout select field.
With this code when "Naeem" or "Other one" are be selected, it will hide "Cash on delivery" (cod) payment method... If another option is selected, "Cash on delivery" will be visible again.
Here is this code:
// Jquery script that send the Ajax request
add_action( 'wp_footer', 'custom_checkout_js_script' );
function custom_checkout_js_script() {
// Only on checkout
if( is_checkout() && ! is_wc_endpoint_url() ) :
?>
<script type="text/javascript">
jQuery(function($){
if (typeof wc_checkout_params === 'undefined')
return false;
var field = 'select[name="wc_billing_field_7378"]';
$( 'form.checkout' ).on('change blur', field, function() {
$.ajax({
type: 'POST',
url: wc_checkout_params.ajax_url,
data: {
'action': 'checkout_chosen_destination',
'chosen_destination': $(this).val(),
},
success: function (result) {
$(document.body).trigger('update_checkout');
console.log(result); // For testing only
},
});
});
});
</script>
<?php
endif;
}
// The Wordpress Ajax PHP receiver
add_action( 'wp_ajax_checkout_chosen_destination', 'get_ajax_checkout_chosen_destination' );
add_action( 'wp_ajax_nopriv_checkout_chosen_destination', 'get_ajax_checkout_chosen_destination' );
function get_ajax_checkout_chosen_destination() {
// Checking that the posted email is valid
if ( isset($_POST['chosen_destination']) ) {
// Set the value in a custom Woocommerce session identifier
WC()->session->set('chosen_destination', esc_attr($_POST['chosen_destination']) );
// Return the session value to jQuery
echo json_encode(WC()->session->get('chosen_destination')); // For testing only
}
die(); // always use die at the end
}
// Show/Hide payment gateways
add_filter('woocommerce_available_payment_gateways', 'show_hide_cod_payment_method', 10, 1 );
function show_hide_cod_payment_method( $available_gateways ) {
// Not in backend (admin)
if( is_admin() )
return $available_gateways;
// HERE below set the not allowed destinations in the array
$not_allowed_destinations = array('naeem', 'other-one');
if ( in_array( WC()->session->get('chosen_destination'), $not_allowed_destinations ) ) {
unset($available_gateways['cod']);
}
return $available_gateways;
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.

Cannot add custom image uploader for custome post type in custom wordpress theme

I am trying to set image uploader for a custom post type on a Theme I am developing.
The aim is to get it to insert the image URL into the textbox of id "meta-image" but instead it inserts the image into the content editor field!
here is the code I have so far: this displays the button and text input:
<?php
global $post;
$prfx_stored_meta = get_post_meta( $post->ID );
?>
<p>
<label for="meta-image" class="prfx-row-title"><?php _e( 'Service Icon', 'prfx-textdomain' ); ?></label>
<input type="text" name="meta-image" id="meta-image" value="<?php if ( isset ( $prfx_stored_meta['meta-image'] ) ) echo $prfx_stored_meta['meta-image'][0]; ?>" />
<input type="button" id="meta-image-button" class="button" value="<?php _e( 'Choose or Upload an Image', 'prfx-textdomain' ); ?>" />
</p>
this includes the necessary js for admin area:
/**
* Loads the image management javascript
*/
function prfx_image_enqueue() {
global $typenow;
if( $typenow == 'service' ) {
wp_enqueue_media();
// Registers and enqueues the required javascript.
wp_register_script( 'meta-box-image', get_bloginfo('stylesheet_directory').'/js/meta-box-image.js', array( 'jquery' ) );
wp_localize_script( 'meta-box-image', 'meta_image',
array(
'title' => __( 'Choose or Upload an Image', 'prfx-textdomain' ),
'button' => __( 'Use this image', 'prfx-textdomain' ),
)
);
wp_enqueue_script( 'meta-box-image' );
}
}
add_action( 'admin_enqueue_scripts', 'prfx_image_enqueue' );
and this is the js:
/*
* Attaches the image uploader to the input field
*/
jQuery(document).ready(function(){
// Instantiates the variable that holds the media library frame.
var meta_image_frame;
// Runs when the image button is clicked.
jQuery('#meta-image-button').click(function(e){
// Prevents the default action from occuring.
e.preventDefault();
// If the frame already exists, re-open it.
if ( meta_image_frame ) {
wp.media.editor.open();
return;
}
// Sets up the media library frame
meta_image_frame = wp.media.frames.meta_image_frame = wp.media({
title: meta_image.title,
button: { text: meta_image.button },
library: { type: 'image' }
});
// Runs when an image is selected.
meta_image_frame.on('select', function(){
// Grabs the attachment selection and creates a JSON representation of the model.
var media_attachment = meta_image_frame.state().get('selection').first().toJSON();
// Sends the attachment URL to our custom image input field.
jQuery('#meta-image').val(media_attachment.url);
});
// Opens the media library frame.
wp.media.editor.open();
});
});
any ideas on how to get this actually storing to the proper area?

Using PHP Options in a Jquery Slider

So I'm not sure if I'm missing something obvious on this. (I think it may have something to do with the incompatibility of the two languages, since as far as I'm aware PHP is interpreted on the server?)… I'm pretty new to PHP though.
I'm using the great Jquery Plugin ResponsiveSlides on the front page of my custom WordPress-based site. That works great, with this code:
$(".home-slides").responsiveSlides({
auto: true,
speed: 500,
pause: true,
timeout: 7000,
pager: true,
nav: true,
maxwidth: 1280,
namespace: "home-slides",
prevText: "",
nextText: "",
navContainer:".home-slides",
manualControls: "#home-tabs"
});
However, I want to be able to allow the client to have some control over the plugin, using custom fields on the home page in the wordpress backend. These custom fields can easily be called and correctly display in an alert:
var speed = <?php echo the_field( "speed" ); ?>;
var timeout = <?php echo the_field( "timeout" ); ?>;
However, if I try and insert them as variables or directly with the above PHP, I have no luck. The closest I've got is:
$(".home-slides").responsiveSlides({
auto: true,
speed: <?php echo the_field( "speed" ); ?>,
pause: true,
timeout: <?php echo the_field( "timeout" ); ?>,
pager: true,
nav: true,
maxwidth: 1280,
namespace: "home-slides",
prevText: "",
nextText: "",
navContainer:".home-slides",
manualControls: "#home-tabs"
});
Which displays correctly in the live page source (i.e. timeout: 7000 etc), but breaks the slider. Is there anyway to make this work? Am I missing something?
Thank you all!
EDIT:
Thanks to Tom Kriek's suggestion, I can echo the script correctly. This produces the correct script in the live page source, but the slider still doesn't work. However, if I copy that same script from the page source to the actual file and test this, it works perfectly. It appears for some reason the browser is ignoring the script when PHP echoed.
echo '<script type="text/javascript">
$(".home-slides").responsiveSlides({
auto: true,
speed: '. the_field("speed") .',
pause: true,
timeout: '. the_field("timeout") .',
pager: true,
nav: true,
maxwidth: 1280,
namespace: "home-slides",
prevText: "",
nextText: "",
navContainer:".home-slides",
manualControls: "#home-tabs"
});
</script>';
To incorporate jQuery plugins into WordPress it's a matter of enqueuing the scripts in the correct order (with wp_enqueue_scripts) and to pass our custom meta data to the JavaScript file (with wp_localize_script).
A simple example, note that JS files are inside the plugin sub-folder /my-plugin/js/. The MAIN-PLUGIN-FILE.js corresponds to the jQuery plugin files (slider, player, gallery), add more wp_register_script as needed. And the CUSTOM-CONFIG.js file contains the plugin's initialization.
plugin.php
<?php
/**
* Plugin Name: (SO) Simple jQuery plugin enqueue
* Plugin URI: http://stackoverflow.com/a/25531753/1287812
* Author: brasofilo
*/
class SO_25527828
{
private $plugin_url;
public function __construct()
{
$this->plugin_url = plugins_url( '/', __FILE__ );
add_action( 'wp_enqueue_scripts', array( $this, 'enqueue' ) );
}
public function enqueue()
{
# Enqueue only on specific places
# http://codex.wordpress.org/Conditional_Tags
if( !is_home() && !is_front_page() )
return;
# Can be anything from unheap.com
wp_register_script(
'main_plugin',
$this->plugin_url . 'js/MAIN-PLUGIN-FILE.js'
);
# You'll have to play with dependencies, on_footer and do separately wp_enqueue_script's
# to achieve the exact HTML that the jQ plugin requires
wp_enqueue_script(
'config_plugin',
$this->plugin_url . 'js/CUSTOM-CONFIG.js',
array( 'jquery', 'main_plugin' ), // dependencies
false, // version
true // on footer
);
# Pass PHP values to JS
wp_localize_script(
'config_plugin',
'my_cfg',
array(
'url' => $this->plugin_url, // To load stuff from the plugin's dir
'option' => get_option( 'my_option' ), // Your custom config values, simple value or full object
)
);
}
}
new SO_25527828();
CUSTOM-CONFIG.js, the my_cfg var is printed on header and contains the values that we localized
jQuery(document).ready(function($)
{
console.dir(my_cfg);
});

WordPress Media Uploader with size select

I want to add an image input to my own WordPress plugin.
For that I use the standard WordPress media-uploader like so:
var custom_uploader;
$('.upload_image_button').click(function(e) {
input = $(this);
e.preventDefault();
custom_uploader = wp.media.frames.file_frame = wp.media({
title: 'Choose Collage Image',
library: {
type: 'image'
},
button: {
text: 'Choose Collage Image'
},
multiple: false,
displaySettings: true,
displayUserSettings: false
});
custom_uploader.on('select', function() {
attachment = custom_uploader.state().get('selection').first().toJSON();
input.prev('input').val(attachment.url);
});
custom_uploader.open();
});
This works perfect.
I add two more image sizes that were exact for my plugin:
if ( function_exists( 'add_image_size' ) ) {
add_image_size( 'collage-large', 460, 660, true );
add_image_size( 'collage-small', 460, 325, true );
}
My problem:
The selector for the image size or better the thumbnail selector is not shown at the media upload form. How do I do that?
You could use the media insertion dialog as shown on the "edit page" site, which adds alignment, link_to and size input fields. To do so add frame: 'post' to your options array:
file_frame = wp.media.frames.file_frame = wp.media({
title: 'Select a image to upload',
button: {
text: 'Use this image',
},
multiple: false,
frame: 'post', // <-- this is the important part
state: 'insert',
});
Instead of listening to the "select" event listen to the "insert" event. This code shows how retrieve the additional properties including the size:
// When an image is inserted, run a callback.
file_frame.on( 'insert', function(selection) {
var state = file_frame.state();
selection = selection || state.get('selection');
if (! selection) return;
// We set multiple to false so only get one image from the uploader
var attachment = selection.first();
var display = state.display(attachment).toJSON(); // <-- additional properties
attachment = attachment.toJSON();
// Do something with attachment.id and/or attachment.url here
var imgurl = attachment.sizes[display.size].url;
jQuery( '#filenameFromURL' ).val( imgurl );
});
I find some where in Internet. May be it useful.
attachment = custom_uploader.state().get('selection').first().toJSON();
With attachment you can working with:
alt
author
caption
compat ( <-- It is Object )
item
meta
date
dateFormatted
description
editLink
filename
height
icon
id
link
menuOrder
mime
modified
name
nonces ( <-- thi is object)
delete
update
proto
orientation
sizes ( <-- this is object)
full ( <-- this is object)
height
orientation
url
width
proto
medium ( <-- this is object)
height
orientation
url
width
proto
thumbnail ( <-- this is object)
height
orientation
url
width
proto
proto ( <-- this is object)
status
subtype
title
type
uploadedTo
url
width
To solve your problem I suggest use with case 20 above:
input.prev('input').val(attchment.sizes.collage-large.url);
Hope this work!
You're VERY close. To make the size selectable within the admin panel, review the add_image_size Codex Entry:
add_filter( 'image_size_names_choose', 'my_custom_sizes' );
function my_custom_sizes( $sizes ) {
return array_merge( $sizes, array(
'your-custom-size' => __('Your Custom Size Name'),
) );
}
So in your case, this should do what you need:
add_filter( 'image_size_names_choose', 'my_custom_sizes' );
function my_custom_sizes( $sizes ) {
return array_merge( $sizes, array(
'collage-large' => __('Collage Large'),
'collage-small' => __('Collage Small'),
) );
}

Categories