public function applyProfileToItem($profile, $item, $update_title = true) { global $wpdb; // get item data $id = $item['id']; $post_id = $item['post_id']; $status = WPLE_ListingQueryHelper::getStatus($id); $ebay_id = self::getEbayIDFromID($id); $post_title = get_the_title($item['post_id']); WPLE()->logger->info("applyProfileToItem() - listing_id: {$id} / post_id: {$post_id}"); // WPLE()->logger->callStack( debug_backtrace() ); // skip ended auctions - or not, if you want to relist them... // if ( $status == 'ended' ) return; // use parent title for single (split) variation if (ProductWrapper::isSingleVariation($post_id)) { $parent_id = ProductWrapper::getVariationParent($post_id); $post_title = get_the_title($parent_id); // check if parent product has a custom eBay title set if (get_post_meta($parent_id, '_ebay_title', true)) { $post_title = trim(get_post_meta($parent_id, '_ebay_title', true)); } // get variations $variations = ProductWrapper::getVariations($parent_id); // find this variation in all variations of this parent foreach ($variations as $var) { if ($var['post_id'] == $post_id) { // append attribute values to title $post_title = self::processSingleVariationTitle($post_title, $var['variation_attributes']); } } } // gather profile data $data = array(); $data['profile_id'] = $profile['profile_id']; $data['account_id'] = $profile['account_id']; $data['site_id'] = $profile['site_id']; $data['auction_type'] = $profile['type']; $data['listing_duration'] = $profile['listing_duration']; $data['template'] = $profile['details']['template']; $data['quantity'] = $profile['details']['quantity']; $data['date_created'] = date('Y-m-d H:i:s'); $data['profile_data'] = self::encodeObject($profile); // echo "<pre>";print_r($data);echo"</pre>";die(); // add prefix and suffix to product title if ($update_title) { // append space to prefix, prepend space to suffix // TODO: make this an option $title_prefix = trim($profile['details']['title_prefix']) . ' '; $title_suffix = ' ' . trim($profile['details']['title_suffix']); // custom post meta fields override profile values if (get_post_meta($post_id, 'ebay_title_prefix', true)) { $title_prefix = trim(get_post_meta($post_id, 'ebay_title_prefix', true)) . ' '; } if (get_post_meta($post_id, 'ebay_title_suffix', true)) { $title_prefix = trim(get_post_meta($post_id, 'ebay_title_suffix', true)) . ' '; } $data['auction_title'] = trim($title_prefix . $post_title . $title_suffix); // custom post meta title override if (get_post_meta($post_id, '_ebay_title', true)) { $data['auction_title'] = trim(get_post_meta($post_id, '_ebay_title', true)); } elseif (get_post_meta($post_id, 'ebay_title', true)) { $data['auction_title'] = trim(get_post_meta($post_id, 'ebay_title', true)); } // process attribute shortcodes in title - like [[attribute_Brand]] if (strpos($data['auction_title'], ']]') > 0) { $templatesModel = new TemplatesModel(); WPLE()->logger->info('auction_title before processing: ' . $data['auction_title'] . ''); $data['auction_title'] = $templatesModel->processAllTextShortcodes($item['post_id'], $data['auction_title'], 80); } WPLE()->logger->info('auction_title after processing : ' . $data['auction_title'] . ''); // trim title to 255 characters - longer titles will break $wpdb->update() if (strlen($data['auction_title']) > 255) { $data['auction_title'] = self::mb_substr($data['auction_title'], 0, 80); // eBay titles can not be longer than 80 characters } } // apply profile price $data['price'] = ProductWrapper::getPrice($post_id); $data['price'] = self::applyProfilePrice($data['price'], $profile['details']['start_price']); // fetch product stock if no quantity set in profile - and apply max_quantity limit if (intval($data['quantity']) == 0) { $max = isset($profile['details']['max_quantity']) && intval($profile['details']['max_quantity']) > 0 ? $profile['details']['max_quantity'] : PHP_INT_MAX; $data['quantity'] = min($max, intval(ProductWrapper::getStock($post_id))); // update listing quantity properly - using setListingQuantity() which regards current quantity_sold self::setListingQuantity($post_id, $data['quantity']); unset($data['quantity']); } // default new status is 'prepared' $data['status'] = 'prepared'; // except for already published items where it is 'changed' if (intval($ebay_id) > 0) { $data['status'] = 'changed'; } // ended items stay 'ended' and sold items stay sold if ($status == 'ended') { $data['status'] = 'ended'; } if ($status == 'sold') { $data['status'] = 'sold'; } if ($status == 'archived') { $data['status'] = 'archived'; } // locked items simply keep their status if (@$item['locked']) { $data['status'] = $status; } // but if apply_changes_to_all_locked checkbox is ticked, even locked published items will be marked as 'changed' if (@$item['locked'] && $status == 'published' && isset($_POST['wpl_e2e_apply_changes_to_all_locked'])) { $data['status'] = 'changed'; } // except for selected items which shouldn't be locked in the first place if ($status == 'selected') { $data['status'] = 'prepared'; } // and reselected items which have already been 'ended' if ($status == 'reselected') { $data['status'] = 'ended'; } // and items which have already been 'changed' and now had a new profile applied if ($status == 'changed_profile') { $data['status'] = 'changed'; } // debug if ($status != $data['status']) { WPLE()->logger->info('applyProfileToItem(' . $id . ') old status: ' . $status); WPLE()->logger->info('applyProfileToItem(' . $id . ') new status: ' . $data['status']); } // update auctions table $wpdb->update($this->tablename, $data, array('id' => $id)); // WPLE()->logger->info('updating listing ID '.$id); // WPLE()->logger->info('data: '.print_r($data,1)); // WPLE()->logger->info('sql: '.$wpdb->last_query); // WPLE()->logger->info('error: '.$wpdb->last_error); }
public function checkProductInventory($mode = 'published', $compare_prices = false, $step = 0) { $batch_size = get_option('wplister_inventory_check_batch_size', 200); $limit = $batch_size; $offset = $batch_size * $step; // get listings - or return false $lm = new ListingsModel(); $listings = $mode == 'published' ? WPLE_ListingQueryHelper::getAllPublished($limit, $offset) : WPLE_ListingQueryHelper::getAllEnded($limit, $offset); if (empty($listings)) { return false; } // restore previous data $tmp_result = get_option('wple_inventory_check_queue_data', false); if ($tmp_result) { $out_of_sync_products = $tmp_result['out_of_sync_products']; $published_count = $tmp_result['published_count']; } else { $out_of_sync_products = array(); $published_count = 0; } // process published listings foreach ($listings as $item) { // check wc product $post_id = $item['post_id']; $_product = ProductWrapper::getProduct($post_id); // echo "<pre>";print_r($_product);echo"</pre>";die(); // get stock level and price $stock = ProductWrapper::getStock($item['post_id']); $price = 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(); // apply profile settings to stock level $profile_data = ListingsModel::decodeObject($item['profile_data'], true); $profile_details = $profile_data['details']; $item['qty'] = $item['quantity'] - $item['quantity_sold']; // echo "<pre>";print_r($profile_details);echo"</pre>";#die(); // apply max_quantity from profile $max_quantity = isset($profile_details['max_quantity']) && intval($profile_details['max_quantity']) > 0 ? $profile_details['max_quantity'] : false; if ($max_quantity) { $stock = min($max_quantity, intval($stock)); } // apply price modified from profile $profile_start_price = isset($profile_details['start_price']) && !empty($profile_details['start_price']) ? $profile_details['start_price'] : false; if ($profile_start_price) { // echo "<pre>price: ";print_r($profile_start_price);echo"</pre>";#die(); } // check if product has variations if ($_product) { $variations = $_product->product_type == 'variable' ? ProductWrapper::getVariations($item['post_id']) : array(); } else { $variations = array(); } // get total stock for all variations if (!empty($variations)) { // reset prices and stock $stock = 0; $price_min = PHP_INT_MAX; $price_max = 0; $ebay_stock = 0; $ebay_price_min = PHP_INT_MAX; $ebay_price_max = 0; // check WooCommerce variations foreach ($variations as $var) { // total stock if ($max_quantity) { $stock += min($max_quantity, intval($var['stock'])); } else { $stock += $var['stock']; } // min / max prices $price_min = min($price_min, $var['price']); $price_max = max($price_max, $var['price']); } // check eBay variations $cached_variations = maybe_unserialize($item['variations']); if (is_array($cached_variations)) { foreach ($cached_variations as $var) { $ebay_stock += $var['stock']; $ebay_price_min = min($ebay_price_min, $var['price']); $ebay_price_max = max($ebay_price_max, $var['price']); } } // set default values $item['qty'] = $ebay_stock; $item['price'] = $ebay_price_min != PHP_INT_MAX ? $ebay_price_min : 0; $item['price_max'] = $ebay_price_max; // echo "<pre>";print_r($cached_variations);echo"</pre>";die(); } else { $price_min = false; $price_max = false; $ebay_price_min = false; $ebay_price_max = false; } // check if product and ebay listing are in sync $in_sync = true; // check stock level if ($stock != $item['qty']) { $in_sync = false; } // check price if ($compare_prices) { $price_to_compare = $price; if ($profile_start_price) { $price_to_compare = ListingsModel::applyProfilePrice($price, $profile_start_price); } if (round($price_to_compare, 2) != round($item['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']) && $_REQUEST['mark_as_changed'] == 'yes') { if ($_product) { // only existing products can have a profile re-applied $lm->markItemAsModified($item['post_id']); } // in case the product is locked or missing, force the listing to be changed ListingsModel::updateListing($item['id'], array('status' => 'changed')); $item['status'] = 'changed'; } // remove unneccessary data to consume less memory - doesn't seem to work... // unset( $item['profile_data'] ); // unset( $item['post_content'] ); // unset( $item['details'] ); // unset( $item['variations'] ); // unset( $item['last_errors'] ); // unset( $item['history'] ); // unset( $item['eps'] ); // unset( $item['template'] ); // 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['profile_start_price'] = $profile_start_price; $out_of_sync_products[] = $item; // count products which have not yet been marked as changed if ($item['status'] == 'published') { $published_count += 1; } } // store result so far $tmp_result = array('mode' => $mode, 'compare_prices' => $compare_prices, 'out_of_sync_products' => $out_of_sync_products, 'published_count' => $published_count); update_option('wple_inventory_check_queue_data', $tmp_result, 'no'); // true means we processed more items return true; }
function buildItem($id, $session, $reviseItem = false, $preview = false) { // fetch record from db $listing = ListingsModel::getItem($id); $post_id = $listing['post_id']; $profile_details = $listing['profile_data']['details']; $hasVariations = ProductWrapper::hasVariations($post_id); $isVariation = ProductWrapper::isSingleVariation($post_id); // remember listing id and account id for checkItem() and buildPayment() $this->listing_id = $id; $this->account_id = $listing['account_id']; // adjust profile details from product level options $profile_details = $this->adjustProfileDetails($id, $post_id, $profile_details); // create Item $item = new ItemType(); // set quantity // $item->Quantity = $listing['quantity']; // get current quantity from WooCommerce $woocom_stock = ProductWrapper::getStock($post_id); // get max_quantity from profile $max_quantity = isset($profile_details['max_quantity']) && intval($profile_details['max_quantity']) > 0 ? $profile_details['max_quantity'] : PHP_INT_MAX; $item->Quantity = min($max_quantity, intval($woocom_stock)); // handle fixed quantity if (intval($profile_details['quantity']) > 0) { $item->Quantity = $profile_details['quantity']; } if ($item->Quantity < 0) { $item->Quantity = 0; } // prevent error for negative qty // set listing title $item->Title = $this->prepareTitle($listing['auction_title']); // set listing duration $product_listing_duration = get_post_meta($post_id, '_ebay_listing_duration', true); $item->ListingDuration = $product_listing_duration ? $product_listing_duration : $listing['listing_duration']; // omit ListingType when revising item if (!$reviseItem) { $product_listing_type = get_post_meta($post_id, '_ebay_auction_type', true); $ListingType = $product_listing_type ? $product_listing_type : $listing['auction_type']; // handle classified ads if ($ListingType == 'ClassifiedAd') { $ListingType = 'LeadGeneration'; $item->setListingSubtype2('ClassifiedAd'); } $item->setListingType($ListingType); } // set eBay Site $item = $this->setEbaySite($item, $session); // add prices $item = $this->buildPrices($id, $item, $post_id, $profile_details, $listing); // add images $item = $this->buildImages($id, $item, $post_id, $profile_details, $session); // if this is a split variation, use parent post_id for all further processing if ($isVariation) { // prepare item specifics / variation attributes $this->prepareSplitVariation($id, $post_id, $listing); // use parent post_id for all further processing $post_id = ProductWrapper::getVariationParent($post_id); } // add various options from $profile_details $item = $this->buildProfileOptions($item, $profile_details); // add various options that depend on $profile_details and $post_id $item = $this->buildProductOptions($id, $item, $post_id, $profile_details, $listing, $hasVariations, $isVariation); // add payment and return options $item = $this->buildPayment($item, $profile_details); // add shipping services and options $item = $this->buildShipping($id, $item, $post_id, $profile_details, $listing, $isVariation); // add seller profiles $item = $this->buildSellerProfiles($id, $item, $post_id, $profile_details); // add ebay categories and store categories $item = $this->buildCategories($id, $item, $post_id, $profile_details); // add variations if ($hasVariations) { if (@$profile_details['variations_mode'] == 'flat') { // don't build variations - list as flat item $item = $this->flattenVariations($id, $item, $post_id, $profile_details); } else { // default: list as variations $item = $this->buildVariations($id, $item, $profile_details, $listing, $session); } } // add item specifics (attributes) - after variations $item = $this->buildItemSpecifics($id, $item, $listing, $post_id); // add part compatibility list $item = $this->buildCompatibilityList($id, $item, $listing, $post_id); // set listing description - after $item has been built $item->Description = $this->getFinalHTML($id, $item, $preview); // adjust item if this is a ReviseItem request if ($reviseItem) { $item = $this->adjustItemForRevision($id, $item, $profile_details, $listing); } else { $item = $this->buildSchedule($item, $profile_details); } // add UUID to prevent duplicate AddItem or RelistItem calls if (!$reviseItem) { // build UUID from listing Title, product_id, previous ItemID and today's date and hour $uuid_src = $item->Title . $post_id . $listing['ebay_id'] . date('Y-m-d h'); $item->setUUID(md5($uuid_src)); WPLE()->logger->info('UUID src: ' . $uuid_src); } // filter final item object before it's sent to eBay $item = apply_filters('wplister_filter_listing_item', $item, $listing, $profile_details, $post_id); $item = apply_filters('wple_filter_listing_item', $item, $listing, $profile_details, $post_id, $reviseItem); return $item; }