/**
  * Clear the product/shop transients cache.
  *
  * ## EXAMPLES
  *
  *     wp wc tool clear_transients
  *
  * @since 2.5.0
  */
 public function clear_transients($args, $assoc_args)
 {
     wc_delete_product_transients();
     wc_delete_shop_order_transients();
     WC_Cache_Helper::get_transient_version('shipping', true);
     WP_CLI::success('Product transients and shop order transients were cleared.');
 }
 /**
  * Save Meta Box
  *
  * The function to be called to save the meta box options.
  *
  * @param   $post_id object the current product id
  * @param   $post object the current product
  * @since   1.0.0
  * @author  Alberto Ruggiero
  * @return  void
  */
 public static function save($post_id, $post)
 {
     global $wpdb;
     $product_type = empty($_POST['product-type']) ? 'simple' : sanitize_title(stripslashes($_POST['product-type']));
     $catalog_mode = isset($_POST['_ywctm_exclude_catalog_mode']) ? 'yes' : 'no';
     $hide_price = isset($_POST['_ywctm_exclude_hide_price']) ? 'yes' : 'no';
     update_post_meta($post_id, '_ywctm_exclude_catalog_mode', $catalog_mode);
     update_post_meta($post_id, '_ywctm_exclude_hide_price', $hide_price);
     do_action('woocommerce_process_product_meta_' . $product_type, $post_id);
     // Clear cache/transients
     wc_delete_product_transients($post_id);
 }
 /**
  * Sync grouped products with the children lowest price (so they can be sorted by price accurately).
  *
  * @access public
  * @return void
  */
 public function grouped_product_sync()
 {
     global $wpdb, $woocommerce;
     if (!$this->get_parent()) {
         return;
     }
     $children_by_price = get_posts(array('post_parent' => $this->get_parent(), 'orderby' => 'meta_value_num', 'order' => 'asc', 'meta_key' => '_price', 'posts_per_page' => 1, 'post_type' => 'product', 'fields' => 'ids'));
     if ($children_by_price) {
         foreach ($children_by_price as $child) {
             $child_price = get_post_meta($child, '_price', true);
             update_post_meta($this->get_parent(), '_price', $child_price);
         }
     }
     wc_delete_product_transients($this->id);
 }
