Location: PHPKode > projects > Livecart > library/import/driver/XCartImport.php
<?php

require_once dirname(__file__) . '/../LiveCartImportDriver.php';

class XCartImport extends LiveCartImportDriver
{
	protected $categoryMap = null;

	protected $productSql;
	private $specFieldSql;

	private $languagesTruncated;
	private $currenciesTruncated;
	private $defLang;
	private $attributes = array();

	public function getName()
	{
		return 'X-Cart';
	}

	public function isPathValid()
	{
		// no path provided - won't be able to import images
		if (!$this->path)
		{
			return true;
		}

		foreach (array('catalog', 'giftcert.php', 'modules') as $file)
		{
			if (!file_exists($this->path . '/' . $file))
			{
				return false;
			}
		}

		return true;
	}

	public function isLanguage()
	{
		return true;
	}

	public function isManufacturer()
	{
		return true;
	}

	public function isState()
	{
		return true;
	}

	public function isUser()
	{
		return true;
	}

	public function isCategory()
	{
		return true;
	}

	public function isSpecField()
	{
		return true;
	}

	public function isProduct()
	{
		return true;
	}

	public function isCustomerOrder()
	{
		return true;
	}

	public function getVerificationTableNames()
	{
		return array('categories', 'orders', 'products', 'customers', 'states', 'extra_fields');
	}

	public function getTableMap()
	{
		return array(
				'Category' => $this->getTablePrefix() . 'categories',
				'CustomerOrder' => $this->getTablePrefix() . 'orders',
				'Language' => array('SELECT COUNT(DISTINCT code) FROM ' . $this->getTablePrefix() . 'languages' => $this->getTablePrefix() . 'languages'),
				'Manufacturer' => $this->getTablePrefix() . 'manufacturers',
				'Product' => $this->getTablePrefix() . 'products',
				'User' => $this->getTablePrefix() . 'customers',
				'State' => $this->getTablePrefix() . 'states',
				'SpecField' => $this->getTablePrefix() . 'extra_fields',
			);
	}

	public function getNextLanguage()
	{
		if (!$this->languagesTruncated)
		{
			ActiveRecord::getDbConnection()->executeQuery('TRUNCATE TABLE Language');
			$this->languagesTruncated = true;
		}

		if (!$data = $this->loadRecord('SELECT DISTINCT code FROM ' . $this->getTablePrefix() . 'languages'))
		{
			return null;
		}

		$isDefault = $this->getConfigValue('default_customer_language') == $data['code'];

		$code = $data['code'];
		if ('US' == $data['code'])
		{
			$data['code'] = 'en';
		}

		$data['code'] = strtolower($data['code']);

		if (!$isDefault)
		{
			$this->languages[$data['code']] = $code;
		}
		else
		{
			$this->defLang = $data['code'];
		}

		$lang = ActiveRecordModel::getNewInstance('Language');
		$lang->setID($data['code']);
		$lang->isEnabled->set(true);

		$lang->isDefault->set($isDefault);

		return $lang;
	}

	public function getNextManufacturer()
	{
		if (!$data = $this->loadRecord('SELECT * FROM ' . $this->getTablePrefix() . 'manufacturers'))
		{
			return null;
		}

		$man = ActiveRecordModel::getNewInstance('Manufacturer');
		$man->setID($data['manufacturerid']);
		$man->name->set($data['manufacturer']);

		return $man;
	}

	public function getNextState()
	{
		if (!$data = $this->loadRecord('SELECT * FROM ' . $this->getTablePrefix() . 'states'))
		{
			return null;
		}

		$rec = ActiveRecordModel::getNewInstance('State');

		foreach (array(
					'countryID' => 'country_code',
					'code' => 'code',
					'name' => 'state',
				) as $lc => $xc)
		{
			$rec->$lc->set($data[$xc]);
		}

		return $rec;
	}

	public function getNextUser()
	{
		if (!$data = $this->loadRecord('SELECT * FROM ' . $this->getTablePrefix() . 'customers'))
		{
			return null;
		}

		$rec = User::getNewInstance($data['email']);

		foreach (array(
					'firstName' => 'firstname',
					'lastName' => 'lastname',
					'companyName' => 'company',
					'dateCreated' => 'first_login',
				) as $lc => $xc)
		{
			$rec->$lc->set($data[$xc]);
		}

		$rec->isEnabled->set($data['status'] == 'Y');

		if ($address = $this->getUserAddress($data, 's_'))
		{
			$rec->defaultShippingAddress->set(ShippingAddress::getNewInstance($rec, $address));
		}

		if ($address = $this->getUserAddress($data, 'b_'))
		{
			$rec->defaultBillingAddress->set(BillingAddress::getNewInstance($rec, $address));
		}

		return $rec;
	}

