/**
  * Bundled product availability that takes quantity into account.
  *
  * @param  WC_Product   $product    the product
  * @param  int          $quantity   the quantity
  * @return array                    availability data
  */
 function get_bundled_product_availability($product, $quantity)
 {
     $availability = $class = '';
     if ($product->managing_stock()) {
         if ($product->is_in_stock() && $product->get_total_stock() > get_option('woocommerce_notify_no_stock_amount') && $product->get_total_stock() >= $quantity) {
             switch (get_option('woocommerce_stock_format')) {
                 case 'no_amount':
                     $availability = __('In stock', 'woocommerce');
                     break;
                 case 'low_amount':
                     if ($product->get_total_stock() <= get_option('woocommerce_notify_low_stock_amount')) {
                         $availability = sprintf(__('Only %s left in stock', 'woocommerce'), $product->get_total_stock());
                         if ($product->backorders_allowed() && $product->backorders_require_notification()) {
                             $availability .= ' ' . __('(can be backordered)', 'woocommerce');
                         }
                     } else {
                         $availability = __('In stock', 'woocommerce');
                     }
                     break;
                 default:
                     $availability = sprintf(__('%s in stock', 'woocommerce'), $product->get_total_stock());
                     if ($product->backorders_allowed() && $product->backorders_require_notification()) {
                         $availability .= ' ' . __('(can be backordered)', 'woocommerce');
                     }
                     break;
             }
             $class = 'in-stock';
         } elseif ($product->backorders_allowed() && $product->backorders_require_notification()) {
             if ($product->get_total_stock() >= $quantity || get_option('woocommerce_stock_format') == 'no_amount') {
                 $availability = __('Available on backorder', 'woocommerce');
             } else {
                 $availability = __('Available on backorder', 'woocommerce') . ' ' . sprintf(__('(only %s left in stock)', 'woocommerce-product-bundles'), $product->get_total_stock());
             }
             $class = 'available-on-backorder';
         } elseif ($product->backorders_allowed()) {
             $availability = __('In stock', 'woocommerce');
             $class = 'in-stock';
         } else {
             if ($product->is_in_stock() && $product->get_total_stock() > get_option('woocommerce_notify_no_stock_amount')) {
                 if (get_option('woocommerce_stock_format') == 'no_amount') {
                     $availability = __('Insufficient stock', 'woocommerce-product-bundles');
                 } else {
                     $availability = __('Insufficient stock', 'woocommerce-product-bundles') . ' ' . sprintf(__('(only %s left in stock)', 'woocommerce-product-bundles'), $product->get_total_stock());
                 }
                 $class = 'out-of-stock';
             } else {
                 $availability = __('Out of stock', 'woocommerce');
                 $class = 'out-of-stock';
             }
         }
     } elseif (!$product->is_in_stock()) {
         $availability = __('Out of stock', 'woocommerce');
         $class = 'out-of-stock';
     }
     _deprecated_function('get_bundled_product_availability', '4.8.8', 'WC_Bundled_Item::get_availability()');
     return apply_filters('woocommerce_get_bundled_product_availability', array('availability' => $availability, 'class' => $class), $product);
 }
 /**
  * Add a product line item to the order
  *
  * @since 2.2
  * @param \WC_Product $product
  * @param int $qty Line item quantity
  * @param array $args
  * @return int|bool Item ID or false
  */
 public function add_product($product, $qty = 1, $args = array())
 {
     $default_args = array('variation' => array(), 'totals' => array());
     $args = wp_parse_args($args, $default_args);
     $item_id = wc_add_order_item($this->id, array('order_item_name' => $product->get_title(), 'order_item_type' => 'line_item'));
     if (!$item_id) {
         return false;
     }
     wc_add_order_item_meta($item_id, '_qty', wc_stock_amount($qty));
     wc_add_order_item_meta($item_id, '_tax_class', $product->get_tax_class());
     wc_add_order_item_meta($item_id, '_product_id', $product->id);
     wc_add_order_item_meta($item_id, '_variation_id', isset($product->variation_id) ? $product->variation_id : 0);
     // Set line item totals, either passed in or from the product
     wc_add_order_item_meta($item_id, '_line_subtotal', wc_format_decimal(isset($args['totals']['subtotal']) ? $args['totals']['subtotal'] : $product->get_price_excluding_tax($qty)));
     wc_add_order_item_meta($item_id, '_line_total', wc_format_decimal(isset($args['totals']['total']) ? $args['totals']['total'] : $product->get_price_excluding_tax($qty)));
     wc_add_order_item_meta($item_id, '_line_subtotal_tax', wc_format_decimal(isset($args['totals']['subtotal_tax']) ? $args['totals']['subtotal_tax'] : 0));
     wc_add_order_item_meta($item_id, '_line_tax', wc_format_decimal(isset($args['totals']['tax']) ? $args['totals']['tax'] : 0));
     // Save tax data - Since 2.2
     if (isset($args['totals']['tax_data'])) {
         $tax_data = array();
         $tax_data['total'] = array_map('wc_format_decimal', $args['totals']['tax_data']['total']);
         $tax_data['subtotal'] = array_map('wc_format_decimal', $args['totals']['tax_data']['subtotal']);
         wc_add_order_item_meta($item_id, '_line_tax_data', $tax_data);
     } else {
         wc_add_order_item_meta($item_id, '_line_tax_data', array('total' => array(), 'subtotal' => array()));
     }
     // Add variation meta
     if (!empty($args['variation'])) {
         foreach ($args['variation'] as $key => $value) {
             wc_add_order_item_meta($item_id, str_replace('attribute_', '', $key), $value);
         }
     }
     // Backorders
     if ($product->backorders_require_notification() && $product->is_on_backorder($qty)) {
         wc_add_order_item_meta($item_id, apply_filters('woocommerce_backordered_item_meta_name', __('Backordered', 'woocommerce')), $qty - max(0, $product->get_total_stock()));
     }
     do_action('woocommerce_order_add_product', $this->id, $item_id, $product, $qty, $args);
     return $item_id;
 }
 /**
  * Low stock notification email.
  *
  * @param WC_Product $product
  */
 public function low_stock($product)
 {
     $subject = sprintf('[%s] %s', $this->get_blogname(), __('Product low in stock', 'woocommerce'));
     $message = sprintf(__('%s is low in stock.', 'woocommerce'), html_entity_decode(strip_tags($product->get_formatted_name()), ENT_QUOTES, get_bloginfo('charset'))) . ' ' . sprintf(__('There are %d left', 'woocommerce'), html_entity_decode(strip_tags($product->get_total_stock())));
     wp_mail(apply_filters('woocommerce_email_recipient_low_stock', get_option('woocommerce_stock_email_recipient'), $product), apply_filters('woocommerce_email_subject_low_stock', $subject, $product), apply_filters('woocommerce_email_content_low_stock', $message, $product), apply_filters('woocommerce_email_headers', '', 'low_stock', $product), apply_filters('woocommerce_email_attachments', array(), 'low_stock', $product));
 }