Exemple #4
0
 /**
  * Test wc_delete_product_transients()
  *
  * @since 2.4
  */
 public function test_wc_delete_product_transients()
 {
     // Create product
     $product = \WC_Helper_Product::create_simple_product();
     update_post_meta($product->id, '_regular_price', wc_format_decimal(10));
     update_post_meta($product->id, '_price', wc_format_decimal(5));
     update_post_meta($product->id, '_sale_price', wc_format_decimal(5));
     update_post_meta($product->id, '_featured', 'yes');
     wc_get_product_ids_on_sale();
     // Creates the transient for on sale products
     wc_get_featured_product_ids();
     // Creates the transient for featured products
     wc_delete_product_transients();
     $this->assertFalse(get_transient('wc_products_onsale'));
     $this->assertFalse(get_transient('wc_featured_products'));
     \WC_Helper_Product::delete_product($product->id);
 }
 /**
  * Save the settings
  */
 public static function save()
 {
     global $current_section, $current_tab;
     if (empty($_REQUEST['_wpnonce']) || !wp_verify_nonce($_REQUEST['_wpnonce'], 'woocommerce-settings')) {
         die(__('Action failed. Please refresh the page and retry.', 'woocommerce'));
     }
     // Trigger actions
     do_action('woocommerce_settings_save_' . $current_tab);
     do_action('woocommerce_update_options_' . $current_tab);
     do_action('woocommerce_update_options');
     // Clear any unwanted data
     wc_delete_product_transients();
     delete_transient('woocommerce_cache_excluded_uris');
     self::add_message(__('Your settings have been saved.', 'woocommerce'));
     self::check_download_folder_protection();
     // Re-add endpoints and flush rules
     WC()->query->init_query_vars();
     WC()->query->add_endpoints();
     flush_rewrite_rules();
     do_action('woocommerce_settings_saved');
 }
 /**
  * Save meta box data
  */
 public static function save($post_id, $post)
 {
     global $wpdb;
     // Add any default post meta
     add_post_meta($post_id, 'total_sales', '0', true);
     // Get types
     $product_type = empty($_POST['product-type']) ? 'simple' : sanitize_title(stripslashes($_POST['product-type']));
     $is_downloadable = isset($_POST['_downloadable']) ? 'yes' : 'no';
     $is_virtual = isset($_POST['_virtual']) ? 'yes' : 'no';
     // Product type + Downloadable/Virtual
     wp_set_object_terms($post_id, $product_type, 'product_type');
     update_post_meta($post_id, '_downloadable', $is_downloadable);
     update_post_meta($post_id, '_virtual', $is_virtual);
     // Update post meta
     if (isset($_POST['_regular_price'])) {
         update_post_meta($post_id, '_regular_price', $_POST['_regular_price'] === '' ? '' : wc_format_decimal($_POST['_regular_price']));
     }
     if (isset($_POST['_sale_price'])) {
         update_post_meta($post_id, '_sale_price', $_POST['_sale_price'] === '' ? '' : wc_format_decimal($_POST['_sale_price']));
     }
     if (isset($_POST['_tax_status'])) {
         update_post_meta($post_id, '_tax_status', wc_clean($_POST['_tax_status']));
     }
     if (isset($_POST['_tax_class'])) {
         update_post_meta($post_id, '_tax_class', wc_clean($_POST['_tax_class']));
     }
     if (isset($_POST['_purchase_note'])) {
         update_post_meta($post_id, '_purchase_note', wp_kses_post(stripslashes($_POST['_purchase_note'])));
     }
     // Featured
     if (update_post_meta($post_id, '_featured', isset($_POST['_featured']) ? 'yes' : 'no')) {
         delete_transient('wc_featured_products');
     }
     // Dimensions
     if ('no' == $is_virtual) {
         if (isset($_POST['_weight'])) {
             update_post_meta($post_id, '_weight', '' === $_POST['_weight'] ? '' : wc_format_decimal($_POST['_weight']));
         }
         if (isset($_POST['_length'])) {
             update_post_meta($post_id, '_length', '' === $_POST['_length'] ? '' : wc_format_decimal($_POST['_length']));
         }
         if (isset($_POST['_width'])) {
             update_post_meta($post_id, '_width', '' === $_POST['_width'] ? '' : wc_format_decimal($_POST['_width']));
         }
         if (isset($_POST['_height'])) {
             update_post_meta($post_id, '_height', '' === $_POST['_height'] ? '' : wc_format_decimal($_POST['_height']));
         }
     } else {
         update_post_meta($post_id, '_weight', '');
         update_post_meta($post_id, '_length', '');
         update_post_meta($post_id, '_width', '');
         update_post_meta($post_id, '_height', '');
     }
     // Save shipping class
     $product_shipping_class = $_POST['product_shipping_class'] > 0 && $product_type != 'external' ? absint($_POST['product_shipping_class']) : '';
     wp_set_object_terms($post_id, $product_shipping_class, 'product_shipping_class');
     // Unique SKU
     $sku = get_post_meta($post_id, '_sku', true);
     $new_sku = wc_clean(stripslashes($_POST['_sku']));
     if ('' == $new_sku) {
         update_post_meta($post_id, '_sku', '');
     } elseif ($new_sku !== $sku) {
         if (!empty($new_sku)) {
             $unique_sku = wc_product_has_unique_sku($post_id, $new_sku);
             if (!$unique_sku) {
                 WC_Admin_Meta_Boxes::add_error(__('Product SKU must be unique.', 'woocommerce'));
             } else {
                 update_post_meta($post_id, '_sku', $new_sku);
             }
         } else {
             update_post_meta($post_id, '_sku', '');
         }
     }
     // Save Attributes
     $attributes = array();
     if (isset($_POST['attribute_names']) && isset($_POST['attribute_values'])) {
         $attribute_names = $_POST['attribute_names'];
         $attribute_values = $_POST['attribute_values'];
         if (isset($_POST['attribute_visibility'])) {
             $attribute_visibility = $_POST['attribute_visibility'];
         }
         if (isset($_POST['attribute_variation'])) {
             $attribute_variation = $_POST['attribute_variation'];
         }
         $attribute_is_taxonomy = $_POST['attribute_is_taxonomy'];
         $attribute_position = $_POST['attribute_position'];
         $attribute_names_max_key = max(array_keys($attribute_names));
         for ($i = 0; $i <= $attribute_names_max_key; $i++) {
             if (empty($attribute_names[$i])) {
                 continue;
             }
             $is_visible = isset($attribute_visibility[$i]) ? 1 : 0;
             $is_variation = isset($attribute_variation[$i]) ? 1 : 0;
             $is_taxonomy = $attribute_is_taxonomy[$i] ? 1 : 0;
             if ($is_taxonomy) {
                 if (isset($attribute_values[$i])) {
                     // Select based attributes - Format values (posted values are slugs)
                     if (is_array($attribute_values[$i])) {
                         $values = array_map('sanitize_title', $attribute_values[$i]);
                         // Text based attributes - Posted values are term names - don't change to slugs
                     } else {
                         $values = array_map('stripslashes', array_map('strip_tags', explode(WC_DELIMITER, $attribute_values[$i])));
                     }
                     // Remove empty items in the array
                     $values = array_filter($values, 'strlen');
                 } else {
                     $values = array();
                 }
                 // Update post terms
                 if (taxonomy_exists($attribute_names[$i])) {
                     foreach ($values as $key => $value) {
                         $term = get_term_by('name', trim($value), $attribute_names[$i]);
                         if ($term) {
                             $values[$key] = intval($term->term_id);
                         } else {
                             $term = wp_insert_term(trim($value), $attribute_names[$i]);
                             if (isset($term->term_id)) {
                                 $values[$key] = intval($term->term_id);
                             }
                         }
                     }
                     wp_set_object_terms($post_id, $values, $attribute_names[$i]);
                 }
                 if (!empty($values)) {
                     // Add attribute to array, but don't set values
                     $attributes[sanitize_title($attribute_names[$i])] = array('name' => wc_clean($attribute_names[$i]), 'value' => '', 'position' => $attribute_position[$i], 'is_visible' => $is_visible, 'is_variation' => $is_variation, 'is_taxonomy' => $is_taxonomy);
                 }
             } elseif (isset($attribute_values[$i])) {
                 // Text based, separate by pipe
                 $values = implode(' ' . WC_DELIMITER . ' ', array_map('wc_clean', wc_get_text_attributes($attribute_values[$i])));
                 // Custom attribute - Add attribute to array and set the values
                 $attributes[sanitize_title($attribute_names[$i])] = array('name' => wc_clean($attribute_names[$i]), 'value' => $values, 'position' => $attribute_position[$i], 'is_visible' => $is_visible, 'is_variation' => $is_variation, 'is_taxonomy' => $is_taxonomy);
             }
         }
     }
     if (!function_exists('attributes_cmp')) {
         function attributes_cmp($a, $b)
         {
             if ($a['position'] == $b['position']) {
                 return 0;
             }
             return $a['position'] < $b['position'] ? -1 : 1;
         }
     }
     uasort($attributes, 'attributes_cmp');
     update_post_meta($post_id, '_product_attributes', $attributes);
     // Sales and prices
     if (in_array($product_type, array('variable', 'grouped'))) {
         // Variable and grouped products have no prices
         update_post_meta($post_id, '_regular_price', '');
         update_post_meta($post_id, '_sale_price', '');
         update_post_meta($post_id, '_sale_price_dates_from', '');
         update_post_meta($post_id, '_sale_price_dates_to', '');
         update_post_meta($post_id, '_price', '');
     } else {
         $date_from = isset($_POST['_sale_price_dates_from']) ? wc_clean($_POST['_sale_price_dates_from']) : '';
         $date_to = isset($_POST['_sale_price_dates_to']) ? wc_clean($_POST['_sale_price_dates_to']) : '';
         // Dates
         if ($date_from) {
             update_post_meta($post_id, '_sale_price_dates_from', strtotime($date_from));
         } else {
             update_post_meta($post_id, '_sale_price_dates_from', '');
         }
         if ($date_to) {
             update_post_meta($post_id, '_sale_price_dates_to', strtotime($date_to));
         } else {
             update_post_meta($post_id, '_sale_price_dates_to', '');
         }
         if ($date_to && !$date_from) {
             $date_from = date('Y-m-d');
             update_post_meta($post_id, '_sale_price_dates_from', strtotime($date_from));
         }
         // Update price if on sale
         if ('' !== $_POST['_sale_price'] && '' == $date_to && '' == $date_from) {
             update_post_meta($post_id, '_price', wc_format_decimal($_POST['_sale_price']));
         } else {
             update_post_meta($post_id, '_price', $_POST['_regular_price'] === '' ? '' : wc_format_decimal($_POST['_regular_price']));
         }
         if ('' !== $_POST['_sale_price'] && $date_from && strtotime($date_from) <= strtotime('NOW', current_time('timestamp'))) {
             update_post_meta($post_id, '_price', wc_format_decimal($_POST['_sale_price']));
         }
         if ($date_to && strtotime($date_to) < strtotime('NOW', current_time('timestamp'))) {
             update_post_meta($post_id, '_price', $_POST['_regular_price'] === '' ? '' : wc_format_decimal($_POST['_regular_price']));
             update_post_meta($post_id, '_sale_price_dates_from', '');
             update_post_meta($post_id, '_sale_price_dates_to', '');
         }
     }
     // Update parent if grouped so price sorting works and stays in sync with the cheapest child
     if ($post->post_parent > 0 || 'grouped' == $product_type || $_POST['previous_parent_id'] > 0) {
         $clear_parent_ids = array();
         if ($post->post_parent > 0) {
             $clear_parent_ids[] = $post->post_parent;
         }
         if ('grouped' == $product_type) {
             $clear_parent_ids[] = $post_id;
         }
         if ($_POST['previous_parent_id'] > 0) {
             $clear_parent_ids[] = absint($_POST['previous_parent_id']);
         }
         if (!empty($clear_parent_ids)) {
             foreach ($clear_parent_ids as $clear_id) {
                 $children_by_price = get_posts(array('post_parent' => $clear_id, 'orderby' => 'meta_value_num', 'order' => 'asc', 'meta_key' => '_price', 'posts_per_page' => 1, 'post_type' => 'product', 'fields' => 'ids'));
                 if ($children_by_price) {
                     foreach ($children_by_price as $child) {
                         $child_price = get_post_meta($child, '_price', true);
                         update_post_meta($clear_id, '_price', $child_price);
                     }
                 }
                 wc_delete_product_transients($clear_id);
             }
         }
     }
     // Sold Individually
     if (!empty($_POST['_sold_individually'])) {
         update_post_meta($post_id, '_sold_individually', 'yes');
     } else {
         update_post_meta($post_id, '_sold_individually', '');
     }
     // Stock Data
     if ('yes' === get_option('woocommerce_manage_stock')) {
         $manage_stock = 'no';
         $backorders = 'no';
         $stock_status = wc_clean($_POST['_stock_status']);
         if ('external' === $product_type) {
             $stock_status = 'instock';
         } elseif ('variable' === $product_type) {
             // Stock status is always determined by children so sync later
             $stock_status = '';
             if (!empty($_POST['_manage_stock'])) {
                 $manage_stock = 'yes';
                 $backorders = wc_clean($_POST['_backorders']);
             }
         } elseif ('grouped' !== $product_type && !empty($_POST['_manage_stock'])) {
             $manage_stock = 'yes';
             $backorders = wc_clean($_POST['_backorders']);
         }
         update_post_meta($post_id, '_manage_stock', $manage_stock);
         update_post_meta($post_id, '_backorders', $backorders);
         if ($stock_status) {
             wc_update_product_stock_status($post_id, $stock_status);
         }
         if (!empty($_POST['_manage_stock'])) {
             wc_update_product_stock($post_id, wc_stock_amount($_POST['_stock']));
         } else {
             update_post_meta($post_id, '_stock', '');
         }
     } else {
         wc_update_product_stock_status($post_id, wc_clean($_POST['_stock_status']));
     }
     // Cross sells and upsells
     $upsells = isset($_POST['upsell_ids']) ? array_filter(array_map('intval', explode(',', $_POST['upsell_ids']))) : array();
     $crosssells = isset($_POST['crosssell_ids']) ? array_filter(array_map('intval', explode(',', $_POST['crosssell_ids']))) : array();
     update_post_meta($post_id, '_upsell_ids', $upsells);
     update_post_meta($post_id, '_crosssell_ids', $crosssells);
     // Downloadable options
     if ('yes' == $is_downloadable) {
         $_download_limit = absint($_POST['_download_limit']);
         if (!$_download_limit) {
             $_download_limit = '';
             // 0 or blank = unlimited
         }
         $_download_expiry = absint($_POST['_download_expiry']);
         if (!$_download_expiry) {
             $_download_expiry = '';
             // 0 or blank = unlimited
         }
         // file paths will be stored in an array keyed off md5(file path)
         $files = array();
         if (isset($_POST['_wc_file_urls'])) {
             $file_names = isset($_POST['_wc_file_names']) ? $_POST['_wc_file_names'] : array();
             $file_urls = isset($_POST['_wc_file_urls']) ? array_map('trim', $_POST['_wc_file_urls']) : array();
             $file_url_size = sizeof($file_urls);
             $allowed_file_types = apply_filters('woocommerce_downloadable_file_allowed_mime_types', get_allowed_mime_types());
             for ($i = 0; $i < $file_url_size; $i++) {
                 if (!empty($file_urls[$i])) {
                     // Find type and file URL
                     if (0 === strpos($file_urls[$i], 'http')) {
                         $file_is = 'absolute';
                         $file_url = esc_url_raw($file_urls[$i]);
                     } elseif ('[' === substr($file_urls[$i], 0, 1) && ']' === substr($file_urls[$i], -1)) {
                         $file_is = 'shortcode';
                         $file_url = wc_clean($file_urls[$i]);
                     } else {
                         $file_is = 'relative';
                         $file_url = wc_clean($file_urls[$i]);
                     }
                     $file_name = wc_clean($file_names[$i]);
                     $file_hash = md5($file_url);
                     // Validate the file extension
                     if (in_array($file_is, array('absolute', 'relative'))) {
                         $file_type = wp_check_filetype(strtok($file_url, '?'));
                         $parsed_url = parse_url($file_url, PHP_URL_PATH);
                         $extension = pathinfo($parsed_url, PATHINFO_EXTENSION);
                         if (!empty($extension) && !in_array($file_type['type'], $allowed_file_types)) {
                             WC_Admin_Meta_Boxes::add_error(sprintf(__('The downloadable file %s cannot be used as it does not have an allowed file type. Allowed types include: %s', 'woocommerce'), '<code>' . basename($file_url) . '</code>', '<code>' . implode(', ', array_keys($allowed_file_types)) . '</code>'));
                             continue;
                         }
                     }
                     // Validate the file exists
                     if ('relative' === $file_is) {
                         $_file_url = $file_url;
                         if ('..' === substr($file_url, 0, 2) || '/' !== substr($file_url, 0, 1)) {
                             $_file_url = realpath(ABSPATH . $file_url);
                         }
                         if (!apply_filters('woocommerce_downloadable_file_exists', file_exists($_file_url), $file_url)) {
                             WC_Admin_Meta_Boxes::add_error(sprintf(__('The downloadable file %s cannot be used as it does not exist on the server.', 'woocommerce'), '<code>' . $file_url . '</code>'));
                             continue;
                         }
                     }
                     $files[$file_hash] = array('name' => $file_name, 'file' => $file_url);
                 }
             }
         }
         // grant permission to any newly added files on any existing orders for this product prior to saving
         do_action('woocommerce_process_product_file_download_paths', $post_id, 0, $files);
         update_post_meta($post_id, '_downloadable_files', $files);
         update_post_meta($post_id, '_download_limit', $_download_limit);
         update_post_meta($post_id, '_download_expiry', $_download_expiry);
         if (isset($_POST['_download_type'])) {
             update_post_meta($post_id, '_download_type', wc_clean($_POST['_download_type']));
         }
     }
     // Product url
     if ('external' == $product_type) {
         if (isset($_POST['_product_url'])) {
             update_post_meta($post_id, '_product_url', esc_url_raw($_POST['_product_url']));
         }
         if (isset($_POST['_button_text'])) {
             update_post_meta($post_id, '_button_text', wc_clean($_POST['_button_text']));
         }
     }
     // Save variations
     if ('variable' == $product_type) {
         // Deprecated since WooCommerce 2.4.0 in favor to WC_AJAX::save_variations()
         // self::save_variations( $post_id, $post );
         // Update parent if variable so price sorting works and stays in sync with the cheapest child
         WC_Product_Variable::sync($post_id);
     }
     // Update version after saving
     update_post_meta($post_id, '_product_version', WC_VERSION);
     // Do action for product type
     do_action('woocommerce_process_product_meta_' . $product_type, $post_id);
     // Clear cache/transients
     wc_delete_product_transients($post_id);
 }
 /**
  *
  */
 public function trs2_clear_transients()
 {
     global $woocommerce;
     if (is_checkout()) {
         wc_delete_product_transients();
     }
 }
 /**
  * Link all variations via ajax function
  */
 public function link_all_variations()
 {
     if (!defined('WC_MAX_LINKED_VARIATIONS')) {
         define('WC_MAX_LINKED_VARIATIONS', 49);
     }
     check_ajax_referer('link-variations', 'security');
     @set_time_limit(0);
     $post_id = intval($_POST['post_id']);
     if (!$post_id) {
         die;
     }
     $variations = array();
     $_product = get_product($post_id, array('product_type' => 'variable'));
     // Put variation attributes into an array
     foreach ($_product->get_attributes() as $attribute) {
         if (!$attribute['is_variation']) {
             continue;
         }
         $attribute_field_name = 'attribute_' . sanitize_title($attribute['name']);
         if ($attribute['is_taxonomy']) {
             $options = wc_get_product_terms($post_id, $attribute['name'], array('fields' => 'slugs'));
         } else {
             $options = explode(WC_DELIMITER, $attribute['value']);
         }
         $options = array_map('sanitize_title', array_map('trim', $options));
         $variations[$attribute_field_name] = $options;
     }
     // Quit out if none were found
     if (sizeof($variations) == 0) {
         die;
     }
     // Get existing variations so we don't create duplicates
     $available_variations = array();
     foreach ($_product->get_children() as $child_id) {
         $child = $_product->get_child($child_id);
         if (!empty($child->variation_id)) {
             $available_variations[] = $child->get_variation_attributes();
         }
     }
     // Created posts will all have the following data
     $variation_post_data = array('post_title' => 'Product #' . $post_id . ' Variation', 'post_content' => '', 'post_status' => 'publish', 'post_author' => get_current_user_id(), 'post_parent' => $post_id, 'post_type' => 'product_variation');
     // Now find all combinations and create posts
     if (!function_exists('array_cartesian')) {
         /**
          * @param array $input
          * @return array
          */
         function array_cartesian($input)
         {
             $result = array();
             while (list($key, $values) = each($input)) {
                 // If a sub-array is empty, it doesn't affect the cartesian product
                 if (empty($values)) {
                     continue;
                 }
                 // Special case: seeding the product array with the values from the first sub-array
                 if (empty($result)) {
                     foreach ($values as $value) {
                         $result[] = array($key => $value);
                     }
                 } else {
                     // Second and subsequent input sub-arrays work like this:
                     //   1. In each existing array inside $product, add an item with
                     //      key == $key and value == first item in input sub-array
                     //   2. Then, for each remaining item in current input sub-array,
                     //      add a copy of each existing array inside $product with
                     //      key == $key and value == first item in current input sub-array
                     // Store all items to be added to $product here; adding them on the spot
                     // inside the foreach will result in an infinite loop
                     $append = array();
                     foreach ($result as &$product) {
                         // Do step 1 above. array_shift is not the most efficient, but it
                         // allows us to iterate over the rest of the items with a simple
                         // foreach, making the code short and familiar.
                         $product[$key] = array_shift($values);
                         // $product is by reference (that's why the key we added above
                         // will appear in the end result), so make a copy of it here
                         $copy = $product;
                         // Do step 2 above.
                         foreach ($values as $item) {
                             $copy[$key] = $item;
                             $append[] = $copy;
                         }
                         // Undo the side effecst of array_shift
                         array_unshift($values, $product[$key]);
                     }
                     // Out of the foreach, we can add to $results now
                     $result = array_merge($result, $append);
                 }
             }
             return $result;
         }
     }
     $variation_ids = array();
     $added = 0;
     $possible_variations = array_cartesian($variations);
     foreach ($possible_variations as $variation) {
         // Check if variation already exists
         if (in_array($variation, $available_variations)) {
             continue;
         }
         $variation_id = wp_insert_post($variation_post_data);
         $variation_ids[] = $variation_id;
         foreach ($variation as $key => $value) {
             update_post_meta($variation_id, $key, $value);
         }
         $added++;
         do_action('product_variation_linked', $variation_id);
         if ($added > WC_MAX_LINKED_VARIATIONS) {
             break;
         }
     }
     wc_delete_product_transients($post_id);
     echo $added;
     die;
 }
 /**
  * Update one or more products.
  *
  * ## OPTIONS
  *
  * <id>
  * : Product ID
  *
  * --<field>=<value>
  * : One or more fields to update.
  *
  * ## AVAILABLE_FIELDS
  *
  * For more fields, see: wp wc product create --help
  *
  * ## EXAMPLES
  *
  *     wp wc product update 123 --title="New Product Title" --description="New description"
  *
  * @since 2.5.0
  */
 public function update($args, $assoc_args)
 {
     try {
         $id = $args[0];
         $data = apply_filters('woocommerce_cli_update_product_data', $this->unflatten_array($assoc_args));
         // Product title.
         if (isset($data['title'])) {
             wp_update_post(array('ID' => $id, 'post_title' => wc_clean($data['title'])));
         }
         // Product name (slug).
         if (isset($data['name'])) {
             wp_update_post(array('ID' => $id, 'post_name' => sanitize_title($data['name'])));
         }
         // Product status.
         if (isset($data['status'])) {
             wp_update_post(array('ID' => $id, 'post_status' => wc_clean($data['status'])));
         }
         // Product short description.
         if (isset($data['short_description'])) {
             // Enable short description html tags.
             $post_excerpt = isset($data['enable_html_short_description']) && true === $data['enable_html_short_description'] ? $data['short_description'] : wc_clean($data['short_description']);
             wp_update_post(array('ID' => $id, 'post_excerpt' => $post_excerpt));
         }
         // Product description.
         if (isset($data['description'])) {
             // Enable description html tags.
             $post_content = isset($data['enable_html_description']) && true === $data['enable_html_description'] ? $data['description'] : wc_clean($data['description']);
             wp_update_post(array('ID' => $id, 'post_content' => $post_content));
         }
         // Validate the product type
         if (isset($data['type']) && !in_array(wc_clean($data['type']), array_keys(wc_get_product_types()))) {
             throw new WC_CLI_Exception('woocommerce_cli_invalid_product_type', sprintf(__('Invalid product type - the product type must be any of these: %s', 'woocommerce'), implode(', ', array_keys(wc_get_product_types()))));
         }
         // Check for featured/gallery images, upload it and set it
         if (isset($data['images'])) {
             $this->save_product_images($id, $data['images']);
         }
         // Save product meta fields
         $this->save_product_meta($id, $data);
         // Save variations
         if (isset($data['type']) && 'variable' == $data['type'] && isset($data['variations']) && is_array($data['variations'])) {
             $this->save_variations($id, $data);
         }
         do_action('woocommerce_cli_update_product', $id, $data);
         // Clear cache/transients
         wc_delete_product_transients($id);
         WP_CLI::success("Updated product {$id}.");
     } catch (WC_CLI_Exception $e) {
         WP_CLI::error($e->getMessage());
     }
 }
 /**
  * Delete a product.
  *
  * @since 2.2
  * @param int $id the product ID.
  * @param bool $force true to permanently delete order, false to move to trash.
  * @return array
  */
 public function delete_product($id, $force = false)
 {
     $id = $this->validate_request($id, 'product', 'delete');
     if (is_wp_error($id)) {
         return $id;
     }
     do_action('woocommerce_api_delete_product', $id, $this);
     // If we're forcing, then delete permanently.
     if ($force) {
         $child_product_variations = get_children('post_parent=' . $id . '&post_type=product_variation');
         if (!empty($child_product_variations)) {
             foreach ($child_product_variations as $child) {
                 wp_delete_post($child->ID, true);
             }
         }
         $child_products = get_children('post_parent=' . $id . '&post_type=product');
         if (!empty($child_products)) {
             foreach ($child_products as $child) {
                 $child_post = array();
                 $child_post['ID'] = $child->ID;
                 $child_post['post_parent'] = 0;
                 wp_update_post($child_post);
             }
         }
         $result = wp_delete_post($id, true);
     } else {
         $result = wp_trash_post($id);
     }
     if (!$result) {
         return new WP_Error('woocommerce_api_cannot_delete_product', sprintf(__('This %s cannot be deleted', 'woocommerce'), 'product'), array('status' => 500));
     }
     // Delete parent product transients.
     if ($parent_id = wp_get_post_parent_id($id)) {
         wc_delete_product_transients($parent_id);
     }
     if ($force) {
         return array('message' => sprintf(__('Permanently deleted %s', 'woocommerce'), 'product'));
     } else {
         $this->server->send_status('202');
         return array('message' => sprintf(__('Deleted %s', 'woocommerce'), 'product'));
     }
 }
 public function save()
 {
     //save the post
     $this->body = apply_filters('woocsv_product_before_body', $this->body, $this->new);
     $this->meta = apply_filters('woocsv_product_before_meta', $this->meta, $this->new);
     $post_id = wp_insert_post($this->body);
     $this->body['ID'] = $post_id;
     do_action('woocsv_before_save', $this);
     do_action('woocsv_product_after_body_save');
     // fixed bug with if condition
     wp_set_object_terms($post_id, $this->product_type, 'product_type', false);
     do_action('woocsv_product_before_meta_save');
     //save the meta
     foreach ($this->meta as $key => $value) {
         update_post_meta($post_id, $key, $value);
     }
     do_action('woocsv_product_before_tags_save');
     //save tags
     if ($this->tags) {
         $this->saveTags($post_id);
     }
     do_action('woocsv_product_before_categorie_save');
     //save categories
     if (!empty($this->categories)) {
         $this->saveCategories($post_id);
     }
     do_action('woocsv_product_before_images_save');
     /* !--deprecated */
     if ($this->images) {
         $this->saveImages($post_id);
     }
     // added empty() else it overrrides the above function)
     if (!empty($this->featuredImage)) {
         $this->saveFeaturedImage();
     }
     if (!empty($this->productGallery)) {
         $this->saveProductGallery();
     }
     do_action('woocsv_product_before_shipping_save');
     if ($this->shippingClass) {
         $this->saveShippingClass();
     }
     do_action('woocsv_after_save', $this);
     /* !version 2.0.4 */
     if (function_exists('wc_delete_product_transients')) {
         wc_delete_product_transients($post_id);
     }
     //and return the ID
     return $post_id;
 }