	public function getNextCategory()
	{
		if (is_null($this->categoryMap))
		{
			$join = $langs = array();
			foreach ($this->languages as $id => $code)
			{
				list($join[], $langs[]) = $this->joinCategoryFields($id, $code);
			}

			// get all categories
			$sql = 'SELECT ' . $this->getTablePrefix() . 'categories.* ' . ($langs ? ',' : '') . implode(', ', $langs) . ' FROM ' . $this->getTablePrefix() . 'categories ' . implode(' ', $join) . ' ORDER BY order_by ASC';
			foreach ($this->getDataBySQL($sql) as $category)
			{
				$this->categoryMap[$category['categoryid']] = $category;
			}

			// get level for each category
			foreach ($this->categoryMap as $id => &$category)
			{
				$level = 0;
				while ($id != 0 && ($level < 100))
				{
					$level++;

					if (isset($this->categoryMap[$id]['parentid']))
					{
						$id = $this->categoryMap[$id]['parentid'];
					}

					// parent category does not exist, so remove the category
					else if ($this->categoryMap[$id]['parentid'] != 0)
					{
						unset($this->categoryMap[$id]);
						$level = 101;
					}
				}

				// circular reference
				if ($level >= 100)
				{
					unset($this->categoryMap[$category['categoryid']]);
				}
				else
				{
					$category['level'] = $level;
				}
			}

			usort($this->categoryMap, array($this, 'sortCategories'));
		}

		// root level categories first
		if ($data = array_shift($this->categoryMap))
		{
			$parentNode = 0 == $data['parentid'] ? Category::getRootNode() : Category::getInstanceById($this->getRealId('Category', $data['parentid']));
			$rec = Category::getNewInstance($parentNode);
		}
		else
		{
			return null;
		}

		$rec->setID($data['categoryid']);
		$rec->isEnabled->set('Y' == $data['avail']);
		$rec->keywords->set($data['meta_keywords']);

		$rec->setValueByLang('name', $this->defLang, $data['category']);
		$rec->setValueByLang('description', $this->defLang, $data['description']);

		foreach ($this->languages as $code => $id)
		{
			$rec->setValueByLang('name', $code, $data['category_' . $code]);
			$rec->setValueByLang('description', $code, $data['description_' . $code]);
		}

		//images
		$images = $this->getDataBySQL('SELECT * FROM ' . $this->getTablePrefix() . 'images_c WHERE id=' . $data['categoryid'] . ' ORDER BY orderby ASC');
		foreach ($images as $image)
		{
			$this->importCategoryImage($rec, $this->path . '/' . $image['image_path']);
		}

		$rec->rawData = $data;

		return $rec;
	}

	protected function joinCategoryFields($code, $id)
	{
		return array('LEFT JOIN ' . $this->getTablePrefix() . 'categories_lng AS category_' . $code . ' ON category_' . $code . '.categoryid=' . $this->getTablePrefix() . 'categories.categoryid AND category_' . $code . '.code="' . $id . '"',
					 'category_' . $code . '.category AS category_' . $code . ', category_' . $code . '.description AS description_' . $code
					);
	}

	public function getNextSpecField()
	{
		if (is_null($this->specFieldSql))
		{
			$join = $langs = array();
			foreach ($this->languages as $id => $code)
			{
				list($join[], $langs[]) = $this->joinAttributeFields($id, $code);
			}

			// get all categories
			$this->specFieldSql = 'SELECT ' . $this->getTablePrefix() . 'extra_fields.* ' . ($langs ? ',' : '') . implode(', ', $langs) . ' FROM ' . $this->getTablePrefix() . 'extra_fields ' . implode(' ', $join) . ' ORDER BY orderby ASC';
		}

		if (!$data = $this->loadRecord($this->specFieldSql))
		{
			return null;
		}

		$this->attributes[] = $data;

		$rec = SpecField::getNewInstance(Category::getRootNode(), SpecField::DATATYPE_TEXT, SpecField::TYPE_TEXT_SIMPLE);
		$rec->setID($data['fieldid']);
		$rec->handle->set($data['service_name']);
		$rec->setValueByLang('name', $this->defLang, $data['field']);
		$rec->isDisplayed->set(true);

		foreach ($this->languages as $code => $id)
		{
			$rec->setValueByLang('name', $code, $data['fieldname_' . $code]);
		}

		return $rec;
	}

