public function removeAllImportedProducts() { global $wpdb; $listing_ids = $wpdb->get_col("\n SELECT al.id\n FROM {$wpdb->prefix}amazon_listings al\n WHERE al.source = 'imported'\n OR al.source = 'foreign_import'\n "); $post_ids = $wpdb->get_col("\n SELECT pm.post_id\n FROM {$wpdb->postmeta} pm\n WHERE pm.meta_key = '_amazon_item_source'\n AND pm.meta_value = 'imported'\n "); // echo "<pre>";print_r($post_ids);echo"</pre>";die(); $mode = isset($_REQUEST['mode']) ? $_REQUEST['mode'] : false; if ($mode == 'deletion_confirmed') { foreach ($post_ids as $post_id) { WPLA_ProductBuilder::deleteProduct($post_id); } foreach ($listing_ids as $listing_id) { $wpdb->delete($wpdb->prefix . 'amazon_listings', array('id' => $listing_id), array('%d')); } wpla_show_message('All imported products and listings have been removed.'); return; } if (!empty($post_ids)) { $nonce = wp_create_nonce('wpla_tools_page'); $btn_delete = '<a href="admin.php?page=wpla-tools&tab=developer&action=wpla_remove_all_imported_products&mode=deletion_confirmed&_wpnonce=' . $nonce . '" class="button button-small button-secondary">' . 'Yes, I want to remove all imported products' . '</a>'; $buttons = ' ' . $btn_delete; wpla_show_message('Are you sure you want to remove ' . sizeof($post_ids) . ' products and ' . sizeof($listing_ids) . ' listings which were imported from Amazon? ' . $buttons, 'warn'); } else { wpla_show_message('There are no imported products to remove.'); } }
public function displayAdvancedSettingsPage() { $wp_roles = new WP_Roles(); // check import folder $upload_dir = wp_upload_dir(); $basedir_name = self::getOption('import_images_basedir_name', 'imported/'); $images_dir = $upload_dir['basedir'] . '/' . $basedir_name; if (!is_dir($images_dir)) { mkdir($images_dir); } if (!is_dir($images_dir)) { wpla_show_message('The folder for imported images <code>' . $images_dir . '</code> could not be created. Please check your folder permissions.', 'error'); } $aData = array('plugin_url' => self::$PLUGIN_URL, 'message' => $this->message, 'dismiss_imported_products_notice' => self::getOption('dismiss_imported_products_notice'), 'enable_missing_details_warning' => self::getOption('enable_missing_details_warning'), 'enable_custom_product_prices' => self::getOption('enable_custom_product_prices', 1), 'enable_minmax_product_prices' => self::getOption('enable_minmax_product_prices', 0), 'enable_item_condition_fields' => self::getOption('enable_item_condition_fields', 2), 'enable_thumbs_column' => self::getOption('enable_thumbs_column'), 'autofetch_listing_quality_feeds' => self::getOption('autofetch_listing_quality_feeds', 1), 'autofetch_inventory_report' => self::getOption('autofetch_inventory_report', 0), 'product_gallery_first_image' => self::getOption('product_gallery_first_image'), 'product_gallery_fallback' => self::getOption('product_gallery_fallback', 'none'), 'pricing_info_expiry_time' => self::getOption('pricing_info_expiry_time', 24), 'repricing_use_lowest_offer' => self::getOption('repricing_use_lowest_offer', 0), 'repricing_margin' => self::getOption('repricing_margin', ''), 'import_parent_category_id' => self::getOption('import_parent_category_id', ''), 'enable_variation_image_import' => self::getOption('enable_variation_image_import', 1), 'enable_gallery_images_import' => self::getOption('enable_gallery_images_import', 1), 'import_images_subfolder_level' => self::getOption('import_images_subfolder_level', 0), 'import_images_basedir_name' => self::getOption('import_images_basedir_name', 'imported/'), 'default_matcher_selection' => self::getOption('default_matcher_selection', 'title'), 'available_attributes' => WPLA_ProductWrapper::getAttributeTaxonomies(), 'variation_attribute_map' => self::getOption('variation_attribute_map', array()), 'variation_merger_map' => self::getOption('variation_merger_map', array()), 'custom_shortcodes' => self::getOption('custom_shortcodes', array()), 'variation_meta_fields' => self::getOption('variation_meta_fields', array()), 'allowed_html_tags' => self::getOption('allowed_html_tags', '<b><i>'), 'process_shortcodes' => self::getOption('process_shortcodes', 'off'), 'remove_links' => self::getOption('remove_links', 'default'), 'variation_title_mode' => self::getOption('variation_title_mode', 'default'), 'profile_editor_mode' => self::getOption('profile_editor_mode', 'default'), 'option_uninstall' => self::getOption('uninstall'), 'available_roles' => $wp_roles->role_names, 'wp_roles' => $wp_roles->roles, 'settings_url' => 'admin.php?page=' . self::ParentMenuId . '-settings', 'form_action' => 'admin.php?page=' . self::ParentMenuId . '-settings' . '&tab=advanced'); $this->display('settings_advanced', $aData); }
public function checkMultisite() { if (is_multisite()) { // check for network activation if (!function_exists('is_plugin_active_for_network')) { require_once ABSPATH . '/wp-admin/includes/plugin.php'; } if (function_exists('is_network_admin') && is_plugin_active_for_network(plugin_basename(WPLA_PATH . '/wp-lister-amazon.php'))) { wpla_show_message("network activated!"); } else { wpla_show_message("not network activated!"); } // $this->showMessage(" // <b>Multisite installation detected</b><br> // <br> // This is a site network...<br> // "); return true; } return false; }
function auto_match_ASIN($post_id) { // check if we have an ASIN $asin = get_post_meta($post_id, '_wpla_asin', true); if (!$asin) { return; } // check if this ASIN / ID already exist - skip if it does $lm = new WPLA_ListingsModel(); if ($lm->getItemByASIN($asin, false)) { return; } if ($lm->getItemByPostID($post_id)) { return; } // get default account $default_account_id = get_option('wpla_default_account_id', 1); if (!$default_account_id) { return; } // insert matched listing $success = $lm->insertMatchedProduct($post_id, $asin, $default_account_id); if ($success) { $msg = isset($lm->lastError) ? $lm->lastError : ''; WPLA()->logger->info("auto-matched product #{$post_id} - {$msg}"); } else { // TODO: implement persistent admin messages $msg = isset($lm->lastError) ? $lm->lastError : ''; wpla_show_message("Failed to match product #{$post_id}: {$msg}", 'error'); // won't show because page is reloaded after saving WPLA()->logger->warn("Failed to match product #{$post_id} - please report this to support."); // echo "Failed to match product #$post_id - please report this to support."; } }
function updateItemFromReportCSV($csv, $account_id) { global $wpdb; // skip if $csv is not the right format - seller-sku is required, // localized report headers would insert empty rows in listings table if (!isset($csv['seller-sku']) || empty($csv['seller-sku'])) { wpla_show_message('Error: Could not parse report row. Make sure to disable localized column headers in seller central.', 'error'); return false; } // map CSV Report Row to DB columns $data = self::mapMerchantReportItemCSVToDB($csv); $data['account_id'] = $account_id; // WPLA()->logger->debug('data: '.print_r($data,1) ); // check if SKU already exists if ($item = $this->getItemBySKU($data['sku'], false)) { // // foreign ASINs should not be updated when they already exist (disabled - SKUs should be updated) // if ( $data['source'] != 'foreign_import') { // $wpdb->update( $this->tablename, $data, array( 'sku' => $data['sku'] ) ); // } // update found SKU $wpdb->update($this->tablename, $data, array('sku' => $data['sku'])); $this->updated_count++; } else { $data['status'] = 'imported'; $wpdb->insert($this->tablename, $data); $this->imported_count++; } echo $wpdb->last_error; #WPLA()->logger->info('sql: '.$wpdb->last_query ); #WPLA()->logger->info( $wpdb->last_error ); return $item; }
/** * If a table only contains utf8 or utf8mb4 or latin1 columns, convert it to utf8mb4. * (modified version of maybe_convert_table_to_utf8mb4() in wp core) * * @since 0.9.6.5 * * @param string $table The table to convert. * @return bool true if the table was converted, false if it wasn't. */ static function convert_custom_table_to_utf8mb4($table) { global $wpdb; global $wp_version; // do nothing before wp42 if (version_compare($wp_version, '4,2', '<')) { wpla_show_message('WordPress 4.2 or better required - your version is ' . $wp_version, 'error'); return false; } // get column information $results = $wpdb->get_results("SHOW FULL COLUMNS FROM `{$table}`"); if (!$results) { wpla_show_message("no columns found for {$table}", 'error'); return false; } // check charset for each column foreach ($results as $column) { if ($column->Collation) { list($charset) = explode('_', $column->Collation); $charset = strtolower($charset); if ('utf8' !== $charset && 'utf8mb4' !== $charset && 'latin1' !== $charset) { // Don't upgrade tables that have non-utf8 and non-latin1 columns. wpla_show_message("skipped column {$column} in table {$table} with charset: {$charset}", 'error'); return false; } } } // convert return $wpdb->query("ALTER TABLE {$table} CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci"); }
public function addProductImage($post_id, $image, $title = 'default', $asin = false, $is_featured_image = true, $suffix = false) { // set image upload dir $imported_images_dir = $this->getImagesDir(basename($image), $asin); $imported_images_url = $this->getImagesUrl(basename($image), $asin); if ($suffix) { $asin = $asin . '-' . $suffix; } // skip empty image if (trim($image) == '') { return false; } // full url to source image $img_url = $image; // limit title to 120 characters - filenames/guids can only have 255 chars $title = strlen($title) > 120 ? trim(substr($title, 0, 120)) : $title; // append amazon id to listing title if ($asin) { $title .= '-' . $asin; } // build local image path - based on title $imgslug = sanitize_file_name($title); // sanitize listing title $imgslug = str_replace('%20', '-', $imgslug); // replace %20 with dash $imgslug = preg_replace('/[^A-Za-z0-9_\\-]/', '', $imgslug); // allow only alphanumeric chars, dashes and underscores $imgfile = sanitize_file_name($imgslug . '.jpg'); // sanitize listing title // copy remote image $img_local_path = $imported_images_dir . $imgfile; // full path to destination image $img_local_url = $imported_images_url . $imgfile; // $is_new_image = $this->copyRemoteImage( $img_url, $img_local_path ); $copy_result = $this->copyRemoteImage($img_url, $img_local_path); // return values: // true - new image downloaded // false - filename already exists // string - matching image found by MD5 hash if (is_wp_error($copy_result)) { WPLA()->logger->error('image download failed: ' . $img_url); // TODO: notify user when image download failed return false; } // if an existing image was found by MD5 hash, try to find its attachment_id if (is_string($copy_result)) { // get new image file name $img_local_path = $copy_result; $imgfile = basename($img_local_path); $attachment_id = $this->get_attachment_id_for_filename($imgfile); if ($attachment_id) { WPLA()->logger->info('found existing attachment_id (md5): ' . $attachment_id); // set post thumbnail if ($is_featured_image) { set_post_thumbnail($post_id, $attachment_id); } WPLA()->logger->info("set_post_thumbnail( {$post_id}, {$attachment_id} )"); return $attachment_id; } } // if image file already exists, try to find attachment_id if ($copy_result === false) { $attachment_id = $this->get_attachment_id_for_filename($imgfile); if ($attachment_id) { WPLA()->logger->info('found existing attachment_id: ' . $attachment_id); // set post thumbnail if ($is_featured_image) { set_post_thumbnail($post_id, $attachment_id); } WPLA()->logger->info("set_post_thumbnail( {$post_id}, {$attachment_id} )"); return $attachment_id; } } // generate name from filename $name_parts = pathinfo($imgfile); $name = trim(substr($imgfile, 0, -(1 + strlen($name_parts['extension'])))); // Construct the attachment array $wp_filetype = wp_check_filetype(basename($imgfile), null); $attachment = array('post_mime_type' => $wp_filetype['type'], 'guid' => $img_local_url, 'post_parent' => $post_id, 'post_title' => $name, 'post_content' => '', 'post_status' => 'inherit'); // Save the attachment data // $attachment_id = wp_insert_attachment( $attachment, $img_local_path, $post_id ); $attachment_id = self::wp_insert_attachment_with_error_handling($attachment, $img_local_path, $post_id); if (!is_wp_error($attachment_id)) { // if ( $is_new_image ) { // wp_update_attachment_metadata( $attachment_id, wp_generate_attachment_metadata( $attachment_id, $img_local_path ) ); // WPLA()->logger->info( 'wp_update_attachment_metadata()' ); // } // if ( $is_new_image ) ... removed because it would leave image meta data empty, resulting a in 1px image in admin // WPLA()->logger->info( 'wp_update_attachment_metadata()' ); WPLA()->logger->info('new attachment_id: ' . $attachment_id); // make sure we have wp_generate_attachment_metadata() available require_once ABSPATH . 'wp-admin/includes/image.php'; // generate and update attachment meta data - will generate thumbnails as well wp_update_attachment_metadata($attachment_id, wp_generate_attachment_metadata($attachment_id, $img_local_path)); // set post thumbnail if ($is_featured_image) { set_post_thumbnail($post_id, $attachment_id); } WPLA()->logger->info('set_post_thumbnail()'); // mark attachment as imported update_post_meta($attachment_id, '_wpla_asin', $post_id); WPLA()->logger->info('product image: ' . $img_local_url); } else { wpla_show_message('Failed to create attachment from image ' . $img_local_path . '<br>Error: ' . $attachment_id->get_error_message(), 'warn'); WPLA()->logger->error('Failed to create attachment from image ' . $img_local_path . '<br>Error: ' . $attachment_id->get_error_message()); } return $attachment_id; }
/** * Invoke request and return response */ private function invoke(array $converted, $dataHandle = null, $contentMd5 = null) { $parameters = $converted[CONVERTED_PARAMETERS_KEY]; $actionName = $parameters["Action"]; $response = array(); $responseBody = null; $statusCode = 200; /* Submit the request and read response body */ try { // Ensure the endpoint URL is set. if (empty($this->config['ServiceURL'])) { throw new MarketplaceWebService_Exception(array('ErrorCode' => 'InvalidServiceUrl', 'Message' => "Missing serviceUrl configuration value. You may obtain a list of valid MWS URLs by consulting the MWS Developer's Guide, or reviewing the sample code published along side this library.")); } /* Add required request parameters */ $parameters = $this->addRequiredParameters($parameters); $converted[CONVERTED_PARAMETERS_KEY] = $parameters; // log to db - before request $this->dblogger->updateLog(array('callname' => $actionName, 'request' => maybe_serialize($converted), 'parameters' => maybe_serialize($parameters), 'account_id' => $this->account_id, 'market_id' => $this->market_id, 'success' => 'pending')); $shouldRetry = false; $retries = 0; do { try { $response = $this->performRequest($actionName, $converted, $dataHandle, $contentMd5); $httpStatus = $response['Status']; // log to db - after request $this->dblogger->updateLog(array('response' => maybe_serialize($response), 'http_code' => $response['Status'], 'success' => 'HTTP OK')); switch ($httpStatus) { case 200: $shouldRetry = false; break; case 500: case 503: require_once 'MarketplaceWebService/Model/ErrorResponse.php'; $errorResponse = MarketplaceWebService_Model_ErrorResponse::fromXML($response['ResponseBody']); // We will not retry throttling errors since this would just add to the throttling problem. $shouldRetry = $errorResponse->getError()->getCode() === 'RequestThrottled' ? false : true; if ($shouldRetry && $retries <= $this->config['MaxErrorRetry']) { $this->pauseOnRetry(++$retries); } else { throw $this->reportAnyErrors($response['ResponseBody'], $response['Status'], null, $response['ResponseHeaderMetadata']); } break; default: $shouldRetry = false; throw $this->reportAnyErrors($response['ResponseBody'], $response['Status'], null, $response['ResponseHeaderMetadata']); break; } /* Rethrow on deserializer error */ } catch (Exception $e) { require_once 'MarketplaceWebService/Exception.php'; // log to db - error $success = 'Error'; $this->dblogger->updateLog(array('result' => $e->getMessage(), 'success' => $success)); wpla_show_message($actionName . ' request failed with error: ' . $e->getMessage(), 'error'); throw new MarketplaceWebService_Exception(array('Exception' => $e, 'Message' => $e->getMessage())); } } while ($shouldRetry); } catch (MarketplaceWebService_Exception $se) { throw $se; } catch (Exception $t) { throw new MarketplaceWebService_Exception(array('Exception' => $t, 'Message' => $t->getMessage())); } // log to db - parsed request // $success = 'Success'; // $this->dblogger->updateLog( array( // 'result' => json_encode( $response['ResponseBody'] ), // 'success' => $success // )); return array('ResponseBody' => $response['ResponseBody'], 'ResponseHeaderMetadata' => $response['ResponseHeaderMetadata']); }
function sendSignedRequest($action, $section = false, $params = array(), $version = '2009-01-01', $return_raw = false) { // $base_url = "https://mws.amazonservices.de/Products/2011-01-01"; // $host = "mws.amazonservices.de"; $api_section = $section ? $section . '/' . $version : ''; $base_params = array('AWSAccessKeyId' => $this->AccessKey, 'Action' => $action, 'SellerId' => $this->SellerId, 'SignatureMethod' => "HmacSHA256", 'SignatureVersion' => "2", 'Timestamp' => gmdate("Y-m-d\\TH:i:s.\\0\\0\\0\\Z", time()), 'Version' => $version); $params = array_merge($base_params, $params); // debug // echo "<pre>params: ";print_r($params);echo"</pre>";#die(); // Sort the URL parameters $url_parts = array(); foreach (array_keys($params) as $key) { $url_parts[] = $key . "=" . str_replace('%7E', '~', rawurlencode($params[$key])); } sort($url_parts); // Construct the string to sign $url_string = implode("&", $url_parts); $string_to_sign = "GET\n" . $this->api_host . "\n/{$api_section}\n" . $url_string; // Sign the request $signature = hash_hmac("sha256", $string_to_sign, $this->SecretKey, TRUE); // Base64 encode the signature and make it URL safe $signature = urlencode(base64_encode($signature)); $url = 'https://' . $this->api_host . '/' . $api_section . '?' . $url_string . "&Signature=" . $signature; // log to db - before request $this->dblogger->updateLog(array('callname' => $action, 'request' => $string_to_sign, 'parameters' => maybe_serialize($params), 'request_url' => $url, 'account_id' => $this->account_id, 'market_id' => $this->market_id, 'success' => 'pending')); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // curl_setopt($ch, CURLOPT_TIMEOUT, 300); curl_setopt($ch, CURLOPT_TIMEOUT, 600); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); // If you are having problems, try adding this to the end of the curl-setopt block: curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); $response = curl_exec($ch); $curlinfo = curl_getinfo($ch); // echo "<pre>response: ";print_r( htmlspecialchars( $response ) );echo"</pre>";#die(); // echo "<pre>curl: ";print_r( $curlinfo );echo"</pre>";#die(); // log to db - after request $this->dblogger->updateLog(array('response' => $response, 'http_code' => $curlinfo['http_code'], 'success' => 'HTTP OK')); curl_close($ch); if ($response === false) { // throw new Exception('Server connection is failed. Please try again later.'); // log to db - parsed request $this->dblogger->updateLog(array('result' => 'The response from Amazon was empty. (Server connection is failed. Please try again later.)', 'curl' => maybe_serialize($curlinfo), 'success' => 'Error')); wpla_show_message("There was a problem communicating with Amazon. Please try again later. (Response to {$action} request was empty)", 'error'); return false; } else { if ($return_raw) { return $response; } $parsed_xml = $this->parseXML($response); // echo "<pre>XML: ";print_r( $parsed_xml );echo"</pre>";#die(); if (isset($parsed_xml->Error)) { $success = 'Error'; } elseif (isset($parsed_xml->GetMatchingProductForIdResult->Error)) { $success = 'Error'; } elseif (isset($parsed_xml->GetCompetitivePricingForASINResult->Error)) { $success = 'Error'; } elseif (isset($parsed_xml->GetLowestOfferListingsForASINResult->Error)) { $success = 'Error'; } elseif (isset($parsed_xml->ListMatchingProductsResult->Error)) { $success = 'Error'; } elseif (isset($parsed_xml->GetOrderResult->Error)) { $success = 'Error'; } elseif (isset($parsed_xml->ListOrderItemsResult->Error)) { $success = 'Error'; } else { $success = 'Success'; } // log to db - parsed request $this->dblogger->updateLog(array('result' => json_encode($parsed_xml), 'curl' => maybe_serialize($curlinfo), 'success' => $success)); } return $parsed_xml; }
public function createProductFromAmazonListing($listing) { $lm = new WPLA_ListingsModel(); if (is_numeric($listing)) { $listing = $lm->getItem($listing); } if (!$listing) { return false; } $listing_id = $listing['id']; WPLA()->logger->info('--- createProductFromAmazonListing() - ID: ' . $listing['id'] . ' / ASIN ' . $listing['asin']); $account = WPLA_AmazonAccount::getAccount($listing['account_id']); if (!$account) { return false; } // init api $api = new WPLA_AmazonAPI($account->id); // get product details from amazon $result = $api->getMatchingProductForId($listing['asin'], 'ASIN'); $this->request_count++; // echo "<pre>getMatchingProductForId() returned: ";print_r($result);echo"</pre>";#die(); // handle Import Variations As Simple option if ($result->success && get_option('wpla_import_variations_as_simple', 0)) { $result->product->variation_type = '_single_'; } // handle empty result error if ($result->success && empty($result->product->AttributeSets->ItemAttributes->Title)) { if (!empty($result->product->GetMatchingProductForIdResult->Error->Message)) { $this->lastError = sprintf(__('There was a problem fetching product details for %s.', 'wpla'), $listing['asin']) . '<br><code>' . $result->product->GetMatchingProductForIdResult->Error->Message . '</code>'; } else { $this->lastError = sprintf(__('There was a problem fetching product details for %s.', 'wpla'), $listing['asin']) . ' The product data received from Amazon was empty.'; } return false; } // first check if product already exists in WooCommerce... $post_id = WPLA_ProductBuilder::getProductIdBySKU($listing['sku']); if ($post_id) { WPLA()->logger->info('found existing product by SKU ' . $listing['sku'] . ' - post_id: ' . $post_id); $this->message = "Found existing product for SKU " . $listing['sku']; // if this SKU exists, check whether it is a variation or not $_product = get_product($post_id); // echo "<pre>";print_r($_product);echo"</pre>";#die(); // handle child variations if ('variation' == $_product->product_type) { // set parent_id $data = array('post_id' => $_product->variation_id, 'parent_id' => $_product->parent->id, 'product_type' => $_product->product_type); $lm->updateListing($listing_id, $data); $this->message = "Found existing variation for SKU " . $listing['sku']; } } else { // SKU does not exist in WC... $variation_type = $result->success ? $result->product->variation_type : '_unknown_'; $variation_type = is_string($variation_type) ? $variation_type : '_none_'; // convert empty object to string WPLA()->logger->info('no WC product found for SKU ' . $listing['sku'] . ' - type: ' . $variation_type); // process child variation - fetch parent item instead if ($result->success && $result->product->variation_type == 'child') { // foreign imports should have their title updated first // $data = array(); // $data['listing_title'] = $result->product->AttributeSets->ItemAttributes->Title; // $lm->updateListing( $listing_id, $data ); // update listing attributes and title from result $lm->updateItemAttributes($result->product->AttributeSets->ItemAttributes, $listing_id); // get parent item - new request $parent_asin = $result->product->VariationParentASIN; $api = new WPLA_AmazonAPI($account->id); // new log record $parent_result = $api->getMatchingProductForId($parent_asin, 'ASIN'); $parent_node = $parent_result->success ? $parent_result->product : false; $this->request_count++; // check for "variations without attributes" // if there are no variation attributes on the parent, fall back to creating a simple product instead if (0 == self::countVariationChildNodes($parent_node)) { $msg = $listing['asin'] . " seems to be a child of parent ASIN {$parent_asin} - but that parent has no variation attributes set, so it will be imported as a simple product."; WPLA()->logger->warn($msg); wpla_show_message($msg, 'warn'); $result->product->variation_type = '_invalid_parent_'; } else { WPLA()->logger->info($listing['asin'] . " is a child of parent ASIN {$parent_asin}"); $result = $parent_result; } } // process parent variation if ($result->success && $result->product->variation_type == 'parent') { // get parent listing - or create if it doesn't exist yet $parent_listing = $this->getOrCreateParentVariation($result, $listing, $account); // all further processing should be using the parent variation - including children $result->product = $this->parseVariationChildNodes($result->product, $parent_listing, $account); // $listing = $parent_listing; // $listing is supposed to be an array, $parent listing is an object $listing_id = $parent_listing->id; $listing = $lm->getItem($listing_id); } } // SKU does not exist in WC // import product... if ($result->success) { // update price for foreign imports (imported by ASIN) if ('foreign_import' == $listing['source'] && !$listing['price']) { $this->updateListingWithLowestPrice($listing, $account); } // update listing attributes and title from result $lm->updateItemAttributes($result->product->AttributeSets->ItemAttributes, $listing_id); $listing = $lm->getItem($listing_id); // create product $woo = new WPLA_ProductBuilder(); $woo->importSingleProduct($listing, $result->product); // post-process variations - add post_id if ($result->product->variation_type == 'parent' && isset($result->product->variations)) { $this->fixNewVariationListings($result->product->variations, $parent_listing); } $success = true; $errors = ''; $this->lastPostID = $woo->last_insert_id; } elseif (@$result->Error->Message) { $errors = sprintf(__('There was a problem fetching product details for %s.', 'wpla'), $listing['asin']) . '<br>Error: ' . $result->Error->Message; $success = false; } else { $errors = sprintf(__('There was a problem fetching product details for %s.', 'wpla'), $listing['asin']); $success = false; } $this->lastError = $errors; return $success; }
public function fetchPageContent($listing_url) { WPLA()->logger->info('fetching URL: ' . $listing_url); // fetch HTML content $response = wp_remote_get($listing_url, array('timeout' => 15, 'user-agent' => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.99 Safari/537.36')); // WPLA()->logger->info("BODY: ".$response['body']); // handle errors if (is_wp_error($response)) { // echo "<pre>";print_r($response);echo"</pre>"; // $this->showMessage( "Couldn't fetch URL $listing_url - ".$response->get_error_message(), 1, 1 ); WPLA()->logger->error("Couldn't fetch URL {$listing_url} - " . $response->get_error_message()); wpla_show_message("Couldn't fetch URL {$listing_url} - " . $response->get_error_message()); $this->errors[] = "Couldn't fetch URL {$listing_url} - " . $response->get_error_message(); // doesn't show return false; } if ($response['response']['code'] != 200) { // echo "<pre>Couldn't fetch URL $listing_url - server returned error code ".$response['response']['code']."</pre>"; // $this->showMessage( "Couldn't fetch URL $listing_url - server returned error code ".$response['response']['code'], 1, 1 ); WPLA()->logger->error("Couldn't fetch URL {$listing_url} - server returned error code " . $response['response']['code']); wpla_show_message("Couldn't fetch URL {$listing_url} - server returned error code " . $response['response']['code']); $this->errors[] = "Couldn't fetch URL {$listing_url} - server returned error code " . $response['response']['code']; return false; } // log to db - enable only for debugging (limited to 64k) // $this->dblogger = new WPLA_AmazonLogger(); // $this->dblogger->updateLog( array( // 'callname' => 'wp_remote_get', // 'request' => 'internal action hook', // 'parameters' => maybe_serialize( $listing_url ), // 'request_url' => $listing_url, // 'account_id' => '', // 'market_id' => '', // 'response' => $response['body'], // 'result' => json_encode( $response ), // 'success' => 'Success' // )); // return HTML content $html_content = $response['body']; $this->success = true; // echo "<pre>";htmlspecialchars($html_content);echo"</pre>";#die(); return $html_content; }
public function importOrder($order, $account) { global $wpdb; $table = $wpdb->prefix . self::TABLENAME; // skip processing if requests are throttled already if ($this->throttling_is_active == true) { return false; } // if ( ! is_object($order) ) // echo "<pre>order is not an object: ";print_r($order);echo"</pre>";die(); // check if order exists in WPLA and is already up to date (TODO: optimize) if ($id = $this->order_id_exists($order->AmazonOrderId)) { $om = new WPLA_OrdersModel(); $amazon_order = $om->getItem($id); if ($amazon_order['LastTimeModified'] == $this->convertIsoDateToSql($order->LastUpdateDate)) { WPLA()->logger->info('Order ' . $order->AmazonOrderId . ' has not been modified since ' . $amazon_order['LastTimeModified'] . ' and is up to date.'); wpla_show_message('Order ' . $order->AmazonOrderId . ' has not been modified since ' . $amazon_order['LastTimeModified'] . ' and is up to date.'); return null; } } $data = array('order_id' => $order->AmazonOrderId, 'status' => $order->OrderStatus, 'total' => isset($order->OrderTotal->Amount) ? $order->OrderTotal->Amount : '', 'currency' => isset($order->OrderTotal->CurrencyCode) ? $order->OrderTotal->CurrencyCode : '', 'buyer_name' => isset($order->BuyerName) ? $order->BuyerName : '', 'buyer_email' => isset($order->BuyerEmail) ? $order->BuyerEmail : '', 'PaymentMethod' => isset($order->PaymentMethod) ? $order->PaymentMethod : '', 'ShippingAddress_City' => isset($order->ShippingAddress->City) ? $order->ShippingAddress->City : '', 'date_created' => $this->convertIsoDateToSql($order->PurchaseDate), 'LastTimeModified' => $this->convertIsoDateToSql($order->LastUpdateDate), 'account_id' => $account->id, 'details' => json_encode($order)); // fetch order line items from Amazon - required for both new and updated orders $this->api = new WPLA_AmazonAPI($account->id); $items = $this->api->getOrderLineItems($order->AmazonOrderId); $data['items'] = maybe_serialize($items); // check if ListOrderItems request is throttled // if true, skip ALL further requests / order processing until next cron run if (is_object($items) && isset($items->Error->Message)) { $this->throttling_is_active = true; wpla_show_message('ListOrderItems requests are throttled. Skipping further order processing until next run.', 'warn'); return false; } // check if order exists in WPLA if ($id = $this->order_id_exists($order->AmazonOrderId)) { // load existing order record from wp_amazon_orders $ordersModel = new WPLA_OrdersModel(); $wpla_order = $ordersModel->getItem($id); // check if order status was updated // if pending -> Canceled: revert stock reduction by processing history records // if pending -> Shipped / Unshipped: create WooCommerce order if enabled (done in createOrUpdateWooCommerceOrder()) if ($order->OrderStatus != $wpla_order['status']) { $old_order_status = $wpla_order['status']; $new_order_status = $order->OrderStatus; // add history record $history_message = "Order status has changed from " . $old_order_status . " to " . $new_order_status; $history_details = array('id' => $id, 'new_status' => $new_order_status, 'old_status' => $old_order_status, 'LastTimeModified' => $data['LastTimeModified']); $this->addHistory($data['order_id'], 'order_status_changed', $history_message, $history_details); // if pending -> Canceled: revert stock reduction by processing history records if ($old_order_status == 'Pending' && $new_order_status == 'Canceled') { // revert stock reduction $this->revertStockReduction($wpla_order); // add history record $history_message = "Stock levels have been replenished"; $history_details = array('id' => $id); $this->addHistory($data['order_id'], 'revert_stock', $history_message, $history_details); } } // if status changed // update existing order $wpdb->update($table, $data, array('order_id' => $order->AmazonOrderId)); $this->updated_count++; // TODO: update WooCommerce order! // add history record $history_message = "Order details were updated - " . $data['LastTimeModified']; $history_details = array('id' => $id, 'status' => $data['status'], 'LastTimeModified' => $data['LastTimeModified']); $this->addHistory($data['order_id'], 'order_updated', $history_message, $history_details); } else { // insert new order $wpdb->insert($table, $data); $this->imported_count++; $id = $wpdb->insert_id; echo $wpdb->last_error; // add history record $history_message = "Order was added with status: " . $data['status']; $history_details = array('id' => $id, 'status' => $data['status'], 'LastTimeModified' => $data['LastTimeModified']); $this->addHistory($data['order_id'], 'order_inserted', $history_message, $history_details); // process ordered items - unless order has been cancelled if ($data['status'] != 'Canceled') { foreach ($items as $item) { // process each item and reduce stock level $success = $this->processListingItem($item, $order); } } } // if order does not exist return $id; }
static function updateAmazonPrice($item, $target_price, $verbose) { // make sure we don't go below min_price if ($item->min_price) { $target_price = max($target_price, $item->min_price); } // make sure we don't go above max_price (prevent feed error) if ($item->max_price) { $target_price = min($target_price, $item->max_price); } // skip if there is no change in price if ($target_price == $item->price) { return false; } // update amazon price in WooCommerce update_post_meta($item->post_id, '_amazon_price', $target_price); // update price in listings table $data = array('price' => $target_price, 'pnq_status' => 1); WPLA_ListingsModel::updateWhere(array('id' => $item->id), $data); // show message if ($verbose) { wpla_show_message($item->sku . ': price was changed from ' . $item->price . ' to <b>' . $target_price . '</b>'); } // price was changed return true; }
static function checkForDeletedProducts() { global $wpdb; $items = $wpdb->get_var("\n SELECT count(a.id)\n FROM {$wpdb->prefix}amazon_listings a\n LEFT JOIN {$wpdb->posts} p ON a.post_id = p.ID\n WHERE a.post_id <> 0\n AND p.ID IS NULL\n ORDER BY a.post_id\n "); if (!empty($items)) { $link_url = wp_nonce_url('admin.php?page=wpla-tools&tab=developer&action=wpla_fix_deleted_products', 'wpla_tools_page'); $link_button = ' <a href="' . $link_url . '" class="button button-small button-primary">Fix It Now</a>'; wpla_show_message(sprintf('Warning: There are %s listings linked to missing WooCommerce products.<br>These items need to be removed from WP-Lister to be able to list or import them again.', $items) . $link_button, 'error'); } }
function updateMarketplaceParticipations() { if (!$this->id) { return; } $api = new WPLA_AmazonAPI($this->id); $result = $api->listMarketplaceParticipations(); if (@$result->success) { $this->allowed_markets = maybe_serialize($result->allowed_markets); $this->update(); } elseif ($result->ErrorMessage) { wpla_show_message($result->ErrorMessage, 'error'); } return $result; }