function processListingItem($order_id, $ebay_id, $quantity_purchased, $data, $VariationSpecifics, $Transaction)
 {
     global $wpdb;
     $has_been_replenished = false;
     // check if this listing exists in WP-Lister
     $listing_id = $wpdb->get_var($wpdb->prepare("SELECT id FROM {$wpdb->prefix}ebay_auctions WHERE ebay_id = %s", $ebay_id));
     if (!$listing_id) {
         $history_message = "Skipped foreign item #{$ebay_id}";
         $history_details = array('ebay_id' => $ebay_id);
         $this->addHistory($order_id, 'skipped_item', $history_message, $history_details);
         return;
     }
     // get current values from db
     // $quantity_purchased = $data['quantity'];
     $quantity_total = $wpdb->get_var($wpdb->prepare("SELECT quantity      FROM {$wpdb->prefix}ebay_auctions WHERE ebay_id = %s", $ebay_id));
     $quantity_sold = $wpdb->get_var($wpdb->prepare("SELECT quantity_sold FROM {$wpdb->prefix}ebay_auctions WHERE ebay_id = %s", $ebay_id));
     // increase the listing's quantity_sold
     $quantity_sold = $quantity_sold + $quantity_purchased;
     $wpdb->update($wpdb->prefix . 'ebay_auctions', array('quantity_sold' => $quantity_sold), array('ebay_id' => $ebay_id));
     // add history record
     $history_message = "Sold quantity increased by {$quantity_purchased} for listing #{$ebay_id} - sold {$quantity_sold}";
     $history_details = array('ebay_id' => $ebay_id, 'quantity_sold' => $quantity_sold, 'quantity_total' => $quantity_total);
     $this->addHistory($order_id, 'reduce_stock', $history_message, $history_details);
     // mark listing as sold when last item is sold - unless Out Of Stock Control (oosc) is enabled
     if (!ListingsModel::thisAccountUsesOutOfStockControl($data['account_id'])) {
         if ($quantity_sold == $quantity_total && !$has_been_replenished) {
             // make sure this product is out of stock before we mark listing as sold - free version excluded
             $listing_item = ListingsModel::getItem($listing_id);
             if (WPLISTER_LIGHT || ListingsModel::checkStockLevel($listing_item) == false) {
                 $wpdb->update($wpdb->prefix . 'ebay_auctions', array('status' => 'sold', 'date_finished' => $data['date_created']), array('ebay_id' => $ebay_id));
                 WPLE()->logger->info('marked item #' . $ebay_id . ' as SOLD ');
             }
         }
     }
 }
 public function checkItem($item, $reviseItem = false)
 {
     $success = true;
     $this->VariationsHaveStock = false;
     // check StartPrice, Quantity and SKU
     if (is_object($item->Variations)) {
         // item has variations
         $VariationsHaveStock = false;
         $VariationsSkuArray = array();
         $VariationsSkuAreUnique = true;
         $VariationsSkuMissing = false;
         // check each variation
         foreach ($item->Variations->Variation as $var) {
             // StartPrice must be greater than 0
             if (self::dbSafeFloatval($var->StartPrice) == 0) {
                 $longMessage = __('Some variations seem to have no price.', 'wplister');
                 $success = false;
             }
             // Quantity must be greater than 0 - at least for one variation
             if (intval($var->Quantity) > 0) {
                 $VariationsHaveStock = true;
             }
             // SKUs must be unique - if present
             if ($var->SKU != '') {
                 if (in_array($var->SKU, $VariationsSkuArray)) {
                     $VariationsSkuAreUnique = false;
                 } else {
                     $VariationsSkuArray[] = $var->SKU;
                 }
             } else {
                 $VariationsSkuMissing = true;
             }
             // VariationSpecifics values can't be longer than 50 characters
             foreach ($var->VariationSpecifics->NameValueList as $spec) {
                 if (strlen($spec->Value) > 50) {
                     $longMessage = __('eBay does not allow attribute values longer than 50 characters.', 'wplister');
                     $longMessage .= '<br>';
                     $longMessage .= __('You need to shorten this value:', 'wplister') . ' <code>' . $spec->Value . '</code>';
                     $success = false;
                 }
             }
         }
         if (!$VariationsSkuAreUnique) {
             foreach ($item->Variations->Variation as &$var) {
                 $var->SKU = '';
             }
             $longMessage = __('You are using the same SKU for more than one variations which is not allowed by eBay.', 'wplister');
             $longMessage .= '<br>';
             $longMessage .= __('To circumvent this issue, your item will be listed without SKU.', 'wplister');
             // $success = false;
         }
         if ($VariationsSkuMissing) {
             $longMessage = __('Some variations are missing a SKU.', 'wplister');
             $longMessage .= '<br>';
             $longMessage .= __('It is required to assign a unique SKU to each variation to prevent issues syncing sales.', 'wplister');
             // $success = false;
         }
         if (!$VariationsHaveStock && !$reviseItem && !ListingsModel::thisAccountUsesOutOfStockControl($this->account_id)) {
             $longMessage = __('None of these variations are in stock.', 'wplister');
             $success = false;
         }
         // make this info available to reviseItem()
         $this->VariationsHaveStock = $VariationsHaveStock;
     } else {
         // item has no variations
         // StartPrice must be greater than 0
         if (self::dbSafeFloatval($item->StartPrice->value) == 0) {
             $longMessage = __('Price can not be zero.', 'wplister');
             $success = false;
         }
         // check minimum start price if found
         // $min_prices = get_option( 'wplister_MinListingStartPrices', array() );
         $min_prices = $this->site_id ? maybe_unserialize(WPLE_eBaySite::getSiteObj($this->site_id)->MinListingStartPrices) : array();
         if (!is_array($min_prices)) {
             $min_prices = array();
         }
         $listing_type = $item->ListingType ? $item->ListingType : 'FixedPriceItem';
         if (isset($min_prices[$listing_type])) {
             $min_price = $min_prices[$listing_type];
             if ($item->StartPrice->value < $min_price) {
                 $longMessage = sprintf(__('eBay requires a minimum price of %s for this listing type.', 'wplister'), $min_price);
                 $success = false;
             }
         }
     }
     // check if any required item specifics are missing
     $primary_category_id = $item->PrimaryCategory->CategoryID;
     $specifics = EbayCategoriesModel::getItemSpecificsForCategory($primary_category_id, $this->site_id, $this->account_id);
     foreach ($specifics as $req_spec) {
         // skip non-required specs
         if (!$req_spec->MinValues) {
             continue;
         }
         // skip if Name already exists in ItemSpecifics
         if (self::thisNameExistsInNameValueList($req_spec->Name, $item->ItemSpecifics->NameValueList)) {
             continue;
         }
         // skip if Name already exists in VariationSpecificsSet
         if (is_object($item->Variations)) {
             $VariationSpecificsSet = $item->Variations->getVariationSpecificsSet();
             if (self::thisNameExistsInNameValueList($req_spec->Name, $VariationSpecificsSet->NameValueList)) {
                 continue;
             }
         }
         $DoesNotApplyText = WPLE_eBaySite::getSiteObj($this->site_id)->DoesNotApplyText;
         $DoesNotApplyText = empty($DoesNotApplyText) ? 'Does not apply' : $DoesNotApplyText;
         // // add missing item specifics
         $NameValueList = new NameValueListType();
         $NameValueList->setName($req_spec->Name);
         $NameValueList->setValue($DoesNotApplyText);
         $item->ItemSpecifics->addNameValueList($NameValueList);
         wple_show_message('<b>Note:</b> Missing item specifics <b>' . $req_spec->Name . '</b> was set to "' . $DoesNotApplyText . '" in order to prevent listing errors.', 'warn');
     }
     // check if any item specific have more values than allowed
     foreach ($specifics as $req_spec) {
         // skip specs without limit
         if (!$req_spec->MaxValues) {
             continue;
         }
         // count values for this item specific
         $number_of_values = self::countValuesForNameInNameValueList($req_spec->Name, $item->ItemSpecifics->NameValueList);
         if ($number_of_values <= $req_spec->MaxValues) {
             continue;
         }
         // remove additional values from item specific
         for ($i = 0; $i < sizeof($item->ItemSpecifics->NameValueList); $i++) {
             if ($item->ItemSpecifics->NameValueList[$i]->Name != $req_spec->Name) {
                 continue;
             }
             $values_array = $item->ItemSpecifics->NameValueList[$i]->Value;
             $item->ItemSpecifics->NameValueList[$i]->Value = reset($values_array);
         }
         wple_show_message('<b>Note:</b> The item specifics <b>' . $req_spec->Name . '</b> has ' . $number_of_values . ' values, but eBay allows only ' . $req_spec->MaxValues . ' value(s).<br>In order to prevent listing errors, additional values will be omitted.', 'warn');
     }
     // ItemSpecifics values can't be longer than 50 characters
     foreach ($item->ItemSpecifics->NameValueList as $spec) {
         $values = is_array($spec->Value) ? $spec->Value : array($spec->Value);
         foreach ($values as $value) {
             if (strlen($value) > 50) {
                 $longMessage = __('eBay does not allow attribute values longer than 50 characters.', 'wplister');
                 $longMessage .= '<br>';
                 $longMessage .= __('You need to shorten this value:', 'wplister') . ' <code>' . $value . '</code>';
                 $success = false;
             }
         }
     }
     // PrimaryCategory->CategoryID must be greater than 0
     if (intval(@$item->PrimaryCategory->CategoryID) == 0) {
         $longMessage = __('There has been no primary category assigned.', 'wplister');
         $success = false;
     }
     // check for main image
     if (trim(@$item->PictureDetails->GalleryURL) == '') {
         $longMessage = __('You need to add at least one image to your product.', 'wplister');
         $success = false;
     }
     // remove ReservedPrice on fixed price items
     if ($item->getReservePrice() && $item->getListingType() == 'FixedPriceItem') {
         $item->setReservePrice(null);
         $longMessage = __('Reserve price does not apply to fixed price listings.', 'wplister');
         // $success = false;
     }
     // omit price and shipping cost when revising an item with promotional sale enabled
     if ($reviseItem && ListingsModel::thisListingHasPromotionalSale($this->listing_id)) {
         $item->setStartPrice(null);
         $item->setShippingDetails(null);
         wple_show_message(__('Price and shipping were omitted since this item has promotional sale enabled.', 'wplister'), 'info');
     }
     if (!$success && !$this->is_ajax()) {
         wple_show_message($longMessage, 'error');
     } elseif ($longMessage != '' && !$this->is_ajax()) {
         wple_show_message($longMessage, 'warn');
     }
     $htmlMsg = '<div id="message" class="error" style="display:block !important;"><p>';
     $htmlMsg .= '<b>' . 'This item did not pass the validation check' . ':</b>';
     $htmlMsg .= '<br>' . $longMessage . '';
     $htmlMsg .= '</p></div>';
     // save error as array of objects
     $errorObj = new stdClass();
     $errorObj->SeverityCode = 'Validation';
     $errorObj->ErrorCode = '42';
     $errorObj->ShortMessage = $longMessage;
     $errorObj->LongMessage = $longMessage;
     $errorObj->HtmlMessage = $htmlMsg;
     $errors = array($errorObj);
     // save results as local property
     $this->result = new stdClass();
     $this->result->success = $success;
     $this->result->errors = $errors;
     return $success;
 }