I've set up Woocommerce with variable products.
These products all have variations on an attribute with the possible values of 1kg, 2kg, and 5kg.
I've also created an "Aziende" user group. I want some product variations to only display for "Aziende" customers. I don't want these variations visible to other customers.
For example: Aziende Customers see the options "1kg, 2kg, 5kg", While other customer roles only see the 1kg option.
Is this possible in Woocommerce?
Yes. If you override the file woocommerce/templates/single-product/add-to-cart/variable.php you find the code for the variations selectbox.
There you could do something like:
First of all I always include this snippet when working with roles:
function user_has_role( $role, $user_id = null ) {
if ( is_numeric( $user_id ) )
$user = get_userdata( $user_id );
else
$user = wp_get_current_user();
if ( empty( $user ) )
return false;
return in_array( $role, (array) $user->roles );
}
So it can be used as:
if(user_has_role("Aziende")){
//do stuff
}
Now having this function, and knowing which template to change you should be able to do something in that file. It could be along this:
// Get terms if this is a taxonomy - ordered
if ( taxonomy_exists( $name ) ) {
$terms = wc_get_product_terms( $post->ID, $name, array( 'fields' => 'all' ) );
foreach ( $terms as $term ) {
if ( ! in_array( $term->slug, $options ) ) {
continue;
}
if($name == 'pa_weight' && $term->slug != '1kg' ) { // or whatever your attribute is called, and whatever the attribute term is called.
if(!user_has_role('aziende'){
continue;
}
}
echo '<option value="' . esc_attr( $term->slug ) . '" ' . selected( sanitize_title( $selected_value ), sanitize_title( $term->slug ), false ) . '>' . apply_filters( 'woocommerce_variation_option_name', $term->name ) . '</option>';
}
} else {
foreach ( $options as $option ) {
if($name == 'pa_weight' && $option != '1kg' ) { // or whatever your attribute is called, and whatever the attribute term is called.
if(!user_has_role('aziende'){
continue;
}
}
echo '<option value="' . esc_attr( sanitize_title( $option ) ) . '" ' . selected( sanitize_title( $selected_value ), sanitize_title( $option ), false ) . '>' . esc_html( apply_filters( 'woocommerce_variation_option_name', $option ) ) . '</option>';
}
}
This code is not tested, so I dont know if it works. But it should give you a pointer in the correct direction.
Related
I have link like that with polylang:
https://test.doamin.eu/pl/category/page/6/
Pagination works on link:
https://test.doamin.eu/pl/product-category/category/page/6/
I want to use first type of link.
Probably problem is with this line of code:
$customRules["{$slug}/{$wp_rewrite->pagination_base}/?([0-9]{1,})/?\$"] = 'index.php?' . $taxonomy . '=' . $term->slug . '&paged=$matches[1]';
Variable with slug is:
$slug = $this->buildTermPath( $term, $hierarchical, $suffix );
The buildTermPath method code is:
private function buildTermPath( $term, $hierarchical, $suffix = false )
{
//urldecode used here to fix copied url via ctrl+c
$slug = urldecode( $term->slug );
if ( $hierarchical && $term->parent ) {
$ancestors = get_ancestors( $term->term_id, 'product_cat' );
foreach ( $ancestors as $ancestor ) {
$ancestor_object = get_term( $ancestor, 'product_cat' );
$slug = urldecode( $ancestor_object->slug ) . '/' . $slug;
}
}
return ( $suffix ? $slug . $suffix : $slug );
}
Problem with pl in adress I fix with that line:
return $wp_rewrite->root . (( $this->polyLang->options['rewrite'] ? '' : '/' )) . '(' . implode( '|', $languages ) . ')/';
Please help. I dont know how to fix that problem.
I have added some custom fields on the WooCommerce checkout page. I have saved the data of those fields and displayed it on the admin order page. Like picture no.1. Everything is OK.
Now I want to edit the data/text/value of this field. Like picture no.2. Like billing and shipping on the admin order page....
How can I solve it?
function display_admin_order_meta ( $order ) {
$strt= $order->get_meta('_checkout_custom_name', true );
if( ! empty( $strt) ){
$label = __( 'Phone' );
if( is_admin() ){
echo '<p><strong>' . $label . ' : </strong> ' . $strt. '</p>';
}
else {
echo '<table class="woocommerce-table"><tbody><tr>
<th>' . $label . ' : </th><td>' . $strt. '</td>
</tr></tbody></table>';
}
}
$strt= $order->get_meta('_checkout_others_address', true );
if( ! empty( $strt) ){
$label = __( 'Address' );
if( is_admin() ){ // Admin
echo '<p><strong>' . $label . ' : </strong> ' . $strt. '</p>';
}
else {
echo '<table class="woocommerce-table"><tbody><tr>
<th>' . $label . ' : </th><td>' . $strt. '</td>
</tr></tbody></table>';
}
}
}
add_action( 'woocommerce_admin_order_data_after_billing_address', 'display_admin_order_meta', 20, 1);
This is the checkout field data I created. I want to edit these like the picture above.
This is a way(customize it if needed)
Add custom billing form data input with woocommerce_admin_billing_fields filter
add_filter('woocommerce_admin_billing_fields', 'add_woocommerce_admin_billing_fields');
function add_woocommerce_admin_billing_fields($billing_fields) {
$billing_fields['_checkout_custom_name'] = array( 'label' => __('Name', 'woocommerce') );
$billing_fields['_checkout_others_address'] = array( 'label' => __('Address', 'woocommerce') );
return $billing_fields;
}
Then save custom fields like this
function cloudways_save_extra_details( $post_id, $post ){
update_post_meta( $post_id, '_checkout_custom_name', $_POST[ '_checkout_custom_name' ] ) );
update_post_meta( $post_id, '_checkout_custom_address', $_POST[ '_checkout_custom_address' ] ) );
}
add_action( 'woocommerce_process_shop_order_meta', 'cloudways_save_extra_details', 45, 2 );
For my custom WP plugin, im trying to get and list the color(hex) and image-url field values of a specific Woocomerce product pa_colors attribute.
so far i can get the attribute title and description using the code seen here, but cant seem to find how to access color preview (hex) and image preview (url) values.
here is my code:
$_product = wc_get_product( $product_id );
$attributes = $_product->get_attributes('pa_colors');
foreach($attributes as $attr=>$attr_dts){
$attribute_label = wc_attribute_label($attr);
if ( isset( $attributes[ $attr ] ) || isset( $attributes[ 'pa_' . $attr ] ) ) {
$attribute = isset( $attributes[ $attr ] ) ? $attributes[ $attr ] : $attributes[ 'pa_' . $attr ];
if ( $attribute['is_taxonomy'] ) {
$values = wc_get_product_terms( $_product->id, $attribute['name'],array( 'fields' => 'all' ));
if( $values ){
foreach ( $values as $term ){
echo '<dh>' . $term->name.' </dh>';
echo '<dd>' . term_description( $term->term_id, $term->taxonomy ) . '</dd>';
//here is where i want to get the term color values and image url.
}
echo '</dl>';
}
} else {
$formatted_attributes[$attribute_label] = $attribute['value'];
}
}
}
this code worked for me
$_product = wc_get_product( $product_id );
$attributes = $_product->get_attributes('pa_colors');
foreach($attributes as $attr=>$attr_dts){
$attribute_label = wc_attribute_label($attr);
if ( isset( $attributes[ $attr ] ) || isset( $attributes[ 'pa_' . $attr ] ) ) {
$attribute = isset( $attributes[ $attr ] ) ? $attributes[ $attr ] : $attributes[ 'pa_' . $attr ];
if ( $attribute['is_taxonomy'] ) {
$values = wc_get_product_terms( $_product->id, $attribute['name'],array( 'fields' => 'all' ));
if( $values ){
foreach ( $values as $term ){
echo '<dh>' . $term->name.' </dh>';
echo '<dd>' . get_term_meta( $term->term_id, 'color', true ); . '</dd>';
echo '<dd><img src="' . get_term_meta( $term->term_id, 'image', true ) . '" /></dd>';
}
echo '</dl>';
}
} else {
$formatted_attributes[$attribute_label] = $attribute['value'];
}
}
}
i want to change the "out of stock" text with html element woocommerce.
Currently, I'm using:
add_filter( 'woocommerce_get_availability', 'change_out_of_stock_text', 1, 2);
function change_out_of_stock_text( $availability, $_product ) {
global $post;
if ( ! $_product->is_in_stock() ) {
$out_of_stock = "Out of Stock";
if(get_post_meta( $post->ID, '_text_field', true )!="") {
$out_of_stock = get_post_meta( $post->ID, '_text_field', true );
}
$availability['availability'] = __($out_of_stock, 'woocommerce');
}
return $availability;
}
It can change the "Out of Stock" text with the value from custom input field i made in product page but i want to show the html element from that value to shop page as well. For example if the value is 'Sold out', it should output the link text as well "Sold out".
I also tried woocommerce_stock_html but it got the same problem:
function change_out_of_stock_text( $html, $_availability, $_product ){
global $post;
$out_of_stock = "Out of Stock";
$_availability = $_product->get_availability();
if(get_post_meta( $post->ID, '_text_field', true )!="") {
$out_of_stock = get_post_meta( $post->ID, '_text_field', true );
}
$html = '<p class="stock ' . esc_attr( $_availability['class'] ) . '">' . $out_of_stock . '</p>';
return $html;
}
add_filter( 'woocommerce_stock_html', 'change_out_of_stock_text', 10, 3 );
Seems like you have the right idea but you are't targeting the appropriate filter which is woocommerce_get_availability
function so_34126704_availability( $array, $product ){
if ( ! $_product->is_in_stock() ) && ( $status = get_post_meta( $product->id, '_text_field', true ) ) != "" ){
$availability['availability'] = $status;
}
return $array;
}
add_filter( 'woocommerce_get_availability', 'so_34126704_availability', 10, 2 );
to filter the output html you need to filter woocommerce_stock_html. it's a bit half-baked because I don't know what you'd want to do with the classes or where you are linking to, but here's a shell example of that:
function so_34126704_availability_html( $html, $_availability, $product ){
$availability = $product->get_availability(); // for some reason the $_availability does not pass the entire array, only the availability key
$status = get_post_meta( $product->id, '_text_field', true );
$html = '<p class="stock ' . esc_attr( $availability['class'] ) . '"><a href="#somewhere"/>' . esc_html( $status ) . '</a></p>';
return $html;
}
add_filter( 'woocommerce_stock_html', 'so_34126704_availability_html', 10, 3 );
I searched a lot how to customize custom posts list,
I managed to add a new columns with manage_commercial_cpi_posts_columns,
But, I need to remove the "title" from the list, and still have the edit, delete options.
How can I do it?
You could hide the title link with CSS or JS, but here's a PHP approach. First remove the title column, and add a custom one:
add_filter( 'manage_commercial_cpi_posts_columns', 'manage_commercial_cpi_posts_columns', 25, 1 );
function manage_commercial_cpi_posts_columns( $cols )
{
// remove title column
unset( $cols['title'] );
// add custom column
$cols['ccpi_links'] = __( 'Edit', 'textdomain' );
// return columns
return $cols;
}
Then, use the row_actions method of the WP_List_Table class to generate the links. Code is copied from the WP_Posts_List_Table class. An important detail is the addition of true as the second parameter of the row_actions method, ensuring the links are always visible.
add_action( 'manage_commercial_cpi_posts_custom_column', 'manage_commercial_cpi_custom_column', 10, 2 );
function manage_commercial_cpi_custom_column( $col, $post_id )
{
switch( $col ) :
case 'ccpi_links' :
// variables
$post = get_post( $post_id );
$title = _draft_or_post_title();
$post_type_object = get_post_type_object( $post->post_type );
$can_edit_post = current_user_can( 'edit_post', $post->ID );
// set up row actions
$actions = array();
if ( $can_edit_post && 'trash' != $post->post_status ) {
$actions['edit'] = '' . __( 'Edit' ) . '';
$actions['inline hide-if-no-js'] = '' . __( 'Quick Edit' ) . '';
}
if ( current_user_can( 'delete_post', $post->ID ) ) {
if ( 'trash' == $post->post_status )
$actions['untrash'] = "<a title='" . esc_attr( __( 'Restore this item from the Trash' ) ) . "' href='" . wp_nonce_url( admin_url( sprintf( $post_type_object->_edit_link . '&action=untrash', $post->ID ) ), 'untrash-post_' . $post->ID ) . "'>" . __( 'Restore' ) . "</a>";
elseif ( EMPTY_TRASH_DAYS )
$actions['trash'] = "<a class='submitdelete' title='" . esc_attr( __( 'Move this item to the Trash' ) ) . "' href='" . get_delete_post_link( $post->ID ) . "'>" . __( 'Trash' ) . "</a>";
if ( 'trash' == $post->post_status || !EMPTY_TRASH_DAYS )
$actions['delete'] = "<a class='submitdelete' title='" . esc_attr( __( 'Delete this item permanently' ) ) . "' href='" . get_delete_post_link( $post->ID, '', true ) . "'>" . __( 'Delete Permanently' ) . "</a>";
}
if ( $post_type_object->public ) {
if ( in_array( $post->post_status, array( 'pending', 'draft', 'future' ) ) ) {
if ( $can_edit_post ) {
$preview_link = set_url_scheme( get_permalink( $post->ID ) );
/** This filter is documented in wp-admin/includes/meta-boxes.php */
$preview_link = apply_filters( 'preview_post_link', add_query_arg( 'preview', 'true', $preview_link ), $post );
$actions['view'] = '' . __( 'Preview' ) . '';
}
} elseif ( 'trash' != $post->post_status ) {
$actions['view'] = '' . __( 'View' ) . '';
}
}
// invoke row actions
$table = new WP_Posts_List_Table;
echo $table->row_actions( $actions, true );
break;
endswitch;
}
result