	protected function joinAttributeFields($code, $id)
	{
		return array('LEFT JOIN ' . $this->getTablePrefix() . 'extra_fields_lng AS field_' . $code . ' ON field_' . $code . '.fieldid=' . $this->getTablePrefix() . 'extra_fields.fieldid AND field_' . $code . '.code="' . $id . '"',
					 'field_' . $code . '.field AS fieldname_' . $code
					);
	}

	public function getNextProduct()
	{
		if (!$this->productSql)
		{
			foreach ($this->languages as $code => $id)
			{
				list($join[], $langs[]) = $this->joinProductFields($id, $code);
			}

			foreach ($this->attributes as $attr)
			{
				$join[] = 'LEFT JOIN ' . $this->getTablePrefix() . 'extra_field_values  AS extra_' . $attr['fieldid'] . ' ON (extra_' . $attr['fieldid'] . '.productid=' . $this->getTablePrefix() . 'products.productid AND extra_' . $attr['fieldid'] . '.fieldid=' . $attr['fieldid'] . ')';
				$langs[] = 'extra_' . $attr['fieldid'] . '.value AS extrafield_' . $attr['fieldid'];
			}

			$this->productSql = 'SELECT ' . $this->getTablePrefix() . 'products.*, ' . $this->getTablePrefix() . 'products_categories.categoryid ' . ($langs ? ',' : '') . implode(', ', $langs) . ', (SELECT price FROM ' . $this->getTablePrefix() . 'pricing WHERE ' . $this->getTablePrefix() . 'pricing.productid=' . $this->getTablePrefix() . 'products.productid ORDER BY quantity ASC LIMIT 1) AS price FROM ' . $this->getTablePrefix() . 'products ' . implode(' ', $join) . ' LEFT JOIN ' . $this->getTablePrefix() . 'products_categories ON (' . $this->getTablePrefix() . 'products.productid=' . $this->getTablePrefix() . 'products_categories.productid AND ' . $this->getTablePrefix() . 'products_categories.main="Y")';
		}

		if (!$data = $this->loadRecord($this->productSql))
		{
			return null;
		}

		$rec = Product::getNewInstance(Category::getInstanceById($this->getRealId('Category', $data['categoryid'])));
		$rec->setID($data['productid']);
		$rec->keywords->set($data['keywords']);

		$rec->setValueByLang('name', $this->defLang, $data['product']);
		$rec->setValueByLang('longDescription', $this->defLang, $data['fulldescr']);
		$rec->setValueByLang('shortDescription', $this->defLang, $data['descr']);

		foreach ($this->languages as $code => $id)
		{
			$rec->setValueByLang('name', $code, $data['name_' . $code]);
			$rec->setValueByLang('longDescription', $code, $data['fulldescr_' . $code]);
			$rec->setValueByLang('shortDescription', $code, $data['descr_' . $code]);
		}

		foreach ($this->attributes as $attr)
		{
			if (!empty($data['extrafield_' . $attr['fieldid']]))
			{
				$rec->setAttributeValueByLang(SpecField::getInstanceByID($this->getRealId('SpecField', $attr['fieldid']), SpecField::LOAD_DATA), $this->defLang, $data['extrafield_' . $attr['fieldid']]);
			}
		}

		if ($data['manufacturerid'])
		{
			$rec->manufacturer->set(Manufacturer::getInstanceById($this->getRealId('Manufacturer', $data['manufacturerid'])));
		}

		foreach (array(
					'sku' => 'productcode',
					'shippingWeight' => 'weight',
					'stockCount' => 'avail',
					'shippingSurchargeAmount' => 'shipping_freight',
					'minimumQuantity' => 'min_amount',
					'dateCreated' => 'add_date',
				) as $lc => $xc)
		{
			$rec->$lc->set($data[$xc]);
		}

		$rec->isEnabled->set('Y' == $data['forsale']);

		$rec->setPrice($this->getDefaultCurrency(), $data['price']);

		//images
		$images = array_merge(
			// main thumbnail
			$this->getDataBySQL('SELECT * FROM ' . $this->getTablePrefix() . 'images_t WHERE id=' . $data['productid'] . ' ORDER BY orderby ASC'),

			// additional large size images
			$this->getDataBySQL('SELECT * FROM ' . $this->getTablePrefix() . 'images_d WHERE id=' . $data['productid'] . ' ORDER BY orderby ASC')
			);

		foreach ($images as $image)
		{
			$this->importProductImage($rec, $this->path . '/' . $image['image_path']);
		}

		$rec->rawData = $data;

		return $rec;
	}

