<?php
ClassLoader::import('application.model.system.Language');
ClassLoader::import('application.model.Currency');
ClassLoader::import('application.model.product.Manufacturer');
ClassLoader::import('application.model.category.Category');
ClassLoader::import('application.model.category.SpecField');
ClassLoader::import('application.model.product.Product');
ClassLoader::import('application.model.product.ProductRelationship');
ClassLoader::import('application.model.order.CustomerOrder');
ClassLoader::import('application.model.user.User');
ClassLoader::import('application.model.user.BillingAddress');
ClassLoader::import('application.model.delivery.State');
ClassLoader::import('application.model.newsletter.NewsletterSubscriber');
ClassLoader::import('application.model.staticpage.StaticPage');
class LiveCartImporter
{
const MAX_RECORDS = 5;
private $driver;
private $offsets;
public function __construct(LiveCartImportDriver $driver)
{
$this->driver = $driver;
$this->driver->setImporter($this);
$this->reset();
}
/**
* Determine what kind of data can be imported
*/
public function getItemTypes()
{
$supportedTypes = array();
foreach ($this->getRecordTypes() as $type)
{
if (call_user_func_array(array($this->driver, 'is' . $type), array()))
{
$supportedTypes[] = $type;
}
}
return $supportedTypes;
}
public function reset()
{
@unlink($this->getTypeFile());
@unlink($this->getProgressFile());
@unlink($this->getCountFile());
@unlink($this->getOffsetsFile());
}
/**
* Get current data type
*/
public function getCurrentType()
{
$file = $this->getTypeFile();
if (!file_exists($file))
{
$this->setNextType();
}
return include $file;
}
/**
* Get total number of importable records of the current data type
*/
public function getCurrentRecordCount()
{
$this->getCurrentType();
return include $this->getCountFile();
}
/**
* Get the number of imported records of the current data type
*/
public function getCurrentProgress()
{
$file = $this->getProgressFile();
if (!file_exists($file))
{
$this->setProgress(0);
}
return include $file;
}
/**
* Processes data import - one type of data at a time
*
* Data size is limited to 50 records per call
*/
public function process()
{
$type = $this->getCurrentType();
// import completed
if (is_null($type))
{
return null;
}
$total = $this->getCurrentRecordCount();
$offsets = $this->getIdOffsets();
$offset = isset($offsets[$type]) ? $offsets[$type] : null;
for ($k = 1; $k <= self::MAX_RECORDS; $k++)
{
$id = $this->getCurrentProgress();
try
{
$record = call_user_func_array(array($this->driver, 'getNext' . $type), array($id));
}
catch (Exception $e)
{
var_dump($e);
}
// import completed?
if (null == $record)
{
$this->setNextType();
break;
}
// apply ID offset
if (is_numeric($record->getID()))
{
$record->setID($record->getID() + $offset);
}
try
{
// call custom save routine if defined
if (method_exists($this->driver, 'save' . $type))
{
call_user_func_array(array($this->driver, 'save' . $type), array($record));
}
else
{
//$record->save(ActiveRecord::PERFORM_INSERT);
$record->save();
}
}
catch (Exception $e)
{
var_dump($e);
throw $e;
}
ActiveRecord::clearPool();
$record->__destruct();
$record->destruct();
unset($record);
$this->setProgress($this->getCurrentProgress() + 1);
}
return array('type' => $type, 'progress' => $this->getCurrentProgress(), 'total' => $total);
}
public function getRealId($type, $id)
{
if (!$this->offsets)
{
$this->offsets = include $this->getOffsetsFile();
}
if (isset($this->offsets[$type]))
{
return $this->offsets[$type] + $id;
}
else
{
return $id;
}
}
private function getIdOffsets()
{
$file = $this->getOffsetsFile();
if (!file_exists($file))
{
$offsets = array();
$types = $this->getRecordTypes();
unset($types[array_search('Language', $types)]);
unset($types[array_search('ProductRelationship', $types)]);
foreach ($types as $type)
{
$f = new ARSelectFilter();
$f->setOrder(new ARFieldHandle($type, 'ID'), 'DESC');
$f->setLimit(1);
$record = array_shift(ActiveRecordModel::getRecordSetArray($type, $f));
if (!$record)
{
$record['ID'] = 0;
}
$offsets[$type] = $record['ID'];
try
{
ActiveRecordModel::executeUpdate('ALTER TABLE ' . $type . ' AUTO_INCREMENT = ' . ($offsets[$type] + 1));
}
catch (Exception $e)
{
// we don't care much if it didn't work (won't work with MySQL <5.0.3)
}
}
file_put_contents($file, '<?php return ' . var_export($offsets, true) . '; ?>');
}
return include $file;
}
public function getRecordTypes()
{
return array(
'Language',
'Currency',
'Manufacturer',
'State',
'Category',
'SpecField',
'Product',
'UserGroup',
'User',
'CustomerOrder',
'BillingAddress',
'ProductRelationship',
'NewsletterSubscriber',
'StaticPage',
);
}
private function setNextType()
{
@unlink($this->getProgressFile());
$file = $this->getTypeFile();
$types = $this->getItemTypes();
if (!file_exists($file))
{
$typeIndex = -1;
}
else
{
$typeIndex = array_search(include $file, $types);
}
$typeIndex++;
$type = isset($types[$typeIndex]) ? $types[$typeIndex] : null;
// get total record count of this type
if (!is_null($type))
{
$count = $this->driver->getTotalRecordCount($type);
file_put_contents($this->getCountFile(), '<?php return ' . var_export($count, true) . '; ?>');
}
file_put_contents($file, '<?php return ' . var_export($type, true) . '; ?>');
}
private function setProgress($progress)
{
file_put_contents($this->getProgressFile(), '<?php return ' . var_export($progress, true) . '; ?>');
}
private function getOffsetsFile()
{
return ClassLoader::getRealPath('cache') . '/currentIdOffsets.php';
}
private function getTypeFile()
{
return ClassLoader::getRealPath('cache') . '/currentImportType.php';
}
private function getProgressFile()
{
return ClassLoader::getRealPath('cache') . '/currentImportProgress.php';
}
private function getCountFile()
{
return ClassLoader::getRealPath('cache') . '/currentImportCount.php';
}
}
?>