ZenCart data import - admin/custom menu.php

from HTYP, the free directory anyone can edit if they can prove to me that they're not a spambot
Revision as of 16:16, 10 March 2007 by Woozle (talk | contribs) (New page: ==Navigation== computing: software: ZenCart: importing data: '''admin/custom menu.php''' ==Overview== This file does the actual import. It conta...)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Navigation

computing: software: ZenCart: importing data: admin/custom menu.php

Overview

This file does the actual import. It contains a number of classes which might later be split off into separate PHP files, as they model particular aspects of the ZenCart data.

Source

<?php
//
// +----------------------------------------------------------------------+
// |zen-cart Open Source E-commerce                                       |
// +----------------------------------------------------------------------+
// | Copyright (c) 2003 The zen-cart developers                           |
// |                                                                      |
// | http://www.zen-cart.com/index.php                                    |
// |                                                                      |
// | Portions Copyright (c) 2003 osCommerce                               |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.0 of the GPL license,       |
// | that is bundled with this package in the file LICENSE, and is        |
// | available through the world-wide-web at the following url:           |
// | http://www.zen-cart.com/license/2_0.txt.                             |
// | If you did not receive a copy of the zen-cart license and are unable |
// | to obtain it through the world-wide-web, please send a note to       |
// | license@zen-cart.com so we can mail you a copy immediately.          |
// +----------------------------------------------------------------------+
//
/*
 2006-09-17 (wzl) handlers for "Custom" menu. Used modules.php as model.

 SET values:
	prod_entry (default): bulk product entry
	ACTION values:
		(none): show bulk product entry form
		check: data is being submitted for preview
		commit: data is being submitted for final commit (update database)
*/

  require('includes/application_top.php');

  define('CUSTOM_MODULE_SET_PROD_ENTRY','prod_entry');
  define('CUSTOM_MODULE_SAVE_DATA','save');
  define('CUSTOM_MODULE_PROD_DATA_NAME','products');
  define('CUSTOM_MODULE_ACT_CHECK','check');
  define('CUSTOM_MODULE_ACT_COMMIT','commit');
  define('CUSTOM_MODULE_BTN_CHECK','Preview Changes');
  define('CUSTOM_MODULE_BTN_COMMIT','COMMIT');

  define('URL_ISBN_SEARCH','http://www.abebooks.com/servlet/SearchResults?isbn=<<1>>');
  define('CUSTOM_DEFAULT_SUPPLIER','Jubilee');  // when import data supplier field is empty
  define('CUSTOM_DEFAULT_CATEGORY','Unfiled');  // when imported category field is empty

  define('TABLE_CUSTOM_IMPORT_PROD',DB_PREFIX.'custom_import_prod');
  define('TABLE_CUSTOM_IMPORT_MFGRS',DB_PREFIX.'custom_import_mfgrs');

  // new item
  define('HTML_STATUS_NEW', '<font color="#ff7f00">NEW</font>');
  // item is saved in list
  define('HTML_STATUS_NOTED', '<font color="#7f7f7f"><i>ok</i></font>');
  // item found in database
  define('HTML_STATUS_EXISTS', '<font color="#006600">found</font>');


  $set = (isset($_GET['set']) ? $_GET['set'] : '');
  $button = (isset($_POST['action']) ? $_POST['action'] : '');
  switch ($button) {
    case CUSTOM_MODULE_BTN_CHECK: $action=CUSTOM_MODULE_ACT_CHECK; break;
    case CUSTOM_MODULE_BTN_COMMIT: $action=CUSTOM_MODULE_ACT_COMMIT; break;
    default: $action='';
  }

/*
 After page has displayed, this handles the user's input
*/

  switch ($action) {
    case CUSTOM_MODULE_SAVE_DATA:
      $doSave = true;

// new SQL code for updating products:
	$sqlUpdateProd = "update " . TABLE_PRODUCTS . " set configuration_value = '" . $value . "' where configuration_key = '" . $key ."'";
      break;
    case 'enter':	// showing data entry form, so this stage (data processing) does nothing
    default:
  }