Exemple #12
0
/**
 * Save the product data meta box.
 *
 * @access public
 * @param mixed $post_id
 * @return void
 */
function dokan_process_product_meta($post_id)
{
    global $wpdb, $woocommerce, $woocommerce_errors;
    // Add any default post meta
    add_post_meta($post_id, 'total_sales', '0', true);
    // Get types
    $product_type = empty($_POST['_product_type']) ? 'simple' : sanitize_title(stripslashes($_POST['_product_type']));
    $is_downloadable = isset($_POST['_downloadable']) ? 'yes' : 'no';
    $is_virtual = isset($_POST['_virtual']) ? 'yes' : 'no';
    // Product type + Downloadable/Virtual
    wp_set_object_terms($post_id, $product_type, 'product_type');
    update_post_meta($post_id, '_downloadable', $is_downloadable);
    update_post_meta($post_id, '_virtual', $is_virtual);
    // Gallery Images
    $attachment_ids = array_filter(explode(',', woocommerce_clean($_POST['product_image_gallery'])));
    update_post_meta($post_id, '_product_image_gallery', implode(',', $attachment_ids));
    // Update post meta
    update_post_meta($post_id, '_regular_price', stripslashes($_POST['_regular_price']));
    update_post_meta($post_id, '_sale_price', stripslashes($_POST['_sale_price']));
    if (isset($_POST['_tax_status'])) {
        update_post_meta($post_id, '_tax_status', stripslashes($_POST['_tax_status']));
    }
    if (isset($_POST['_tax_class'])) {
        update_post_meta($post_id, '_tax_class', stripslashes($_POST['_tax_class']));
    }
    update_post_meta($post_id, '_visibility', stripslashes($_POST['_visibility']));
    update_post_meta($post_id, '_purchase_note', stripslashes($_POST['_purchase_note']));
    // Dimensions
    if ($is_virtual == 'no') {
        update_post_meta($post_id, '_weight', stripslashes($_POST['_weight']));
        update_post_meta($post_id, '_length', stripslashes($_POST['_length']));
        update_post_meta($post_id, '_width', stripslashes($_POST['_width']));
        update_post_meta($post_id, '_height', stripslashes($_POST['_height']));
    } else {
        update_post_meta($post_id, '_weight', '');
        update_post_meta($post_id, '_length', '');
        update_post_meta($post_id, '_width', '');
        update_post_meta($post_id, '_height', '');
    }
    //For pin code
    if ($_POST['sell_in'] == 'all') {
        $sell_in = $_POST['sell_in'];
    } elseif ($_POST['sell_in'] == 'state') {
        $sell_in = $_POST['sell_in'];
        foreach ($_POST['states_state'] as $p_states) {
            $p_state .= '"' . $p_states . '",';
        }
        $p_state = rtrim($p_state, ',');
    } elseif ($_POST['sell_in'] == 'city') {
        $sell_in = $_POST['sell_in'];
        $p_state = '"' . $_POST['cities_state'] . '"';
        foreach ($_POST['cities_city'] as $p_cities) {
            $p_city .= '"' . $p_cities . '",';
        }
        $p_city = rtrim($p_city, ',');
    }
    if ($_POST['enable_cod'] == 'Y') {
        $cod = $_POST['enable_cod'];
    } else {
        $cod = 'N';
    }
    $sell = array('cod' => $cod, 'sell_in' => $sell_in, 'state' => $p_state, 'city' => $p_city);
    update_post_meta($post_id, 'sell_in', $sell);
    // Shipping Type
    update_post_meta($post_id, '_shipping_type', stripslashes($_POST['_shipping_type']));
    update_post_meta($post_id, '_flat_shipping_cost', stripslashes($_POST['_flat_shipping_cost']));
    // Save shipping class
    $product_shipping_class = $_POST['product_shipping_class'] > 0 && $product_type != 'external' ? absint($_POST['product_shipping_class']) : '';
    wp_set_object_terms($post_id, $product_shipping_class, 'product_shipping_class');
    // Unique SKU
    $sku = get_post_meta($post_id, '_sku', true);
    $new_sku = woocommerce_clean(stripslashes($_POST['_sku']));
    if ($new_sku == '') {
        update_post_meta($post_id, '_sku', '');
    } elseif ($new_sku !== $sku) {
        if (!empty($new_sku)) {
            if ($wpdb->get_var($wpdb->prepare("\n                    SELECT {$wpdb->posts}.ID\n                    FROM {$wpdb->posts}\n                    LEFT JOIN {$wpdb->postmeta} ON ({$wpdb->posts}.ID = {$wpdb->postmeta}.post_id)\n                    WHERE {$wpdb->posts}.post_type = 'product'\n                    AND {$wpdb->posts}.post_status = 'publish'\n                    AND {$wpdb->postmeta}.meta_key = '_sku' AND {$wpdb->postmeta}.meta_value = '%s'\n                 ", $new_sku))) {
                $woocommerce_errors[] = __('Product SKU must be unique.', 'woocommerce');
            } else {
                update_post_meta($post_id, '_sku', $new_sku);
            }
        } else {
            update_post_meta($post_id, '_sku', '');
        }
    }
    // Save Attributes
    $attributes = array();
    if (isset($_POST['attribute_names'])) {
        $attribute_names = $_POST['attribute_names'];
        $attribute_values = $_POST['attribute_values'];
        if (isset($_POST['attribute_visibility'])) {
            $attribute_visibility = $_POST['attribute_visibility'];
        }
        if (isset($_POST['attribute_variation'])) {
            $attribute_variation = $_POST['attribute_variation'];
        }
        $attribute_is_taxonomy = $_POST['attribute_is_taxonomy'];
        $attribute_position = $_POST['attribute_position'];
        $attribute_names_count = sizeof($attribute_names);
        for ($i = 0; $i < $attribute_names_count; $i++) {
            if (!$attribute_names[$i]) {
                continue;
            }
            $is_visible = isset($attribute_visibility[$i]) ? 1 : 0;
            $is_variation = isset($attribute_variation[$i]) ? 1 : 0;
            $is_taxonomy = $attribute_is_taxonomy[$i] ? 1 : 0;
            if ($is_taxonomy) {
                if (isset($attribute_values[$i])) {
                    // Select based attributes - Format values (posted values are slugs)
                    if (is_array($attribute_values[$i])) {
                        $values = array_map('sanitize_title', $attribute_values[$i]);
                        // Text based attributes - Posted values are term names - don't change to slugs
                    } else {
                        $values = array_map('stripslashes', array_map('strip_tags', explode('|', $attribute_values[$i])));
                    }
                    // Remove empty items in the array
                    $values = array_filter($values, 'strlen');
                } else {
                    $values = array();
                }
                // Update post terms
                if (taxonomy_exists($attribute_names[$i])) {
                    wp_set_object_terms($post_id, $values, $attribute_names[$i]);
                }
                if ($values) {
                    // Add attribute to array, but don't set values
                    $attributes[sanitize_title($attribute_names[$i])] = array('name' => woocommerce_clean($attribute_names[$i]), 'value' => '', 'position' => $attribute_position[$i], 'is_visible' => $is_visible, 'is_variation' => $is_variation, 'is_taxonomy' => $is_taxonomy);
                }
            } elseif (isset($attribute_values[$i])) {
                // Text based, separate by pipe
                $values = implode(' | ', array_map('woocommerce_clean', $attribute_values[$i]));
                // Custom attribute - Add attribute to array and set the values
                $attributes[sanitize_title($attribute_names[$i])] = array('name' => woocommerce_clean($attribute_names[$i]), 'value' => $values, 'position' => $attribute_position[$i], 'is_visible' => $is_visible, 'is_variation' => $is_variation, 'is_taxonomy' => $is_taxonomy);
            }
        }
    }
    if (!function_exists('attributes_cmp')) {
        function attributes_cmp($a, $b)
        {
            if ($a['position'] == $b['position']) {
                return 0;
            }
            return $a['position'] < $b['position'] ? -1 : 1;
        }
    }
    uasort($attributes, 'attributes_cmp');
    update_post_meta($post_id, '_product_attributes', $attributes);
    // Sales and prices
    if (in_array($product_type, array('variable'))) {
        // Variable products have no prices
        update_post_meta($post_id, '_regular_price', '');
        update_post_meta($post_id, '_sale_price', '');
        update_post_meta($post_id, '_sale_price_dates_from', '');
        update_post_meta($post_id, '_sale_price_dates_to', '');
        update_post_meta($post_id, '_price', '');
    } else {
        $date_from = isset($_POST['_sale_price_dates_from']) ? $_POST['_sale_price_dates_from'] : '';
        $date_to = isset($_POST['_sale_price_dates_to']) ? $_POST['_sale_price_dates_to'] : '';
        // Dates
        if ($date_from) {
            update_post_meta($post_id, '_sale_price_dates_from', strtotime($date_from));
        } else {
            update_post_meta($post_id, '_sale_price_dates_from', '');
        }
        if ($date_to) {
            update_post_meta($post_id, '_sale_price_dates_to', strtotime($date_to));
        } else {
            update_post_meta($post_id, '_sale_price_dates_to', '');
        }
        if ($date_to && !$date_from) {
            update_post_meta($post_id, '_sale_price_dates_from', strtotime('NOW', current_time('timestamp')));
        }
        // Update price if on sale
        if ($_POST['_sale_price'] != '' && $date_to == '' && $date_from == '') {
            update_post_meta($post_id, '_price', stripslashes($_POST['_sale_price']));
        } else {
            update_post_meta($post_id, '_price', stripslashes($_POST['_regular_price']));
        }
        if ($_POST['_sale_price'] != '' && $date_from && strtotime($date_from) < strtotime('NOW', current_time('timestamp'))) {
            update_post_meta($post_id, '_price', stripslashes($_POST['_sale_price']));
        }
        if ($date_to && strtotime($date_to) < strtotime('NOW', current_time('timestamp'))) {
            update_post_meta($post_id, '_price', stripslashes($_POST['_regular_price']));
            update_post_meta($post_id, '_sale_price_dates_from', '');
            update_post_meta($post_id, '_sale_price_dates_to', '');
        }
    }
    // Sold Individuall
    if (!empty($_POST['_sold_individually'])) {
        update_post_meta($post_id, '_sold_individually', 'yes');
    } else {
        update_post_meta($post_id, '_sold_individually', '');
    }
    // Stock Data
    if (get_option('woocommerce_manage_stock') == 'yes') {
        if (!empty($_POST['_manage_stock'])) {
            // Manage stock
            update_post_meta($post_id, '_stock', (int) $_POST['_stock']);
            update_post_meta($post_id, '_stock_status', stripslashes($_POST['_stock_status']));
            update_post_meta($post_id, '_backorders', stripslashes($_POST['_backorders']));
            update_post_meta($post_id, '_manage_stock', 'yes');
            // Check stock level
            if ($product_type !== 'variable' && $_POST['_backorders'] == 'no' && (int) $_POST['_stock'] < 1) {
                update_post_meta($post_id, '_stock_status', 'outofstock');
            }
        } else {
            // Don't manage stock
            update_post_meta($post_id, '_stock', '');
            update_post_meta($post_id, '_stock_status', stripslashes($_POST['_stock_status']));
            update_post_meta($post_id, '_backorders', stripslashes($_POST['_backorders']));
            update_post_meta($post_id, '_manage_stock', 'no');
        }
    } else {
        update_post_meta($post_id, '_stock_status', stripslashes($_POST['_stock_status']));
    }
    // Upsells
    if (isset($_POST['upsell_ids'])) {
        $upsells = array();
        $ids = $_POST['upsell_ids'];
        foreach ($ids as $id) {
            if ($id && $id > 0) {
                $upsells[] = $id;
            }
        }
        update_post_meta($post_id, '_upsell_ids', $upsells);
    } else {
        delete_post_meta($post_id, '_upsell_ids');
    }
    // Cross sells
    if (isset($_POST['crosssell_ids'])) {
        $crosssells = array();
        $ids = $_POST['crosssell_ids'];
        foreach ($ids as $id) {
            if ($id && $id > 0) {
                $crosssells[] = $id;
            }
        }
        update_post_meta($post_id, '_crosssell_ids', $crosssells);
    } else {
        delete_post_meta($post_id, '_crosssell_ids');
    }
    // Downloadable options
    if ($is_downloadable == 'yes') {
        $_download_limit = absint($_POST['_download_limit']);
        if (!$_download_limit) {
            $_download_limit = '';
        }
        // 0 or blank = unlimited
        $_download_expiry = absint($_POST['_download_expiry']);
        if (!$_download_expiry) {
            $_download_expiry = '';
        }
        // 0 or blank = unlimited
        // file paths will be stored in an array keyed off md5(file path)
        if (isset($_POST['_wc_file_urls'])) {
            $files = array();
            $file_names = isset($_POST['_wc_file_names']) ? array_map('wc_clean', $_POST['_wc_file_names']) : array();
            $file_urls = isset($_POST['_wc_file_urls']) ? array_map('esc_url_raw', array_map('trim', $_POST['_wc_file_urls'])) : array();
            $file_url_size = sizeof($file_urls);
            for ($i = 0; $i < $file_url_size; $i++) {
                if (!empty($file_urls[$i])) {
                    $files[md5($file_urls[$i])] = array('name' => $file_names[$i], 'file' => $file_urls[$i]);
                }
            }
            // grant permission to any newly added files on any existing orders for this product prior to saving
            do_action('woocommerce_process_product_file_download_paths', $post_id, 0, $files);
            update_post_meta($post_id, '_downloadable_files', $files);
        }
        update_post_meta($post_id, '_download_limit', $_download_limit);
        update_post_meta($post_id, '_download_expiry', $_download_expiry);
        if (isset($_POST['_download_limit'])) {
            update_post_meta($post_id, '_download_limit', esc_attr($_download_limit));
        }
        if (isset($_POST['_download_expiry'])) {
            update_post_meta($post_id, '_download_expiry', esc_attr($_download_expiry));
        }
    }
    // Save variations
    if ($product_type == 'variable') {
        dokan_save_variations($post_id);
    }
    // Do action for product type
    do_action('woocommerce_process_product_meta_' . $product_type, $post_id);
    do_action('dokan_process_product_meta', $post_id);
    // Clear cache/transients
    wc_delete_product_transients($post_id);
}
 /**
  * Actually executes a a tool.
  *
  * @param  string $tool
  * @return array
  */
 public function execute_tool($tool)
 {
     global $wpdb;
     $ran = true;
     switch ($tool) {
         case 'clear_transients':
             wc_delete_product_transients();
             wc_delete_shop_order_transients();
             WC_Cache_Helper::get_transient_version('shipping', true);
             $message = __('Product Transients Cleared', 'woocommerce');
             break;
         case 'clear_expired_transients':
             /*
              * Deletes all expired transients. The multi-table delete syntax is used.
              * to delete the transient record from table a, and the corresponding.
              * transient_timeout record from table b.
              *
              * Based on code inside core's upgrade_network() function.
              */
             $sql = "DELETE a, b FROM {$wpdb->options} a, {$wpdb->options} b\n\t\t\t\t\tWHERE a.option_name LIKE %s\n\t\t\t\t\tAND a.option_name NOT LIKE %s\n\t\t\t\t\tAND b.option_name = CONCAT( '_transient_timeout_', SUBSTRING( a.option_name, 12 ) )\n\t\t\t\t\tAND b.option_value < %d";
             $rows = $wpdb->query($wpdb->prepare($sql, $wpdb->esc_like('_transient_') . '%', $wpdb->esc_like('_transient_timeout_') . '%', time()));
             $sql = "DELETE a, b FROM {$wpdb->options} a, {$wpdb->options} b\n\t\t\t\t\tWHERE a.option_name LIKE %s\n\t\t\t\t\tAND a.option_name NOT LIKE %s\n\t\t\t\t\tAND b.option_name = CONCAT( '_site_transient_timeout_', SUBSTRING( a.option_name, 17 ) )\n\t\t\t\t\tAND b.option_value < %d";
             $rows2 = $wpdb->query($wpdb->prepare($sql, $wpdb->esc_like('_site_transient_') . '%', $wpdb->esc_like('_site_transient_timeout_') . '%', time()));
             $message = sprintf(__('%d Transients Rows Cleared', 'woocommerce'), $rows + $rows2);
             break;
         case 'reset_roles':
             // Remove then re-add caps and roles
             WC_Install::remove_roles();
             WC_Install::create_roles();
             $message = __('Roles successfully reset', 'woocommerce');
             break;
         case 'recount_terms':
             $product_cats = get_terms('product_cat', array('hide_empty' => false, 'fields' => 'id=>parent'));
             _wc_term_recount($product_cats, get_taxonomy('product_cat'), true, false);
             $product_tags = get_terms('product_tag', array('hide_empty' => false, 'fields' => 'id=>parent'));
             _wc_term_recount($product_tags, get_taxonomy('product_tag'), true, false);
             $message = __('Terms successfully recounted', 'woocommerce');
             break;
         case 'clear_sessions':
             $wpdb->query("TRUNCATE {$wpdb->prefix}woocommerce_sessions");
             wp_cache_flush();
             $message = __('Sessions successfully cleared', 'woocommerce');
             break;
         case 'install_pages':
             WC_Install::create_pages();
             return __('All missing WooCommerce pages was installed successfully.', 'woocommerce');
             break;
         case 'delete_taxes':
             $wpdb->query("TRUNCATE TABLE {$wpdb->prefix}woocommerce_tax_rates;");
             $wpdb->query("TRUNCATE TABLE {$wpdb->prefix}woocommerce_tax_rate_locations;");
             WC_Cache_Helper::incr_cache_prefix('taxes');
             $message = __('Tax rates successfully deleted', 'woocommerce');
             break;
         case 'reset_tracking':
             delete_option('woocommerce_allow_tracking');
             WC_Admin_Notices::add_notice('tracking');
             $message = __('Usage tracking settings successfully reset.', 'woocommerce');
             break;
         default:
             $tools = $this->get_tools();
             if (isset($tools[$tool]['callback'])) {
                 $callback = $tools[$tool]['callback'];
                 $return = call_user_func($callback);
                 if ($return === false) {
                     $callback_string = is_array($callback) ? get_class($callback[0]) . '::' . $callback[1] : $callback;
                     $ran = false;
                     $message = sprintf(__('There was an error calling %s', 'woocommerce'), $callback_string);
                 } else {
                     $message = __('Tool ran.', 'woocommerce');
                 }
             } else {
                 $ran = false;
                 $message = __('There was an error calling this tool. There is no callback present.', 'woocommerce');
             }
             break;
     }
     return array('success' => $ran, 'message' => $message);
 }
 /**
  * Fetches inventory from fortnox and updates WooCommerce inventory
  *
  * @return string
  */
 public function run_inventory_cron_job()
 {
     include_once "class-fortnox3-api.php";
     $options = get_option('woocommerce_fortnox_general_settings');
     if (!isset($options['activate-fortnox-products-sync'])) {
         return;
     }
     //Init API
     $apiInterface = new WCF_API();
     if (!$apiInterface->create_api_validation_request()) {
         return $this->ERROR_API_KEY;
     }
     if ($apiInterface->has_error) {
         return $this->ERROR_LOGIN;
     }
     //fetch all articles
     $articles = $apiInterface->get_inventory();
     $pf = new WC_Product_Factory();
     $product = null;
     include_once "class-fortnox3-product-xml.php";
     foreach ($articles as $article) {
         //Query DB for id by SKU
         $args = array('post_type' => array('product', 'product_variation'), 'orderby' => 'id', 'meta_key' => '_sku', 'meta_value' => $article['ArticleNumber']);
         $query = new WP_Query($args);
         if ($query->post_count == 1) {
             $product = $pf->get_product($query->posts[0]->ID);
         } else {
             $article = null;
             continue;
         }
         if (!$product || null === $product) {
             $product = null;
             $article = null;
             continue;
         }
         if ($product instanceof WC_Product_Variation) {
             if ($product->parent == '') {
                 $product = null;
                 $article = null;
                 continue;
             }
         }
         if ($product instanceof WC_Product_Variable) {
             $this->update_product_inventory($product, null);
         } else {
             $this->update_product_inventory($product, $article['QuantityInStock']);
         }
         wc_delete_product_transients($product->id);
         $product = null;
     }
     $articles = null;
     return "Lager uppdaterat";
 }
 /**
  * Quick and bulk edit saving
  *
  * @access public
  * @param int $post_id
  * @param WP_Post $post
  * @return int
  */
 public function bulk_and_quick_edit_save_post($post_id, $post)
 {
     // If this is an autosave, our form has not been submitted, so we don't want to do anything.
     if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
         return $post_id;
     }
     // Don't save revisions and autosaves
     if (wp_is_post_revision($post_id) || wp_is_post_autosave($post_id)) {
         return $post_id;
     }
     // Check post type is product
     if ($post->post_type != 'product') {
         return $post_id;
     }
     // Check user permission
     if (!current_user_can('edit_post', $post_id)) {
         return $post_id;
     }
     // Check nonces
     if (!isset($_REQUEST['woocommerce_quick_edit_nonce']) && !isset($_REQUEST['woocommerce_bulk_edit_nonce'])) {
         return $post_id;
     }
     if (isset($_REQUEST['woocommerce_quick_edit_nonce']) && !wp_verify_nonce($_REQUEST['woocommerce_quick_edit_nonce'], 'woocommerce_quick_edit_nonce')) {
         return $post_id;
     }
     if (isset($_REQUEST['woocommerce_bulk_edit_nonce']) && !wp_verify_nonce($_REQUEST['woocommerce_bulk_edit_nonce'], 'woocommerce_bulk_edit_nonce')) {
         return $post_id;
     }
     // Get the product and save
     $product = get_product($post);
     if (!empty($_REQUEST['woocommerce_quick_edit'])) {
         $this->quick_edit_save($post_id, $product);
     } else {
         $this->bulk_edit_save($post_id, $product);
     }
     // Clear transient
     wc_delete_product_transients($post_id);
     return $post_id;
 }