	protected function joinProductFields($id, $code)
	{
		return array('LEFT JOIN ' . $this->getTablePrefix() . 'products_lng AS product_' . $code . ' ON (product_' . $code . '.productid=' . $this->getTablePrefix() . 'products.productid AND product_' . $code . '.code="' . $id . '")',
					 'product_' . $code . '.product AS name_' . $code . ', ' . 'product_' . $code . '.descr AS descr_' . $code . ', ' . 'product_' . $code . '.fulldescr AS fulldescr_' . $code
					);
	}

	public function getNextCustomerOrder()
	{
		if (!$data = $this->loadRecord('SELECT ' . $this->getTablePrefix() . 'orders.*, ' . $this->getTablePrefix() . 'customers.email AS userEmail FROM ' . $this->getTablePrefix() . 'orders LEFT JOIN ' . $this->getTablePrefix() . 'customers ON ' . $this->getTablePrefix() . 'orders.login=' . $this->getTablePrefix() . 'customers.login'))
		{
			return null;
		}

		if (!$user = User::getInstanceByEmail($data['userEmail']))
		{
			return $this->getNextCustomerOrder();
		}

		$order = CustomerOrder::getNewInstance($user);
		$order->currency->set(Currency::getInstanceById($this->getDefaultCurrency()));
		$order->dateCompleted->set($data['date']);

		// products
		foreach ($this->getDataBySql('SELECT * FROM ' . $this->getTablePrefix() . 'order_details WHERE orderid=' . $data['orderid']) as $prod)
		{
			try
			{
				$product = Product::getInstanceById($this->getRealId('Product', $prod['productid']), true);
				$order->addProduct($product, $prod['amount'], true);
				$item = array_shift($order->getItemsByProduct($product));
				$item->price->set($prod['price']);
			}
			catch (ARNotFoundException $e)
			{
				// the product no longer exists
			}
		}

		// addresses
		$order->shippingAddress->set($this->getUserAddress($data, 's_'));
		$order->billingAddress->set($this->getUserAddress($data, 'b_'));

		// assume that all orders are paid and shipped
		$order->status->set(CustomerOrder::STATUS_SHIPPED);
		$order->isPaid->set(true);

		$order->rawData = $data;

		return $order;
	}

	private function getUserAddress($data, $prefix)
	{
		$address = UserAddress::getNewInstance();
		$map = array(
				'company' => 'companyName',
				'address' => 'address1',
				'city' => 'city',
				'zipcode' => 'postalCode',
				'state' => 'stateName',
				'firstname' => 'firstName',
				'lastname' => 'lastName',
				'country' => 'countryID',
			   );

		$isData = false;
		foreach ($map as $osc => $lc)
		{
			if (isset($data[$prefix . $osc]))
			{
				$address->$lc->set($data[$prefix . $osc]);
				$isData = true;
			}
		}

		if (!$isData)
		{
			return null;
		}

		if (!empty($data['phone']))
		{
			$address->phone->set($data['phone']);
		}

		return $address;
	}

	public function saveCustomerOrder(CustomerOrder $order)
	{
		$order->shippingAddress->get()->save();
		$order->billingAddress->get()->save();

		$order->save();

		$shipment = $order->getShipments()->get(0);
		$shipment->shippingAmount->set($order->rawData['shipping_cost']);
		$shipment->save();

		if ($order->rawData['tax'] > 0)
		{
			$tax = ActiveRecordModel::getNewInstance('ShipmentTax');
			$tax->shipment->set($shipment);
			$tax->amount->set($order->rawData['tax']);
			$tax->save();

			$shipment->addFixedTax($tax);
			$shipment->status->set(Shipment::STATUS_SHIPPED);
			$shipment->save();
		}

		return parent::saveCustomerOrder($order);
	}

	private function sortCategories($a, $b)
	{
		if ($a['level'] == $b['level'])
		{
			if ($a['order_by'] == $b['order_by'])
			{
				return 0;
			}
			else
			{
				return $a['order_by'] > $b['order_by'] ? 1 : -1;
			}
		}

		return $a['level'] > $b['level'] ? 1 : -1;
	}

	protected function getConfigData()
	{
		$map = array();

		foreach ($this->getDataBySQL('SELECT * FROM ' . $this->getTablePrefix() . 'config') as $row)
		{
			$map[$row['name']] = $row['value'];
		}

		return $map;
	}
}

?>
Return current item: Livecart