?>
<!doctype html public "-//W3C//DTD HTML 4.01 Transitional//EN">
<html <?php echo HTML_PARAMS; ?>>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=<?php echo CHARSET; ?>">
<title><?php echo TITLE; ?></title>
<link rel="stylesheet" type="text/css" href="includes/stylesheet.css">
<link rel="stylesheet" type="text/css" href="includes/cssjsmenuhover.css" media="all" id="hoverJS">
<script language="javascript" src="includes/menu.js"></script>
<script language="javascript" src="includes/general.js"></script>
<script type="text/javascript">
  <!--
  function init()
  {
    cssjsmenu('navbar');
    if (document.getElementById)
    {
      var kill = document.getElementById('hoverJS');
      kill.disabled = true;
    }
  }
  // -->
</script>
</head>
<body onload="init()">
<!-- header //-->
<?php require(DIR_WS_INCLUDES . 'header.php'); ?>
<!-- header_eof //-->

<!-- body //-->

This feature is currently being debugged; do not use yet. <i>N. Staddon 2006-10-11</i><br>

<!-- SET=<?php echo $set?> ACTION=<?php echo $action?> -->

<?php
  switch ($set) {
    case CUSTOM_MODULE_SET_PROD_ENTRY:
    default:
      switch ($action) {
        case CUSTOM_MODULE_ACT_CHECK:
	  echo "<b>Previewing entered data:</b>";
	  ProcessData(false);
        break;
        case CUSTOM_MODULE_ACT_COMMIT:
	  echo "<b>Saving entered data:</b>";
	  $hide_form = 1;
	  ProcessData(true);
        break;
        default:
      }
/*
 DEFAULT: show bulk product entry form
 check: data is being submitted for preview
 commit: data is being submitted for final commit (update database)
*/
  
// always show data entry form:
  }
  if (!$hide_form) {
    $htmlSep = '<font color="#7f7f7f"><tab></font>';
    echo zen_draw_form('prod_entry', CUSTOM_MENU_MODULE);
    echo '<center><table><tr><td colspan=2>';
    echo 'Enter product data here:<br>';
    echo '<i>Format is:</i> '
      .'<b>ID string</b>'.$htmlSep
      .'(ignored)'.$htmlSep
      .'<b>Title</b>'.$htmlSep
      .'(ignored)'.$htmlSep
      .'<b>Supplier</b>'.$htmlSep
      .'<b>Price</b><br>';
    echo '<center>';
    echo zen_draw_textarea_field(CUSTOM_MODULE_PROD_DATA_NAME, '', '100', '20');
// later on this can use Zen functions for more slickness, but for now this should work:
    echo '</center></td></tr><tr><td>';
    echo '<input type="submit" name="action" value="'.CUSTOM_MODULE_BTN_CHECK.'">';
    echo '<input type="submit" name="action" value="'.CUSTOM_MODULE_BTN_COMMIT.'">';
    echo '</td><td align=right>';
    echo '<input type="reset" value="Undo all edits">';
    echo '</td></tr></table></center>';
    echo '</form>';
  }
?>

<!-- body_eof //-->
<!-- footer //-->
<?php require(DIR_WS_INCLUDES . 'footer.php'); ?>
<!-- footer_eof //-->
<br>
</body>
</html>
<?php
require(DIR_WS_INCLUDES . 'application_bottom.php');

function Pluralize($iQty, $iSing='', $iPlur='s') {
  if ($iQty == 1) {
    return $iSing;
  } else {
    return $iPlur;
  }
}