Exemple #16
0
/**
 * Save the product data meta box.
 *
 * @access public
 * @param mixed $post_id
 * @return void
 */
function dokan_process_product_meta($post_id)
{
    global $wpdb, $woocommerce, $woocommerce_errors;
    // Add any default post meta
    add_post_meta($post_id, 'total_sales', '0', true);
    // Get types
    $product_type = 'simple';
    $is_downloadable = isset($_POST['_downloadable']) ? 'yes' : 'no';
    $is_virtual = isset($_POST['_virtual']) ? 'yes' : 'no';
    // Product type + Downloadable/Virtual
    wp_set_object_terms($post_id, $product_type, 'product_type');
    update_post_meta($post_id, '_downloadable', $is_downloadable);
    update_post_meta($post_id, '_virtual', $is_virtual);
    // Gallery Images
    $attachment_ids = array_filter(explode(',', woocommerce_clean($_POST['product_image_gallery'])));
    update_post_meta($post_id, '_product_image_gallery', implode(',', $attachment_ids));
    // Update post meta
    if (isset($_POST['_regular_price'])) {
        update_post_meta($post_id, '_regular_price', $_POST['_regular_price'] === '' ? '' : wc_format_decimal($_POST['_regular_price']));
    }
    if (isset($_POST['_sale_price'])) {
        update_post_meta($post_id, '_sale_price', $_POST['_sale_price'] === '' ? '' : wc_format_decimal($_POST['_sale_price']));
    }
    if (isset($_POST['_tax_status'])) {
        update_post_meta($post_id, '_tax_status', stripslashes($_POST['_tax_status']));
    }
    if (isset($_POST['_tax_class'])) {
        update_post_meta($post_id, '_tax_class', stripslashes($_POST['_tax_class']));
    }
    update_post_meta($post_id, '_visibility', stripslashes($_POST['_visibility']));
    // Unique SKU
    $sku = get_post_meta($post_id, '_sku', true);
    $new_sku = woocommerce_clean(stripslashes($_POST['_sku']));
    if ($new_sku == '') {
        update_post_meta($post_id, '_sku', '');
    } elseif ($new_sku !== $sku) {
        if (!empty($new_sku)) {
            if ($wpdb->get_var($wpdb->prepare("\n                    SELECT {$wpdb->posts}.ID\n                    FROM {$wpdb->posts}\n                    LEFT JOIN {$wpdb->postmeta} ON ({$wpdb->posts}.ID = {$wpdb->postmeta}.post_id)\n                    WHERE {$wpdb->posts}.post_type = 'product'\n                    AND {$wpdb->posts}.post_status = 'publish'\n                    AND {$wpdb->postmeta}.meta_key = '_sku' AND {$wpdb->postmeta}.meta_value = '%s'\n                 ", $new_sku))) {
                $woocommerce_errors[] = __('Product SKU must be unique.', 'woocommerce');
            } else {
                update_post_meta($post_id, '_sku', $new_sku);
            }
        } else {
            update_post_meta($post_id, '_sku', '');
        }
    }
    // Sales and prices
    $date_from = isset($_POST['_sale_price_dates_from']) ? $_POST['_sale_price_dates_from'] : '';
    $date_to = isset($_POST['_sale_price_dates_to']) ? $_POST['_sale_price_dates_to'] : '';
    // Dates
    if ($date_from) {
        update_post_meta($post_id, '_sale_price_dates_from', strtotime($date_from));
    } else {
        update_post_meta($post_id, '_sale_price_dates_from', '');
    }
    if ($date_to) {
        update_post_meta($post_id, '_sale_price_dates_to', strtotime($date_to));
    } else {
        update_post_meta($post_id, '_sale_price_dates_to', '');
    }
    if ($date_to && !$date_from) {
        update_post_meta($post_id, '_sale_price_dates_from', strtotime('NOW', current_time('timestamp')));
    }
    // Update price if on sale
    if ('' !== $_POST['_sale_price'] && '' == $date_to && '' == $date_from) {
        update_post_meta($post_id, '_price', wc_format_decimal($_POST['_sale_price']));
    } else {
        update_post_meta($post_id, '_price', $_POST['_regular_price'] === '' ? '' : wc_format_decimal($_POST['_regular_price']));
    }
    if ('' !== $_POST['_sale_price'] && $date_from && strtotime($date_from) < strtotime('NOW', current_time('timestamp'))) {
        update_post_meta($post_id, '_price', wc_format_decimal($_POST['_sale_price']));
    }
    if ($date_to && strtotime($date_to) < strtotime('NOW', current_time('timestamp'))) {
        update_post_meta($post_id, '_price', $_POST['_regular_price'] === '' ? '' : wc_format_decimal($_POST['_regular_price']));
        update_post_meta($post_id, '_sale_price_dates_from', '');
        update_post_meta($post_id, '_sale_price_dates_to', '');
    }
    // reset price is discounted checkbox was not checked
    if (!isset($_POST['_discounted_price'])) {
        update_post_meta($post_id, '_price', wc_format_decimal($_POST['_regular_price']));
        update_post_meta($post_id, '_regular_price', wc_format_decimal($_POST['_regular_price']));
        update_post_meta($post_id, '_sale_price', '');
    }
    // Sold Individuall
    if (isset($_POST['_sold_individually'])) {
        update_post_meta($post_id, '_sold_individually', 'yes');
    } else {
        update_post_meta($post_id, '_sold_individually', '');
    }
    // Stock Data
    if (get_option('woocommerce_manage_stock') == 'yes') {
        if (!empty($_POST['_manage_stock'])) {
            // Manage stock
            update_post_meta($post_id, '_stock', (int) $_POST['_stock']);
            update_post_meta($post_id, '_stock_status', stripslashes($_POST['_stock_status']));
            update_post_meta($post_id, '_backorders', stripslashes($_POST['_backorders']));
            update_post_meta($post_id, '_manage_stock', 'yes');
            // Check stock level
            if ($product_type !== 'variable' && $_POST['_backorders'] == 'no' && (int) $_POST['_stock'] < 1) {
                update_post_meta($post_id, '_stock_status', 'outofstock');
            }
        } else {
            // Don't manage stock
            update_post_meta($post_id, '_stock', '');
            update_post_meta($post_id, '_stock_status', stripslashes($_POST['_stock_status']));
            update_post_meta($post_id, '_backorders', stripslashes($_POST['_backorders']));
            update_post_meta($post_id, '_manage_stock', 'no');
        }
    } else {
        update_post_meta($post_id, '_stock_status', stripslashes($_POST['_stock_status']));
    }
    // Upsells
    if (isset($_POST['upsell_ids'])) {
        $upsells = array();
        $ids = $_POST['upsell_ids'];
        foreach ($ids as $id) {
            if ($id && $id > 0) {
                $upsells[] = $id;
            }
        }
        update_post_meta($post_id, '_upsell_ids', $upsells);
    } else {
        delete_post_meta($post_id, '_upsell_ids');
    }
    // Cross sells
    if (isset($_POST['crosssell_ids'])) {
        $crosssells = array();
        $ids = $_POST['crosssell_ids'];
        foreach ($ids as $id) {
            if ($id && $id > 0) {
                $crosssells[] = $id;
            }
        }
        update_post_meta($post_id, '_crosssell_ids', $crosssells);
    } else {
        delete_post_meta($post_id, '_crosssell_ids');
    }
    // Downloadable options
    if ($is_downloadable == 'yes') {
        // file paths will be stored in an array keyed off md5(file path)
        if (isset($_POST['_wc_file_urls'])) {
            $files = array();
            $file_names = isset($_POST['_wc_file_names']) ? array_map('wc_clean', $_POST['_wc_file_names']) : array();
            $file_urls = isset($_POST['_wc_file_urls']) ? array_map('esc_url_raw', array_map('trim', $_POST['_wc_file_urls'])) : array();
            $file_url_size = sizeof($file_urls);
            for ($i = 0; $i < $file_url_size; $i++) {
                if (!empty($file_urls[$i])) {
                    $files[md5($file_urls[$i])] = array('name' => $file_names[$i], 'file' => $file_urls[$i]);
                }
            }
            // grant permission to any newly added files on any existing orders for this product prior to saving
            do_action('woocommerce_process_product_file_download_paths', $post_id, 0, $files);
            update_post_meta($post_id, '_downloadable_files', $files);
        }
    }
    // Do action for product type
    do_action('woocommerce_process_product_meta_simple', $post_id);
    do_action('dokan_process_product_meta', $post_id);
    // Clear cache/transients
    wc_delete_product_transients($post_id);
}
 /**
  * Removes variations etc belonging to a deleted post, and clears transients
  *
  * @param mixed $id ID of post being deleted
  */
 public function delete_post($id)
 {
     global $woocommerce, $wpdb;
     if (!current_user_can('delete_posts')) {
         return;
     }
     if ($id > 0) {
         $post_type = get_post_type($id);
         switch ($post_type) {
             case 'product':
                 $child_product_variations = get_children('post_parent=' . $id . '&post_type=product_variation');
                 if (!empty($child_product_variations)) {
                     foreach ($child_product_variations as $child) {
                         wp_delete_post($child->ID, true);
                     }
                 }
                 $child_products = get_children('post_parent=' . $id . '&post_type=product');
                 if (!empty($child_products)) {
                     foreach ($child_products as $child) {
                         $child_post = array();
                         $child_post['ID'] = $child->ID;
                         $child_post['post_parent'] = 0;
                         wp_update_post($child_post);
                     }
                 }
                 if ($parent_id = wp_get_post_parent_id($id)) {
                     wc_delete_product_transients($parent_id);
                 }
                 break;
             case 'product_variation':
                 wc_delete_product_transients(wp_get_post_parent_id($id));
                 break;
             case 'shop_order':
                 $refunds = $wpdb->get_results($wpdb->prepare("SELECT ID FROM {$wpdb->posts} WHERE post_type = 'shop_order_refund' AND post_parent = %d", $id));
                 if (!is_null($refunds)) {
                     foreach ($refunds as $refund) {
                         wp_delete_post($refund->ID, true);
                     }
                 }
                 break;
         }
     }
 }
