public function checkProductInventory($mode = 'published', $compare_prices = false)
 {
     // get all published listings
     $lm = new WPLA_ListingsModel();
     $listings = $mode == 'published' ? $lm->getWhere('status', 'online') : $lm->getWhere('status', 'sold');
     $out_of_sync_products = array();
     $published_count = 0;
     // echo "<pre>";print_r($listings);echo"</pre>";#die();
     // process published listings
     foreach ($listings as $item) {
         // check wc product
         $item = (array) $item;
         $post_id = $item['post_id'];
         $_product = $this->getProduct($post_id);
         // echo "<pre>";print_r($_product);echo"</pre>";die();
         // checking parent variations makes no sense in WPLA, so skip them
         if ($_product->product_type == 'variable') {
             continue;
         }
         // get stock level and price
         $stock = WPLA_ProductWrapper::getStock($item['post_id']);
         $price = WPLA_ProductWrapper::getPrice($item['post_id']);
         // $item['price_max'] = $price;
         // echo "<pre>";print_r($price);echo"</pre>";#die();
         // echo "<pre>";print_r($item);echo"</pre>";die();
         // check for sale price on amazon side
         $sale_price = $this->getSalePriceForItem($item);
         $amazon_price = $sale_price ? $sale_price : $item['price'];
         // check if product and amazon listing are in sync
         $in_sync = true;
         // check stock level
         if ($stock != $item['quantity']) {
             $in_sync = false;
         }
         // check price
         if ($compare_prices) {
             if (round($price, 2) != round($amazon_price, 2)) {
                 $in_sync = false;
             }
         }
         // check max price
         // if ( isset( $price_max ) && isset( $item['price_max'] ) && ( round( $price_max, 2 ) != round ( $item['price_max'], 2 ) ) )
         // 	$in_sync = false;
         // if in sync, continue with next item
         if ($in_sync) {
             continue;
         }
         // mark listing as changed
         if (isset($_REQUEST['mark_as_changed'])) {
             if ($_product) {
                 // only existing products can have a profile re-applied
                 $lm->markItemAsModified($item['post_id']);
             }
             // in case the product is missing, force the listing to be changed (?)
             $lm->updateListing($item['id'], array('status' => 'changed'));
             $item['status'] = 'changed';
         }
         // add to list of out of sync products
         $item['price_woo'] = $price;
         $item['price_woo_max'] = isset($price_max) ? $price_max : false;
         $item['stock'] = $stock;
         $item['exists'] = $_product ? true : false;
         $item['type'] = $_product ? $_product->product_type : 'missing';
         $item['parent_id'] = $_product->product_type == 'variation' ? $_product->parent->id : false;
         $out_of_sync_products[] = $item;
         // count products which have not yet been marked as changed
         if ($item['status'] == 'online') {
             $published_count += 1;
         }
     }
     // return if empty
     if (empty($out_of_sync_products)) {
         WPLA()->showMessage('All ' . $mode . ' listings seem to be in sync.', 0, 1);
         return;
     }
     $msg = '<p>';
     $msg .= 'Warning: ' . sizeof($out_of_sync_products) . ' ' . $mode . ' listings are out of sync or missing in WooCommerce.';
     $msg .= '</p>';
     // table header
     $msg .= '<table style="width:100%">';
     $msg .= "<tr>";
     $msg .= "<th style='text-align:left'>SKU</th>";
     $msg .= "<th style='text-align:left'>Product</th>";
     $msg .= "<th style='text-align:left'>Local Qty</th>";
     $msg .= "<th style='text-align:left'>Amazon Qty</th>";
     $msg .= "<th style='text-align:left'>Local Price</th>";
     $msg .= "<th style='text-align:left'>Amazon Price</th>";
     $msg .= "<th style='text-align:left'>ASIN</th>";
     $msg .= "<th style='text-align:left'>Status</th>";
     $msg .= "</tr>";
     // table rows
     foreach ($out_of_sync_products as $item) {
         // echo "<pre>";print_r($item['asin']);echo"</pre>";#die();
         // get column data
         $sku = $item['sku'];
         $qty = $item['quantity'];
         $stock = $item['stock'];
         $title = $item['listing_title'];
         $post_id = $item['post_id'];
         $asin = $item['asin'];
         $status = $item['status'];
         $exists = $item['exists'];
         $price = woocommerce_price($item['price']);
         $price_woo = woocommerce_price($item['price_woo']);
         $product_type = $item['type'] == 'simple' ? '' : $item['type'];
         // highlight changed values
         $changed_stock = intval($item['quantity']) == intval($item['stock']) ? false : true;
         $changed_price = floatval($item['price']) == floatval($item['price_woo']) ? false : true;
         $changed_price_max = floatval(@$item['price_max']) == floatval($item['price_woo_max']) ? false : true;
         $stock_css = $changed_stock ? 'color:darkred;' : '';
         $price_css = $changed_price || $changed_price_max ? 'color:darkred;' : '';
         if (!$compare_prices) {
             $price_css = '';
         }
         // build links
         // $amazon_url  = $item['ViewItemURL'] ? $item['ViewItemURL'] : $amazon_url = 'http://www.amazon.com/itm/'.$asin;
         $amazon_url = 'admin.php?page=wpla&s=' . $asin;
         $amazon_link = '<a href="' . $amazon_url . '" target="_blank">' . $asin . '</a>';
         $edit_link = '<a href="post.php?action=edit&post=' . ($item['parent_id'] ? $item['parent_id'] : $post_id) . '" target="_blank">' . $title . '</a>';
         // mark non existent products
         if (!$exists) {
             $stock = 'N/A';
             $post_id .= ' missing!';
         }
         // show price range for variations
         // if ( $item['price_woo_max'] )
         // 	$price_woo .= ' - '.woocommerce_price( $item['price_woo_max'] );
         // if ( @$item['price_max'] )
         // 	$price .= ' - '.woocommerce_price( $item['price_max'] );
         // build table row
         $msg .= "<tr>";
         $msg .= "<td>{$sku}</td>";
         $msg .= "<td>{$edit_link} <span style='color:silver'>{$product_type} (#{$post_id})</span></td>";
         $msg .= "<td style='{$stock_css}'>{$stock}</td>";
         $msg .= "<td style='{$stock_css}'>{$qty}</td>";
         $msg .= "<td style='{$price_css}'>{$price_woo}</td>";
         $msg .= "<td style='{$price_css}'>{$price}</td>";
         $msg .= "<td>{$amazon_link}</td>";
         $msg .= "<td>{$status}</td>";
         $msg .= "</tr>";
     }
     $msg .= '</table>';
     // buttons
     $msg .= '<p>';
     // show 'check again' button
     $url = 'admin.php?page=wpla-tools&tab=inventory&action=check_wc_out_of_sync&mode=' . $mode . '&prices=' . $compare_prices . '&_wpnonce=' . wp_create_nonce('wpla_tools_page');
     $msg .= '<a href="' . $url . '" class="button">' . __('Check again', 'wpla') . '</a> &nbsp; ';
     // show 'mark all as changed' button
     if ($mode == 'published') {
         if ($published_count) {
             $url = 'admin.php?page=wpla-tools&tab=inventory&action=check_wc_out_of_sync&mark_as_changed=yes&mode=' . $mode . '&prices=' . $compare_prices . '&_wpnonce=' . wp_create_nonce('wpla_tools_page');
             $msg .= '<a href="' . $url . '" class="button">' . __('Mark all as changed', 'wpla') . '</a> &nbsp; ';
             $msg .= 'Click this button to mark all found listings as changed in WP-Lister.';
         } else {
             // $msg .= '<a id="btn_revise_all_changed_items_reminder" class="btn_revise_all_changed_items_reminder button wpl_job_button">' . __('Revise all changed items','wpla') . '</a>';
             // $msg .= ' &nbsp; ';
             // $msg .= 'Click to revise all changed items.';
         }
     }
     $msg .= '</p>';
     WPLA()->showMessage($msg, 1, 1);
 }
 function update_products_on_shutdown()
 {
     // get queue
     $collected_products = get_option('wpla_updated_products_queue', array());
     if (!is_array($collected_products)) {
         $collected_products = array();
     }
     // DEBUG
     WPLA()->logger->info("CSV: update_products_on_shutdown() - collected_products: " . print_r($collected_products, 1));
     // mark each queued product as modified
     $lm = new WPLA_ListingsModel();
     foreach ($collected_products as $post_id) {
         // do_action( 'wpla_product_has_changed', $post_id );
         $lm->markItemAsModified($post_id, true);
         // set $skip_updating_feeds = true
     }
     // clear queue
     delete_option('wpla_updated_products_queue');
     // update pending feeds - after all items have been updated
     if (!empty($collected_products)) {
         WPLA_AmazonFeed::updatePendingFeeds();
     }
 }
 public function ajax_wpla_apply_lowest_price()
 {
     if (!current_user_can('edit_products')) {
         echo "You're not allowed to do this.";
         exit;
     }
     // TODO: check nonce
     if (isset($_REQUEST['post_id']) && isset($_REQUEST['new_price'])) {
         $post_id = $_REQUEST['post_id'];
         $listing_id = $_REQUEST['listing_id'];
         $new_price = $_REQUEST['new_price'];
         $price_type_select = $_REQUEST['price_type_select'];
         // apply new price
         if ('sale' == $price_type_select) {
             update_post_meta($post_id, '_price', $new_price);
             update_post_meta($post_id, '_sale_price', $new_price);
         } else {
             update_post_meta($post_id, '_price', $new_price);
             update_post_meta($post_id, '_regular_price', $new_price);
         }
         update_option('wpla_default_lowest_price_selection', $price_type_select);
         // mark item as modified - and reload status
         $lm = new WPLA_ListingsModel();
         $lm->markItemAsModified($post_id);
         $listing = $lm->getItem($listing_id, OBJECT);
         if ($listing) {
             // build response
             $response = new stdClass();
             $response->post_id = $post_id;
             $response->listing_id = $listing_id;
             $response->listing_status = $listing->status;
             $response->error_msg = false;
             $response->success = true;
             $this->returnJSON($response);
             exit;
         } else {
             if (isset($lm->lastError)) {
                 echo $lm->lastError . "\n";
             }
             echo "Failed to match product!";
         }
     }
 }
 function wpla_on_woocommerce_product_quick_edit_save($post_id, $post)
 {
     if (!$_POST) {
         return $post_id;
     }
     if (is_int(wp_is_post_revision($post_id))) {
         return;
     }
     if (is_int(wp_is_post_autosave($post_id))) {
         return;
     }
     if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
         return $post_id;
     }
     // if ( !isset($_POST['woocommerce_quick_edit_nonce']) || (isset($_POST['woocommerce_quick_edit_nonce']) && !wp_verify_nonce( $_POST['woocommerce_quick_edit_nonce'], 'woocommerce_quick_edit_nonce' ))) return $post_id;
     if (!current_user_can('edit_post', $post_id)) {
         return $post_id;
     }
     if ($post->post_type != 'product') {
         return $post_id;
     }
     // global $woocommerce, $wpdb;
     // $product = self::getProduct( $post_id );
     // don't mark as changed when listing has been revised earlier in this request
     // if ( isset( $_POST['wpla_amazon_revise_on_update'] ) ) return;
     $lm = new WPLA_ListingsModel();
     $lm->markItemAsModified($post_id);
     // Clear transient
     // $woocommerce->clear_product_transients( $post_id );
 }