function ProcessData($iCommit)
{

  $data_raw = $_POST[CUSTOM_MODULE_PROD_DATA_NAME];
  $data_lines = explode("\n",$data_raw);
  echo '<table>';
  echo '<tr><th colspan=5></th><th colspan=3 bgcolor="#eeeeee">Data Entry Status</th></tr>';
  echo '<tr><th>Catg</th><th>ID</th><th>Title</th><th>Supplier</th><th>Price</th><th bgcolor="#eeeeee">Supplier</th><th bgcolor="#eeeeee">Title</th><th bgcolor="#eeeeee">Category</th></tr><tr>';

  $ctrTitlesNew = 0;
  $ctrTitlesOld = 0;

  foreach ($data_lines as $data_line) {
// create title object for each import line. Title object should do all the lookups and printing and stuff.

    if ($data_line) {
      $objTitle = clsTitles::Import($data_line);

      $ctrSuppFnd = clsSuppliers::Count(); // # of suppliers found
      $ctrSuppNew = clsSuppliers::CountNew(); // # of *new* suppliers
      $ctrCatgFnd = clsCategories::Count(); // # of new categories
      $ctrCatgNew = clsCategories::CountNew(); // # of new categories

      echo '<tr>'.$objTitle->TableRowCells().'</tr>';
    }
  }
  if ($ctrSuppNew) {
    $htmlSuppList = ': '.clsSuppliers::DoListNew('<b>','</b>',', ');
    $htmlSuppList .= ' OLD: '.clsSuppliers::DoListOld('<b>','</b>',', ');
  }
  if ($ctrCatgNew) {
    $htmlCatgList = ': '.clsCategories::DoListNew('<b>','</b>',', ');
    $htmlCatgList .= ' OLD: '.clsCategories::DoListOld('<b>','</b>',', ');
  }
  echo '</table><hr>';
  echo '<big>Processed <b>'.$ctrLines.'</b> lines:</big><ul>'
    .'<li><b>'.clsTitles::Records()->CountNew().'</b> new titles to add'
    .'<li><b>'.clsTitles::Records()->CountOld().'</b> titles to update <i>(ignored for now)</i>'
    .'<li><b>'.$ctrSuppFnd.'</b> supplier'.Pluralize($ctrSuppFnd).' in import, <b>'.$ctrSuppNew.'</b> new'.$htmlSuppList
    .'<li><b>'.$ctrCatgFnd.'</b> categor'.Pluralize($ctrCatgFnd,'y','ies').' in import, <b>'.$ctrCatgNew.'</b> new'.$htmlCatgList
    .'</ul>';
  echo '<b>Adding suppliers</b>: '.clsSuppliers::Save($iCommit).'<br>';
  echo '<b>Adding categories</b>: '.clsCategories::Save($iCommit).'<br>';
  echo '<b>Adding titles</b>: '.clsTitles::Save($iCommit).'<br>';
}
function MakeKey($iStr) {
  return preg_replace('/[ -\.,;]*/','',strtolower($iStr));
}
/*
 ===== CLASSES =====
*/

class clsRecords {
  public $List;		// actual unique records
  public $qtyNew;	// number of *new* records found during import
  public $qtyOld;

  public function Count() {
    return Count($this->List);
  }
  public function CountOld() {
    if ($this->qtyOld) {
      return $this->qtyOld;
    } else {
      return 0;
    }
  }
  public function CountNew() {
    if ($this->qtyNew) {
      return $this->qtyNew;
    } else {
      return 0;
    }
  }
  public function AddObject($iName,$iObj) {
    if (!$this->List[$iName]) {
      $this->List[$iName] = $iObj;
    }
    if ($iObj->isFound) {
      $this->qtyOld++;
    } else {
      $this->qtyNew++;
    }
  }
  public function Exists($iName) {
    if (is_array($this->List)) {
      $isSet = isset($this->List[$iName]);
      return $isSet;
    } else {
      return false;
    }
  }
  public function DoListNew($iPfx,$iSfx,$iSep) {
    foreach ($this->List as $obj) {
      if (!$obj->isFound) {
        if ($out) {
          $out .= $iSep;
        }
        $out .= $iPfx.$obj->Name.$iSfx;
      }
    }
    return $out;
  }
  public function DoListOld($iPfx,$iSfx,$iSep) {
    foreach ($this->List as $obj) {
      if ($obj->isFound) {
        if ($out) {
          $out .= $iSep;
        }
        $out .= $iPfx.$obj->Name.$iSfx;
      }
    }
    return $out;
  }
}

class clsTitles {
  private static $objRecords;

  public function Records() {
    self::InitRecords();
    return self::$objRecords;
  }

  public function Import($iLine) {
    $obj = new clsTitle;
    $obj->ImportLine($iLine);
    if (!$obj->isCatg) {
      self::Records()->AddObject($obj->ImportKey,$obj);
    }
    return $obj;
  }