/**
 * Clear all transients cache for product data.
 *
 * @param int $post_id (default: 0)
 */
function wc_delete_product_transients($post_id = 0)
{
    // Core transients
    $transients_to_clear = array('wc_products_onsale', 'wc_featured_products', 'wc_outofstock_count', 'wc_low_stock_count');
    // Transient names that include an ID
    $post_transient_names = array('wc_product_children_', 'wc_product_total_stock_', 'wc_var_prices_', 'wc_related_');
    if ($post_id > 0) {
        foreach ($post_transient_names as $transient) {
            $transients_to_clear[] = $transient . $post_id;
        }
        // Does this product have a parent?
        if ($parent_id = wp_get_post_parent_id($post_id)) {
            wc_delete_product_transients($parent_id);
        }
    }
    // Delete transients
    foreach ($transients_to_clear as $transient) {
        delete_transient($transient);
    }
    // Increments the transient version to invalidate cache
    WC_Cache_Helper::get_transient_version('product', true);
    do_action('woocommerce_delete_product_transients', $post_id);
}
 /**
  * Clear any caches.
  *
  * @param WC_Product
  * @since 2.7.0
  */
 protected function clear_caches(&$product)
 {
     wc_delete_product_transients($product->get_id());
     wp_cache_delete('product-' . $product->get_id(), 'products');
 }
 /**
  * Delete a single item.
  *
  * @param WP_REST_Request $request Full details about the request.
  * @return WP_REST_Response|WP_Error
  */
 public function delete_item($request)
 {
     $id = (int) $request['id'];
     $force = (bool) $request['force'];
     $post = get_post($id);
     $product = wc_get_product($id);
     if (!empty($post->post_type) && 'product_variation' === $post->post_type && 'product' === $this->post_type) {
         return new WP_Error("woocommerce_rest_invalid_{$this->post_type}_id", __('To manipulate product variations you should use the /products/&lt;product_id&gt;/variations/&lt;id&gt; endpoint.', 'woocommerce'), array('status' => 404));
     } elseif (empty($id) || empty($post->ID) || $post->post_type !== $this->post_type) {
         return new WP_Error("woocommerce_rest_{$this->post_type}_invalid_id", __('Invalid post ID.', 'woocommerce'), array('status' => 404));
     }
     $supports_trash = EMPTY_TRASH_DAYS > 0;
     /**
      * Filter whether an item is trashable.
      *
      * Return false to disable trash support for the item.
      *
      * @param boolean $supports_trash Whether the item type support trashing.
      * @param WP_Post $post           The Post object being considered for trashing support.
      */
     $supports_trash = apply_filters("woocommerce_rest_{$this->post_type}_trashable", $supports_trash, $post);
     if (!wc_rest_check_post_permissions($this->post_type, 'delete', $post->ID)) {
         /* translators: %s: post type */
         return new WP_Error("woocommerce_rest_user_cannot_delete_{$this->post_type}", sprintf(__('Sorry, you are not allowed to delete %s.', 'woocommerce'), $this->post_type), array('status' => rest_authorization_required_code()));
     }
     $request->set_param('context', 'edit');
     $response = $this->prepare_item_for_response($post, $request);
     // If we're forcing, then delete permanently.
     if ($force) {
         if ($product->is_type('variable')) {
             foreach ($product->get_children() as $child_id) {
                 $child = wc_get_product($child_id);
                 $child->delete(true);
             }
         } elseif ($product->is_type('grouped')) {
             foreach ($product->get_children() as $child_id) {
                 $child = wc_get_product($child_id);
                 $child->set_parent_id(0);
                 $child->save();
             }
         }
         $product->delete(true);
         $result = $product->get_id() > 0 ? false : true;
     } else {
         // If we don't support trashing for this type, error out.
         if (!$supports_trash) {
             /* translators: %s: post type */
             return new WP_Error('woocommerce_rest_trash_not_supported', sprintf(__('The %s does not support trashing.', 'woocommerce'), $this->post_type), array('status' => 501));
         }
         // Otherwise, only trash if we haven't already.
         if ('trash' === $post->post_status) {
             /* translators: %s: post type */
             return new WP_Error('woocommerce_rest_already_trashed', sprintf(__('The %s has already been deleted.', 'woocommerce'), $this->post_type), array('status' => 410));
         }
         // (Note that internally this falls through to `wp_delete_post` if
         // the trash is disabled.)
         $product->delete();
         $result = 'trash' === $product->get_status();
     }
     if (!$result) {
         /* translators: %s: post type */
         return new WP_Error('woocommerce_rest_cannot_delete', sprintf(__('The %s cannot be deleted.', 'woocommerce'), $this->post_type), array('status' => 500));
     }
     // Delete parent product transients.
     if ($parent_id = wp_get_post_parent_id($id)) {
         wc_delete_product_transients($parent_id);
     }
     /**
      * Fires after a single item is deleted or trashed via the REST API.
      *
      * @param object           $post     The deleted or trashed item.
      * @param WP_REST_Response $response The response data.
      * @param WP_REST_Request  $request  The request sent to the API.
      */
     do_action("woocommerce_rest_delete_{$this->post_type}", $post, $response, $request);
     return $response;
 }
