shop.balmet.com

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

ebay.php (62071B)


      1 <?php
      2 namespace openbay;
      3 
      4 final class Ebay {
      5 	private $token;
      6     private $encryption_key;
      7     private $encryption_iv;
      8 	private $url = 'https://uk.openbaypro.com/';
      9 	private $registry;
     10 	private $no_log = array('notification/getPublicNotifications/', 'setup/getEbayCategories/', 'item/getItemAllList/', 'account/validate/', 'item/getItemListLimited/');
     11 	private $logger;
     12 	private $max_log_size = 50; //max log size in Mb
     13 
     14 	public function __construct($registry) {
     15 		$this->registry = $registry;
     16 		$this->token = $this->config->get('ebay_token');
     17 		$this->secret = $this->config->get('ebay_secret');
     18 		$this->logging = $this->config->get('ebay_logging');
     19 		$this->tax = $this->config->get('ebay_tax');
     20 		$this->server = 1;
     21 		$this->lasterror = '';
     22 		$this->lastmsg = '';
     23 
     24 		if ($this->logging == 1) {
     25 			$this->setLogger();
     26 		}
     27 
     28 		$this->setEncryptionKey($this->config->get('ebay_encryption_key'));
     29 		$this->setEncryptionIv($this->config->get('ebay_encryption_iv'));
     30 	}
     31 
     32 	public function __get($name) {
     33 		return $this->registry->get($name);
     34 	}
     35 
     36     public function getEncryptionKey() {
     37         return $this->encryption_key;
     38     }
     39 
     40 	public function setEncryptionKey($key) {
     41 	    $this->encryption_key = $key;
     42     }
     43 
     44     public function getEncryptionIv() {
     45         return $this->encryption_iv;
     46     }
     47 
     48     public function setEncryptionIv($encryption_iv) {
     49         $this->encryption_iv = $encryption_iv;
     50     }
     51 
     52 	public function call($call, array $post = null, array $options = array(), $content_type = 'json', $status_override = false) {
     53 		if ($this->config->get('ebay_status') == 1 || $status_override == true) {
     54 			$this->lasterror    = '';
     55 			$this->lastmsg      = '';
     56 
     57 			if (!in_array($call, $this->no_log)) {
     58 				$this->log('call(' . $call . ') - Data: ' .  json_encode($post));
     59 			}
     60 
     61 			if (defined("HTTPS_CATALOG")) {
     62 				$domain = HTTPS_CATALOG;
     63 			} else {
     64 				$domain = $this->config->get('config_url');
     65 			}
     66 
     67             $headers = array();
     68             $headers[] = 'X-Endpoint-Version: 2';
     69 
     70 			$data = array('token' => $this->token, 'secret' => $this->secret, 'server' => $this->server, 'domain' => $domain, 'openbay_version' => (int)$this->config->get('feed_openbaypro_version'), 'opencart_version' => VERSION, 'data' => $post, 'content_type' => $content_type, 'language' => $this->config->get('openbay_language'));
     71 
     72 			$defaults = array(
     73                 CURLOPT_HEADER      	=> 0,
     74                 CURLOPT_HTTPHEADER      => $headers,
     75 				CURLOPT_POST            => 1,
     76 				CURLOPT_URL             => $this->url . $call,
     77 				CURLOPT_USERAGENT       => "OpenBay Pro for eBay",
     78 				CURLOPT_FRESH_CONNECT   => 1,
     79 				CURLOPT_RETURNTRANSFER  => 1,
     80 				CURLOPT_FORBID_REUSE    => 1,
     81 				CURLOPT_TIMEOUT         => 0,
     82 				CURLOPT_SSL_VERIFYPEER  => 0,
     83 				CURLOPT_SSL_VERIFYHOST  => 0,
     84 				CURLOPT_POSTFIELDS      => http_build_query($data, '', "&")
     85 			);
     86 
     87 			$curl = curl_init();
     88 			curl_setopt_array($curl, ($options + $defaults));
     89 			if (! $result = curl_exec($curl)) {
     90 				$this->log('call() - Curl Failed ' . curl_error($curl) . ' ' . curl_errno($curl));
     91 			}
     92 			curl_close($curl);
     93 
     94 			if (!in_array($call, $this->no_log)) {
     95 				$this->log('call() - Result of : "' . $result . '"');
     96 			}
     97 
     98 			if ($content_type == 'json') {
     99 				$encoding = mb_detect_encoding($result);
    100 
    101 				if ($encoding == 'UTF-8') {
    102 					$result = preg_replace('/[^(\x20-\x7F)]*/', '', $result);
    103 				}
    104 
    105 				$result             = json_decode($result, 1);
    106 				$this->lasterror    = $result['error'];
    107 				$this->lastmsg      = $result['msg'];
    108 
    109 				if (!empty($result['data'])) {
    110 					return $result['data'];
    111 				} else {
    112 					return false;
    113 				}
    114 			}elseif ($content_type == 'xml') {
    115 				$result             = simplexml_load_string($result);
    116 				$this->lasterror    = $result->error;
    117 				$this->lastmsg      = $result->msg;
    118 
    119 				if (!empty($result->data)) {
    120 					return $result->data;
    121 				} else {
    122 					return false;
    123 				}
    124 			}
    125 		} else {
    126 			$this->log('call() - OpenBay Pro not active');
    127 		}
    128 	}
    129 
    130 	public function callNoResponse($call, array $post = null, array $options = array(), $content_type = 'json') {
    131 		if ($this->config->get('ebay_status') == 1) {
    132 			$this->log('openbay_noresponse_call(' . $call . ') - Data :' .  json_encode($post));
    133 
    134 			if (defined("HTTPS_CATALOG")) {
    135 				$domain = HTTPS_CATALOG;
    136 			} else {
    137 				$domain = $this->config->get('config_url');
    138 			}
    139 
    140             $headers = array();
    141             $headers[] = 'X-Endpoint-Version: 2';
    142 
    143 			$data = array('token' => $this->token, 'secret' => $this->secret, 'server' => $this->server, 'domain' => $domain, 'openbay_version' => (int)$this->config->get('feed_openbaypro_version'), 'opencart_version' => VERSION, 'data' => $post, 'content_type' => $content_type, 'language' => $this->config->get('openbay_language'));
    144 
    145 			$defaults = array(
    146                 CURLOPT_HEADER          => $headers,
    147 				CURLOPT_POST            => 1,
    148 				CURLOPT_URL             => $this->url . $call,
    149 				CURLOPT_USERAGENT       => "OpenBay Pro for eBay",
    150 				CURLOPT_FRESH_CONNECT   => 1,
    151 				CURLOPT_RETURNTRANSFER  => 0,
    152 				CURLOPT_FORBID_REUSE    => 1,
    153 				CURLOPT_TIMEOUT         => 5,
    154 				CURLOPT_SSL_VERIFYPEER  => 0,
    155 				CURLOPT_SSL_VERIFYHOST  => 0,
    156 				CURLOPT_POSTFIELDS      => http_build_query($data, '', "&")
    157 			);
    158 
    159 			$curl = curl_init();
    160 			curl_setopt_array($curl, ($options + $defaults));
    161 			curl_exec($curl);
    162 			$this->log(curl_error($curl));
    163 			curl_close($curl);
    164 		} else {
    165 			$this->log('openbay_noresponse_call() - OpenBay Pro not active . ');
    166 		}
    167 	}
    168 
    169 	private function setLogger() {
    170 		if(file_exists(DIR_LOGS . 'ebaylog.log')) {
    171 			if(filesize(DIR_LOGS . 'ebaylog.log') > ($this->max_log_size * 1000000)) {
    172 				rename(DIR_LOGS . 'ebaylog.log', DIR_LOGS . '_ebaylog_' . date('Y-m-d_H-i-s') . '.log');
    173 			}
    174 		}
    175 
    176 		$this->logger = new \Log('ebaylog.log');
    177 	}
    178 
    179 	public function log($data, $write = true) {
    180 		if ($this->logging == 1) {
    181 			if (function_exists('getmypid')) {
    182 				$process_id = getmypid();
    183 				$data = $process_id . ' - ' . print_r($data, true);
    184 			}
    185 
    186             $this->logger->write($data);
    187 		}
    188 	}
    189 
    190 	public function getServer() {
    191 		return $this->url;
    192 	}
    193 
    194 	public function getSetting($key) {
    195 		$qry = $this->db->query("SELECT `data` FROM `" . DB_PREFIX . "ebay_setting_option` WHERE `key` = '" . $this->db->escape($key) . "' LIMIT 1");
    196 
    197 		if ($qry->num_rows > 0) {
    198 			return unserialize($qry->row['data']);
    199 		} else {
    200 			return false;
    201 		}
    202 	}
    203 
    204 	public function getEbayItemId($product_id) {
    205 		$this->log('getEbayItemId() - Product ID: ' . $product_id);
    206 
    207 		$qry = $this->db->query("SELECT `ebay_item_id` FROM `" . DB_PREFIX . "ebay_listing` WHERE `product_id` = '" . (int)$product_id . "' AND `status` = '1' LIMIT 1");
    208 
    209 		if (!$qry->num_rows) {
    210 			$this->log('No link found - getEbayItemId()');
    211 			return false;
    212 		} else {
    213 			$this->log('Returning ' . $qry->row['ebay_item_id'] . ' - getEbayItemId()');
    214 			return $qry->row['ebay_item_id'];
    215 		}
    216 	}
    217 
    218 	public function getEndedEbayItemId($product_id) {
    219 		$this->log('getEndedEbayItemId() - ID: ' . $product_id);
    220 
    221 		$qry = $this->db->query("SELECT `ebay_item_id` FROM `" . DB_PREFIX . "ebay_listing` WHERE `product_id` = '" . (int)$product_id . "' AND `status` = '0' ORDER BY `ebay_listing_id` DESC LIMIT 1");
    222 
    223 		if (!$qry->num_rows) {
    224 			$this->log('getEndedEbayItemId() - No link');
    225 			return false;
    226 		} else {
    227 			$this->log('getEndedEbayItemId() - Returning ' . $qry->row['ebay_item_id']);
    228 			return $qry->row['ebay_item_id'];
    229 		}
    230 	}
    231 
    232 	public function removeItemByItemId($item_id) {
    233 		$this->log('removeItemByItemId() - ID: ' . $item_id);
    234 
    235 		$this->db->query("UPDATE `" . DB_PREFIX . "ebay_listing` SET `status` = '0' WHERE `ebay_item_id` = '" . $this->db->escape($item_id) . "'");
    236 
    237 		$this->db->query("DELETE FROM `" . DB_PREFIX . "ebay_stock_reserve` WHERE `item_id` = '" . $this->db->escape($item_id) . "'");
    238 	}
    239 
    240 	public function removeItemByProductId($product_id) {
    241 		$this->log('removeItemByProductId() - ID: ' . $product_id . '');
    242 
    243 		$this->db->query("UPDATE `" . DB_PREFIX . "ebay_listing` SET `status` = '0' WHERE `product_id` = '" . (int)$product_id . "'");
    244 
    245 		$this->db->query("DELETE FROM `" . DB_PREFIX . "ebay_stock_reserve` WHERE `product_id` = '" . (int)$product_id . "'");
    246 	}
    247 
    248 	public function deleteProduct($product_id) {
    249 		$this->log('deleteProduct() - ID: ' . $product_id);
    250 
    251 		$this->db->query("DELETE FROM `" . DB_PREFIX . "ebay_listing` WHERE `product_id` = '" . (int)$product_id . "'");
    252 		$this->db->query("DELETE FROM `" . DB_PREFIX . "ebay_stock_reserve` WHERE `product_id` = '" . (int)$product_id . "'");
    253 	}
    254 
    255 	public function orderDelete($order_id) {
    256 		/**
    257 		 * @todo
    258 		 */
    259 	}
    260 
    261 	public function getLiveListingArray() {
    262 	/*
    263 	 * Returns the list of linked items with eBay from the database
    264 	 * @return array ([product id] = ebay item id)
    265 	 */
    266 		$this->log('getLiveListingArray()');
    267 
    268 		$qry = $this->db->query("SELECT `product_id`, `ebay_item_id` FROM `" . DB_PREFIX . "ebay_listing` WHERE `status` = '1'");
    269 
    270 		$data = array();
    271 		if ($qry->num_rows > 0) {
    272 			foreach ($qry->rows as $row) {
    273 				$data[$row['product_id']] = $row['ebay_item_id'];
    274 			}
    275 		}
    276 
    277 		return $data;
    278 	}
    279 
    280 	public function getEndedListingArray() {
    281 		$this->log('getEndedListingArray()');
    282 		$active = $this->getLiveListingArray();
    283 
    284 		$qry = $this->db->query("SELECT e.* FROM (SELECT `product_id`, MAX(`ebay_listing_id`) as `ebay_listing_id` FROM `" . DB_PREFIX . "ebay_listing` WHERE `status` = 0 GROUP BY `product_id`) `a` INNER JOIN `" . DB_PREFIX . "ebay_listing` `e` ON (`e`.`ebay_listing_id` = `a`.`ebay_listing_id`)");
    285 
    286 		$data = array();
    287 		if ($qry->num_rows > 0) {
    288 			foreach ($qry->rows as $row) {
    289 				$data[$row['product_id']] = $row['ebay_item_id'];
    290 			}
    291 		}
    292 
    293 		foreach ($active as $k => $v) {
    294 			if (array_key_exists($k, $data)) {
    295 				unset($data[$k]);
    296 			}
    297 		}
    298 
    299 		return $data;
    300 	}
    301 
    302 	public function getLiveProductArray() {
    303 		/**
    304 		* Returns the list of linked items with eBay from the database
    305 		* @return array ([ebay item id] = product id)
    306 		*/
    307 		$qry = $this->db->query("SELECT `product_id`, `ebay_item_id` FROM `" . DB_PREFIX . "ebay_listing` WHERE `status` = '1'");
    308 
    309 		$data = array();
    310 		if ($qry->num_rows) {
    311 			foreach ($qry->rows as $row) {
    312 				$data[$row['ebay_item_id']] = $row['product_id'];
    313 			}
    314 		}
    315 
    316 		return $data;
    317 	}
    318 
    319 	public function endItem($item_id) {
    320 		$this->log('endItem() - ID "' . $item_id);
    321 
    322 		if ($this->config->get('ebay_enditems') == 1) {
    323 			$this->call('item/endItem/', array('id' => $item_id));
    324 			$this->removeItemByItemId($item_id);
    325 
    326 			if ($this->lasterror != true) {
    327 				$this->log('endItem() - OK');
    328 				return array('error' => false, 'msg' => 'ok');
    329 			} else {
    330 				return array('error' => true, 'msg' => $this->lasterror);
    331 			}
    332 		} else {
    333 			$this->removeItemByItemId($item_id);
    334 			$this->log('endItem() - config has disabled ending items');
    335 
    336 			$message = "An item has gone out of stock but your settings are not set to end eBay items automatically.\r\n\r\n";
    337 			$message.= "You need to ensure you have stock left of this item or end your eBay listing manually.\r\n\r\n";
    338 			$message.= "eBay item ID: $item_id";
    339 
    340 			$this->notifyAdmin('eBay item not ended: ' . $item_id, $message);
    341 
    342 			return array('error' => true, 'msg' => 'Settings do not allow you to end items, but the link has been removed . ');
    343 		}
    344 	}
    345 
    346 	public function ebaySaleStockReduce($product_id, $sku = null) {
    347 		/**
    348 		* Gets the product info from an ID and sends to ebay update method.
    349 		*/
    350 		$this->log('ebaySaleStockReduce() - Is stock update needed (Item ID: ' . $product_id . ',SKU: ' . $sku . ')');
    351 
    352 		if (!empty($product_id)) {
    353 			if ($sku == null) {
    354 				$query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "product` WHERE `product_id` = '" . (int)$product_id . "' LIMIT 1");
    355 				$this->log('ebaySaleStockReduce() - Send item ID: "' . $product_id . '", Stock: "' . $query->row['quantity'] . '" to decideEbayStockAction()');
    356 				$this->decideEbayStockAction($product_id, $query->row['quantity'], $query->row['subtract']);
    357 			} else {
    358 				$query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "product_option_variant` WHERE `product_id` = '" . (int)$product_id . "' AND `sku` = '" . $this->db->escape($sku) . "' LIMIT 1");
    359 				$this->log('ebaySaleStockReduce() - Send item ID: ' . $product_id . ', VAR: ' . $sku . ', passing ' . $query->row['stock'] . ' to decideEbayStockAction()');
    360 				$this->decideEbayStockAction($product_id, $query->row['stock'], $query->row['subtract'], $sku);
    361 			}
    362 		}
    363 	}
    364 
    365 	public function notifyAdmin($subject, $message) {
    366 		$this->log('Sending email to: ' . $this->config->get('config_email') . ' - notifyAdmin()');
    367 
    368 		$mail = new \Mail();
    369 		$mail->protocol = $this->config->get('config_mail_protocol');
    370 		$mail->parameter = $this->config->get('config_mail_parameter');
    371 		$mail->smtp_hostname = $this->config->get('config_mail_smtp_hostname');
    372 		$mail->smtp_username = $this->config->get('config_mail_smtp_username');
    373 		$mail->smtp_password = html_entity_decode($this->config->get('config_mail_smtp_password'), ENT_QUOTES, 'UTF-8');
    374 		$mail->smtp_port = $this->config->get('config_mail_smtp_port');
    375 		$mail->smtp_timeout = $this->config->get('config_mail_smtp_timeout');
    376 
    377 		$mail->setTo($this->config->get('config_email'));
    378 		$mail->setFrom($this->config->get('config_email'));
    379 		$mail->setSender(html_entity_decode($this->config->get('config_name'), ENT_QUOTES, 'UTF-8'));
    380 		$mail->setSubject(html_entity_decode($subject, ENT_QUOTES, 'UTF-8'));
    381 		$mail->setText($message);
    382 		$mail->send();
    383 	}
    384 
    385 	public function validateJsonDecode($data) {
    386 		$data = (string)$data;
    387 
    388 		$encoding = mb_detect_encoding($data);
    389 
    390 		if ($encoding == 'UTF-8') {
    391 			$data = preg_replace('/[^(\x20-\x7F)]*/', '', $data);
    392 			$data = preg_replace('#\\\\x[0-9a-fA-F]{2,2}#', '', $data);
    393 		}
    394 
    395 		$data = json_decode($data);
    396 
    397 		if (function_exists('json_last_error')) {
    398 			switch (json_last_error()) {
    399 				case JSON_ERROR_NONE:
    400 					$this->log('validateJsonDecode() - No json decode errors');
    401 				break;
    402 				case JSON_ERROR_DEPTH:
    403 					$this->log('validateJsonDecode() - Maximum stack depth exceeded');
    404 				break;
    405 				case JSON_ERROR_STATE_MISMATCH:
    406 					$this->log('validateJsonDecode() - Underflow or the modes mismatch');
    407 				break;
    408 				case JSON_ERROR_CTRL_CHAR:
    409 					$this->log('validateJsonDecode() - Unexpected control character found');
    410 				break;
    411 				case JSON_ERROR_SYNTAX:
    412 					$this->log('validateJsonDecode() - Syntax error, malformed JSON');
    413 				break;
    414 				case JSON_ERROR_UTF8:
    415 					$this->log('validateJsonDecode() - Malformed UTF-8 characters, possibly incorrectly encoded');
    416 				break;
    417 				default:
    418 					$this->log('validateJsonDecode() - Unknown error');
    419 				break;
    420 			}
    421 		} else {
    422 			$this->log('validateJsonDecode() - json_last_error PHP function does not exist');
    423 		}
    424 
    425 		return $data;
    426 	}
    427 
    428 	private function eBayShippingStatus($item, $txn, $status, $tracking_no = '', $carrier_id = '') {
    429 		$this->log('eBayShippingStatus() - Update order shipping status (Item: ' . $item . ',Txn: ' . $txn . ',Status:' . $status . ',Tracking: ' . $tracking_no . ', Carrier: ' . $carrier_id . ')');
    430 		return $this->call('order/shippingStatus/', array('item' => $item, 'txn' => $txn, 'status' => $status, 'carrier' => $carrier_id, 'tracking' => $tracking_no));
    431 	}
    432 
    433 	private function eBayPaymentStatus($item, $txn, $status) {
    434 		$this->log('eBayPaymentStatus() - Updates order payment status (Item: ' . $item . ',Txn: ' . $txn . ',Status:' . $status . ')');
    435 		return $this->call('order/paymentStatus/', array('item' => $item, 'txn' => $txn, 'status' => $status));
    436 	}
    437 
    438 	private function getSaleRecord($sale_id) {
    439 		$this->log('getSaleRecord() - Get ebay sale record ID: ' . $sale_id);
    440 		return $this->call('order/getSmpRecord/', array('id' => $sale_id));
    441 	}
    442 
    443 	public function getEbayActiveListings() {
    444 		$this->log('getEbayActiveListings() - Get active eBay items from API');
    445 		return $this->call('item/getItemAllList/');
    446 	}
    447 
    448 	public function getEbayItemList($limit = 100, $page = 1, $filter = array()) {
    449 		$this->log('getEbayItemList() - Get active eBay items from API');
    450 		return $this->call('item/getItemListLimited/', array('page' => $page, 'limit' => $limit, 'filter' => $filter));
    451 	}
    452 
    453 	public function disableProduct($product_id) {
    454 		$this->db->query("UPDATE `" . DB_PREFIX . "product` SET `status` = 0 WHERE `product_id` = '" . (int)$product_id . "' LIMIT 1");
    455 	}
    456 
    457 	public function disableVariant($product_id, $sku) {
    458 		$this->db->query("UPDATE `" . DB_PREFIX . "product_option_variant` SET `active` = 0 WHERE `product_id` = '" . (int)$product_id . "' AND `sku` = '" . $this->db->escape($sku) . "' LIMIT 1");
    459 	}
    460 
    461 	public function putStockUpdate($item_id, $stock, $sku = null) {
    462 		$this->log('putStockUpdate()');
    463 		$this->log('putStockUpdate() - New local stock: ' . $stock);
    464 
    465 		$listing    = $this->call('item/getItem', array('itemId' => $item_id));
    466 		$product_id = $this->getProductId($item_id);
    467 		$reserve    = $this->getReserve($product_id, $item_id, (($sku != null) ? $sku : ''));
    468 
    469 		if ($listing['status'] == 1 ) {
    470 			if ($reserve != false) {
    471 				$this->log('putStockUpdate() - Reserve stock: ' . $reserve);
    472 
    473 				if ($stock > $reserve) {
    474 					$this->log('putStockUpdate() - Stock is larger than reserve, setting level to reserve');
    475 					$stock = $reserve;
    476 				}
    477 			}
    478 
    479 			if ($sku == null) {
    480 				$this->log('putStockUpdate() - Listing stock: ' . $listing['qty'] . ', new stock: ' . $stock);
    481 
    482 				if ($stock <= 0) {
    483 					if ($this->config->get('ebay_disable_nostock') == 1) {
    484 						$this->disableProduct($product_id);
    485 					}
    486 
    487 					$this->endItem($item_id);
    488 					return true;
    489 				}elseif ($listing['qty'] != $stock) {
    490 					$this->call('item/reviseStock/', array('itemId' => $item_id, 'stock' => $stock));
    491 					$this->log('putStockUpdate() - OK');
    492 					return true;
    493 				} else {
    494 					$this->log('putStockUpdate() - No update needed');
    495 					return false;
    496 				}
    497 			} else {
    498 				// Need to loop over current item check if other variants have stock
    499 				$variant_stock = false;
    500 				foreach ($listing['variation']['vars'] as $var) {
    501 					if (($var['sku'] != $sku) && ($var['qty'] > 0)) {
    502 						//other variations have stock
    503 						$variant_stock = true;
    504 						$this->log('Another variation has stock (SKU: ' . $var['sku'] . ')');
    505 						break;
    506 					}
    507 				}
    508 
    509 				if ($stock <= 0) {
    510 					if ($this->config->get('ebay_disable_nostock') == 1) {
    511 						$this->disableVariant($product_id, $sku);
    512 					}
    513 				}
    514 
    515 				if ($variant_stock == true || $stock > 0) {
    516 					$this->log('putStockUpdate() - Revising item with Item ID "' . $item_id . '" to stock level "' . $stock . '", sku "' . $sku . '"');
    517 					$this->call('item/reviseStock/', array('itemId' => $item_id, 'stock' => $stock, 'sku' => $sku));
    518 					return true;
    519 				} else {
    520 					$this->log('putStockUpdate() - Sending end for item, no variants have stock!');
    521 					$this->endItem($item_id);
    522 				}
    523 			}
    524 		} else {
    525 			$this->removeItemByItemId($item_id);
    526 
    527 			if($sku == null) {
    528 				if ($stock <= 0 && $this->config->get('ebay_disable_nostock') == 1) {
    529 					$this->disableProduct($product_id);
    530 				}
    531 			} else {
    532 				if ($stock <= 0 && $this->config->get('ebay_disable_nostock') == 1) {
    533 					$this->disableVariant($product_id, $sku);
    534 				}
    535 			}
    536 
    537 			$this->log('putStockUpdate() - Listing not active, item id: ' . $item_id . ', status returned: ' . $listing['statusActual']);
    538 		}
    539 	}
    540 
    541 	public function putStockUpdateBulk($product_id_array, $end_inactive = false) {
    542 		// We know is that these product ID's have been modified. They should only be passed if the stock has changed so we can assume this.
    543 		$this->log('putStockUpdateBulk()');
    544 
    545 		$openstock = false;
    546 		if ($this->openbay->addonLoad('openstock') == true) {
    547 			$this->load->model('extension/module/openstock');
    548 			$openstock = true;
    549 		}
    550 
    551 		// Get the active OpenCart items that were linked to eBay If they have stock now, relist them.
    552 		$ended_data = $this->getEndedListingArray();
    553 
    554 		/**
    555 		 * Get the active OpenCart items that are also linked
    556 		 * Compare against the stock from eBay
    557 		 * If listing active and local stock = 0, end it
    558 		 * If listing inactive, remove link
    559 		 * If listing active and local stock not the same, update it
    560 		 */
    561 		$ebay_listings = $this->getEbayActiveListings();
    562 		$live_data = $this->getLiveListingArray();
    563 
    564 		$linked_items        = array();
    565 		$linked_ended_items   = array();
    566 
    567 		foreach ($product_id_array as $product_id) {
    568 			if (array_key_exists((int)$product_id, $live_data)) {
    569 				//product has been passed and is linked to active item
    570 				$linked_items[] = array('productId' => (int)$product_id, 'itemId' => $live_data[$product_id]);
    571 			}elseif (array_key_exists((int)$product_id, $ended_data)) {
    572 				//product has been passed and is not currently active
    573 				$linked_ended_items[] = array('productId' => (int)$product_id, 'itemId' => $ended_data[$product_id]);
    574 			} else {
    575 				//product does not exist in live or ended links so has never been linked.
    576 			}
    577 		}
    578 
    579 		//loop through ended listings, if back in stock and not multi var - relist it
    580 		foreach ($linked_ended_items as $item) {
    581 			if ($openstock == true) {
    582 				$options = $this->model_extension_module_openstock->getVariants($item['productId']);
    583 			} else {
    584 				$options = array();
    585 			}
    586 
    587 			if (empty($options)) {
    588 				//get the stock level of the linked items
    589 				$local_stock = $this->getProductStockLevel($item['productId']);
    590 
    591 				if ((int)$local_stock['quantity'] > 0 && $local_stock['status'] == 1) {
    592 					//product has stock and is enabled, so re list it.
    593 					$reserve = $this->getReserve($item['productId'], $item['itemId']);
    594 
    595 					if ($reserve != false) {
    596 						if ($local_stock['quantity'] > $reserve) {
    597 							$local_stock['quantity'] = $reserve;
    598 						}
    599 					}
    600 
    601 					if ($this->config->get('ebay_relistitems') == 1) {
    602 						//relist item with new stock
    603 						$this->relistItem($item['itemId'], $item['productId'], (int)$local_stock['quantity']);
    604 					}
    605 				}
    606 			} else {
    607 				$this->log('putStockUpdateBulk() - options existed for item (' . $item['itemId'] . ') when trying to relist');
    608 				// @todo - support relisting of variant items, if possible with ebay!
    609 			}
    610 		}
    611 
    612 		//loop through the active listings and update the store or end the item
    613 		foreach ($linked_items as $item) {
    614 			//get the stock level of the linked item
    615 			$local_stock = $this->getProductStockLevel($item['productId']);
    616 
    617 			//check if the itemid was returned by ebay, if not unlink it as it is ended.
    618 			if (!isset($ebay_listings[$item['itemId']])) {
    619 				$this->log('eBay item was not returned, removing link (' . $item['itemId'] . ')');
    620 				$this->removeItemByItemId($item['itemId']);
    621 			} else {
    622 				//check if the local item is now inactive - end if it is
    623 				if ($end_inactive == true && $local_stock['status'] == 0) {
    624 					$this->endItem($item['itemId']);
    625 				} else {
    626 					//get any options that are set for this product
    627 					if ($openstock == true) {
    628 						$options = $this->model_extension_module_openstock->getVariants($item['productId']);
    629 					} else {
    630 						$options = array();
    631 					}
    632 
    633 					if (empty($options) && empty($ebay_listings[$item['itemId']]['variants'])) {
    634 						$this->log('putStockUpdateBulk() - Item has no variants');
    635 
    636 						//compare to the ebay data get retrieved
    637 						if ((int)$local_stock['quantity'] != (int)$ebay_listings[$item['itemId']]['qty']) {
    638 							$reserve = $this->getReserve($item['productId'], $item['itemId']);
    639 
    640 							if ($reserve != false) {
    641 								if ($local_stock['quantity'] > $reserve) {
    642 									$local_stock['quantity'] = $reserve;
    643 								}
    644 							}
    645 
    646 							$this->putStockUpdate($item['itemId'], (int)$local_stock['quantity']);
    647 						}
    648 					}elseif (!empty($options) && !empty($ebay_listings[$item['itemId']]['variants'])) {
    649 						// This item has variants
    650 						$this->log('putStockUpdateBulk() - Variants found');
    651 
    652 						//create an index of var codes to search against
    653 						$var_ids = array();
    654 						foreach ($options as $k => $v) {
    655 							$var_ids[$k] = $v['var'];
    656 						}
    657 
    658 						//loop over eBay variants
    659 						foreach ($ebay_listings[$item['itemId']]['variants'] as $ebay_variant) {
    660 							$this->log('Checking eBay SKU: ' . $ebay_variant['sku'] . ' for item: ' . $item['itemId']);
    661 
    662 							if (in_array($ebay_variant['sku'], $var_ids)) {
    663 								$option_id = array_search($ebay_variant['sku'], $var_ids);
    664 
    665 								//compare the stock - if different trigger update
    666 								if ($ebay_variant['qty'] != $options[$option_id]['stock']) {
    667 									$reserve = $this->getReserve($item['productId'], $item['itemId'], $ebay_variant['sku']);
    668 
    669 									if ($reserve != false) {
    670 										if ($options[$option_id]['stock'] > $reserve) {
    671 											$options[$option_id]['stock'] = $reserve;
    672 										}
    673 									}
    674 
    675 									$this->log('putStockUpdateBulk() - Revising variant item: ' . $item['itemId'] . ',Stock: ' . $options[$option_id]['stock'] . ', SKU ' . $ebay_variant['sku']);
    676 									$this->call('item/reviseStock/', array('itemId' => $item['itemId'], 'stock' => $options[$option_id]['stock'], 'sku' => $ebay_variant['sku']));
    677 								}
    678 							}
    679 						}
    680 					} else {
    681 						$this->log('Unsure if this item has variants, debug:');
    682 						$this->log('Local: ' . $options);
    683 						$this->log('eBay: ' . serialize($ebay_listings[$item['itemId']]['variants']));
    684 					}
    685 				}
    686 			}
    687 		}
    688 	}
    689 
    690 	public function getProductStockLevel($product_id, $sku = '') {
    691 		$this->log('getProductStockLevel() - ID: ' . $product_id . ', SKU: ' . $sku);
    692 
    693 		if ($sku == '' || $sku == null) {
    694 			$qry = $this->db->query("SELECT `quantity`, `status` FROM `" . DB_PREFIX . "product` WHERE `product_id` = '" . (int)$product_id . "' LIMIT 1");
    695 
    696 			return array('quantity' => (int)$qry->row['quantity'], 'status' => ($qry->row['status']));
    697 		} else {
    698 			$qry = $this->db->query("SELECT `stock`, `active` FROM `" . DB_PREFIX . "product_option_variant` WHERE `product_id` = '" . (int)$product_id . "' AND `sku` = '" . $this->db->escape($sku) . "' LIMIT 1");
    699 
    700 			return array('quantity' => (int)$qry->row['stock'], 'status' => ($qry->row['active']));
    701 		}
    702 	}
    703 
    704 	public function productUpdateListen($product_id, $data = array()) {
    705 		$this->log('productUpdateListen(' . $product_id . ')');
    706 
    707 		$item_id = $this->getEbayItemId($product_id);
    708 
    709 		$product = $this->db->query("SELECT DISTINCT * FROM `" . DB_PREFIX . "product` WHERE `product_id` = '" . (int)$product_id . "' LIMIT 1")->row;
    710 
    711 		if ($item_id != false) {
    712 			$this->log('productUpdateListen(' . $product_id . ') - listing found (' . $item_id . ')');
    713 
    714 			if ($this->openbay->addonLoad('openstock') && (isset($product['has_option']) && $product['has_option'] == 1)) {
    715 				$this->load->model('extension/module/openstock');
    716 				$this->load->model('tool/image');
    717 				$this->load->model('catalog/product');
    718 
    719 				$this->log('productUpdateListen(' . $product_id . ') - Variant');
    720 
    721 				if (!isset($data['variant'])) {
    722 					$variants = $this->model_extension_module_openstock->getVariants($product_id);
    723 				} else {
    724 					$variants = $data['variant'];
    725 				}
    726 
    727 				$variant_data = array();
    728 
    729 				$groups = $this->openbay->getProductOptions($product_id);
    730 				$variant_data['groups']  = array();
    731 				$variant_data['related'] = array();
    732 
    733 				foreach ($groups as $grp) {
    734 					$t_tmp = array();
    735 					foreach ($grp['product_option_value'] as $grp_node) {
    736 						$t_tmp[$grp_node['option_value_id']] = $grp_node['name'];
    737 
    738 						$variant_data['related'][$grp_node['product_option_value_id']] = $grp['name'];
    739 					}
    740 					$variant_data['groups'][] = array('name' => $grp['name'], 'child' => $t_tmp);
    741 				}
    742 
    743 				$v = 0;
    744 				$stock = false;
    745 
    746 				foreach ($variants as $option) {
    747 					if (!empty($option['sku'])) {
    748 						if ($option['stock'] > 0 || $stock == true) {
    749 							$stock = true;
    750 						}
    751 
    752 						// PRODUCT RESERVE LEVELS FOR VARIANT ITEMS (DOES NOT PASS THROUGH NORMAL SYSTEM)
    753 						$reserve = $this->getReserve($product_id, $item_id, $option['sku']);
    754 						if ($reserve != false) {
    755 							$this->log('productUpdateListen() / Variant (' . $option['sku'] . ') - Reserve stock: ' . $reserve);
    756 
    757 							if ($option['stock'] > $reserve) {
    758 								$this->log('putStockUpdate() - Stock (' . $option['stock'] . ') is larger than reserve (' . $reserve . '), setting level to reserve');
    759 								$option['stock'] = $reserve;
    760 							}
    761 						}
    762 
    763 						$variant_data['opt'][$v]['sku'] = $option['sku'];
    764 						$variant_data['opt'][$v]['qty'] = $option['stock'];
    765 						$variant_data['opt'][$v]['active'] = 0;
    766 
    767 						if ($option['active'] == 1) {
    768 							$variant_data['opt'][$v]['active'] = 1;
    769 						}
    770 
    771 						$v++;
    772 					}
    773 				}
    774 
    775 				$variant_data['groups'] = base64_encode(serialize($variant_data['groups']));
    776 				$variant_data['related'] = base64_encode(serialize($variant_data['related']));
    777 				$variant_data['id'] = $item_id;
    778 
    779 				//send to the api to process
    780 				if (!empty($variant_data['opt'])) {
    781 					if ($stock == true) {
    782 						$this->log('productUpdateListen() - Sending to API');
    783 						$response = $this->call('item/reviseStockVariants', $variant_data);
    784 
    785 						return $response;
    786 					} else {
    787 						$this->log('productUpdateListen() - Ending item');
    788 						$this->endItem($item_id);
    789 					}
    790 				}
    791 			} else {
    792 				$this->log('productUpdateListen(' . $product_id . ') - Not a variant');
    793 
    794 				$this->decideEbayStockAction($product_id, $product['quantity'], $product['subtract']);
    795 
    796 				return array('msg' => 'ok', 'error' => false);
    797 			}
    798 		} else {
    799 			$old_item_id = $this->getEndedEbayItemId($product_id);
    800 			$this->log('productUpdateListen(' . $product_id . ') - Standard item. Old ID: ' . $old_item_id);
    801 
    802 			if ($old_item_id != false) {
    803 				if ($this->openbay->addonLoad('openstock') && (isset($product['has_option']) && $product['has_option'] == 1)) {
    804 					$this->log('productUpdateListen(' . $product_id . ') - multi variant items relist not supported');
    805 					/**
    806 					 * reserved for multi variant products can be relisted automatically.
    807 					 */
    808 				} else {
    809 					$this->log('productUpdateListen(' . $product_id . ') - Normal, stock(' . $product['quantity'] . ') > 0');
    810 					if ($product['quantity'] > 0) {
    811 						if ($this->config->get('ebay_relistitems') == 1) {
    812 							$this->relistItem($old_item_id, $product_id, $product['quantity']);
    813 						}
    814 					}
    815 				}
    816 			} else {
    817 				$this->log('productUpdateListen() - stoping, nothing found');
    818 			}
    819 		}
    820 	}
    821 
    822 	public function orderStatusListen($order_id, $status_id, $data = array()) {
    823 		$ebay_order = $this->getOrder($order_id);
    824 
    825 		if (isset($ebay_order['smp_id'])) {
    826 			$ebay_id = $ebay_order['smp_id'];
    827 		} else {
    828 			$ebay_id = false;
    829 		}
    830 
    831 		$this->log('orderStatusListen() - Order ' . $order_id . ' changed status');
    832 
    833 		if ($ebay_id != false) {
    834 			$this->log('orderStatusListen() - It is an eBay order, new status: ' . $status_id);
    835 
    836 			$item_txn_array = $this->getSaleRecord($ebay_id);
    837 
    838 			if (!empty($item_txn_array)) {
    839 				//Has it been marked as paid?
    840 				if ($status_id == $this->config->get('ebay_status_paid_id')) {
    841 					$this->log('orderStatusListen() - Updating to paid status');
    842 					foreach ($item_txn_array as $item) {
    843 						$tmp = simplexml_load_string($this->eBayPaymentStatus($item['item'], $item['txn'], true));
    844 					}
    845 				}
    846 
    847 				// Has it been marked as shipped?
    848 				if ($status_id == $this->config->get('ebay_status_shipped_id')) {
    849 					$this->log('orderStatusListen() - Updating to shipped status');
    850 					foreach ($item_txn_array as $item) {
    851 						$tmp = simplexml_load_string($this->eBayShippingStatus($item['item'], $item['txn'], true, (isset($data['tracking_no']) ? $data['tracking_no'] : ''), (isset($data['carrier_id']) ? $data['carrier_id'] : '')));
    852 					}
    853 					$this->db->query("UPDATE `" . DB_PREFIX . "ebay_order` SET `carrier_id` = '" . $this->db->escape((isset($data['carrier_id']) ? $data['carrier_id'] : '')) . "', `tracking_no` = '" . $this->db->escape((isset($data['tracking_no']) ? $data['tracking_no'] : '')) . "' WHERE `order_id` = '" . (int)$order_id . "' LIMIT 1");
    854 				}
    855 
    856 				//Has it been marked as cancelled?
    857 				if ($status_id == $this->config->get('ebay_status_cancelled_id')) {
    858 					$this->log('orderStatusListen() - Updating to cancelled status');
    859 					foreach ($item_txn_array as $item) {
    860 						$tmp = simplexml_load_string($this->eBayPaymentStatus($item['item'], $item['txn'], false));
    861 					}
    862 
    863 					foreach ($item_txn_array as $item) {
    864 						$tmp = simplexml_load_string($this->eBayShippingStatus($item['item'], $item['txn'], false));
    865 					}
    866 				}
    867 
    868 				//Has it been marked as refunded?
    869 				if ($status_id == $this->config->get('ebay_status_refunded_id')) {
    870 					$this->log('orderStatusListen() - Updating to refunded status');
    871 					foreach ($item_txn_array as $item) {
    872 						$tmp = simplexml_load_string($this->eBayPaymentStatus($item['item'], $item['txn'], false));
    873 					}
    874 
    875 					foreach ($item_txn_array as $item) {
    876 						$tmp = simplexml_load_string($this->eBayShippingStatus($item['item'], $item['txn'], false));
    877 					}
    878 				}
    879 			} else {
    880 				// @todo return error to use here
    881 				$this->log('orderStatusListen() - The TXN array was empty, could not get order info to update status. ');
    882 			}
    883 		} else {
    884 			$this->log('orderStatusListen() - It is not an eBay order');
    885 		}
    886 	}
    887 
    888 	public function decideEbayStockAction($product_id, $qty, $subtract, $sku = null) {
    889 		if ($subtract == 1) {
    890 			$this->log('decideEbayStockAction() - Product ID: ' . $product_id . ', Current stock: ' . $qty);
    891 
    892 			$item_id = $this->getEbayItemId($product_id);
    893 
    894 			if ($item_id != false) {
    895 				$this->putStockUpdate($item_id, $qty, $sku);
    896 			}
    897 		} else {
    898 			$this->log('decideEbayStockAction() - Product ID: ' . $product_id . ' does not subtract stock');
    899 		}
    900 	}
    901 
    902 	public function getProductId($ebay_item, $status = 0) {
    903 		$this->log('getProductId() - Item: ' . $ebay_item);
    904 
    905 		$status_sql = '';
    906 		if ($status == 1) {
    907 			$status_sql = ' AND `status` = 1';
    908 		}
    909 
    910 		$qry = $this->db->query("SELECT `product_id` FROM `" . DB_PREFIX . "ebay_listing` WHERE `ebay_item_id` = '" . $this->db->escape($ebay_item) . "'" . $status_sql . " ORDER BY `status` DESC, `ebay_listing_id` DESC LIMIT 1");
    911 
    912 		if (!$qry->num_rows) {
    913 			return false;
    914 		} else {
    915 			return $qry->row['product_id'];
    916 		}
    917 	}
    918 
    919 	public function getProductIdFromKey($key) {
    920 		$qry = $this->db->query("SELECT `product_id` FROM `" . DB_PREFIX . "ebay_listing_pending` WHERE `key` = '" . $this->db->escape($key) . "' LIMIT 1");
    921 
    922 		if (!$qry->num_rows) {
    923 			return false;
    924 		} else {
    925 			return $qry->row['product_id'];
    926 		}
    927 	}
    928 
    929 	public function validate() {
    930 		if ($this->config->get('ebay_status') != 0 && $this->config->get('ebay_token') != '' && $this->config->get('ebay_secret') != '' && $this->config->get('ebay_encryption_key') != '' && $this->config->get('ebay_encryption_iv') != '') {
    931 			return true;
    932 		} else {
    933 			return false;
    934 		}
    935 	}
    936 
    937 	public function getAllocatedStock($product_id) {
    938 		$qry = $this->db->query("SELECT SUM(`qty`) AS `total` FROM `" . DB_PREFIX . "ebay_transaction` WHERE `product_id` = '" . (int)$product_id . "' AND `order_id` = '0' LIMIT 1");
    939 		return (int)$qry->row['total'];
    940 	}
    941 
    942 	public function getImages() {
    943 		$this->log('getImages() - Getting product images . ');
    944 		$qry = $this->db->query("SELECT * FROM `" . DB_PREFIX . "ebay_image_import`");
    945 
    946 		if ($qry->num_rows) {
    947 			foreach ($qry->rows as $img) {
    948 				$this->log('Image: ' . $img['name']);
    949 
    950 				$img_large = str_replace(array('$_1.JPG', '$_01.JPG', '$_12.JPG'), '$_57.JPG', $img['image_original']);
    951 
    952 				$header_response = $this->getImageInfo($img_large);
    953 
    954 				$copy_status = false;
    955 
    956 				if ($header_response == 200) {
    957 					// a supersize version was found.
    958 					$copy_status = $this->getImageCopy($img_large, $img['image_new']);
    959 				} else {
    960 					// fall back to trying the original image
    961 					$header_response = $this->getImageInfo($img['image_original']);
    962 
    963 					if ($header_response == 200) {
    964 						$copy_status = $this->getImageCopy($img['image_original'], $img['image_new']);
    965 					}
    966 				}
    967 
    968 				if ($copy_status == true) {
    969 					if ($img['imgcount'] == 0) {
    970 						$this->db->query("UPDATE `" . DB_PREFIX . "product` SET `image` = 'catalog/" . $img['name'] . "' WHERE `product_id` = '" . (int)$img['product_id'] . "' LIMIT 1");
    971 					} else {
    972 						$this->db->query("INSERT INTO `" . DB_PREFIX . "product_image` SET `product_id` = '" . (int)$img['product_id'] . "', `image` = 'catalog/" . $this->db->escape($img['name']) . "', `sort_order` = '" . (int)$img['imgcount'] . "'");
    973 					}
    974 
    975 					$this->db->query("DELETE FROM `" . DB_PREFIX . "ebay_image_import` WHERE `id` = '" . (int)$img['id'] . "' LIMIT 1");
    976 				}
    977 			}
    978 		}
    979 	}
    980 
    981 	private function getImageInfo($url) {
    982 		$curl = curl_init($url);
    983 		curl_setopt($curl, CURLOPT_NOBODY, true);
    984 
    985 		if(curl_exec($curl) === false) {
    986 			$this->log('Curl Error: ' . curl_error($curl));
    987 		}
    988 
    989 		$header_response = curl_getinfo($curl, CURLINFO_HTTP_CODE);
    990 
    991 		$this->log($header_response);
    992 
    993 		curl_close($curl);
    994 
    995 		return $header_response;
    996 	}
    997 
    998 	private function getImageCopy($url, $image_new) {
    999 		$handle = @fopen($url, 'r');
   1000 
   1001 		if ($handle !== false) {
   1002 			if (!@copy($url, $image_new)) {
   1003 				$this->log('getImages() - FAILED COPY: ' . $url);
   1004 				$this->log(print_r(error_get_last(), true));
   1005 				return false;
   1006 			} else {
   1007 				$this->log('getImages() - Copy OK : ' . $url);
   1008 				return true;
   1009 			}
   1010 		} else {
   1011 			$this->log('getImages() - URL not found : ' . $url);
   1012 			return false;
   1013 		}
   1014 	}
   1015 
   1016 	public function getEbayListing($item_id) {
   1017 		$this->log('getEbayListing()');
   1018 		return $this->call('item/getItem/', array('itemId' => $item_id));
   1019 	}
   1020 
   1021 	public function relistItem($item_id, $product_id, $qty) {
   1022 		$this->log('relistItem() - Starting relist item, ID: ' . $item_id . ', product: ' . $product_id . ', qty: ' . $qty);
   1023 
   1024 		$response = $this->call('listing/relistItem/', array('itemId' => $item_id, 'qty' => $qty));
   1025 
   1026 		if (!empty($response['ItemID'])) {
   1027 			$this->log('relistItem() - Created: ' . $response['ItemID']);
   1028 			$this->createLink($product_id, $response['ItemID'], '');
   1029 			return $response['ItemID'];
   1030 		} else {
   1031 			$this->log('relistItem() - Relisting failed ID: ' . $item_id);
   1032 			return false;
   1033 		}
   1034 	}
   1035 
   1036 	public function createLink($product_id, $item_id, $variant) {
   1037 		$this->deleteProduct($product_id);
   1038 		$this->removeItemByItemId($item_id);
   1039 
   1040 		$this->db->query("INSERT INTO `" . DB_PREFIX . "ebay_listing` SET `product_id` = '" . (int)$product_id . "', `ebay_item_id` = '" . $this->db->escape($item_id) . "', `variant` = '" . (int)$variant . "', `status` = '1'");
   1041 	}
   1042 
   1043 	public function addReserve($data, $item_id, $variant) {
   1044 		if ($variant == 1) {
   1045 			foreach ($data['opt'] as $variation) {
   1046 				$query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "product_option_variant` WHERE `product_id` = '" . (int)$data['product_id'] . "' AND `sku` = '" . $this->db->escape($variation['sku']) . "' LIMIT 1");
   1047 
   1048 				if ($query->row['stock'] != $variation['qty']) {
   1049 					$this->db->query("INSERT INTO `" . DB_PREFIX . "ebay_stock_reserve` SET `product_id` = '" . (int)$data['product_id'] . "', `item_id` = '" . $this->db->escape($item_id) . "', `variant_id` = '" . $this->db->escape($variation['sku']) . "', `reserve` = '" . (int)$variation['qty'] . "'");
   1050 				}
   1051 			}
   1052 		} else {
   1053 			$query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "product` WHERE `product_id` = '" . (int)$data['product_id'] . "' LIMIT 1");
   1054 
   1055 			if ($query->row['quantity'] != $data['qty'][0]) {
   1056 				$this->db->query("INSERT INTO `" . DB_PREFIX . "ebay_stock_reserve` SET `product_id`    = '" . (int)$data['product_id'] . "', `item_id` = '" . $this->db->escape($item_id) . "', `variant_id` = '', `reserve` = '" . (int)$data['qty'][0] . "'");
   1057 			}
   1058 		}
   1059 	}
   1060 
   1061 	public function getReserve($product_id, $item_id, $sku = '') {
   1062 		$this->log('getReserve()');
   1063 		$query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "ebay_stock_reserve` WHERE `product_id` = '" . (int)$product_id . "' AND `variant_id` = '" . $this->db->escape($sku) . "' AND `item_id` = '" . $this->db->escape($item_id) . "'  LIMIT 1");
   1064 
   1065 		if ($query->num_rows > 0) {
   1066 			$this->log('getReserve() - returning: ' . $query->row['reserve']);
   1067 			return $query->row['reserve'];
   1068 		} else {
   1069 			$this->log('getReserve() - none');
   1070 			return false;
   1071 		}
   1072 	}
   1073 
   1074 	public function updateReserve($product_id, $item_id, $reserve, $sku = '', $variant = 0) {
   1075 		$this->log('updateReserve() - start');
   1076 		$this->log('updateReserve() - $product_id: ' . $product_id);
   1077 		$this->log('updateReserve() - $item_id: ' . $item_id);
   1078 		$this->log('updateReserve() - $reserve: ' . $reserve);
   1079 		$this->log('updateReserve() - $sku: ' . $sku);
   1080 		$this->log('updateReserve() - $variant: ' . $variant);
   1081 
   1082 		if ($reserve == 0) {
   1083 			$this->deleteReserve($product_id, $item_id, $sku);
   1084 		} else {
   1085 			if ($this->getReserve($product_id, $item_id, $sku) != false) {
   1086 				$this->db->query("UPDATE `" . DB_PREFIX . "ebay_stock_reserve` SET `reserve` = '" . (int)$reserve . "' WHERE `product_id` = '" . (int)$product_id . "' AND `variant_id` = '" . $this->db->escape($sku) . "' AND `item_id` = '" . $this->db->escape($item_id) . "'  LIMIT 1");
   1087 			} else {
   1088 				if ($variant == 0) {
   1089 					$this->log('updateReserve() - not a variant');
   1090 					$this->addReserve(array('product_id' => $product_id, 'qty' => array(0 => $reserve)), $item_id, 0);
   1091 				} else {
   1092 					$this->log('updateReserve() - variant');
   1093 					$this->addReserve(array('product_id' => $product_id, 'opt' => array(array('sku' => $sku, 'qty' => $reserve))), $item_id, 1);
   1094 				}
   1095 			}
   1096 		}
   1097 	}
   1098 
   1099 	public function deleteReserve($product_id, $item_id, $sku = '') {
   1100 		$this->log('deleteReserve()');
   1101 		$this->db->query("DELETE FROM `" . DB_PREFIX . "ebay_stock_reserve` WHERE `product_id` = '" . (int)$product_id . "' AND `variant_id` = '" . $this->db->escape($sku) . "' AND `item_id` = '" . $this->db->escape($item_id) . "'  LIMIT 1");
   1102 	}
   1103 
   1104 	public function getCarriers() {
   1105 		$qry = $this->db->query("SELECT * FROM " . DB_PREFIX . "ebay_shipping");
   1106 
   1107 		$couriers = array();
   1108 		foreach ($qry->rows as $row) {
   1109 			$couriers[] = $row;
   1110 		}
   1111 
   1112 		return $couriers;
   1113 	}
   1114 
   1115 	public function getOrder($order_id) {
   1116 		if ($this->openbay->testDbTable(DB_PREFIX . "ebay_order") == true) {
   1117 			$qry = $this->db->query("SELECT * FROM `" . DB_PREFIX . "ebay_order` WHERE `order_id` = '" . (int)$order_id . "' LIMIT 1");
   1118 
   1119 			if ($qry->num_rows > 0) {
   1120 				return $qry->row;
   1121 			} else {
   1122 				return false;
   1123 			}
   1124 		} else {
   1125 			return false;
   1126 		}
   1127 	}
   1128 
   1129 	public function getOrderBySmpId($smp_id) {
   1130 		if ($this->openbay->testDbTable(DB_PREFIX . "ebay_order") == true) {
   1131 			$qry = $this->db->query("SELECT * FROM `" . DB_PREFIX . "ebay_order` WHERE `smp_id` = '" . (int)$smp_id . "' LIMIT 1");
   1132 
   1133 			if ($qry->num_rows > 0) {
   1134 				return $qry->row;
   1135 			} else {
   1136 				return false;
   1137 			}
   1138 		} else {
   1139 			return false;
   1140 		}
   1141 	}
   1142 
   1143 	public function updateCategories() {
   1144 		$cat_array = $this->call('setup/getEbayCategories/', array(), array(), 'json', true);
   1145 
   1146 		if ($this->lasterror != true) {
   1147 			$this->db->query("TRUNCATE TABLE `" . DB_PREFIX . "ebay_category`");
   1148 
   1149 			if (!empty($cat_array)) {
   1150 				foreach ($cat_array as $cat) {
   1151 					if ($cat['BestOfferEnabled'] == true) {
   1152 						$cat['BestOfferEnabled'] = 1;
   1153 					} else {
   1154 						$cat['BestOfferEnabled'] = 0;
   1155 					}
   1156 
   1157 					if ($cat['AutoPayEnabled'] == true) {
   1158 						$cat['AutoPayEnabled'] = 1;
   1159 					} else {
   1160 						$cat['AutoPayEnabled'] = 0;
   1161 					}
   1162 
   1163 					$this->db->query("
   1164 						INSERT INTO `" . DB_PREFIX . "ebay_category` SET
   1165 							`CategoryID`        = '" . (int)$cat['CategoryID'] . "',
   1166 							`CategoryParentID`  = '" . (int)$cat['CategoryParentID'] . "',
   1167 							`CategoryLevel`     = '" . (int)$cat['CategoryLevel'] . "',
   1168 							`BestOfferEnabled`  = '" . (int)$cat['BestOfferEnabled'] . "',
   1169 							`AutoPayEnabled`    = '" . (int)$cat['AutoPayEnabled'] . "',
   1170 							`CategoryName`      = '" . $this->db->escape((string)$cat['CategoryName']) . "'
   1171 					");
   1172 				}
   1173 			}
   1174 		}
   1175 
   1176 		return array('msg' => $this->lastmsg, 'error' => $this->lasterror);
   1177 	}
   1178 
   1179 	public function updateSettings() {
   1180 		$response = $this->call('setup/getEbayDetails/', array(), array(), 'json', true);
   1181 
   1182 		$this->log('Getting eBay settings / sync');
   1183 
   1184 		if ($this->lasterror === false) {
   1185 			if (isset($response['listing_restrictions'])) {
   1186 				$qry = $this->db->query("SELECT * FROM `" . DB_PREFIX . "ebay_setting_option` WHERE `key` = 'listing_restrictions' LIMIT 1");
   1187 
   1188 				if ($qry->num_rows > 0) {
   1189 					$this->db->query("UPDATE `" . DB_PREFIX . "ebay_setting_option` SET `data` = '" . $this->db->escape(serialize($response['listing_restrictions'])) . "', `last_updated`  = now() WHERE `key` = 'listing_restrictions' LIMIT 1");
   1190 					$this->log('Updated listing_restrictions into ebay_setting_option table');
   1191 				} else {
   1192 					$this->db->query("INSERT INTO `" . DB_PREFIX . "ebay_setting_option` SET `key` = 'listing_restrictions', `data` = '" . $this->db->escape(serialize($response['listing_restrictions'])) . "', `last_updated`  = now()");
   1193 					$this->log('Inserted listing_restrictions into ebay_setting_option table');
   1194 				}
   1195 			} else {
   1196 				$this->log('listing_restrictions data not set!');
   1197 			}
   1198 
   1199 			if (isset($response['product_details'])) {
   1200 				$qry = $this->db->query("SELECT * FROM `" . DB_PREFIX . "ebay_setting_option` WHERE `key` = 'product_details' LIMIT 1");
   1201 
   1202 				if ($qry->num_rows > 0) {
   1203 					$this->db->query("UPDATE `" . DB_PREFIX . "ebay_setting_option` SET `data` = '" . $this->db->escape(serialize($response['product_details'])) . "', `last_updated`  = now() WHERE `key` = 'product_details' LIMIT 1");
   1204 					$this->log('Updated product_details into ebay_setting_option table');
   1205 				} else {
   1206 					$this->db->query("INSERT INTO `" . DB_PREFIX . "ebay_setting_option` SET `key` = 'product_details', `data` = '" . $this->db->escape(serialize($response['product_details'])) . "', `last_updated`  = now()");
   1207 					$this->log('Inserted product_details into ebay_setting_option table');
   1208 				}
   1209 			} else {
   1210 				$this->log('Non identifier text not set!');
   1211 			}
   1212 
   1213 			if (isset($response['urls']['ViewItemURL'])) {
   1214 				$this->db->query("DELETE FROM `" . DB_PREFIX . "setting` WHERE  `key` = 'ebay_itm_link' LIMIT 1");
   1215 
   1216 				$this->db->query("INSERT INTO `" . DB_PREFIX . "setting` SET `value` = '" . $this->db->escape((string)$response['urls']['ViewItemURL']) . "', `key` = 'ebay_itm_link', `code` = 'openbay'");
   1217 
   1218 				$this->log('Updated eBay item link');
   1219 			} else {
   1220 				$this->log('Item link URL not set!');
   1221 			}
   1222 
   1223 			//ebay payment methods
   1224 			if (isset($response['payment_options'])) {
   1225 				$this->db->query("TRUNCATE TABLE `" . DB_PREFIX . "ebay_payment_method`");
   1226 				$this->log('Emptied ebay_payment_method table');
   1227 
   1228 				foreach ($response['payment_options'] as $child) {
   1229 					$this->db->query("INSERT INTO `" . DB_PREFIX . "ebay_payment_method` SET `ebay_name` = '" . $this->db->escape((string)$child['PaymentOption']) . "', `local_name` = '" . $this->db->escape((string)$child['Description']) . "'");
   1230 				}
   1231 
   1232 				$this->log('Populated ebay_payment_method table');
   1233 			} else {
   1234 				$this->log('No payment options set!');
   1235 			}
   1236 
   1237 			//ebay shipping
   1238 			if (isset($response['shipping_service'])) {
   1239 				$this->db->query("TRUNCATE TABLE `" . DB_PREFIX . "ebay_shipping`");
   1240 				$this->log('Emptied ebay_shipping table');
   1241 				foreach ($response['shipping_service'] as $service) {
   1242 					if (!empty($service['InternationalService']) && $service['InternationalService'] == 'true') {
   1243 						$service['InternationalService'] = 1;
   1244 					} else {
   1245 						$service['InternationalService'] = 0;
   1246 					}
   1247 
   1248 					if (!empty($service['ValidForSellingFlow'])) {
   1249 						$service['ValidForSellingFlow'] = 1;
   1250 					} else {
   1251 						$service['ValidForSellingFlow'] = 0;
   1252 					}
   1253 
   1254 					if (!empty($service['ShippingTimeMin'])) {
   1255 						$min = (int)$service['ShippingTimeMin'];
   1256 					} else {
   1257 						$min = 1;
   1258 					}
   1259 					if (!empty($service['ShippingTimeMax'])) {
   1260 						$max = (int)$service['ShippingTimeMax'];
   1261 					} else {
   1262 						$max = 21;
   1263 					}
   1264 
   1265 					$this->db->query("
   1266 						INSERT INTO `" . DB_PREFIX . "ebay_shipping` SET
   1267 							`description`               = '" . $this->db->escape((string)$service['Description']) . "',
   1268 							`InternationalService`      = '" . (int)$service['InternationalService'] . "',
   1269 							`ShippingService`           = '" . $this->db->escape((string)$service['ShippingService']) . "' ,
   1270 							`ShippingServiceID`         = '" . (int)$service['ShippingServiceID'] . "',
   1271 							`ServiceType`               = '" . $this->db->escape(strtolower(implode(',', $service['ServiceType']))) . "' ,
   1272 							`ValidForSellingFlow`       = '" . (int)$service['ValidForSellingFlow'] . "',
   1273 							`ShippingCategory`          = '" . $this->db->escape((string)$service['ShippingCategory']) . "' ,
   1274 							`ShippingTimeMin`           = '" . (int)$min . "',
   1275 							`ShippingTimeMax`           = '" . (int)$max . "'
   1276 					");
   1277 				}
   1278 				$this->log('Populated ebay_shipping table');
   1279 			} else {
   1280 				$this->log('No shiopping details set!');
   1281 			}
   1282 
   1283 			//shipping locations
   1284 			if (isset($response['shipping_location'])) {
   1285 				$this->db->query("TRUNCATE TABLE `" . DB_PREFIX . "ebay_shipping_location`");
   1286 				$this->log('Emptied ebay_shipping_location table');
   1287 				foreach ($response['shipping_location'] as $service) {
   1288 					$this->db->query("
   1289 						INSERT INTO `" . DB_PREFIX . "ebay_shipping_location`
   1290 						SET
   1291 							`description`         = '" . $this->db->escape((string)$service['Description']) . "',
   1292 							`detail_version`      = '" . $this->db->escape($service['DetailVersion']) . "',
   1293 							`shipping_location`   = '" . $this->db->escape((string)$service['ShippingLocation']) . "' ,
   1294 							`update_time`         = '" . (int)$service['UpdateTime'] . "'
   1295 					");
   1296 				}
   1297 				$this->log('Populated ebay_shipping_location table');
   1298 			} else {
   1299 				$this->log('No shipping locations set!');
   1300 			}
   1301 
   1302 			//shipping locations exclude
   1303 			if (isset($response['exclude_shipping_location'])) {
   1304 				$this->db->query("TRUNCATE TABLE `" . DB_PREFIX . "ebay_shipping_location_exclude`");
   1305 				$this->log('Emptied ebay_shipping_location_exclude table');
   1306 				foreach ($response['exclude_shipping_location'] as $service) {
   1307 					$this->db->query("
   1308 						INSERT INTO `" . DB_PREFIX . "ebay_shipping_location_exclude`
   1309 						SET
   1310 							`description`   = '" . $this->db->escape((string)$service['Description']) . "',
   1311 							`location`      = '" . $this->db->escape((string)$service['Location']) . "',
   1312 							`region`        = '" . $this->db->escape((string)$service['Region']) . "'
   1313 					");
   1314 				}
   1315 				$this->log('Populated exclude_shipping_location table');
   1316 			} else {
   1317 				$this->log('No shipping exclude locations set!');
   1318 			}
   1319 
   1320 			//max dispatch times
   1321 			if (isset($response['dispatch_time_max'])) {
   1322 				$qry = $this->db->query("SELECT * FROM `" . DB_PREFIX . "ebay_setting_option` WHERE `key` = 'dispatch_time_max' LIMIT 1");
   1323 
   1324 				if ($qry->num_rows > 0) {
   1325 					$this->db->query("UPDATE `" . DB_PREFIX . "ebay_setting_option` SET `data` = '" . $this->db->escape(serialize($response['dispatch_time_max'])) . "', `last_updated`  = now() WHERE `key` = 'dispatch_time_max' LIMIT 1");
   1326 					$this->log('Updated dispatch_time_max into ebay_setting_option table');
   1327 				} else {
   1328 					$this->db->query("INSERT INTO `" . DB_PREFIX . "ebay_setting_option` SET `key` = 'dispatch_time_max', `data` = '" . $this->db->escape(serialize($response['dispatch_time_max'])) . "', `last_updated`  = now()");
   1329 					$this->log('Inserted dispatch_time_max into ebay_setting_option table');
   1330 				}
   1331 			} else {
   1332 				$this->log('No dispatch_time_max set!');
   1333 			}
   1334 
   1335 			//countries
   1336 			if (isset($response['countries'])) {
   1337 				$qry = $this->db->query("SELECT * FROM `" . DB_PREFIX . "ebay_setting_option` WHERE `key` = 'countries' LIMIT 1");
   1338 
   1339 				if ($qry->num_rows > 0) {
   1340 					$this->db->query("UPDATE `" . DB_PREFIX . "ebay_setting_option` SET `data` = '" . $this->db->escape(serialize($response['countries'])) . "', `last_updated`  = now() WHERE `key` = 'countries' LIMIT 1");
   1341 					$this->log('Updated countries into ebay_setting_option table');
   1342 				} else {
   1343 					$this->db->query("INSERT INTO `" . DB_PREFIX . "ebay_setting_option` SET `key` = 'countries', `data` = '" . $this->db->escape(serialize($response['countries'])) . "', `last_updated`  = now()");
   1344 					$this->log('Inserted countries into ebay_setting_option table');
   1345 				}
   1346 			} else {
   1347 				$this->log('No countries set!');
   1348 			}
   1349 
   1350 			//returns
   1351 			if (isset($response['returns'])) {
   1352 				$qry = $this->db->query("SELECT * FROM `" . DB_PREFIX . "ebay_setting_option` WHERE `key` = 'returns' LIMIT 1");
   1353 
   1354 				if ($qry->num_rows > 0) {
   1355 					$this->db->query("UPDATE `" . DB_PREFIX . "ebay_setting_option` SET `data` = '" . $this->db->escape(serialize($response['returns'])) . "', `last_updated`  = now() WHERE `key` = 'returns' LIMIT 1");
   1356 					$this->log('Updated returns info in to ebay_setting_option table');
   1357 				} else {
   1358 					$this->db->query("INSERT INTO `" . DB_PREFIX . "ebay_setting_option` SET `key` = 'returns', `data` = '" . $this->db->escape(serialize($response['returns'])) . "', `last_updated`  = now()");
   1359 					$this->log('Inserted returns info in to ebay_setting_option table');
   1360 				}
   1361 			} else {
   1362 				$this->log('No returns set!');
   1363 			}
   1364 
   1365 			//package sizes
   1366 			if (isset($response['package_type'])) {
   1367 				$qry = $this->db->query("SELECT * FROM `" . DB_PREFIX . "ebay_setting_option` WHERE `key` = 'package_type' LIMIT 1");
   1368 
   1369 				if ($qry->num_rows > 0) {
   1370 					$this->db->query("UPDATE `" . DB_PREFIX . "ebay_setting_option` SET `data` = '" . $this->db->escape(serialize($response['package_type'])) . "', `last_updated`  = now() WHERE `key` = 'package_type' LIMIT 1");
   1371 					$this->log('Updated package_type info in to ebay_setting_option table');
   1372 				} else {
   1373 					$this->db->query("INSERT INTO `" . DB_PREFIX . "ebay_setting_option` SET `key` = 'package_type', `data` = '" . $this->db->escape(serialize($response['package_type'])) . "', `last_updated`  = now()");
   1374 					$this->log('Inserted package_type info in to ebay_setting_option table');
   1375 				}
   1376 			} else {
   1377 				$this->log('No package_type set!');
   1378 			}
   1379 
   1380 			//vat enabled
   1381 			if (isset($response['vat_enabled'])) {
   1382 				$qry = $this->db->query("SELECT * FROM `" . DB_PREFIX . "ebay_setting_option` WHERE `key` = 'vat_enabled' LIMIT 1");
   1383 
   1384 				if ($qry->num_rows > 0) {
   1385 					$this->db->query("UPDATE `" . DB_PREFIX . "ebay_setting_option` SET `data` = '" . (int)$response['package_type'] . "', `last_updated`  = now() WHERE `key` = 'vat_enabled' LIMIT 1");
   1386 					$this->log('Updated vat_enabled in to ebay_setting_option table');
   1387 				} else {
   1388 					$this->db->query("INSERT INTO `" . DB_PREFIX . "ebay_setting_option` SET `key` = 'vat_enabled', `data` = '" . (int)$response['package_type'] . "', `last_updated`  = now()");
   1389 					$this->log('Inserted vat_enabled info in to ebay_setting_option table');
   1390 				}
   1391 			} else {
   1392 				$this->log('No vat_enabled set!');
   1393 			}
   1394 
   1395 			//shipping types
   1396 			if (isset($response['shipping_types'])) {
   1397 				$qry = $this->db->query("SELECT * FROM `" . DB_PREFIX . "ebay_setting_option` WHERE `key` = 'shipping_types' LIMIT 1");
   1398 
   1399 				if ($qry->num_rows > 0) {
   1400 					$this->db->query("UPDATE `" . DB_PREFIX . "ebay_setting_option` SET `data` = '" . $this->db->escape(serialize($response['shipping_types'])) . "', `last_updated`  = now() WHERE `key` = 'shipping_types' LIMIT 1");
   1401 					$this->log('Updated shipping_types info in to ebay_setting_option table');
   1402 				} else {
   1403 					$this->db->query("INSERT INTO `" . DB_PREFIX . "ebay_setting_option` SET `key` = 'shipping_types', `data` = '" . $this->db->escape(serialize($response['shipping_types'])) . "', `last_updated`  = now()");
   1404 					$this->log('Inserted shipping_types info in to ebay_setting_option table');
   1405 				}
   1406 			} else {
   1407 				$this->log('No shipping_types set!');
   1408 			}
   1409 
   1410 			//measurement types
   1411 			if (isset($response['measurement_types'])) {
   1412 				$qry = $this->db->query("SELECT * FROM `" . DB_PREFIX . "ebay_setting_option` WHERE `key` = 'measurement_types' LIMIT 1");
   1413 
   1414 				if ($qry->num_rows > 0) {
   1415 					$this->db->query("UPDATE `" . DB_PREFIX . "ebay_setting_option` SET `data` = '" . $this->db->escape(serialize($response['measurement_types'])) . "', `last_updated`  = now() WHERE `key` = 'measurement_types' LIMIT 1");
   1416 					$this->log('Updated measurement_types info in to ebay_setting_option table');
   1417 				} else {
   1418 					$this->db->query("INSERT INTO `" . DB_PREFIX . "ebay_setting_option` SET `key` = 'measurement_types', `data` = '" . $this->db->escape(serialize($response['measurement_types'])) . "', `last_updated`  = now()");
   1419 					$this->log('Inserted measurement_types info in to ebay_setting_option table');
   1420 				}
   1421 			} else {
   1422 				$this->log('No measurement_types set!');
   1423 			}
   1424 
   1425 			// Product details
   1426 			if (isset($response['product_details'])) {
   1427 				$qry = $this->db->query("SELECT * FROM `" . DB_PREFIX . "ebay_setting_option` WHERE `key` = 'product_details' LIMIT 1");
   1428 
   1429 				if ($qry->num_rows > 0) {
   1430 					$this->db->query("UPDATE `" . DB_PREFIX . "ebay_setting_option` SET `data` = '" . $this->db->escape(serialize($response['product_details'])) . "', `last_updated`  = now() WHERE `key` = 'product_details' LIMIT 1");
   1431 					$this->log('Updated product_details info in to ebay_setting_option table');
   1432 				} else {
   1433 					$this->db->query("INSERT INTO `" . DB_PREFIX . "ebay_setting_option` SET `key` = 'product_details', `data` = '" . $this->db->escape(serialize($response['product_details'])) . "', `last_updated`  = now()");
   1434 					$this->log('Inserted product_details info in to ebay_setting_option table');
   1435 				}
   1436 			} else {
   1437 				$this->log('No product_details set!');
   1438 			}
   1439 		}
   1440 
   1441 		return array('msg' => $this->lastmsg, 'error' => $this->lasterror);
   1442 	}
   1443 
   1444 	public function updateStore() {
   1445 		$store = $this->call('setup/getSellerStore/', array(), array(), 'json', true);
   1446 
   1447 		if ($this->lasterror != true) {
   1448 			if ($store['store'] == true) {
   1449 				$this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "ebay_store_category`;");
   1450 				$this->db->query("
   1451 							CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "ebay_store_category` (
   1452 							  `ebay_store_category_id` int(11) NOT NULL AUTO_INCREMENT,
   1453 							  `parent_id` int(11) NOT NULL,
   1454 							  `CategoryID` char(100) NOT NULL,
   1455 							  `CategoryName` char(100) NOT NULL,
   1456 							  PRIMARY KEY (`ebay_store_category_id`)
   1457 							) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;");
   1458 
   1459 				if (!empty($store['settings']['categories'])) {
   1460 					foreach ($store['settings']['categories'] as $cat1) {
   1461 						$this->db->query("INSERT INTO `" . DB_PREFIX . "ebay_store_category` SET `CategoryID` = '" . $this->db->escape($cat1['id']) . "', `CategoryName` = '" . $this->db->escape($cat1['name']) . "'");
   1462 						$id1 = $this->db->getLastId();
   1463 
   1464 						if (!empty($cat1['children'])) {
   1465 							foreach ($cat1['children'] as $cat2) {
   1466 								$this->db->query("INSERT INTO `" . DB_PREFIX . "ebay_store_category` SET `CategoryID` = '" . $this->db->escape($cat2['id']) . "', `CategoryName` = '" . $this->db->escape($cat2['name']) . "', `parent_id` = '" . $this->db->escape($id1) . "'");
   1467 								$id2 = $this->db->getLastId();
   1468 
   1469 								if (!empty($cat2['children'])) {
   1470 									foreach ($cat2['children'] as $cat3) {
   1471 										$this->db->query("INSERT INTO `" . DB_PREFIX . "ebay_store_category` SET `CategoryID` = '" . $this->db->escape($cat3['id']) . "', `CategoryName` = '" . $this->db->escape($cat3['name']) . "', `parent_id` = '" . $this->db->escape($id2) . "'");
   1472 										$id3 = $this->db->getLastId();
   1473 
   1474 										if (!empty($cat3['children'])) {
   1475 											foreach ($cat3['children'] as $cat4) {
   1476 												$this->db->query("INSERT INTO `" . DB_PREFIX . "ebay_store_category` SET `CategoryID` = '" . $this->db->escape($cat4['id']) . "', `CategoryName` = '" . $this->db->escape($cat4['name']) . "', `parent_id` = '" . $this->db->escape($id3) . "'");
   1477 												$id4 = $this->db->getLastId();
   1478 											}
   1479 										}
   1480 									}
   1481 								}
   1482 							}
   1483 						}
   1484 					}
   1485 				}
   1486 			}
   1487 		}
   1488 
   1489 		return array('msg' => $this->lastmsg, 'error' => $this->lasterror);
   1490 	}
   1491 
   1492 	public function editSetting($group, $data, $store_id = 0) {
   1493 		$this->db->query("DELETE FROM " . DB_PREFIX . "setting WHERE store_id = '" . (int)$store_id . "' AND `code` = '" . $this->db->escape($group) . "'");
   1494 
   1495 		foreach ($data as $key => $value) {
   1496 			if (!is_array($value)) {
   1497 				$this->db->query("INSERT INTO " . DB_PREFIX . "setting SET store_id = '" . (int)$store_id . "', `code` = '" . $this->db->escape($group) . "', `key` = '" . $this->db->escape($key) . "', `value` = '" . $this->db->escape($value) . "'");
   1498 			} else {
   1499 				$this->db->query("INSERT INTO " . DB_PREFIX . "setting SET store_id = '" . (int)$store_id . "', `code` = '" . $this->db->escape($group) . "', `key` = '" . $this->db->escape($key) . "', `value` = '" . $this->db->escape(serialize($value)) . "', serialized = '1'");
   1500 			}
   1501 		}
   1502 	}
   1503 
   1504 	public function getShippingServiceInfo($service_code) {
   1505 		$qry = $this->db->query("SELECT * FROM `" . DB_PREFIX . "ebay_shipping` WHERE `ShippingService` = '" . $this->db->escape($service_code) . "' LIMIT 1");
   1506 
   1507 		if ($qry->num_rows) {
   1508 			return $qry->row;
   1509 		} else {
   1510 			return false;
   1511 		}
   1512 	}
   1513 }