public function processListingDataResults($feed_rows, $result_rows)
 {
     $lm = new WPLA_ListingsModel();
     // index results by SKU
     $results = array();
     foreach ($result_rows as $r) {
         if (!isset($r['sku']) && isset($r['SKU'])) {
             $r['sku'] = $r['SKU'];
         }
         // translate column SKU -> sku
         if (!isset($r['sku']) || empty($r['sku'])) {
             continue;
         }
         $results[$r['sku']][] = $r;
         WPLA()->logger->info('result sku: ' . $r['sku']);
     }
     // process each result row
     foreach ($feed_rows as $row) {
         $listing_data = array();
         $row_sku = isset($row['item_sku']) ? $row['item_sku'] : $row['sku'];
         if (!$row_sku) {
             WPLA()->logger->warn('skipping row without SKU: ' . print_r($row, 1));
             continue;
         }
         $row_results = isset($results[$row_sku]) ? $results[$row_sku] : false;
         WPLA()->logger->info('processing feed sku: ' . $row_sku);
         // check if this is a delete feed (Inventory Loader)
         $add_delete_column = isset($row['add-delete']) ? $row['add-delete'] : '';
         $is_delete_feed = $add_delete_column == 'x' ? true : false;
         // if there are no result rows for this SKU, set status to 'online'
         if (!$row_results) {
             if ($is_delete_feed) {
                 $listing = $lm->getItemBySKU($row_sku);
                 if (!$listing) {
                     continue;
                 }
                 if ($listing->status == 'trashed') {
                     $lm->deleteItem($listing->id);
                     WPLA()->logger->info('DELETED listing ID ' . $listing->id . ' SKU: ' . $row_sku);
                 } else {
                     WPLA()->logger->warn('INVALID listing status for deletion - ID ' . $listing->id . ' / SKU: ' . $row_sku . ' / status: ' . $listing->status);
                 }
                 continue;
             }
             $listing_data['status'] = 'online';
             $listing_data['history'] = '';
             $lm->updateWhere(array('sku' => $row_sku, 'account_id' => $this->account_id), $listing_data);
             WPLA()->logger->info('changed status to online: ' . $row_sku);
             continue;
         }
         // handle errors and warnings
         $errors = array();
         $warnings = array();
         $processed_keys = array();
         foreach ($row_results as $row_result) {
             // translate error-type
             if ($row_result['error-type'] == 'Fehler') {
                 $row_result['error-type'] = 'Error';
             }
             // amazon.de
             if ($row_result['error-type'] == 'Warnung') {
                 $row_result['error-type'] = 'Warning';
             }
             if ($row_result['error-type'] == 'Erreur') {
                 $row_result['error-type'] = 'Error';
             }
             // amazon.fr
             if ($row_result['error-type'] == 'Avertissement') {
                 $row_result['error-type'] = 'Warning';
             }
             // compute hash to identify duplicate errors
             $row_key = md5($row_result['sku'] . $row_result['error-code'] . $row_result['error-type'] . $row_result['original-record-number']);
             // store feed id in error array
             $row_result['feed_id'] = $this->id;
             if ('Error' == $row_result['error-type']) {
                 WPLA()->logger->info('error: ' . $row_sku . ' - ' . $row_key . ' - ' . $row_result['error-message']);
                 if (!in_array($row_key, $processed_keys)) {
                     $errors[] = $row_result;
                     $processed_keys[] = $row_key;
                 }
             } elseif ('Warning' == $row_result['error-type']) {
                 WPLA()->logger->info('warning: ' . $row_sku . ' - ' . $row_key . ' - ' . $row_result['error-message']);
                 if (!in_array($row_key, $processed_keys)) {
                     $warnings[] = $row_result;
                     $processed_keys[] = $row_key;
                 }
             }
         }
         // foreach result row
         // update listing
         if (!empty($errors)) {
             $listing_data['status'] = 'failed';
             $listing_data['history'] = serialize(array('errors' => $errors, 'warnings' => $warnings));
             $lm->updateWhere(array('sku' => $row_sku, 'account_id' => $this->account_id), $listing_data);
             WPLA()->logger->info('changed status to FAILED: ' . $row_sku);
             $this->errors = array_merge($this->errors, $errors);
             $this->warnings = array_merge($this->warnings, $warnings);
         } elseif (!empty($warnings)) {
             $listing_data['status'] = $is_delete_feed ? 'trashed' : 'online';
             $listing_data['history'] = serialize(array('errors' => $errors, 'warnings' => $warnings));
             $lm->updateWhere(array('sku' => $row_sku, 'account_id' => $this->account_id), $listing_data);
             WPLA()->logger->info('changed status to online: ' . $row_sku);
             $this->warnings = array_merge($this->warnings, $warnings);
         }
     }
     // foreach row
 }
 public function findMissingProducts()
 {
     $items = WPLA_ListingQueryHelper::findMissingProducts();
     $mode = isset($_REQUEST['mode']) ? $_REQUEST['mode'] : false;
     if ($mode == 'delete') {
         foreach ($items as $item) {
             WPLA_ListingsModel::deleteItem($item->id);
         }
         wpla_show_message(sizeof($items) . ' items have been deleted.');
         return;
     }
     if ($mode == 'import') {
         foreach ($items as $item) {
             $data = array('status' => 'imported');
             WPLA_ListingsModel::updateWhere(array('id' => $item->id), $data);
         }
         wpla_show_message(sizeof($items) . ' items have been added to the import queue.');
         return;
     }
     if (!empty($items)) {
         $nonce = wp_create_nonce('wpla_tools_page');
         $btn_delete = '<a href="admin.php?page=wpla-tools&tab=inventory&action=wpla_check_for_missing_products&mode=delete&_wpnonce=' . $nonce . '" class="button button-small button-secondary">' . 'Delete all from DB' . '</a> &nbsp; ';
         $btn_import = '<a href="admin.php?page=wpla-tools&tab=inventory&action=wpla_check_for_missing_products&mode=import&_wpnonce=' . $nonce . '" class="button button-small button-primary"  >' . 'Add to import queue' . '</a>';
         $buttons = ' &nbsp; ' . $btn_delete . $btn_import;
         wpla_show_message('There are ' . sizeof($items) . ' listing(s) without a linked product in WooCommerce.' . $buttons, 'error');
     } else {
         wpla_show_message('No missing products found.');
     }
 }
 public function handleActions()
 {
     // handle save listing
     if ($this->requestAction() == 'save_listing') {
         $this->saveListing();
     }
     // trigger create product
     if ($this->requestAction() == 'create_product') {
         $lm = new WPLA_ListingsModel();
         $listing = $lm->getItem($_REQUEST['listing']);
         if (!$listing) {
             return;
         }
         // create product
         $ProductsImporter = new WPLA_ProductsImporter();
         $success = $ProductsImporter->createProductFromAmazonListing($listing);
         $error = $ProductsImporter->lastError;
         $post_id = $ProductsImporter->lastPostID;
         $message = $ProductsImporter->message;
         if ($success) {
             // get parent post_id - for View Product button
             $_product = get_product($post_id);
             if ('variation' == $_product->product_type) {
                 $post_id = $_product->parent->id;
             }
             $msg = $message ? $message : sprintf(__('A new product (ID %s) was created for ASIN %s.', 'wpla'), $post_id, $listing['asin']);
             $msg .= sprintf('&nbsp;&nbsp;<a href="post.php?post=%s&action=edit" class="button button-small" target="_blank">%s</a>', $post_id, __('View product', 'wpla'));
             $this->showMessage($msg);
         } else {
             $error_msg = sprintf(__('Item %s could not be imported.', 'wpla'), $listing['asin']) . '<br>Error: ' . $error;
             $this->showMessage($error_msg, 1);
         }
     }
     // handle update from Amazon action
     if ($this->requestAction() == 'update') {
         // $this->initAC();
         // $this->EC->updateItemsFromEbay( $_REQUEST['listing'] );
         // $this->EC->closeEbay();
         // $this->showMessage( __('Selected items were updated from Amazon.','wpla') );
         $this->showMessage(__('Not implemented yet.', 'wpla'));
     }
     // handle delete action
     if ($this->requestAction() == 'delete') {
         $lm = new WPLA_ListingsModel();
         if (is_array($_REQUEST['listing'])) {
             foreach ($_REQUEST['listing'] as $id) {
                 $lm->deleteItem($id);
             }
         } elseif (is_numeric($_REQUEST['listing'])) {
             $lm->deleteItem($_REQUEST['listing']);
         }
         $this->showMessage(__('Selected listings were removed from WP-Lister.', 'wpla'));
     }
     // handle trash_listing action
     if ($this->requestAction() == 'trash_listing') {
         $items = is_array($_REQUEST['listing']) ? $_REQUEST['listing'] : array($_REQUEST['listing']);
         $lm = new WPLA_ListingsModel();
         foreach ($items as $id) {
             $lm->updateWhere(array('id' => $id), array('status' => 'trash'));
         }
         $this->showMessage(__('Selected items have been scheduled to be removed from your Amazon account.', 'wpla'));
     }
     // handle resubmit action
     if ($this->requestAction() == 'resubmit') {
         $items = is_array($_REQUEST['listing']) ? $_REQUEST['listing'] : array($_REQUEST['listing']);
         $lm = new WPLA_ListingsModel();
         foreach ($items as $id) {
             $lm->resubmitItem($id);
         }
         $this->showMessage(__('Selected items were prepared for resubmission.', 'wpla'));
     }
     if ($this->requestAction() == 'resubmit_all_failed') {
         $lm = new WPLA_ListingsModel();
         $items = $lm->getWhere('status', 'failed');
         foreach ($items as $item) {
             $lm->resubmitItem($item->id);
         }
         $this->showMessage(sprintf(__('%s failed items were prepared for resubmission.', 'wpla'), count($items)));
     }
     if ($this->requestAction() == 'wpla_clear_import_queue') {
         $lm = new WPLA_ListingsModel();
         $items = $lm->getWhere('status', 'imported');
         foreach ($items as $item) {
             $lm->deleteItem($item->id);
         }
         $this->showMessage(sprintf(__('%s items have been removed from the import queue.', 'wpla'), count($items)));
     }
     // handle toolbar action - prepare listing from product
     if ($this->requestAction() == 'wpla_prepare_single_listing') {
         // get profile
         $profile = isset($_REQUEST['profile_id']) ? WPLA_AmazonProfile::getProfile($_REQUEST['profile_id']) : false;
         if ($profile) {
             // prepare product
             $listingsModel = new WPLA_ListingsModel();
             $success = $listingsModel->prepareProductForListing($_REQUEST['product_id'], $_REQUEST['profile_id']);
             // $listingsModel->applyProfileToNewListings( $profile );
             if ($success) {
                 $this->showMessage(__('New listing was prepared from product.', 'wpla'));
             } else {
                 $this->showMessage(join('<br>', $listingsModel->warnings), 1);
             }
         }
     }
     // handle bulk action - get_compet_price
     if ($this->requestAction() == 'get_compet_price') {
         $this->get_compet_price();
         $this->get_lowest_offers();
         // do both
     }
     // handle bulk action - get_lowest_offers
     if ($this->requestAction() == 'get_lowest_offers') {
         $this->get_lowest_offers();
     }
     // handle wpla_dismiss_imported_products_notice action
     if ($this->requestAction() == 'wpla_dismiss_imported_products_notice') {
         self::updateOption('dismiss_imported_products_notice', '1');
     }
 }