Exemple #21
0
 function woo_pi_ajax_product_importer()
 {
     if (isset($_POST['step'])) {
         global $import;
         @ini_set('memory_limit', WP_MAX_MEMORY_LIMIT);
         ob_start();
         // Split the CSV data from the main transient
         if ($_POST['step'] != 'prepare_data') {
             $import = get_transient(WOO_PI_PREFIX . '_import');
             if (is_object($import)) {
                 if (isset($_POST['settings']) && !is_string($_POST['settings'])) {
                     foreach ($_POST['settings'] as $key => $value) {
                         if (is_array($value)) {
                             foreach ($value as $value_key => $value_value) {
                                 if (!is_array($value_value)) {
                                     $value[$value_key] = stripslashes($value_value);
                                 }
                             }
                             $import->{$key} = $value;
                         } else {
                             $import->{$key} = stripslashes($value);
                         }
                     }
                 }
                 // Merge the split transients into the $import global
                 if (isset($import->headers)) {
                     $args = array('generate_categories', 'generate_tags', 'prepare_product_import', 'save_product');
                     foreach ($import->headers as $header) {
                         // Exclude $import->csv_category and $import->csv_brand for most of the import
                         if (in_array($header, array('category', 'brand'))) {
                             if (in_array($_POST['step'], $args)) {
                                 $import->{'csv_' . $header} = get_transient(WOO_PI_PREFIX . '_csv_' . $header);
                             }
                         } else {
                             $import->{'csv_' . $header} = get_transient(WOO_PI_PREFIX . '_csv_' . $header);
                         }
                     }
                 }
             } else {
                 $import = new stdClass();
                 $import->cancel_import = true;
                 $troubleshooting_url = 'http://www.visser.com.au/woocommerce/documentation/plugins/product-importer-deluxe/usage/';
                 $import->failed_import = sprintf(__('Your CSV contained special characters that WordPress and Product Importer Deluxe could not filter. %s', 'woo_pi'), __('Need help?', 'woo_pi') . ' ' . $troubleshooting_url);
             }
         }
         $timeout = 0;
         if (isset($import->timeout)) {
             $timeout = $import->timeout;
         }
         if (!ini_get('safe_mode')) {
             @set_time_limit($timeout);
         }
         switch ($_POST['step']) {
             case 'prepare_data':
                 $import = new stdClass();
                 $import->start_time = time();
                 $import->cancel_import = false;
                 $import->failed_import = '';
                 $import->log = '';
                 $import->timeout = isset($_POST['timeout']) ? $_POST['timeout'] : false;
                 $import->delimiter = $_POST['delimiter'];
                 $import->category_separator = $_POST['category_separator'];
                 $import->parent_child_delimiter = $_POST['parent_child_delimiter'];
                 $import->delete_file = woo_pi_get_option('delete_file', 0);
                 $import->import_method = isset($_POST['import_method']) ? $_POST['import_method'] : 'new';
                 $import->advanced_log = isset($_POST['advanced_log']) ? (int) $_POST['advanced_log'] : 0;
                 $import->log .= '<br />' . sprintf(__('Import method: %s', 'woo_pi'), $import->import_method);
                 woo_pi_prepare_data('prepare_data');
                 if ($import->advanced_log) {
                     $import->log .= "<br />" . __('Validating required columns...', 'woo_pi');
                 }
                 if (!$import->cancel_import) {
                     woo_pi_prepare_columns();
                 }
                 $import->skip_first = $_POST['skip_first'];
                 $import->log .= "<br />" . __('Product columns have been grouped', 'woo_pi');
                 $import->log .= "<br /><br />" . __('Generating Categories...', 'woo_pi');
                 $import->loading_text = __('Generating Categories...', 'woo_pi');
                 break;
             case 'generate_categories':
                 $import->products_added = 0;
                 $import->products_deleted = 0;
                 $import->products_failed = 0;
                 // Category generation
                 if (in_array($import->import_method, array('new')) && isset($import->csv_category)) {
                     woo_pi_generate_categories();
                 } else {
                     $import->log .= "<br />" . __('Categories skipped', 'woo_pi');
                 }
                 $import->log .= "<br /><br />" . __('Generating Tags...', 'woo_pi');
                 $import->loading_text = __('Generating Tags...', 'woo_pi');
                 break;
             case 'generate_tags':
                 // Tag generation
                 if (in_array($import->import_method, array('new')) && isset($import->csv_tag)) {
                     woo_pi_generate_tags();
                 } else {
                     $import->log .= "<br />" . __('Tags skipped', 'woo_pi');
                 }
                 if ($import->import_method == 'new') {
                     $import->log .= "<br /><br />" . __('Generating Products...', 'woo_pi');
                 } else {
                     if ($import->import_method == 'delete') {
                         $import->log .= "<br /><br />" . __('Checking for matching Products to delete...', 'woo_pi');
                     }
                 }
                 $import->loading_text = __('Importing Products...', 'woo_pi');
                 break;
             case 'prepare_product_import':
                 global $import, $product;
                 if ($import->advanced_log) {
                     $import->log .= "<br />>>> " . __('Including non-essential reporting in this import log', 'woo_pi');
                 }
                 if ($import->skip_first) {
                     $import->i = 1;
                     $import->log .= "<br />>>> " . __('Skipping import of first CSV row', 'woo_pi');
                 } else {
                     $import->i = 0;
                     $import->log .= "<br />>>> " . __('Starting import at first CSV row', 'woo_pi');
                 }
                 $import->failed_products = array();
                 $i = $import->i;
                 woo_pi_prepare_product($i);
                 // This runs once as part of the import preparation
                 $import->active_product = $product;
                 if ($import->import_method == 'delete') {
                     if (!empty($product->name)) {
                         $import->log .= "<br />>>> " . sprintf(__('Searching for %s...', 'woo_pi'), $product->name);
                     } else {
                         $import->log .= "<br />>>> " . sprintf(__('Searching for (no title) - SKU: %s...', 'woo_pi'), $product->sku);
                     }
                     $import->loading_text = sprintf(__('Searching for Product %d of %d...', 'woo_pi'), $i, $import->skip_first ? $import->rows - 1 : $import->rows);
                 } else {
                     if (!empty($product->name)) {
                         $import->log .= "<br />>>> " . sprintf(__('Importing %s...', 'woo_pi'), $product->name);
                     } else {
                         $import->log .= "<br />>>> " . sprintf(__('Importing (no title) - SKU: %s...', 'woo_pi'), $product->sku);
                     }
                     $import->loading_text = sprintf(__('Importing Product %d of %d...', 'woo_pi'), $i, $import->skip_first ? $import->rows - 1 : $import->rows);
                 }
                 break;
             case 'save_product':
                 global $import, $product;
                 $i = $_POST['i'];
                 if ($import->active_product) {
                     if (!isset($product)) {
                         $product = new stdClass();
                     }
                     foreach ($import->active_product as $key => $value) {
                         $product->{$key} = $value;
                     }
                 }
                 $import->product_start_time = microtime(true);
                 if (in_array($import->import_method, array('new'))) {
                     // Build Categories
                     woo_pi_process_categories();
                     // Build Tags
                     woo_pi_process_tags();
                 }
                 // Check for duplicate SKU
                 woo_pi_duplicate_product_exists();
                 woo_pi_validate_product();
                 if ($product->fail_requirements) {
                     if ($import->advanced_log) {
                         $import->log .= "<br />>>>>>> " . sprintf(__('Skipping Product, see Import Report for full explanation. Reason: %s', 'woo_pi'), $product->failed_reason);
                     } else {
                         $import->log .= "<br />>>>>>> " . sprintf(__('Skipping Product, reason: %s', 'woo_pi'), $product->failed_reason);
                     }
                     $import->products_failed++;
                 } else {
                     if ($import->import_method == 'delete' && $product->duplicate_exists) {
                         woo_pi_delete_product();
                     } else {
                         if (in_array($import->import_method, array('new')) && !$product->duplicate_exists) {
                             woo_pi_create_product();
                         }
                     }
                     if ($import->import_method == 'delete') {
                         if ($product->deleted) {
                             if (!empty($product->name)) {
                                 $import->log .= "<br />>>>>>> " . sprintf(__('%s successfully deleted', 'woo_pi'), $product->name);
                             } else {
                                 $import->log .= "<br />>>>>>> " . sprintf(__('(no title) - SKU: %s successfully deleted', 'woo_pi'), $product->sku);
                             }
                         } else {
                             if ($import->advanced_log) {
                                 $import->log .= "<br />>>>>>> " . sprintf(__('Skipping Product, see Import Report for full explanation. Reason: %s', 'woo_pi'), $product->failed_reason);
                             } else {
                                 $import->log .= "<br />>>>>>> " . sprintf(__('Skipping Product, reason: %s', 'woo_pi'), $product->failed_reason);
                             }
                         }
                     } else {
                         if ($product->imported) {
                             if ($import->import_method == 'new') {
                                 if (!empty($product->name)) {
                                     $import->log .= "<br />>>>>>> " . sprintf(__('%s successfully imported', 'woo_pi'), $product->name);
                                 } else {
                                     $import->log .= "<br />>>>>>> " . sprintf(__('(no title) - SKU: %s successfully imported', 'woo_pi'), $product->sku);
                                 }
                             }
                         } else {
                             if ($import->advanced_log) {
                                 $import->log .= "<br />>>>>>> " . sprintf(__('Skipping Product, see Import Report for full explanation. Reason: %s', 'woo_pi'), $product->failed_reason);
                             } else {
                                 $import->log .= "<br />>>>>>> " . sprintf(__('Skipping Product, reason: %s', 'woo_pi'), $product->failed_reason);
                             }
                         }
                     }
                 }
                 $import->product_end_time = microtime(true);
                 $import->product_min_time = isset($import->product_min_time) ? $import->product_min_time : $import->product_end_time - $import->product_start_time;
                 $import->product_max_time = isset($import->product_max_time) ? $import->product_max_time : $import->product_end_time - $import->product_start_time;
                 // Update minimum product import time if it is shorter than the last
                 if ($import->product_end_time - $import->product_start_time < $import->product_min_time) {
                     $import->product_min_time = $import->product_end_time - $import->product_start_time;
                 }
                 // Update maximum product import time if it is longer than the last
                 if ($import->product_end_time - $import->product_start_time > $import->product_max_time) {
                     $import->product_max_time = $import->product_end_time - $import->product_start_time;
                 }
                 // All import rows have been processed
                 if ($i + 1 == $import->rows) {
                     if ($import->import_method == 'new') {
                         $import->log .= "<br />" . __('Products have been generated', 'woo_pi');
                     } else {
                         if ($import->import_method == 'delete') {
                             $import->log .= "<br />" . __('Products have been deleted', 'woo_pi');
                         }
                     }
                     $import->log .= "<br /><br />" . __('Cleaning up...', 'woo_pi');
                     $import->loading_text = __('Cleaning up...', 'woo_pi');
                 } else {
                     unset($import->active_product);
                     woo_pi_prepare_product($i + 1);
                     // This runs for each additional Product imported
                     $import->active_product = $product;
                     if ($import->import_method == 'delete') {
                         if (!empty($product->name)) {
                             $import->log .= "<br />>>> " . sprintf(__('Searching for %s...', 'woo_pi'), $product->name);
                         } else {
                             $import->log .= "<br />>>> " . sprintf(__('Searching for (no title) - SKU: %s...', 'woo_pi'), $product->sku);
                         }
                         $import->loading_text = sprintf(__('Searching for Product %d of %d...', 'woo_pi'), $i + 1, $import->skip_first ? $import->rows - 1 : $import->rows);
                     } else {
                         if (!empty($product->name)) {
                             $import->log .= "<br />>>> " . sprintf(__('Importing %s...', 'woo_pi'), $product->name);
                         } else {
                             $import->log .= "<br />>>> " . sprintf(__('Importing (no title) - SKU: %s...', 'woo_pi'), $product->sku);
                         }
                         $import->loading_text = sprintf(__('Importing Product %d of %d...', 'woo_pi'), $i + 1, $import->skip_first ? $import->rows - 1 : $import->rows);
                     }
                 }
                 break;
             case 'clean_up':
                 global $wpdb, $product;
                 // Organise Categories
                 if (isset($import->csv_category)) {
                     $term_taxonomy = 'product_cat';
                     $import->log .= "<br />>>> " . __('Organise Categories', 'woo_pi');
                 }
                 // Organise Tags
                 if (isset($import->csv_tag)) {
                     $import->log .= "<br />>>> " . __('Organise Tags', 'woo_pi');
                 }
                 $import->log .= "<br />" . __('Clean up has completed', 'woo_pi');
                 $import->end_time = time();
                 // Post-import Product details
                 if ($import->advanced_log) {
                     $import->log .= "<br /><br />" . __('Import summary', 'woo_pi');
                     if (in_array($import->import_method, array('new', 'merge'))) {
                         $import->log .= "<br />>>> " . sprintf(__('%d Products added', 'woo_pi'), $import->products_added);
                     } else {
                         if ($import->import_method == 'delete') {
                             $import->log .= "<br />>>> " . sprintf(__('%d Products deleted', 'woo_pi'), $import->products_deleted);
                         }
                     }
                     $import->log .= "<br />>>> " . sprintf(__('%d Products skipped', 'woo_pi'), $import->products_failed);
                     $import->log .= "<br />>>> " . sprintf(__('Import took %s to complete', 'woo_pi'), woo_pi_display_time_elapsed($import->start_time, $import->end_time));
                     $import->log .= "<br />>>> " . sprintf(__('Fastest Product took < %s to process', 'woo_pi'), woo_pi_display_time_elapsed(time(), strtotime(sprintf('+%d seconds', $import->product_min_time))));
                     $import->log .= "<br />>>> " . sprintf(__('Slowest Product took > %s to process', 'woo_pi'), woo_pi_display_time_elapsed(time(), strtotime(sprintf('+%d seconds', $import->product_max_time))));
                 }
                 $import->log .= "<br /><br />" . __('Import complete!', 'woo_pi');
                 $import->loading_text = __('Completed', 'woo_pi');
                 break;
         }
         // Clear transients
         if (function_exists('wc_delete_product_transients')) {
             wc_delete_product_transients();
         }
         $import->step = $_POST['step'];
         $import->errors = ob_get_clean();
         // Encode our transients in UTF-8 before storing them
         add_filter('pre_set_transient_woo_pi_import', 'woo_pi_filter_set_transient');
         // Split the import data from the main transient
         if (isset($import->headers)) {
             foreach ($import->headers as $header) {
                 if (isset($import->{'csv_' . $header})) {
                     $response = set_transient(WOO_PI_PREFIX . '_csv_' . $header, $import->{'csv_' . $header});
                     // Check if the Transient was saved
                     if (is_wp_error($response)) {
                         error_log(sprintf(__('[product-importer] Could not save the import data Transient for the column %s', 'woo_pi'), $header));
                     }
                     unset($import->{'csv_' . $header});
                 }
             }
         }
         $response = set_transient(WOO_PI_PREFIX . '_import', $import);
         // Check if the Transient was saved
         if (is_wp_error($response)) {
             error_log('[product-importer] Could not save the import Transient prior to starting AJAX import engine', 'woo_pi');
         }
         $return = array();
         if (isset($import->log)) {
             $return['log'] = $import->log;
         }
         if (isset($import->rows)) {
             $return['rows'] = $import->rows;
         }
         if (isset($import->skip_first)) {
             $return['skip_first'] = $import->skip_first;
         }
         if (isset($import->loading_text)) {
             $return['loading_text'] = $import->loading_text;
         }
         if (isset($import->cancel_import)) {
             $return['cancel_import'] = $import->cancel_import;
         }
         if (isset($import->failed_import)) {
             $return['failed_import'] = $import->failed_import;
         }
         if (isset($i)) {
             $return['i'] = $i;
         }
         if (isset($import->next)) {
             $return['next'] = $import->next;
         }
         if (isset($import->html)) {
             $return['html'] = $import->html;
         }
         if (isset($import->step)) {
             $return['step'] = $import->step;
         }
         @array_map('utf8_encode', $return);
         header("Content-type: application/json");
         echo json_encode($return);
     }
     die;
 }
 /**
  * Install WC
  */
 public function install()
 {
     $this->create_options();
     $this->create_tables();
     $this->create_roles();
     // Register post types
     include_once 'class-wc-post-types.php';
     WC_Post_types::register_taxonomies();
     $this->create_terms();
     $this->create_cron_jobs();
     $this->create_files();
     $this->create_css_from_less();
     // Clear transient cache
     wc_delete_product_transients();
     // Queue upgrades
     $current_version = get_option('woocommerce_version', null);
     $current_db_version = get_option('woocommerce_db_version', null);
     if (version_compare($current_db_version, '2.1.0', '<') && null !== $current_db_version) {
         update_option('_wc_needs_update', 1);
     } else {
         update_option('woocommerce_db_version', WC()->version);
     }
     // Update version
     update_option('woocommerce_version', WC()->version);
     // Check if pages are needed
     if (wc_get_page_id('shop') < 1) {
         update_option('_wc_needs_pages', 1);
     }
     // Flush rewrite rules
     flush_rewrite_rules();
     // Redirect to welcome screen
     set_transient('_wc_activation_redirect', 1, 60 * 60);
 }
 public function run_import()
 {
     global $woocsv_product;
     /**
      * Are we starting for the first time, than create a batch and continue, else just pick uo the batch code and start where you left
      */
     do_action('woocsv_start_import');
     if (empty($_POST['batch_code'])) {
         //create a new batch
         $batch_code = woocsv_batches::create();
         if ($batch_code) {
             //get max time we have and set the block size
             $max_execution_time = @ini_get('max_execution_time');
             if ($max_execution_time == 0) {
                 $max_execution_time = 30;
             }
             $block_size = $this->get_blocksize();
             $data = array('filename' => $_POST['filename'], 'row' => 0, 'block_size' => $block_size, 'header_name' => $_POST['header_name'], 'seperator' => $_POST['seperator'], 'total_rows' => (int) $_POST['total_rows'], 'start_date' => time(), 'max_execution_time' => $max_execution_time);
             woocsv_batches::update($batch_code, $data);
         } else {
             //@todo die nice
         }
         //and get the batch
         $batch = woocsv_batches::get_batch($batch_code);
     } else {
         $batch_code = $_POST['batch_code'];
         $batch = woocsv_batches::get_batch($_POST['batch_code']);
     }
     //lets check if we are done?
     if ($batch['row'] >= $batch['total_rows']) {
         $batch['end_date'] = time();
         $batch['status'] = 'done';
         woocsv_batches::update($batch_code, $batch);
         do_action('woocsv_after_import_finished');
         //@todo DIE NICE
         $this->die_nicer($batch_code, $batch);
     }
     // do we need to skip the first line?
     if ($this->get_skip_first_line() == 1 && $batch['row'] == 0) {
         $batch['row'] = 1;
     }
     //get the from and till
     $from = $batch['row'];
     $till = $batch['row'] + $batch['block_size'] < $batch['total_rows'] ? $batch['row'] + $batch['block_size'] : $batch['total_rows'];
     //get the lines
     $lines = $this->get_lines_from_file($batch['filename'], $from, $till, $batch['seperator']);
     //get the header
     $header = $this->get_header_from_name($batch['header_name']);
     //turn stuff off
     if (function_exists('wp_suspend_cache_invalidation')) {
         wp_suspend_cache_invalidation(true);
     }
     if (function_exists('wp_defer_term_counting ')) {
         wp_defer_term_counting(true);
     }
     $time_started = microtime(true);
     //loop over the lines and fill,pase and save the lines
     foreach ($lines['lines'] as $line) {
         //reset time ever time around
         @set_time_limit(0);
         //new one and fill in the header and the raw data
         $woocsv_product = new woocsv_import_product();
         $woocsv_product->header = $header;
         $woocsv_product->raw_data = $line;
         //fill it, parse it and save it
         $woocsv_product->fill_in_data();
         $this->write_to_log($batch_code, '-----> row: ' . $batch['row']);
         $woocsv_product->parse_data();
         $this->write_to_log($batch_code, $woocsv_product->log);
         $woocsv_product->save();
         $this->write_to_log($batch_code, $woocsv_product->log);
         //write tot log if debug is on
         if ($this->get_debug() == 0) {
             $this->write_to_log($batch_code, '-----> product dump');
             $this->write_to_log($batch_code, $woocsv_product);
         }
         //close log
         $this->write_to_log($batch_code, '-----> end row: ' . $batch['row']);
         $this->write_to_log($batch_code, '');
         //goto the next row
         $batch['row']++;
         //delete transionts
         if (function_exists('wc_delete_product_transients')) {
             wc_delete_product_transients($woocsv_product->body['ID']);
         }
     }
     $time_finished = microtime(true);
     if (!$this->get_blocksize()) {
         $time_factor = ceil(($batch['max_execution_time'] - ($time_finished - $time_started)) / $batch['max_execution_time'] * 100);
         switch ($time_factor) {
             case $time_factor > 90:
                 $block_size = 10;
                 break;
             case $time_factor > 50:
                 $block_size = 5;
                 break;
             case $time_factor > 10:
                 $block_size = 1;
                 break;
             default:
                 $block_size = 0;
         }
         $batch['block_size'] += $block_size;
         woocsv_batches::update($batch_code, $batch);
     }
     $this->die_nicer($batch_code, $batch);
 }
