static function parseProductColumn($column, $item, $product, $profile)
 {
     wpla_logger_start_timer('parseProductColumn');
     $profile_fields = $profile ? maybe_unserialize($profile->fields) : array();
     $profile_details = $profile ? maybe_unserialize($profile->details) : array();
     $variations_mode = isset($profile_details['variations_mode']) ? $profile_details['variations_mode'] : 'default';
     $value = '';
     // handle FBA mode / fallback
     if (get_option('wpla_fba_enable_fallback') == 1) {
         // fallback enabled
         // if there is no FBA qty, FBA will be disabled
         $fba_enabled = $item['fba_quantity'] > 0 ? true : false;
         // if there is FBA qty, always enable FBA
     } else {
         // fallback disabled
         $fba_enabled = $item['fba_fcid'] && $item['fba_fcid'] != 'DEFAULT';
         // regard fba_fcid column - ignore stock
     }
     // if fulfillment_center_id is forced to AMAZON_NA in the listing profile,
     // make sure to set fba_enabled to regarding this overwrite in ListingLoader feeds as well
     if (isset($profile_fields['fulfillment_center_id']) && !empty($profile_fields['fulfillment_center_id'])) {
         $fba_enabled = $profile_fields['fulfillment_center_id'] == 'DEFAULT' ? false : true;
     }
     // get custom product level feed columns - and merge with profile columns
     $custom_feed_columns = get_post_meta($product->id, '_wpla_custom_feed_columns', true);
     if ($custom_feed_columns && is_array($custom_feed_columns) && !empty($custom_feed_columns)) {
         $profile_fields = array_merge($profile_fields, $custom_feed_columns);
     }
     // set correct post_id for variations
     $post_id = $product->id;
     if ($product->product_type == 'variation') {
         $post_id = $product->variation_id;
     }
     // process hard coded fields
     switch ($column) {
         case 'external_product_id':
             $value = get_post_meta($post_id, '_amazon_product_id', true);
             break;
         case 'external_product_id_type':
             $value = get_post_meta($post_id, '_amazon_id_type', true);
             // // leave id type empty if there is no product id (parent variations) (incompatible with amazon.in)
             // $external_product_id = WPLA()->memcache->getColumnValue( $product->sku, 'external_product_id' );
             // if ( empty( $external_product_id ) ) $value = '[---]';
             break;
         case 'sku':
             // update feed
         // update feed
         case 'item_sku':
             // new items feed
             // $value = $product->sku;
             $value = $item['sku'];
             // we have to use the item SKU - or feed processing would fail if SKU is different in WooCommerce and WP-Lister
             break;
         case 'price':
             // update feed
             // $value = $product->get_price();			// WC2.1+
             $value = $product->regular_price;
             // WC2.0
             $value = $profile ? $profile->processProfilePrice($value) : $value;
             $value = apply_filters('wpla_filter_product_price', $value, $post_id, $product, $item, $profile);
             if ($post_id != $product->id && ($product_value = get_post_meta($product->id, '_amazon_price', true))) {
                 // parent price
                 if ($product_value > 0) {
                     $value = $product_value;
                 }
             }
             if ($product_value = get_post_meta($post_id, '_amazon_price', true)) {
                 // variation price
                 if ($product_value > 0) {
                     $value = $product_value;
                 }
             }
             $value = $value ? round($value, 2) : $value;
             // make sure price stays within min/max boundaries - prevent errors in PNQ feed
             if ($item['min_price'] > 0) {
                 $value = max($value, $item['min_price']);
             }
             if ($item['max_price'] > 0) {
                 $value = min($value, $item['max_price']);
             }
             break;
         case 'sale-price':
             // update feed
         // update feed
         case 'sale_price':
             // new items feed
             // $value = $product->get_sale_price();		// WC2.1+
             $value = $product->sale_price;
             // WC2.0
             $value = $profile ? $profile->processProfilePrice($value) : $value;
             $value = apply_filters('wpla_filter_sale_price', $value, $post_id, $product, $item, $profile);
             $value = $value ? round($value, 2) : $value;
             // make sure sale_price is not higher than standard_price / price - Amazon might silently ignore price updates otherwise
             $standard_price = self::getStandardPriceForRow($product->sku);
             if ($standard_price && $value > $standard_price) {
                 $value = '';
             }
             // if no sale price is set, send regular price with sale end date in the past to remove previously sent sale prices
             if (empty($value)) {
                 $value = $standard_price;
             }
             break;
         case 'sale_from_date':
             // new items feed
         // new items feed
         case 'sale-start-date':
             // update feed
             $date = get_post_meta($post_id, '_sale_price_dates_from', true);
             if ($date) {
                 $value = date('Y-m-d', $date);
             }
             // if sale price exists but no start date, fill in 2011-01-01
             $has_sale_price = self::hasActiveSalePrice($product->sku);
             if (!$value && $has_sale_price) {
                 $value = '2011-01-01';
             }
             // fall back to default past date if standard price is set
             $standard_price = self::getStandardPriceForRow($product->sku);
             if (!$value && $standard_price) {
                 $value = '2000-01-01';
             }
             // default past date
             // if sale price is intentionally left blank by [---] shortcode, leave sale date blank as well
             $sale_price = self::getSalePriceForRow($product->sku);
             if (!$sale_price) {
                 $value = '';
             }
             break;
         case 'sale_end_date':
             // new items feed
         // new items feed
         case 'sale-end-date':
             // update feed
             $date = get_post_meta($post_id, '_sale_price_dates_to', true);
             if ($date) {
                 $value = date('Y-m-d', $date);
             }
             // if sale price exists but no end date, fill in 2029-12-31
             $has_sale_price = self::hasActiveSalePrice($product->sku);
             if (!$value && $has_sale_price) {
                 $value = '2029-12-31';
             }
             // fall back to default past date if standard price is set
             $standard_price = self::getStandardPriceForRow($product->sku);
             if (!$value && $standard_price) {
                 $value = '2000-01-02';
             }
             // default past date
             // if sale price is intentionally left blank by [---] shortcode, leave sale date blank as well
             $sale_price = self::getSalePriceForRow($product->sku);
             if (!$sale_price) {
                 $value = '';
             }
             break;
         case 'minimum-seller-allowed-price':
             $value = get_post_meta($post_id, '_amazon_minimum_price', true);
             break;
         case 'maximum-seller-allowed-price':
             $value = get_post_meta($post_id, '_amazon_maximum_price', true);
             break;
         case 'quantity':
             if (!$fba_enabled) {
                 $value = $product->product_type == 'variable' ? '' : intval($product->get_total_stock());
                 if ($value < 0) {
                     $value = 0;
                 }
                 // amazon doesn't allow negative values
             }
             break;
         case 'fulfillment_latency':
             // if qty is empty, make sure fulfillment_latency is empty as well (prevent error 99006)
             $quantity = WPLA()->memcache->getColumnValue($product->sku, 'quantity');
             if ($quantity === '') {
                 $value = '[---]';
             }
             if ($quantity === false) {
                 $value = '[---]';
             }
             break;
         case 'bullet_point1':
             $value = get_post_meta($product->id, '_amazon_bullet_point1', true);
             break;
         case 'bullet_point2':
             $value = get_post_meta($product->id, '_amazon_bullet_point2', true);
             break;
         case 'bullet_point3':
             $value = get_post_meta($product->id, '_amazon_bullet_point3', true);
             break;
         case 'bullet_point4':
             $value = get_post_meta($product->id, '_amazon_bullet_point4', true);
             break;
         case 'bullet_point5':
             $value = get_post_meta($product->id, '_amazon_bullet_point5', true);
             break;
         case 'generic_keywords1':
             $value = get_post_meta($product->id, '_amazon_generic_keywords1', true);
             break;
         case 'generic_keywords2':
             $value = get_post_meta($product->id, '_amazon_generic_keywords2', true);
             break;
         case 'generic_keywords3':
             $value = get_post_meta($product->id, '_amazon_generic_keywords3', true);
             break;
         case 'generic_keywords4':
             $value = get_post_meta($product->id, '_amazon_generic_keywords4', true);
             break;
         case 'generic_keywords5':
             $value = get_post_meta($product->id, '_amazon_generic_keywords5', true);
             break;
             // case 'standard_price':
             // 	$value = $product->get_price();
             // 	break;
             // case 'sale_price':
             // 	$value = $product->get_sale_price();
             // 	break;
         // case 'standard_price':
         // 	$value = $product->get_price();
         // 	break;
         // case 'sale_price':
         // 	$value = $product->get_sale_price();
         // 	break;
         case 'main_image_url':
             // $value = $product->get_image('full');
             $attachment_id = get_post_thumbnail_id($post_id);
             $image_url = wp_get_attachment_image_src($attachment_id, 'full');
             $value = @$image_url[0];
             // maybe fall back to parent variation featured image
             if (empty($value) && $product->product_type == 'variation') {
                 $attachment_id = get_post_thumbnail_id($product->id);
                 $image_url = wp_get_attachment_image_src($attachment_id, 'full');
                 $value = @$image_url[0];
             }
             // if main image is disabled, use first enabled gallery image
             $disabled_images = explode(',', get_post_meta($product->id, '_wpla_disabled_gallery_images', true));
             if (in_array($attachment_id, $disabled_images)) {
                 // $gallery_images = $product->get_gallery_attachment_ids();
                 $gallery_images = WPLA_ProductWrapper::getGalleryAttachmentIDs($product);
                 $gallery_images = array_values(array_diff($gallery_images, $disabled_images));
                 $gallery_images = apply_filters('wpla_product_gallery_attachment_ids', $gallery_images, $post_id);
                 if (isset($gallery_images[0])) {
                     $image_url = wp_get_attachment_image_src($gallery_images[0], 'full');
                     $value = @$image_url[0];
                 }
             }
             $value = apply_filters('wpla_product_main_image_url', $value, $post_id);
             $value = self::convertImageUrl($value);
             break;
         case 'other_image_url1':
         case 'other_image_url2':
         case 'other_image_url3':
         case 'other_image_url4':
         case 'other_image_url5':
         case 'other_image_url6':
         case 'other_image_url7':
         case 'other_image_url8':
             if ('skip' == get_option('wpla_product_gallery_first_image')) {
                 $image_index = substr($column, -1);
                 // skip first image
             } else {
                 $image_index = substr($column, -1) - 1;
                 // include first image
             }
             // build list of enabled gallery images (attachment_ids)
             $disabled_images = explode(',', get_post_meta($product->id, '_wpla_disabled_gallery_images', true));
             // $gallery_images = $product->get_gallery_attachment_ids();
             $gallery_images = WPLA_ProductWrapper::getGalleryAttachmentIDs($product);
             $gallery_images = array_values(array_diff($gallery_images, $disabled_images));
             $gallery_images = apply_filters('wpla_product_gallery_attachment_ids', $gallery_images, $post_id);
             if (isset($gallery_images[$image_index])) {
                 $image_url = wp_get_attachment_image_src($gallery_images[$image_index], 'full');
                 $value = @$image_url[0];
                 $value = self::convertImageUrl($value);
             }
             break;
             /* Inventory Loader (delete) feed columns */
         /* Inventory Loader (delete) feed columns */
         case 'add-delete':
             $value = $item['status'] == 'trash' ? 'x' : 'a';
             break;
             /* Listing Loader feed columns */
         /* Listing Loader feed columns */
         case 'product-id':
             $value = get_post_meta($post_id, '_wpla_asin', true);
             break;
         case 'product-id-type':
             if ($matched_asin = get_post_meta($post_id, '_wpla_asin', true)) {
                 $value = 'ASIN';
             } elseif ($custom_id_type = get_post_meta($post_id, '_amazon_id_type', true)) {
                 $value = $custom_id_type;
             } else {
                 $value = '';
             }
             break;
         case 'condition-type':
             // update feed (ListingLoader - no profile)
             $value = get_post_meta($product->id, '_amazon_condition_type', true);
             // if this item was imported but has no product level condition, use original report value
             if (!$value && $item['source'] == 'imported') {
                 $report_row = json_decode($item['details'], true);
                 if (is_array($report_row) && isset($report_row['item-condition'])) {
                     $value = WPLA_ImportHelper::convertNumericConditionIdToType($report_row['item-condition']);
                 }
             }
             if (!$value && !isset($profile_fields[$column])) {
                 $value = 'New';
                 // avoid an empty value for Offer feeds without profile
             }
             break;
         case 'condition_type':
             // new items feed
             $value = get_post_meta($product->id, '_amazon_condition_type', true);
             // if ( ! $value ) $value = 'New';
             break;
         case 'condition-note':
         case 'condition_note':
             // new items feed
             $value = get_post_meta($product->id, '_amazon_condition_note', true);
             break;
             /* FBA */
         /* FBA */
         case 'fulfillment-center-id':
             // ListingLoader
         // ListingLoader
         case 'fulfillment_center_id':
             // Category Feed
             if ($fba_enabled) {
                 $value = $item['fba_fcid'];
             }
             break;
             /* variation columns */
         /* variation columns */
         case 'parent-sku':
         case 'parent_sku':
             if ($item['parent_id']) {
                 $parent_product = get_product($item['parent_id']);
                 if ($parent_product) {
                     $value = $parent_product->sku;
                 }
             }
             if ($variations_mode == 'flat') {
                 $value = '';
             }
             break;
         case 'parentage':
         case 'parent_child':
             if ($product->product_type == 'variable') {
                 $value = 'parent';
             } elseif ($product->product_type == 'variation') {
                 $value = 'child';
             }
             if ($variations_mode == 'flat') {
                 $value = '';
             }
             break;
         case 'relationship-type':
         case 'relationship_type':
             if ($product->product_type == 'variation') {
                 $value = 'Variation';
             }
             if ($variations_mode == 'flat') {
                 $value = '';
             }
             break;
         case 'variation-theme':
         case 'variation_theme':
             $value = str_replace('-', '', $item['vtheme']);
             $value = self::convertToEnglishAttributeLabel($value);
             if (strtolower($value) == 'colour') {
                 $value = 'Color';
             }
             if (strtolower($value) == 'colorsize') {
                 $value = 'SizeColor';
             }
             if (strtolower($value) == 'coloursize') {
                 $value = 'SizeColor';
             }
             if ($variations_mode == 'flat') {
                 $value = '';
             }
             if (isset($profile_fields[$column]) && !empty($profile_fields[$column])) {
                 $value = $profile_fields[$column];
             }
             break;
         default:
             # code...
             break;
     }
     // handle variation attribute values / attribute columns
     if (in_array($product->product_type, array('variation', 'variable'))) {
         // if ( ( strpos( $column, '_name') > 0 ) || ( strpos( $column, '_type') > 0 ) ) {
         if (substr($column, -5) == '_name' || substr($column, -5) == '_type') {
             wpla_logger_start_timer('parseVariationAttributeColumn');
             $value = self::parseVariationAttributeColumn($value, $column, $item, $product);
             wpla_logger_end_timer('parseVariationAttributeColumn');
         }
     }
     // forced empty value (fulfillment_latency)
     // (why is '[---]' == 0 true? should be false - be careful...)
     if ('[---]' === $value) {
         return '';
     }
     // process profile fields - if not empty
     if (!isset($profile_fields[$column]) || empty($profile_fields[$column])) {
         return $value;
     }
     // empty shortcode overrides default value
     if ('[---]' === $profile_fields[$column]) {
         return '';
     }
     // use profile value as it is - if $value is still empty (ie. there is no product level value for this column)
     if (empty($value)) {
         $value = $profile_fields[$column];
     }
     // find and parse all placeholders
     if (preg_match_all('/\\[([^\\]]+)\\]/', $value, $matches)) {
         foreach ($matches[0] as $placeholder) {
             // echo "<pre>processing ";print_r($placeholder);echo"</pre>";
             wpla_logger_start_timer('parseProfileShortcode');
             $value = self::parseProfileShortcode($value, $placeholder, $item, $product, $post_id, $profile);
             wpla_logger_end_timer('parseProfileShortcode');
             // echo "<pre>";print_r($value);echo"</pre>";#die();
         }
     }
     // parent variations should only have certain columns
     // these three seem to work on Amazon CA / Automotive: item_sku, parent_child, variation_theme
     // but on US and DE, more columns are required:
     // $parent_var_columns = array('item_sku','parent_child','variation_theme'); // CA
     $parent_var_columns = array('item_sku', 'parent_child', 'variation_theme', 'brand_name', 'item_name', 'department_name', 'product_description', 'item_type', 'feed_product_type', 'bullet_point1', 'bullet_point2', 'bullet_point3', 'bullet_point4', 'bullet_point5', 'special_features1', 'special_features2', 'special_features3', 'special_features4', 'special_features5', 'style_name', 'closure_type', 'lifestyle', 'material_type', 'material_type1', 'pattern_type', 'model_year', 'shoe_dimension_unit_of_measure');
     if ($product->product_type == 'variable' && !in_array($column, $parent_var_columns)) {
         $value = '';
     }
     wpla_logger_end_timer('parseProductColumn');
     return $value;
 }
 public function updateProductFromItem($item, $report_row)
 {
     global $woocommerce;
     WPLA()->logger->info("==============================================================================");
     //WPLA()->logger->info( "updateProductFromItem() - ID: ".$data['asin'] );
     // some shortcuts
     $asin = $item->asin;
     $product_id = $item->post_id;
     $amazon_name = $item->listing_title;
     $amazon_price = $item->price;
     $amazon_quantity = $item->quantity;
     $report_quantity = $report_row['quantity'];
     $updated = false;
     // get WC product for reference
     $product = $this->getProduct($product_id);
     if (!$product) {
         return;
     }
     // echo "<pre>";print_r($product);echo"</pre>";#die();
     // get options
     $reports_update_woo_stock = get_option('wpla_reports_update_woo_stock', 1) == 1 ? true : false;
     $reports_update_woo_price = get_option('wpla_reports_update_woo_price', 1) == 1 ? true : false;
     $reports_update_woo_condition = get_option('wpla_reports_update_woo_condition', 1) == 1 ? true : false;
     //
     // update item-condition - if enabled
     //
     if ($reports_update_woo_condition) {
         $amazon_condition_type = WPLA_ImportHelper::convertNumericConditionIdToType($report_row['item-condition']);
         update_post_meta($product_id, '_amazon_condition_type', $amazon_condition_type);
         $amazon_condition_note = WPLA_ListingsModel::convertToUTF8($report_row['item-note']);
         update_post_meta($product_id, '_amazon_condition_note', $amazon_condition_note);
         WPLA()->logger->info("updated condition for product {$product_id}: {$amazon_condition_type} / " . $amazon_condition_note);
         // WPLA()->logger->info( "stored condition note: " . get_post_meta( $product_id, '_amazon_condition_note', true ) );
     }
     //
     // update price - if enabled
     //
     if ($reports_update_woo_price) {
         // if this item has a profile, we need to apply the price modifiers to the product price
         $product_price = $product->price;
         $profile = $item->profile_id ? new WPLA_AmazonProfile($item->profile_id) : false;
         if ($profile) {
             $product_price = $profile->processProfilePrice($product_price);
             $amazon_price = $profile->reverseProfilePrice($amazon_price);
         }
         // update price - unless custom amazon price is set
         if ($product_price != $amazon_price) {
             if (!get_post_meta($product_id, '_amazon_price', true)) {
                 update_post_meta($product_id, '_price', $amazon_price);
                 update_post_meta($product_id, '_regular_price', $amazon_price);
                 WPLA()->logger->info("updated price for product {$product_id} - new price: " . $amazon_price);
                 $updated = true;
             }
         }
     }
     // if update price
     //
     // update stock - if enabled and the report quantity column is not empty
     //
     if ($reports_update_woo_stock && $report_quantity !== '' && $report_quantity !== false) {
         if ($product->stock != $amazon_quantity) {
             update_post_meta($product_id, '_stock', $amazon_quantity);
             WPLA()->logger->info("updated stock for product {$product_id} - new stock: " . $amazon_quantity);
             $updated = true;
         }
         // update out of stock attribute
         if ($amazon_quantity > 0) {
             $stock_status = 'instock';
         } elseif ($item->product_type == 'variable') {
             $stock_status = 'instock';
         } else {
             $stock_status = 'outofstock';
         }
         update_post_meta($product_id, '_stock_status', $stock_status);
     }
     if ($updated) {
         // $woocommerce->clear_product_transients( $product_id );
         if (function_exists('wc_delete_product_transients')) {
             wc_delete_product_transients($product_id);
         }
         WPLA()->logger->info("updated product {$product_id} ({$asin}): {$amazon_name} ");
         $this->updated_count++;
     }
     return $product_id;
 }