  public function Save($iCommit) {
    global $db;
    $result = '<ul>';
    foreach (self::Records()->List as $obj) {
      $result .= $obj->Save($iCommit);
    }
    $result .= '</ul>';
    return $result;
  }
  public function Count() {
    return self::Records()->Count();
  }
  public function CountNew() {
    return self::Records()->CountNew();
  }
  public function DoListNew($iPfx,$iSfx,$iSep) {
    return self::Records()->DoListNew($iPfx,$iSfx,$iSep);
  }
  protected function InitRecords() {
    if (!isset(self::$objRecords)) {
      self::$objRecords = new clsRecords;
    }
  }
}

class clsTitle {
  public $ImportKey;
  private $intID;
  public $Name;
  public $Price;
  public $Supplier;
  public $SuppImp;
  public $Category;
  public $CatgImp;
  public $isCatg;
// calculated fields
  public $ISBN;
  public $ISBN_URL;
  public $HtmlName;
// status fields
  public $Status;
  public $isFound;
//  public static $lstTitles;

  public function ID() {
    if (!isset($this->intID)) {
      $this->UpdateName();
    }
//echo 'TITLE ID='.$this->intID;
    return $this->intID;
  }

  public function ImportLine($iLine) {
    global $db;

    list($ImportKeyRaw,$notUsed,$this->Name,$notUsed,$strSupplierName,$notUsed,$this->Price) = explode("\t",$iLine);
//echo 'NAME='.$Name.'<br>';
// Check to see if the title is actually a category record - price is 0, name is empty or contains "classification"
    $this->isCatg = false;
    if ($this->Price == 0.0) {
      if ((!MakeKey($this->Name)) || (eregi('classification',$this->Name))) {
        $this->isCatg = true;
      }
    }
    if ($this->isCatg) {
// for now, we're not really doing anything with category lines
      $this->HtmlName = '<span style="background-color: #eeeeff;"><i>'.$this->Name.'</i></span>';
    } else {
// ** Supplier
      if ($strSupplierName == '') {
        $strSupplierName = CUSTOM_DEFAULT_SUPPLIER;
      }
      $this->SuppImp = clsSuppliers::Import($strSupplierName);
      $this->Supplier = $this->SuppImp->Supplier;

// Parse out the category and title key
      $listTitleParts = array_reverse(split(':',$ImportKeyRaw));
      $this->ImportKey = MakeKey(array_shift($listTitleParts));
      $strCatg = array_shift($listTitleParts);   // for now, assume just one level of category
      if (!$strCatg) {
        $strCatg = CUSTOM_DEFAULT_CATEGORY;
      }
      $this->CatgImp = clsCategoryImports::Import($strCatg);
      $this->Category = $this->CatgImp->Category;
//echo 'CATG='.$strCatg.' stored='.$this->Category->Name.'<br>';

      $this->UpdateName();

// ** Title: cross-reference import key to title ID
      $sqlFind = 'SELECT * FROM '.TABLE_CUSTOM_IMPORT_PROD.' WHERE import_key="'.$this->ImportKey.'";';
      $qryTitle = $db->Execute($sqlFind);
      if ($qryTitle->RecordCount()) {
        $this->isFound = true;
        $this->Status = HTML_STATUS_EXISTS;
        $this->ID = $qryTitle->fields['prod_key'];
      } else {
        $this->isFound = false;
	if ($lstTitles[$this->ImportKey]) {
	  $this->Status = HTML_STATUS_NOTED;
        } else {
          $this->Status = HTML_STATUS_NEW;
//          $lstTitles[$this->ImportKey] = $this->ID;  // may eventually want to save an object, not just a string
        }
      }
    }
  }

  public function UpdateName() {
    $subject = $this->Name;
    $pattern = '/ISBN *[0-9\-]*/';
    preg_match($pattern, $subject, $matches, PREG_OFFSET_CAPTURE);
// This operation is unnecessarily complicated, but it is what seems to work:
    $this->ISBN = trim(preg_replace('/ISBN/','',$matches[0][0]));
    if ($this->ISBN) {
      $this->ISBN_URL = preg_replace('/<<1>>/',$this->ISBN,URL_ISBN_SEARCH);
      $this->HtmlName = '<a href="'.$this->ISBN_URL.'">'.$this->Name.'</a>';
    } else {
      $this->HtmlName = $this->Name;
      $this->ISBN_URL = '';
    }
  }