Exemple #24
0
 /**
  * @deprecated 2.1.0
  * @param int $post_id
  */
 public function clear_product_transients($post_id = 0)
 {
     _deprecated_function('Woocommerce->clear_product_transients', '2.1', 'wc_delete_product_transients');
     wc_delete_product_transients($post_id);
 }
 /**
  * Bulk edit variations via AJAX
  */
 public static function bulk_edit_variations()
 {
     ob_start();
     check_ajax_referer('bulk-edit-variations', 'security');
     // Check permissions again and make sure we have what we need
     if (!current_user_can('edit_products') || empty($_POST['product_id']) || empty($_POST['bulk_action'])) {
         die(-1);
     }
     $product_id = absint($_POST['product_id']);
     $bulk_action = wc_clean($_POST['bulk_action']);
     $data = !empty($_POST['data']) ? array_map('wc_clean', $_POST['data']) : array();
     $variations = array();
     if (apply_filters('woocommerce_bulk_edit_variations_need_children', true)) {
         $variations = get_posts(array('post_parent' => $product_id, 'posts_per_page' => -1, 'post_type' => 'product_variation', 'fields' => 'ids', 'post_status' => array('publish', 'private')));
     }
     if (method_exists(__CLASS__, "variation_bulk_action_{$bulk_action}")) {
         call_user_func(array(__CLASS__, "variation_bulk_action_{$bulk_action}"), $variations, $data);
     } else {
         do_action('woocommerce_bulk_edit_variations_default', $bulk_action, $data, $product_id, $variations);
     }
     do_action('woocommerce_bulk_edit_variations', $bulk_action, $data, $product_id, $variations);
     // Sync and update transients
     WC_Product_Variable::sync($product_id);
     wc_delete_product_transients($product_id);
     die;
 }
 /**
  * Handles output of tools
  */
 public static function status_tools()
 {
     global $wpdb;
     $tools = self::get_tools();
     if (!empty($_GET['action']) && !empty($_REQUEST['_wpnonce']) && wp_verify_nonce($_REQUEST['_wpnonce'], 'debug_action')) {
         switch ($_GET['action']) {
             case 'clear_transients':
                 wc_delete_product_transients();
                 wc_delete_shop_order_transients();
                 WC_Cache_Helper::get_transient_version('shipping', true);
                 echo '<div class="updated"><p>' . __('Product Transients Cleared', 'woocommerce') . '</p></div>';
                 break;
             case 'clear_expired_transients':
                 // http://w-shadow.com/blog/2012/04/17/delete-stale-transients/
                 $rows = $wpdb->query("\n\t\t\t\t\t\tDELETE\n\t\t\t\t\t\t\ta, b\n\t\t\t\t\t\tFROM\n\t\t\t\t\t\t\t{$wpdb->options} a, {$wpdb->options} b\n\t\t\t\t\t\tWHERE\n\t\t\t\t\t\t\ta.option_name LIKE '_transient_%' AND\n\t\t\t\t\t\t\ta.option_name NOT LIKE '_transient_timeout_%' AND\n\t\t\t\t\t\t\tb.option_name = CONCAT(\n\t\t\t\t\t\t\t\t'_transient_timeout_',\n\t\t\t\t\t\t\t\tSUBSTRING(\n\t\t\t\t\t\t\t\t\ta.option_name,\n\t\t\t\t\t\t\t\t\tCHAR_LENGTH('_transient_') + 1\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\tAND b.option_value < UNIX_TIMESTAMP()\n\t\t\t\t\t");
                 $rows2 = $wpdb->query("\n\t\t\t\t\t\tDELETE\n\t\t\t\t\t\t\ta, b\n\t\t\t\t\t\tFROM\n\t\t\t\t\t\t\t{$wpdb->options} a, {$wpdb->options} b\n\t\t\t\t\t\tWHERE\n\t\t\t\t\t\t\ta.option_name LIKE '_site_transient_%' AND\n\t\t\t\t\t\t\ta.option_name NOT LIKE '_site_transient_timeout_%' AND\n\t\t\t\t\t\t\tb.option_name = CONCAT(\n\t\t\t\t\t\t\t\t'_site_transient_timeout_',\n\t\t\t\t\t\t\t\tSUBSTRING(\n\t\t\t\t\t\t\t\t\ta.option_name,\n\t\t\t\t\t\t\t\t\tCHAR_LENGTH('_site_transient_') + 1\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\tAND b.option_value < UNIX_TIMESTAMP()\n\t\t\t\t\t");
                 echo '<div class="updated"><p>' . sprintf(__('%d Transients Rows Cleared', 'woocommerce'), $rows + $rows2) . '</p></div>';
                 break;
             case 'reset_roles':
                 // Remove then re-add caps and roles
                 WC_Install::remove_roles();
                 WC_Install::create_roles();
                 echo '<div class="updated"><p>' . __('Roles successfully reset', 'woocommerce') . '</p></div>';
                 break;
             case 'recount_terms':
                 $product_cats = get_terms('product_cat', array('hide_empty' => false, 'fields' => 'id=>parent'));
                 _wc_term_recount($product_cats, get_taxonomy('product_cat'), true, false);
                 $product_tags = get_terms('product_tag', array('hide_empty' => false, 'fields' => 'id=>parent'));
                 _wc_term_recount($product_tags, get_taxonomy('product_tag'), true, false);
                 echo '<div class="updated"><p>' . __('Terms successfully recounted', 'woocommerce') . '</p></div>';
                 break;
             case 'clear_sessions':
                 $wpdb->query("\n\t\t\t\t\t\tDELETE FROM {$wpdb->options}\n\t\t\t\t\t\tWHERE option_name LIKE '_wc_session_%' OR option_name LIKE '_wc_session_expires_%'\n\t\t\t\t\t");
                 wp_cache_flush();
                 echo '<div class="updated"><p>' . __('Sessions successfully cleared', 'woocommerce') . '</p></div>';
                 break;
             case 'install_pages':
                 WC_Install::create_pages();
                 echo '<div class="updated"><p>' . __('All missing WooCommerce pages was installed successfully.', 'woocommerce') . '</p></div>';
                 break;
             case 'delete_taxes':
                 $wpdb->query("TRUNCATE " . $wpdb->prefix . "woocommerce_tax_rates");
                 $wpdb->query("TRUNCATE " . $wpdb->prefix . "woocommerce_tax_rate_locations");
                 echo '<div class="updated"><p>' . __('Tax rates successfully deleted', 'woocommerce') . '</p></div>';
                 break;
             case 'reset_tracking':
                 delete_option('woocommerce_allow_tracking');
                 WC_Admin_Notices::add_notice('tracking');
                 echo '<div class="updated"><p>' . __('Usage tracking settings successfully reset.', 'woocommerce') . '</p></div>';
                 break;
             default:
                 $action = esc_attr($_GET['action']);
                 if (isset($tools[$action]['callback'])) {
                     $callback = $tools[$action]['callback'];
                     $return = call_user_func($callback);
                     if ($return === false) {
                         if (is_array($callback)) {
                             echo '<div class="error"><p>' . sprintf(__('There was an error calling %s::%s', 'woocommerce'), get_class($callback[0]), $callback[1]) . '</p></div>';
                         } else {
                             echo '<div class="error"><p>' . sprintf(__('There was an error calling %s', 'woocommerce'), $callback) . '</p></div>';
                         }
                     }
                 }
                 break;
         }
     }
     // Manual translation update messages
     if (isset($_GET['translation_updated'])) {
         switch ($_GET['translation_updated']) {
             case 2:
                 echo '<div class="error"><p>' . __('Failed to install/update the translation:', 'woocommerce') . ' ' . __('Seems you don\'t have permission to do this!', 'woocommerce') . '</p></div>';
                 break;
             case 3:
                 echo '<div class="error"><p>' . __('Failed to install/update the translation:', 'woocommerce') . ' ' . sprintf(__('An authentication error occurred while updating the translation. Please try again or configure your %sUpgrade Constants%s.', 'woocommerce'), '<a href="http://codex.wordpress.org/Editing_wp-config.php#WordPress_Upgrade_Constants">', '</a>') . '</p></div>';
                 break;
             case 4:
                 echo '<div class="error"><p>' . __('Failed to install/update the translation:', 'woocommerce') . ' ' . __('Sorry but there is no translation available for your language =/', 'woocommerce') . '</p></div>';
                 break;
             default:
                 // Force WordPress find for new updates and hide the WooCommerce translation update
                 set_site_transient('update_plugins', null);
                 echo '<div class="updated"><p>' . __('Translations installed/updated successfully!', 'woocommerce') . '</p></div>';
                 break;
         }
     }
     // Display message if settings settings have been saved
     if (isset($_REQUEST['settings-updated'])) {
         echo '<div class="updated"><p>' . __('Your changes have been saved.', 'woocommerce') . '</p></div>';
     }
     include_once 'views/html-admin-page-status-tools.php';
 }
 /**
  * Sync variable product prices with the childs lowest/highest prices.
  *
  * @access public
  * @return void
  */
 public function variable_product_sync($product_id = '')
 {
     global $woocommerce;
     parent::variable_product_sync();
     $children = get_posts(array('post_parent' => $this->id, 'posts_per_page' => -1, 'post_type' => 'product_variation', 'fields' => 'ids', 'post_status' => 'publish'));
     $lowest_initial_amount = $highest_initial_amount = $lowest_price = $highest_price = '';
     $shortest_initial_period = $longest_initial_period = $shortest_trial_period = $longest_trial_period = $shortest_trial_length = $longest_trial_length = '';
     $longest_initial_interval = $shortest_initial_interval = $variable_subscription_period = $variable_subscription_period_interval = '';
     $lowest_regular_price = $highest_regular_price = $lowest_sale_price = $highest_sale_price = $max_subscription_period = $max_subscription_period_interval = '';
     $variable_subscription_sign_up_fee = $variable_subscription_trial_period = $variable_subscription_trial_length = $variable_subscription_length = $variable_subscription_sign_up_fee = $variable_subscription_trial_period = $variable_subscription_trial_length = $variable_subscription_length = '';
     $min_variation_id = $max_variation_id = NULL;
     if ($children) {
         foreach ($children as $child) {
             $is_max = $is_min = false;
             // WC has already determined the correct price which accounts for sale price
             $child_price = get_post_meta($child, '_price', true);
             $child_billing_period = get_post_meta($child, '_subscription_period', true);
             $child_billing_interval = get_post_meta($child, '_subscription_period_interval', true);
             $child_sign_up_fee = get_post_meta($child, '_subscription_sign_up_fee', true);
             $child_free_trial_length = get_post_meta($child, '_subscription_trial_length', true);
             $child_free_trial_period = get_post_meta($child, '_subscription_trial_period', true);
             if ($child_price === '' && $child_sign_up_fee === '') {
                 continue;
             }
             $child_price = $child_price === '' ? 0 : $child_price;
             $child_sign_up_fee = $child_sign_up_fee === '' ? 0 : $child_sign_up_fee;
             $has_free_trial = $child_free_trial_length !== '' && $child_free_trial_length > 0 ? true : false;
             // Determine some recurring price flags
             $is_lowest_price = $child_price < $lowest_price || '' === $lowest_price ? true : false;
             $is_longest_period = $child_billing_period === WC_Subscriptions::get_longest_period($variable_subscription_period, $child_billing_period) ? true : false;
             $is_longest_interval = $child_billing_interval >= $variable_subscription_period_interval || '' === $variable_subscription_period_interval ? true : false;
             // Find the amount the subscriber will have to pay up-front
             if ($has_free_trial) {
                 $initial_amount = $child_sign_up_fee;
                 $initial_period = $child_free_trial_period;
                 $initial_interval = $child_free_trial_length;
             } else {
                 $initial_amount = $child_price + $child_sign_up_fee;
                 $initial_period = $child_billing_period;
                 $initial_interval = $child_billing_interval;
             }
             // We have a free trial & no sign-up fee, so need to choose the longest free trial (and maybe the shortest)
             if ($has_free_trial && $child_sign_up_fee == 0) {
                 // First variation
                 if ('' === $longest_trial_period) {
                     $is_min = true;
                     // If two variations have the same free trial, choose the variation with the lowest recurring price for the longest period
                 } elseif ($variable_subscription_trial_period === $child_free_trial_period && $child_free_trial_length === $variable_subscription_trial_length) {
                     // If the variation has the lowest recurring price, it's the cheapest
                     if ($is_lowest_price) {
                         $is_min = true;
                         // When current variation's free trial is the same as the lowest, it's the cheaper if it has a longer billing schedule
                     } elseif ($child_price === $lowest_price) {
                         if ($is_longest_period && $is_longest_interval) {
                             $is_min = true;
                             // Longest with a new billing period
                         } elseif ($is_longest_period && $child_billing_period !== $variable_subscription_trial_period) {
                             $is_min = true;
                         }
                     }
                     // Otherwise the cheapest variation is the one with the longer trial
                 } elseif ($variable_subscription_trial_period === $child_free_trial_period) {
                     $is_min = $child_free_trial_length > $variable_subscription_trial_length ? true : false;
                     // Otherwise just a longer trial period (that isn't equal to the longest period)
                 } elseif ($child_free_trial_period === WC_Subscriptions::get_longest_period($longest_trial_period, $child_free_trial_period)) {
                     $is_min = true;
                 }
                 if ($is_min) {
                     $longest_trial_period = $child_free_trial_period;
                     $longest_trial_length = $child_free_trial_length;
                 }
                 // If the current cheapest variation is also free then the shortest trial period is the most expensive
                 if (0 == $lowest_price || '' === $lowest_price) {
                     if ('' === $shortest_trial_period) {
                         $is_max = true;
                         // Need to check trial length
                     } elseif ($shortest_trial_period === $child_free_trial_period) {
                         $is_max = $child_free_trial_length < $shortest_trial_length ? true : false;
                         // Need to find shortest period
                     } elseif ($child_free_trial_period === WC_Subscriptions::get_shortest_period($shortest_trial_period, $child_free_trial_period)) {
                         $is_max = true;
                     }
                     if ($is_max) {
                         $shortest_trial_period = $child_free_trial_period;
                         $shortest_trial_length = $child_free_trial_length;
                     }
                 }
             } else {
                 $longest_initial_period = WC_Subscriptions::get_longest_period($longest_initial_period, $initial_period);
                 $shortest_initial_period = WC_Subscriptions::get_shortest_period($shortest_initial_period, $initial_period);
                 $is_lowest_initial_amount = $initial_amount < $lowest_initial_amount || '' === $lowest_initial_amount ? true : false;
                 $is_longest_initial_period = $initial_period === $longest_initial_period ? true : false;
                 $is_longest_initial_interval = $initial_interval >= $longest_initial_interval || '' === $longest_initial_interval ? true : false;
                 $is_highest_initial = $initial_amount > $highest_initial_amount || '' === $highest_initial_amount ? true : false;
                 $is_shortest_period = $initial_period === $shortest_initial_period || '' === $shortest_initial_period ? true : false;
                 $is_shortest_interval = $initial_interval < $shortest_initial_interval || '' === $shortest_initial_interval ? true : false;
                 // If we're not dealing with the lowest initial access amount, then ignore this variation
                 if (!$is_lowest_initial_amount && $initial_amount !== $lowest_initial_amount) {
                     continue;
                 }
                 // If the variation has the lowest price, it's the cheapest
                 if ($is_lowest_initial_amount) {
                     $is_min = true;
                     // When current variation's price is the same as the lowest, it's the cheapest only if it has a longer billing schedule
                 } elseif ($initial_amount === $lowest_initial_amount) {
                     // We need to check the recurring schedule when the sign-up fee & free trial periods are equal
                     if ($has_free_trial && $initial_period == $longest_initial_period && $initial_interval == $longest_initial_interval) {
                         // If the variation has the lowest recurring price, it's the cheapest
                         if ($is_lowest_price) {
                             $is_min = true;
                             // When current variation's price is the same as the lowest, it's the cheapest only if it has a longer billing schedule
                         } elseif ($child_price === $lowest_price) {
                             if ($is_longest_period && $is_longest_interval) {
                                 $is_min = true;
                                 // Longest with a new billing period
                             } elseif ($is_longest_period && $child_billing_period !== $variable_subscription_period) {
                                 $is_min = true;
                             }
                         }
                         // Longest initial term is the cheapest
                     } elseif ($is_longest_initial_period && $is_longest_initial_interval) {
                         $is_min = true;
                         // Longest with a new billing period
                     } elseif ($is_longest_initial_period && $initial_period !== $longest_initial_period) {
                         $is_min = true;
                     }
                 }
                 // If we have the highest price for the shortest period, we might have the maximum variation
                 if ($is_highest_initial && $is_shortest_period && $is_shortest_interval) {
                     $is_max = true;
                     // But only if its for the shortest billing period
                 } elseif ($child_price === $highest_price) {
                     if ($is_shortest_period && $is_shortest_interval) {
                         $is_max = true;
                     } elseif ($is_shortest_period) {
                         $is_max = true;
                     }
                 }
             }
             // If it's the min subscription terms
             if ($is_min) {
                 $min_variation_id = $child;
                 $lowest_price = $child_price;
                 $lowest_regular_price = get_post_meta($child, '_regular_price', true);
                 $lowest_sale_price = get_post_meta($child, '_sale_price', true);
                 $lowest_regular_price = '' === $lowest_regular_price ? 0 : $lowest_regular_price;
                 $lowest_sale_price = '' === $lowest_sale_price ? 0 : $lowest_sale_price;
                 $lowest_initial_amount = $initial_amount;
                 $longest_initial_period = $initial_period;
                 $longest_initial_interval = $initial_interval;
                 $variable_subscription_sign_up_fee = $child_sign_up_fee;
                 $variable_subscription_period = $child_billing_period;
                 $variable_subscription_period_interval = $child_billing_interval;
                 $variable_subscription_trial_length = $child_free_trial_length;
                 $variable_subscription_trial_period = $child_free_trial_period;
                 $variable_subscription_length = get_post_meta($child, '_subscription_length', true);
             }
             if ($is_max) {
                 $max_variation_id = $child;
                 $highest_price = $child_price;
                 $highest_regular_price = get_post_meta($child, '_regular_price', true);
                 $highest_sale_price = get_post_meta($child, '_sale_price', true);
                 $highest_initial_amount = $initial_amount;
                 $highest_regular_price = '' === $highest_regular_price ? 0 : $highest_regular_price;
                 $highest_sale_price = '' === $highest_sale_price ? 0 : $highest_sale_price;
                 $max_subscription_period = $child_billing_period;
                 $max_subscription_period_interval = $child_billing_interval;
             }
         }
         update_post_meta($this->id, '_min_price_variation_id', $min_variation_id);
         update_post_meta($this->id, '_max_price_variation_id', $max_variation_id);
         update_post_meta($this->id, '_price', $lowest_price);
         update_post_meta($this->id, '_min_variation_price', $lowest_price);
         update_post_meta($this->id, '_max_variation_price', $highest_price);
         update_post_meta($this->id, '_min_variation_regular_price', $lowest_regular_price);
         update_post_meta($this->id, '_max_variation_regular_price', $highest_regular_price);
         update_post_meta($this->id, '_min_variation_sale_price', $lowest_sale_price);
         update_post_meta($this->id, '_max_variation_sale_price', $highest_sale_price);
         update_post_meta($this->id, '_min_variation_period', $variable_subscription_period);
         update_post_meta($this->id, '_max_variation_period', $variable_subscription_period_interval);
         update_post_meta($this->id, '_min_variation_period_interval', $max_subscription_period);
         update_post_meta($this->id, '_max_variation_period_interval', $max_subscription_period_interval);
         update_post_meta($this->id, '_subscription_price', $lowest_price);
         update_post_meta($this->id, '_subscription_sign_up_fee', $variable_subscription_sign_up_fee);
         update_post_meta($this->id, '_subscription_period', $variable_subscription_period);
         update_post_meta($this->id, '_subscription_period_interval', $variable_subscription_period_interval);
         update_post_meta($this->id, '_subscription_trial_period', $variable_subscription_trial_period);
         update_post_meta($this->id, '_subscription_trial_length', $variable_subscription_trial_length);
         update_post_meta($this->id, '_subscription_length', $variable_subscription_length);
         $this->subscription_price = $lowest_price;
         $this->subscription_sign_up_fee = $variable_subscription_sign_up_fee;
         $this->subscription_period = $variable_subscription_period;
         $this->subscription_period_interval = $variable_subscription_period_interval;
         $this->subscription_trial_period = $variable_subscription_trial_period;
         $this->subscription_trial_length = $variable_subscription_trial_length;
         $this->subscription_length = $variable_subscription_length;
         if (function_exists('wc_delete_product_transients')) {
             wc_delete_product_transients($this->id);
         } else {
             $woocommerce->clear_product_transients($this->id);
         }
     } else {
         // No variations yet
         $this->subscription_price = '';
         $this->subscription_sign_up_fee = '';
         $this->subscription_period = 'day';
         $this->subscription_period_interval = 1;
         $this->subscription_trial_period = 'day';
         $this->subscription_trial_length = 1;
         $this->subscription_length = 0;
     }
 }
 /**
  * Handles output of tools
  */
 public static function status_tools()
 {
     global $wpdb;
     $tools = self::get_tools();
     if (!empty($_GET['action']) && !empty($_REQUEST['_wpnonce']) && wp_verify_nonce($_REQUEST['_wpnonce'], 'debug_action')) {
         switch ($_GET['action']) {
             case 'clear_transients':
                 wc_delete_product_transients();
                 wc_delete_shop_order_transients();
                 WC_Cache_Helper::get_transient_version('shipping', true);
                 echo '<div class="updated"><p>' . __('Product Transients Cleared', 'woocommerce') . '</p></div>';
                 break;
             case 'clear_expired_transients':
                 /*
                  * Deletes all expired transients. The multi-table delete syntax is used
                  * to delete the transient record from table a, and the corresponding
                  * transient_timeout record from table b.
                  *
                  * Based on code inside core's upgrade_network() function.
                  */
                 $sql = "DELETE a, b FROM {$wpdb->options} a, {$wpdb->options} b\r\n\t\t\t\t\t\tWHERE a.option_name LIKE %s\r\n\t\t\t\t\t\tAND a.option_name NOT LIKE %s\r\n\t\t\t\t\t\tAND b.option_name = CONCAT( '_transient_timeout_', SUBSTRING( a.option_name, 12 ) )\r\n\t\t\t\t\t\tAND b.option_value < %d";
                 $rows = $wpdb->query($wpdb->prepare($sql, $wpdb->esc_like('_transient_') . '%', $wpdb->esc_like('_transient_timeout_') . '%', time()));
                 $sql = "DELETE a, b FROM {$wpdb->options} a, {$wpdb->options} b\r\n\t\t\t\t\t\tWHERE a.option_name LIKE %s\r\n\t\t\t\t\t\tAND a.option_name NOT LIKE %s\r\n\t\t\t\t\t\tAND b.option_name = CONCAT( '_site_transient_timeout_', SUBSTRING( a.option_name, 17 ) )\r\n\t\t\t\t\t\tAND b.option_value < %d";
                 $rows2 = $wpdb->query($wpdb->prepare($sql, $wpdb->esc_like('_site_transient_') . '%', $wpdb->esc_like('_site_transient_timeout_') . '%', time()));
                 echo '<div class="updated"><p>' . sprintf(__('%d Transients Rows Cleared', 'woocommerce'), $rows + $rows2) . '</p></div>';
                 break;
             case 'reset_roles':
                 // Remove then re-add caps and roles
                 WC_Install::remove_roles();
                 WC_Install::create_roles();
                 echo '<div class="updated"><p>' . __('Roles successfully reset', 'woocommerce') . '</p></div>';
                 break;
             case 'recount_terms':
                 $product_cats = get_terms('product_cat', array('hide_empty' => false, 'fields' => 'id=>parent'));
                 _wc_term_recount($product_cats, get_taxonomy('product_cat'), true, false);
                 $product_tags = get_terms('product_tag', array('hide_empty' => false, 'fields' => 'id=>parent'));
                 _wc_term_recount($product_tags, get_taxonomy('product_tag'), true, false);
                 echo '<div class="updated"><p>' . __('Terms successfully recounted', 'woocommerce') . '</p></div>';
                 break;
             case 'clear_sessions':
                 $wpdb->query("\r\n\t\t\t\t\t\tDELETE FROM {$wpdb->options}\r\n\t\t\t\t\t\tWHERE option_name LIKE '_wc_session_%' OR option_name LIKE '_wc_session_expires_%'\r\n\t\t\t\t\t");
                 wp_cache_flush();
                 echo '<div class="updated"><p>' . __('Sessions successfully cleared', 'woocommerce') . '</p></div>';
                 break;
             case 'install_pages':
                 WC_Install::create_pages();
                 echo '<div class="updated"><p>' . __('All missing WooCommerce pages was installed successfully.', 'woocommerce') . '</p></div>';
                 break;
             case 'delete_taxes':
                 $wpdb->query("TRUNCATE " . $wpdb->prefix . "woocommerce_tax_rates");
                 $wpdb->query("TRUNCATE " . $wpdb->prefix . "woocommerce_tax_rate_locations");
                 echo '<div class="updated"><p>' . __('Tax rates successfully deleted', 'woocommerce') . '</p></div>';
                 break;
             case 'reset_tracking':
                 delete_option('woocommerce_allow_tracking');
                 WC_Admin_Notices::add_notice('tracking');
                 echo '<div class="updated"><p>' . __('Usage tracking settings successfully reset.', 'woocommerce') . '</p></div>';
                 break;
             default:
                 $action = esc_attr($_GET['action']);
                 if (isset($tools[$action]['callback'])) {
                     $callback = $tools[$action]['callback'];
                     $return = call_user_func($callback);
                     if ($return === false) {
                         if (is_array($callback)) {
                             echo '<div class="error"><p>' . sprintf(__('There was an error calling %s::%s', 'woocommerce'), get_class($callback[0]), $callback[1]) . '</p></div>';
                         } else {
                             echo '<div class="error"><p>' . sprintf(__('There was an error calling %s', 'woocommerce'), $callback) . '</p></div>';
                         }
                     }
                 }
                 break;
         }
     }
     // Manual translation update messages
     if (isset($_GET['translation_updated'])) {
         WC_Language_Pack_Upgrader::language_update_messages();
     }
     // Display message if settings settings have been saved
     if (isset($_REQUEST['settings-updated'])) {
         echo '<div class="updated"><p>' . __('Your changes have been saved.', 'woocommerce') . '</p></div>';
     }
     include_once 'views/html-admin-page-status-tools.php';
 }
 /**
  * Edit a product
  *
  * @since 2.2
  * @param int $id the product ID
  * @param array $data
  * @return array
  */
 public function edit_product($id, $data)
 {
     try {
         if (!isset($data['product'])) {
             throw new WC_API_Exception('woocommerce_api_missing_product_data', sprintf(__('No %1$s data specified to edit %1$s', 'woocommerce'), 'product'), 400);
         }
         $data = $data['product'];
         $id = $this->validate_request($id, 'product', 'edit');
         if (is_wp_error($id)) {
             return $id;
         }
         $data = apply_filters('woocommerce_api_edit_product_data', $data, $this);
         // Product title.
         if (isset($data['title'])) {
             wp_update_post(array('ID' => $id, 'post_title' => wc_clean($data['title'])));
         }
         // Product name (slug).
         if (isset($data['name'])) {
             wp_update_post(array('ID' => $id, 'post_name' => sanitize_title($data['name'])));
         }
         // Product status.
         if (isset($data['status'])) {
             wp_update_post(array('ID' => $id, 'post_status' => wc_clean($data['status'])));
         }
         // Product short description.
         if (isset($data['short_description'])) {
             // Enable short description html tags.
             $post_excerpt = isset($data['enable_html_short_description']) && true === $data['enable_html_short_description'] ? $data['short_description'] : wc_clean($data['short_description']);
             wp_update_post(array('ID' => $id, 'post_excerpt' => $post_excerpt));
         }
         // Product description.
         if (isset($data['description'])) {
             // Enable description html tags.
             $post_content = isset($data['enable_html_description']) && true === $data['enable_html_description'] ? $data['description'] : wc_clean($data['description']);
             wp_update_post(array('ID' => $id, 'post_content' => $post_content));
         }
         // Validate the product type
         if (isset($data['type']) && !in_array(wc_clean($data['type']), array_keys(wc_get_product_types()))) {
             throw new WC_API_Exception('woocommerce_api_invalid_product_type', sprintf(__('Invalid product type - the product type must be any of these: %s', 'woocommerce'), implode(', ', array_keys(wc_get_product_types()))), 400);
         }
         // Check for featured/gallery images, upload it and set it
         if (isset($data['images'])) {
             $this->save_product_images($id, $data['images']);
         }
         // Save product meta fields
         $this->save_product_meta($id, $data);
         // Save variations
         $product = get_product($id);
         if ($product->is_type('variable')) {
             if (isset($data['variations']) && is_array($data['variations'])) {
                 $this->save_variations($id, $data);
             } else {
                 // Just sync variations
                 WC_Product_Variable::sync($id);
             }
         }
         do_action('woocommerce_api_edit_product', $id, $data);
         // Clear cache/transients
         wc_delete_product_transients($id);
         return $this->get_product($id);
     } catch (WC_API_Exception $e) {
         return new WP_Error($e->getErrorCode(), $e->getMessage(), array('status' => $e->getCode()));
     }
 }
 /**
  * Delete a product.
  *
  * @since 2.2
  * @param int $id the product ID.
  * @param bool $force true to permanently delete order, false to move to trash.
  * @return array
  */
 public function delete_product($id, $force = false)
 {
     $id = $this->validate_request($id, 'product', 'delete');
     if (is_wp_error($id)) {
         return $id;
     }
     do_action('woocommerce_api_delete_product', $id, $this);
     $parent_id = wp_get_post_parent_id($id);
     $result = $force ? wp_delete_post($id, true) : wp_trash_post($id);
     if (!$result) {
         return new WP_Error('woocommerce_api_cannot_delete_product', sprintf(__('This %s cannot be deleted', 'woocommerce'), 'product'), array('status' => 500));
     }
     // Delete parent product transients.
     if ($parent_id) {
         wc_delete_product_transients($parent_id);
     }
     if ($force) {
         return array('message' => sprintf(__('Permanently deleted %s', 'woocommerce'), 'product'));
     } else {
         $this->server->send_status('202');
         return array('message' => sprintf(__('Deleted %s', 'woocommerce'), 'product'));
     }
 }