Example #4
0
function woocommerce_custom_product_columns($column)
{
    global $post, $woocommerce;
    $product = new WC_Product($post->ID);
    switch ($column) {
        case "thumb":
            $product->get_image();
            break;
        case "name":
            $edit_link = get_edit_post_link($post->ID);
            $title = _draft_or_post_title();
            $post_type_object = get_post_type_object($post->post_type);
            $can_edit_post = current_user_can($post_type_object->cap->edit_post, $post->ID);
            echo '<strong><a class="row-title" href="' . $edit_link . '">' . $title . '</a>';
            _post_states($post);
            echo '</strong>';
            if ($post->post_parent > 0) {
                echo '&nbsp;&nbsp;&larr; <a href="' . get_edit_post_link($post->post_parent) . '">' . get_the_title($post->post_parent) . '</a>';
            }
            // Excerpt view
            if (isset($_GET['mode']) && $_GET['mode'] == 'excerpt') {
                echo apply_filters('the_excerpt', $post->post_excerpt);
            }
            // Get actions
            $actions = array();
            $actions['id'] = 'ID: ' . $post->ID;
            if ($can_edit_post && 'trash' != $post->post_status) {
                $actions['inline hide-if-no-js'] = '<a href="#" class="editinline" title="' . esc_attr(__('Edit this item inline', 'woocommerce')) . '">' . __('Quick&nbsp;Edit', 'woocommerce') . '</a>';
            }
            if (current_user_can($post_type_object->cap->delete_post, $post->ID)) {
                if ('trash' == $post->post_status) {
                    $actions['untrash'] = "<a title='" . esc_attr(__('Restore this item from the Trash', 'woocommerce')) . "' href='" . wp_nonce_url(admin_url(sprintf($post_type_object->_edit_link . '&amp;action=untrash', $post->ID)), 'untrash-' . $post->post_type . '_' . $post->ID) . "'>" . __('Restore', 'woocommerce') . "</a>";
                } elseif (EMPTY_TRASH_DAYS) {
                    $actions['trash'] = "<a class='submitdelete' title='" . esc_attr(__('Move this item to the Trash', 'woocommerce')) . "' href='" . get_delete_post_link($post->ID) . "'>" . __('Trash', 'woocommerce') . "</a>";
                }
                if ('trash' == $post->post_status || !EMPTY_TRASH_DAYS) {
                    $actions['delete'] = "<a class='submitdelete' title='" . esc_attr(__('Delete this item permanently', 'woocommerce')) . "' href='" . get_delete_post_link($post->ID, '', true) . "'>" . __('Delete Permanently', 'woocommerce') . "</a>";
                }
            }
            if ($post_type_object->public) {
                if (in_array($post->post_status, array('pending', 'draft'))) {
                    if ($can_edit_post) {
                        $actions['view'] = '<a href="' . esc_url(add_query_arg('preview', 'true', get_permalink($post->ID))) . '" title="' . esc_attr(sprintf(__('Preview &#8220;%s&#8221;', 'woocommerce'), $title)) . '" rel="permalink">' . __('Preview', 'woocommerce') . '</a>';
                    }
                } elseif ('trash' != $post->post_status) {
                    $actions['view'] = '<a href="' . get_permalink($post->ID) . '" title="' . esc_attr(sprintf(__('View &#8220;%s&#8221;', 'woocommerce'), $title)) . '" rel="permalink">' . __('View', 'woocommerce') . '</a>';
                }
            }
            $actions = apply_filters('post_row_actions', $actions, $post);
            echo '<div class="row-actions">';
            $i = 0;
            $action_count = sizeof($actions);
            foreach ($actions as $action => $link) {
                ++$i;
                $i == $action_count ? $sep = '' : ($sep = ' | ');
                echo "<span class='{$action}'>{$link}{$sep}</span>";
            }
            echo '</div>';
            get_inline_data($post);
            /* Custom inline data for woocommerce */
            echo '
				<div class="hidden" id="woocommerce_inline_' . $post->ID . '">
					<div class="sku">' . $product->sku . '</div>
					<div class="regular_price">' . $product->regular_price . '</div>
					<div class="sale_price">' . $product->sale_price . '</div>
					<div class="weight">' . $product->weight . '</div>
					<div class="length">' . $product->length . '</div>
					<div class="width">' . $product->width . '</div>
					<div class="height">' . $product->height . '</div>
					<div class="visibility">' . $product->visibility . '</div>
					<div class="stock_status">' . $product->stock_status . '</div>
					<div class="stock">' . $product->stock . '</div>
					<div class="manage_stock">' . $product->manage_stock . '</div>
					<div class="featured">' . $product->featured . '</div>
					<div class="product_type">' . $product->product_type . '</div>
					<div class="product_is_virtual">' . $product->virtual . '</div>
				</div>
			';
            break;
        case "sku":
            if ($product->get_sku()) {
                echo $product->get_sku();
            } else {
                echo '<span class="na">&ndash;</span>';
            }
            break;
        case "product_type":
            if ($product->product_type == 'grouped') {
                echo '<span class="product-type tips ' . $product->product_type . '" tip="' . __('Grouped', 'woocommerce') . '"></span>';
            } elseif ($product->product_type == 'external') {
                echo '<span class="product-type tips ' . $product->product_type . '" tip="' . __('External/Affiliate', 'woocommerce') . '"></span>';
            } elseif ($product->product_type == 'simple') {
                if ($product->is_virtual()) {
                    echo '<span class="product-type tips virtual" tip="' . __('Virtual', 'woocommerce') . '"></span>';
                } elseif ($product->is_downloadable()) {
                    echo '<span class="product-type tips downloadable" tip="' . __('Downloadable', 'woocommerce') . '"></span>';
                } else {
                    echo '<span class="product-type tips ' . $product->product_type . '" tip="' . __('Simple', 'woocommerce') . '"></span>';
                }
            } elseif ($product->product_type == 'variable') {
                echo '<span class="product-type tips ' . $product->product_type . '" tip="' . __('Variable', 'woocommerce') . '"></span>';
            } else {
                // Assuming that we have other types in future
                echo '<span class="product-type tips ' . $product->product_type . '" tip="' . ucwords($product->product_type) . '"></span>';
            }
            break;
        case "price":
            if ($product->get_price_html()) {
                echo $product->get_price_html();
            } else {
                echo '<span class="na">&ndash;</span>';
            }
            break;
        case "product_cat":
            if (!($terms = get_the_term_list($post->ID, 'product_cat', '', ', ', ''))) {
                echo '<span class="na">&ndash;</span>';
            } else {
                echo $terms;
            }
            break;
        case "product_tags":
            if (!($terms = get_the_term_list($post->ID, 'product_tag', '', ', ', ''))) {
                echo '<span class="na">&ndash;</span>';
            } else {
                echo $terms;
            }
            break;
        case "featured":
            $url = wp_nonce_url(admin_url('admin-ajax.php?action=woocommerce-feature-product&product_id=' . $post->ID), 'woocommerce-feature-product');
            echo '<a href="' . $url . '" title="' . __('Change', 'woocommerce') . '">';
            if ($product->is_featured()) {
                echo '<a href="' . $url . '"><img src="' . $woocommerce->plugin_url() . '/assets/images/featured.png" alt="yes" />';
            } else {
                echo '<img src="' . $woocommerce->plugin_url() . '/assets/images/featured-off.png" alt="no" />';
            }
            echo '</a>';
            break;
        case "is_in_stock":
            if ($product->is_in_stock()) {
                echo '<mark class="instock">' . __('In stock', 'woocommerce') . '</mark>';
            } else {
                echo '<mark class="outofstock">' . __('Out of stock', 'woocommerce') . '</mark>';
            }
            if ($product->managing_stock()) {
                echo ' &times; ' . $product->get_total_stock();
            }
            break;
    }
}
 /**
  * Reduce stock level of the product
  *
  * @param   int		$by		Amount to reduce by
  */
 function reduce_stock($by = 1)
 {
     global $woocommerce;
     if ($this->variation_has_stock) {
         if ($this->managing_stock()) {
             $this->stock = $this->stock - $by;
             $this->total_stock = $this->total_stock - $by;
             update_post_meta($this->variation_id, '_stock', $this->stock);
             $woocommerce->clear_product_transients($this->id);
             // Clear transient
             // Check parents out of stock attribute
             if (!$this->is_in_stock()) {
                 // Check parent
                 $parent_product = new WC_Product($this->id);
                 // Only continue if the parent has backorders off
                 if (!$parent_product->backorders_allowed() && $parent_product->get_total_stock() <= 0) {
                     update_post_meta($this->id, '_stock_status', 'outofstock');
                 }
             }
             return $this->stock;
         }
     } else {
         return parent::reduce_stock($by);
     }
 }
 function process_qty()
 {
     global $woocommerce;
     // Save quantities
     if (!empty($_POST['stock_quantity']) && !empty($_POST['save_stock'])) {
         check_admin_referer('save', 'wc-stock-management');
         $quantities = $_POST['stock_quantity'];
         $current_quantities = $_POST['current_stock_quantity'];
         foreach ($quantities as $id => $qty) {
             if ($qty == '') {
                 continue;
             }
             if (isset($current_quantities[$id])) {
                 // Check the qty has not changed since showing the form
                 $current_stock = (int) get_post_meta($id, '_stock', true);
                 if ($current_stock == $current_quantities[$id]) {
                     $post = get_post($id);
                     // Format $qty
                     $qty = (int) $qty;
                     // Update stock amount
                     update_post_meta($id, '_stock', $qty);
                     // Update stock status
                     if ($post->post_type == 'product') {
                         // Update manage stock variable for products
                         update_post_meta($id, '_manage_stock', 'yes');
                         if (function_exists('get_product')) {
                             $product = get_product($post->ID);
                         } else {
                             $product = new WC_Product($post->ID);
                         }
                         if ($product->managing_stock() && !$product->backorders_allowed() && $product->get_total_stock() <= 0) {
                             update_post_meta($post->ID, '_stock_status', 'outofstock');
                         } elseif ($product->managing_stock() && ($product->backorders_allowed() || $product->get_total_stock() > 0)) {
                             update_post_meta($post->ID, '_stock_status', 'instock');
                         }
                         $woocommerce->clear_product_transients($post->ID);
                         // Clear transient
                     } else {
                         if (function_exists('get_product')) {
                             $product = get_product($post->post_parent);
                         } else {
                             $product = new WC_Product($post->post_parent);
                         }
                         if ($product->managing_stock() && !$product->backorders_allowed() && $product->get_total_stock() <= 0) {
                             update_post_meta($post->post_parent, '_stock_status', 'outofstock');
                         } elseif ($product->managing_stock() && ($product->backorders_allowed() || $product->get_total_stock() > 0)) {
                             update_post_meta($post->post_parent, '_stock_status', 'instock');
                         }
                         $woocommerce->clear_product_transients($post->post_parent);
                         // Clear transient
                     }
                 } else {
                     $this->messages[] = sprintf(__('Product # %s was not updated - the stock amount has changed since posting.', 'wc_stock_management'), $id);
                 }
             }
         }
         $this->messages[] = __('Stock quantities saved.', 'wc_stock_management');
     }
 }
 /**
  * Update a line item for the order.
  *
  * Note this does not update order totals.
  *
  * @param object|int $item order item ID or item object.
  * @param WC_Product $product
  * @param array $args data to update.
  * @return int updated order item ID
  */
 public function update_product($item, $product, $args)
 {
     _deprecated_function('WC_Order::update_product', '2.7', 'Interact with WC_Order_Item_Product class');
     if (is_numeric($item)) {
         $item = $this->get_item($item);
     }
     if (!is_object($item) || !$item->is_type('line_item')) {
         return false;
     }
     if (!$this->get_id()) {
         $this->save();
         // Order must exist
     }
     // BW compatibility with old args
     if (isset($args['totals'])) {
         foreach ($args['totals'] as $key => $value) {
             if ('tax' === $key) {
                 $args['total_tax'] = $value;
             } elseif ('tax_data' === $key) {
                 $args['taxes'] = $value;
             } else {
                 $args[$key] = $value;
             }
         }
     }
     // Handly qty if set
     if (isset($args['qty'])) {
         if ($product->backorders_require_notification() && $product->is_on_backorder($args['qty'])) {
             $item->add_meta_data(apply_filters('woocommerce_backordered_item_meta_name', __('Backordered', 'woocommerce')), $args['qty'] - max(0, $product->get_total_stock()), true);
         }
         $args['subtotal'] = $args['subtotal'] ? $args['subtotal'] : $product->get_price_excluding_tax($args['qty']);
         $args['total'] = $args['total'] ? $args['total'] : $product->get_price_excluding_tax($args['qty']);
     }
     $item->set_order_id($this->get_id());
     $item->set_all($args);
     $item->save();
     do_action('woocommerce_order_edit_product', $this->get_id(), $item->get_id(), $args, $product);
     return $item->get_id();
 }