  public function Save($iCommit) {
    global $db;

    if ($this->isFound) {
// TO DO: write update routine
    } else {
// Check for missing manufacturer:
     if (!$this->Supplier->ID()) {
       echo '<b>MISSING SUPPLIER</b> for title "'.$this->Name.'"<br>';
     }
     if (!$this->Category->ID()) {
       echo '<b>MISSING CATEGORY</b> for title "'.$this->Name.'"<br>';
     }

// only insert items with a numerically valid price
      if (is_numeric(trim($this->Price))) {
// Theory: MySQL defaults to using the first index as an auto-increment key. We'll see if this works.
// Update main PRODUCTS table:
        $sqlAdd = 'INSERT INTO '.TABLE_PRODUCTS.' (products_status,products_price,products_date_added,manufacturers_id,master_categories_id)'
	.'VALUES('
	.'1,'				// products_status (1 = active)
	.$this->Price.','		// products_price
	.'NOW(),'			// products_date_added
	.$this->Supplier->ID().','	// manufacturers_id
	.$this->Category->ID().')';	// master_categories_id
        $result .= '<li><b>SQL</b>: '.$sqlAdd;
        if ($iCommit) {
          $db->Execute($sqlAdd);
          $result .= '<li><b>main products table status</b>: '.mysql_info();
          $this->intID = mysql_insert_id();
          $result .= '<li><b>ID</b>: '.$this->intID;
        } else {
          $this->intID = 0;
        }
// Update product import table:
        $sqlAdd = 'INSERT INTO '.TABLE_CUSTOM_IMPORT_PROD.' (import_key,prod_key) VALUES("'.mysql_real_escape_string($this->ImportKey).'",'.$this->ID().')';
        $result .= '<li><b>SQL</b>: '.$sqlAdd;
        if ($iCommit) {
          $db->Execute($sqlAdd);
          $result .= '<li><b>products import table status</b>: '.mysql_info();
        }

// Update PRODUCTS_DESCRIPTION:
        $sqlAdd = 'INSERT INTO '.TABLE_PRODUCTS_DESCRIPTION.' (products_id,products_name) VALUES('.$this->ID().',"'.mysql_real_escape_string($this->Name).'")';
        $result .= '<li><b>SQL</b>: '.$sqlAdd;
        if ($iCommit) {
          $db->Execute($sqlAdd);
          $result .= '<li><b>products description status</b>: '.mysql_info();
        }
// Update PRODUCT CATEGORIES:
        $sqlAdd = 'INSERT INTO '.TABLE_PRODUCTS_TO_CATEGORIES.' (products_id,categories_id) VALUES('.$this->ID().','.$this->Category->ID().')';
        $result .= '<li><b>SQL</b>: '.$sqlAdd;
        if ($iCommit) {
          $db->Execute($sqlAdd);
          $result .= '<li><b>products description status</b>: '.mysql_info();
        }
      } else {
        $result = '<li><b>Warning</b>: product ['.$this->Name.'] has no price set ('.$this->Price.'); skipping.';
      }
      return $result;
    }
  }

  public function TableRowCells() {
    $out = '<td>'.$this->Category->Name.'</td><td>'.$this->ImportKey.'</td><td>'.$this->HtmlName.'</td>';
    if ($this->isCatg) {
      $out .= '<td colspan=5 align=center bgcolor="#eeeeff"><b>category</b> (ignored)</td>';
    } else {
      $out .= '<td>(<b>'.$this->Supplier->ID().'</b>) '.$this->Supplier->Name.'</td><td>'.$this->Price.'</td><td align=center>'.$this->SuppImp->Status.'</td><td align=center>'.$this->Status.'</td><td>'.$this->CatgImp->Status.'</td>';
    }
    return $out;
  }
}

class clsSuppliers {
  private static $Records;

  public function Import($iName) {
    self::InitRecords();
    $objSuppImp = new clsSupplierImport;
    if (self::$Records->List[$iName]) {
// supplier has already been seen this session
      $objSupp = self::$Records->List[$iName];  // retrieve existing supplier record
      $objSuppImp->ImportOld($objSupp);  // attach it to supplier import record for this import
    } else {
// new supplier for this session
      $objSuppImp->ImportNew($iName);
      self::$Records->AddObject($iName,$objSuppImp->Supplier);
//      self::$Records->List[$iName] = $objSuppImp->Supplier;
 //     if (!$objSuppImp->Supplier->isFound) {
  //     $this->Records->qtyNew++;
    //  }
    }
    return $objSuppImp;
  }

// save list of (new) suppliers to database
  public function Save($iCommit) {
    global $db;
    $result = '<ul>';

    foreach (self::$Records->List as $obj) {
      if (!$obj->isFound) {
        if ($strValues) {
          $strValues .= ',';
        }
        $strValues .= '("'.mysql_real_escape_string($obj->Name).'",NOW())';
      }
    }

    if ($strValues) {
      $sqlAdd = 'INSERT INTO '.TABLE_MANUFACTURERS.' (manufacturers_name, date_added) VALUES'.$strValues;
      $result .= '<li><b>SQL</b>: '.$sqlAdd;
      if ($iCommit) {
        $db->Execute($sqlAdd);
        $result .= '<li><b>status</b>: '.mysql_info();
      }
    }
    $result .= '</ul>';
    return $result;
  }
  public function Count() {
    self::InitRecords();
    return self::$Records->Count();
  }
  public function CountNew() {
    self::InitRecords();
    return self::$Records->CountNew();
  }
  public function DoListNew($iPfx,$iSfx,$iSep) {
    self::InitRecords();
    return self::$Records->DoListNew($iPfx,$iSfx,$iSep);
  }
  public function DoListOld($iPfx,$iSfx,$iSep) {
    self::InitRecords();
    return self::$Records->DoListOld($iPfx,$iSfx,$iSep);
  }
  protected function InitRecords() {
    if (!isset(self::$Records)) {
      self::$Records = new clsRecords;
    }
  }
}

class clsSupplier {
  private $intID;
  public $Name;
  public $Key;
  public $isFound;

  public function Init($iName) {
    global $db;

    $this->Name = $iName;
    $this->UpdateName();
  }
  public function Init_fromID($iID) {
    global $db;

    $this->intID = $iID;
    $sqlFind = 'SELECT * FROM '.TABLE_MANUFACTURERS.' WHERE manufacturers_id="'.$iID.'";';
    $qryFind = $db->Execute($sqlFind);
    $this->isFound = $qryFind->RecordCount();
    if ($this->isFound) {
      $this->Name = $qryFind->fields['manufacturers_name'];
    }
  }
  private function UpdateName() {
    global $db;

    $sqlFind = 'SELECT * FROM '.TABLE_MANUFACTURERS.' WHERE manufacturers_name="'.$this->Name.'";';
    $qryFind = $db->Execute($sqlFind);
    $this->isFound = $qryFind->RecordCount();
    if ($this->isFound) {
      $this->intID = $qryFind->fields['manufacturers_id'];
    } else {
// not found in main list, so check aliases
      $sqlFind = 'SELECT * FROM '.TABLE_CUSTOM_IMPORT_MFGRS.' WHERE LCASE(import_alias)="'.mysql_real_escape_string(strtolower($this->Name)).'";';
      $qryFind = $db->Execute($sqlFind);
      $this->isFound = $qryFind->RecordCount();
      if ($this->isFound) {
        $this->Init_fromID($qryFind->fields['id_mfgr']);
      }
    }
  }
  public function ID() {
    if ($this->intID) {
      $this->UpdateName();
    }
    return $this->intID;
  }
}

class clsSupplierImport {
  public $Supplier;	// points to supplier data
  public $Status;	// indicates status of this particular import of that data

// Supplier record has already been created, so use it:
  public function ImportOld($iObj) {
    $this->Supplier = $iObj;
    $this->Status = HTML_STATUS_NOTED;
  }
// Supplier record needs to be created:
  public function ImportNew($iName) {
    global $db;

    $this->Supplier = new clsSupplier;
    $this->Supplier->Init($iName);
    if ($this->Supplier->isFound) {
      $this->Status = HTML_STATUS_EXISTS;
    } else {
      $this->Status = HTML_STATUS_NEW;
    }
  }
}

/*
 ===== CATEGORIES =====
*/

class clsCategories {
  private static $Records;

  public function Create($iName) {
// This function is only called if category has not been seen before in this run
    global $db;

    $objNew = new clsCategory;
    self::InitRecords();
    
    $objNew->Init($iName);
    self::$Records->AddObject($iName,$objNew);
/*    self::$Records->List[$iName] = $objNew;
    if (!$objNew->isFound) {
      self::$Records->qtyNew++;
    }
*/
    return $objNew;
  }

// add any new categories to database
  public function Save($iCommit) {
    foreach (self::$Records->List as $obj) {
      if (!$obj->isFound) {
        $sqlOut .= $obj->Save($iCommit);
      }
    }
    return $sqlOut;
  }
  public function GetObject($ID) {
    self::InitRecords();
    return self::$Records->List[$ID];
  }
  public function Count() {
    self::InitRecords();
    return self::$Records->Count();
  }
  public function CountNew() {
    self::InitRecords();
    return self::$Records->CountNew();
  }
  public function Exists($iName) {
    self::InitRecords();
    return self::$Records->Exists($iName);
  }
  public function DoListNew($iPfx,$iSfx,$iSep) {
    self::InitRecords();
    return self::$Records->DoListNew($iPfx,$iSfx,$iSep);
  }
  public function DoListOld($iPfx,$iSfx,$iSep) {
    self::InitRecords();
    return self::$Records->DoListOld($iPfx,$iSfx,$iSep);
  }
  protected function InitRecords() {
    if (!isset(self::$Records)) {
      self::$Records = new clsRecords;
    }
  }
}
class clsCategory {
  private $intID;
  public $Name;
  public $ImportKey;
// status
  public $isFound;

  public function Init($iName) {
    global $db;

//echo 'storing 2:'.$iName.' ';
    $this->Name = $iName;
    $this->ImportKey = MakeKey($iName);
    $this->UpdateName();
  }
  private function UpdateName() {
    global $db;

    $sqlFind = 'SELECT * FROM '.TABLE_CATEGORIES_DESCRIPTION.' WHERE categories_name="'.$this->Name.'"';
    $qryFind = $db->Execute($sqlFind);
    $this->isFound = $qryFind->RecordCount();
    $this->intID = $qryFind->fields['categories_id'];
  }
  public function ID() {
    if (!$this->intID) {
      $this->UpdateName();
    }
    return $this->intID;
  }
  public function Save($iCommit) {
    global $db;

    $result = '<ul>';
    $sqlAdd = 'INSERT INTO '.TABLE_CATEGORIES.' (date_added) VALUES(NOW())';
    $result .= '<li><b>SQL</b>: '.$sqlAdd;
    if ($iCommit) {
      $db->Execute($sqlAdd);
      $result .= '<li><b>status</b>: '.mysql_info();
      $idNew = mysql_insert_id();
      $result .= '<li><b>ID</b>: '.$idNew;
    } else {
      $idNew = '?';
    }
    $sqlAdd = 'INSERT INTO '.TABLE_CATEGORIES_DESCRIPTION.' (categories_id,categories_name) VALUES('
      .$idNew.',"'.mysql_real_escape_string($this->Name).'");';
    $result .= '<li><b>SQL</b>: '.$sqlAdd;
    if ($iCommit) {
      $db->Execute($sqlAdd);
      $result .= '<li><b>status</b>: '.mysql_info();
    }
    $result .= '</ul>';
    return $result;
  }
}

class clsCategoryImports {
  public function Import($iName) {
    $objImport = new clsCategoryImport;
    $objImport->Import($iName);
    return $objImport;
  }
}

class clsCategoryImport {
  public $Category;
  public $Status;

  public function Import($iName) {
//    echo 'storing 1:'.$iName.' ';
    if (clsCategories::Exists($iName)) {
//echo 'EXISTS ';
      $this->Category = clsCategories::GetObject($iName);
      $this->Status = HTML_STATUS_NOTED;
    } else {
//echo '*NEW* ';
      $this->Category = clsCategories::Create($iName);
      if ($this->Category->isFound) {
        $this->Status = HTML_STATUS_EXISTS;
      } else {
        $this->Status = HTML_STATUS_NEW;
      }
    }
  }
}

?>