ZenCart data import - admin/custom menu.php

From HTYP, the free directory anyone can edit

Jump to: navigation, search

[edit] Navigation

computing: software: ZenCart: importing data: $zc/admin/custom_menu.php

[edit] 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.

[edit] 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_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_ACT_UPLOAD','upload');
  define('CUSTOM_MODULE_ACT_DELETE','delete');
  define('CUSTOM_MODULE_ACT_ASSIGN','assign');
  define('CUSTOM_MODULE_ACT_VIEW','view');
  define('CUSTOM_MODULE_ACT_LOOSE_DEL','loose_del');
  define('CUSTOM_MODULE_ACT_LOOSE_EXT','loose_unzip');
  define('CUSTOM_MODULE_ACT_LOOSE_VIEW','loose_view');
  define('CUSTOM_MODULE_BTN_CHECK','Preview Changes');
  define('CUSTOM_MODULE_BTN_COMMIT','COMMIT');
  define('CUSTOM_MODULE_BTN_UPLOAD','Upload File');
  define('CUSTOM_MODULE_BTN_DELETE_FILE','Delete File');
  define('CUSTOM_MODULE_BTN_ASSIGN_IMG','Assign Image');
  define('CUSTOM_MODULE_BTN_VIEW_PROD','View Product');
 
  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');
  define('TABLE_CUSTOM_UPLOADS',DB_PREFIX.'custom_uploads');
  define('TABLE_CUSTOM_UPLOAD_FILES',DB_PREFIX.'custom_upload_files');
  define('TABLE_CUSTOM_UPLOAD_THUMBS',DB_PREFIX.'custom_upload_thumbs');
 
  // 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>');
 
  $intOpt_MaxThumbs = 50;	// default
 
// Get any expected parameters
  if (count($_POST)) {
    $button = (isset($_POST['action']) ? $_POST['action'] : '');
    $idProd = $_POST['prod-id'];
    $idImg = $_POST['img-id'];
  } else {
    $set = (isset($_GET['set']) ? $_GET['set'] : '');
    $idImg = $_GET['img-id'];
    $strFileName = $_GET['file'];
  }
 
  switch ($button) {
    case CUSTOM_MODULE_BTN_CHECK: $action=CUSTOM_MODULE_ACT_CHECK; break;
    case CUSTOM_MODULE_BTN_COMMIT: $action=CUSTOM_MODULE_ACT_COMMIT; break;
    case CUSTOM_MODULE_BTN_UPLOAD: $action=CUSTOM_MODULE_ACT_UPLOAD; break;
    case CUSTOM_MODULE_BTN_DELETE_FILE: $action=CUSTOM_MODULE_ACT_DELETE; break;
    case CUSTOM_MODULE_BTN_ASSIGN_IMG: $action=CUSTOM_MODULE_ACT_ASSIGN; break;
    case CUSTOM_MODULE_BTN_VIEW_PROD: $action=CUSTOM_MODULE_ACT_VIEW; break;
    default: $action=$_GET['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 //-->
 
<!-- SET=<?php echo $set?> ACTION=<?php echo $action?> -->
 
<?php
/* Apparently the $set is only sent on the initial stage of each operation.
  So first we check for an $action; if no $action, then look for a $set.
*/
  $show_data_entry_form = 0;
  $idAdmin = $_SESSION['admin_id'];
  $doSet = false;
  switch ($action) {
  case CUSTOM_MODULE_ACT_CHECK:
    $show_data_entry_form = 1;
    echo "<b>Previewing entered data:</b>";
    ProcessData(false);
  break;
  case CUSTOM_MODULE_ACT_COMMIT:
    $show_data_entry_form = 1;
    echo "<b>Saving entered data:</b>";
    $hide_form = 1;
    ProcessData(true);
  break;
  case CUSTOM_MODULE_ACT_UPLOAD: // we've got the zipfile, so unpack it etc.
    $objUpload = clsUploads::AddNew();	// log the start of the upload processing
// process the upload
    $objUpload->UnzipUpload();
// log upload completion
    $objUpload->Finish();
// ** image-editing actions
    case CUSTOM_MODULE_ACT_DELETE:
      $show_img_assign_form = true;
      $objFile = clsUploadFiles::File_fromID($idImg);
      echo '<b>Deleting image</b> ['.$objFile->filespec.'] (ID='.$idImg.')...';
      $objFile->Delete();
      echo '<hr>';
// clear image so we go back to the list of unassigned images:
      unset($idImg);
      $doSet = true;
    break;
    case CUSTOM_MODULE_ACT_ASSIGN:
      echo '<span class="pageHeading">Assigning displayed image to the displayed product</span><p>';
      $objProd = clsTitles::Item($idProd);
      $objFile = clsUploadFiles::File_fromID($idImg);
      echo 'Assigning image [<b>'.$objFile->filespec.'</b>] to product ID='.$idProd.' [<b>'.$objProd->DescrObj()->name.'</b>] '.$objProd->HTML_Links().'<br>';
      $objProd->image = 'bulk/'.$objFile->filespec;
      $objFile->ID_Prod = $idProd;
      $objProd->Save();
      $objFile->Save();
// clear image so we go back to the list of unassigned images and display the updated product:
      unset($idImg);
      $show_img_assign_form = true;
    break;
    case CUSTOM_MODULE_ACT_VIEW:
      echo '<span class="pageHeading">Viewing image, with unassigned product information</span><p>';
      $objProd = clsTitles::Item($idProd);
      echo $objProd->HTML();
      echo '<hr>';
      $show_img_assign_form = true;
    break;
    case CUSTOM_MODULE_ACT_LOOSE_DEL:
      $strFileName = $_GET['file'];
      $strFileSpec = clsUploads::PathToBulkUpload().$strFileName;
      if (strstr($strFileName,'../')) {
        echo 'Ignoring dangerous filename ['.$strFileName.'].';
      } else {
        echo 'Deleting [<b>'.$strFileSpec.'</b>]...';
        if (unlink($strFileSpec)) {
          echo 'ok';
        } else {
          echo '<font color=red>error!</font>';
        }
        echo '<hr>';
      }
      $doSet = true;
    break;
    case CUSTOM_MODULE_ACT_LOOSE_EXT:
      echo 'Unzipping the file ['.$strFileName.']...';
      $objUpload = new clsUpload;
      $objUpload->Start_fromLoose($strFileName,'FTP upload');
      $objUpload->UnzipArchive();
      $objUpload->Finish();
    break;
    case CUSTOM_MODULE_ACT_LOOSE_VIEW:
      echo '<big>Viewing <b>'.$strFileName.'</b>:</big><br>';
      echo '<img src="'.clsUploads::URLToBulkUpload().$strFileName.'">';
      $doSet = true;
  break;
  default:
    $doSet = true;
  }
  if ($doSet) {
    switch ($set) {
      case CUSTOM_MODULE_SET_PROD_ENTRY:
/*
 SET: show bulk product entry form
 check: data is being submitted for preview
 commit: data is being submitted for final commit (update database)
*/
        $show_data_entry_form = true;
      break;
      case CUSTOM_MODULE_SET_BULK_UPLOAD:
        $show_img_upload_form = true;
      break;
      case CUSTOM_MODULE_SET_BULK_ASSIGN:
	$show_img_assign_form = true;
      break;
      default:
	if ($set) {
	  echo "<b>Sorry, this function ($set) is not implemented yet!</b>";
	  if ($action) {
	    echo "<br>action=[$action]";
	  }
	} else {
// The action for the top level of the custom menu goes here.
// This seemed like a good place to have an explanation of what the menu choices do.
// You could put in just an "echo" and the text, but the following code extracts it
//	from a wiki page:
//	  error_reporting(E_ALL ^ E_NOTICE ^ E_WARNING); // turn off the session warning
 	  require_once('../../w/extract.php');
	  echo getWikiPage('Embed:menu:Import');
        }
    break;
  }
 
}
 
  if ($show_data_entry_form) {
    $htmlSep = '<font color="#7f7f7f">&lt;tab&gt;</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>';
  }
  if ($show_img_upload_form) {
    require_once('../../w/extract.php');
    // display the help text
    echo getWikiPage('Embed:menu:Upload');
    // check to see if there are any files already uploaded
    clsUploads::ListUnrecorded();
    // display the upload form
    echo zen_draw_form('img_bulk_upload',CUSTOM_MENU_MODULE,'','post','enctype="multipart/form-data"');
    echo '<center><table>';
    echo '<tr>';
    echo '<td align=right>Image zipfile:</td>';
    echo '<td>'.zen_draw_file_field('upload_file',true).'</td>';
    echo '</tr>';
    echo '<tr>';
    echo '<tr><td colspan=2><small>Make a note of what the upload is for:</small></td></tr>';
    echo '<td align=right>Description:</td>';
    echo '<td>'.zen_draw_input_field('upload_descr').'</td>';
    echo '</tr>';
    echo '<tr><td><input type="submit" name="action" value="'.CUSTOM_MODULE_BTN_UPLOAD.'"></td><td> (Please be patient...)</td></tr>';
    echo '</table></center>';
    echo '</form>';
  }
  if ($show_img_assign_form) {
    require_once('../../w/extract.php');
    if ($idImg) {
      // show single-image edit form
      $objImg = clsUploadFiles::File_fromID($idImg);
      echo $objImg->HTML('align=left');
      echo '<table><tr><td>';
      echo $objImg->AutoDescrHTML('<br>');
      echo zen_draw_form('img_edit', CUSTOM_MENU_MODULE);
      echo '<hr><input type="submit" name="action" value="'.CUSTOM_MODULE_BTN_DELETE_FILE.'">';
      $sql = 'select p.products_id, pd.products_name from products AS p LEFT JOIN products_description AS pd ON pd.products_id=p.products_id WHERE (p.products_image IS NULL) AND (pd.products_name IS NOT NULL) ORDER BY pd.products_name';
      $qry = $db->Execute($sql);
      $idx = 0;
      if ($qry->RecordCount()) {
        while (!$qry->EOF) {
          $arrProd[$idx]['id'] = $qry->fields['products_id'];
          $arrProd[$idx]['text'] = $qry->fields['products_name'];
          $qry->MoveNext();
          $idx++;
        }
        echo '<hr>';
        echo zen_draw_hidden_field('img-id',$idImg);
        echo zen_draw_pull_down_menu('prod-id',$arrProd,$idProd);
        echo '<br>'
          .'<input type="submit" name="action" value="'.CUSTOM_MODULE_BTN_ASSIGN_IMG.'">'
          .'<input type="submit" name="action" value="'.CUSTOM_MODULE_BTN_VIEW_PROD.'">';
//        echo zen_draw_checkbox_field('in-new-window','',true);
//        echo 'open product in new window';
        echo '</td></tr></table>';
      } else {
        echo 'There are currently no unassigned products.';
      }
    } else {
      echo getWikiPage('Embed:menu:Import.assign');
      // show gallery of unassigned thumbnails
      clsUploads::ListAvail();
    }
  }
?>
 
<!-- 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::SaveImport($iCommit).'<br>';
  echo '<b>Adding categories</b>: '.clsCategories::SaveImport($iCommit).'<br>';
  echo '<b>Adding titles</b>: '.clsTitles::SaveImport($iCommit).'<br>';
}
function MakeKey($iStr) {
  return preg_replace('/[ -\.,;]*/','',strtolower($iStr));
}
function FieldDate() {
// ACTION: Returns a date formatted suitably for a datetime field in a database
  return '"'.date('Y-m-d H:i:s').'"';
}
/*
 ===== CLASSES =====
*/
 
class clsUploads {
  public function AddNew() {
 
    $obj = new clsUpload;
    $obj->Start();
    return $obj;
  }
  public function ListUnrecorded() {
// PURPOSE: Display a list of uploaded files not yet registered
//	This would happen either when a web-based upload got interrupted,
//	or if we had to FTP a file because the web-based upload takes too long
 
// get a listing of all files in the bulk-upload area:
    $fpBulkUpload = clsUploads::PathToBulkUpload();
//    $fpBulkUpload = '/hsphere/local/home/hypertwi/thejubileestore.com/shop/images/bulk';
 
    $lstFiles = dirlist($fpBulkUpload);
    $cntKnown = 0; $cntNew = 0;
    if (count($lstFiles)) {
      $out = 'Loose files found in bulk upload area:<ul>';
      foreach ($lstFiles as $objFile) {
//        $objFile = new clsUploadFile;
//        $objFile->MakeSpec($this,$strFSpec);
        if (clsUploadFiles::File_isKnown($objFile->SpecRel())) {
          $cntKnown++;
        } else {
          $cntNew++;
          if ($objFile->pathRel) {
            $strSpec = $objFile->pathRel.'/';
          } else {
            $strSpec = '';
          }
          $strSpec .= $objFile->name;
          $strParam = '?set='.CUSTOM_MODULE_SET_BULK_UPLOAD.'&file='.urlencode($strSpec).'&action=';
          $out .= '<li>'.$strSpec;
          $out .= ' '
            .'[<a href="'.$strParam.CUSTOM_MODULE_ACT_LOOSE_DEL.'">delete</a>]'
            .'[<a href="'.$strParam.CUSTOM_MODULE_ACT_LOOSE_EXT.'">extract</a>]'
            .'[<a href="'.$strParam.CUSTOM_MODULE_ACT_LOOSE_VIEW.'">view</a>]';
        }
      }
      if ($cntKnown) {
        if ($cntKnown == 1) {
          $out .= '<li>'.$objFile->name;
          if ($objFile->pathRel != '') {
            $out .= ' in ['.$objFile->pathRel.']';
          }
          $out .= ' (previously extracted)';
        } else {
          $out .= '<li>'.$cntKnown.' previously extracted files';
        }
      }
      $out .= '</ul><hr>';
      if ($cntNew) {
        echo $out;
      }
    }
  }
  public function ListAvail() {
// PURPOSE: Display a list of unassigned images
    global $db;
    global $intOpt_MaxThumbs;
 
    $sql = 'SELECT * FROM '.TABLE_CUSTOM_UPLOAD_FILES.' WHERE (when_deleted IS NULL) AND (id_prod IS NULL)';
    $qry = $db->Execute($sql);
    $intCount = $qry->RecordCount();
    if ($intCount) {
      echo 'There are <b>'.$intCount.'</b> image'.Pluralize($intCount).' currently unassigned';
      if ($intOpt_MaxThumbs < $intCount) {
        $sql .= ' LIMIT '.$intOpt_MaxThumbs;
        $qry = $db->Execute($sql);
        echo '; showing the first <b>'.$intOpt_MaxThumbs.'</b>';
      }
      echo ':<br>';
 
      while (!$qry->EOF) {
	$objImg = new clsUploadFile();
        $objImg->LoadFields($qry);
        $objThumb = new clsUploadThumb();
        $objThumb->Make($objImg, 0, 100);
        if ($objThumb->error) {
          echo $objThumb->status;
        } else {
          $strHTML = $objThumb->HTML();
          echo $strHTML;
        }
        $qry->MoveNext();
      }
//      echo '</ul>';
    } else {
      require_once('../../w/extract.php');
      echo getWikiPage('Embed:menu:Import.assign.no-files');
//      echo 'No unassigned files to show.';
    }
  }
 
  public function PathToBulkUpload() {
    return DIR_FS_CATALOG_IMAGES.'bulk/';
//    return '../images/bulk/';
  }
  public function URLToBulkUpload() {
    return DIR_WS_CATALOG_IMAGES.'bulk/';
  }
}
 
class clsUpload {
  public $ID;
  public $idAdmin;	// ID of admin doing the upload
  public $filename;	// name of bulk upload file (zipfile or tarball)
  public $tempname;	// local temporary filename
  public $comment;	// admin comment for this upload
  public $status;	// status string (not stored)
 
/* NOT USED
  public function LoadRecord($iData) {
    $this->ID = $iData->fields['id'];
    $this->idAdmin = $iData->fields['id_admin'];
    $this->filename = $iData->fields['filename'];
    $this->comment = $iData->fields['comment'];
  }
*/
  public function Start() {
    global $db;
// fetch values from global arrays
    $this->filename = $_FILES['upload_file']['name'];
    $this->comment = $_POST['upload_descr'];
    $this->tempname = $_FILES['upload_file']['tmp_name'];
 
    echo 'Uploading file ['.$this->filename.'], description ['.$this->comment.']...';
//    echo '_FILES:';
//    var_dump($_FILES);
//    echo '_POST:';
//    var_dump($_POST);
//    echo 'TEST=['.$_FILES['upload_file']['tmp_name'].']';
    $this->DoRecord();
  }
  public function Start_fromLoose($iFileName,$iComment) {
    $this->filename = $iFileName;
    $this->comment = $iComment;
    $this->tempname = ''; // not applicable
    $this->DoRecord();
  }
  private function DoRecord() {
    global $db;
 
    $this->idAdmin = $_SESSION['admin_id'];
 
    $sqlComment = mysql_real_escape_string($this->comment);
    $sqlFilename = mysql_real_escape_string($this->filename);
    $sqlTempname = mysql_real_escape_string($this->tempname);
// log beginning of the upload
    $sqlAdd = 'INSERT INTO '.TABLE_CUSTOM_UPLOADS.' (id_admin,when_started,filename,comment) '
	.'VALUES('
	.$this->idAdmin.','		// ID of current administrator
	.FieldDate().','		// current timestamp
	.'"'.$sqlFilename.'",'
	.'"'.$sqlComment.'");';
 
    $db->Execute($sqlAdd);
    $this->ID = mysql_insert_id();
    $this->status = mysql_info();
  }
 
  public function UnzipUpload() {
// ACTION: 
//   * Moves a PHP-uploaded file into the bulk upload area, with a unique name
//   * Calls UnzipArchive() to unzip the file
// USAGE: PHP bulk upload function should call:
//   * Start() to set up values and log the new upload (clsUploads::AddNew() also creates the object for you)
//   * UnzipUpload() to move the temp file into a normal folder, and extract the files
//   * Finish() to record the timestamp when extraction completed
//  To properly record non-PHP-uploaded archives:
//   * Start_fromLoose() to set up values and log the new archive
//   * UnzipArchive() to extract the files
//   * Finish() same as above
 
// * Move the temporary upload file over to the bulk uploads area:
    global $db;
 
    //$fpBulkUpload = DIR_FS_CATALOG_IMAGES.'bulk/';
    $fpBulkUpload = clsUploads::PathToBulkUpload();
    $fnBulkUpload = 'upload-'.$this->idAdmin.'.zip';	// unique filename for each admin
    $fsBulkUpload = $fpBulkUpload.$fnBulkUpload;
 
    echo '<br>Moving ['.$this->tempname.'] to ['.$fsBulkUpload.']...';
// do the actual move
    move_uploaded_file($this->tempname,$fsBulkUpload);
    echo ' copied.<br>Unpacking...<br>';
// unzip the file and save results in permanent location:
    $this->UnzipArchive($fnBulkUpload);
  }
  public function UnzipArchive() {
    $fpBulkUpload = clsUploads::PathToBulkUpload();
    $fnBulkUpload = $this->filename;
 
    echo '<pre>';
    system('cd "'.$fpBulkUpload.'";tar -xvvzf "'.$fnBulkUpload.'"',$intErr);
    echo '</pre>';
    if ($intErr) {
      echo 'Some kind of error was encountered while extracting the files. (code='.$intErr.')<br>';
    } else {
      unlink($fsBulkUpload);	// delete the zipfile, now that everything is extracted
      echo '<br>Changing file permissions...<br><pre>';
      system('chmod -vR 777 '.$fpBulkUpload.'*');
      echo '</pre><br>Files found in bulk upload area:<br><ul>';
// get a listing of all bulk-uploaded files:
      $lstFiles = dirlist($fpBulkUpload);
      foreach ($lstFiles as $objFile) {
        $objFileUp = new clsUploadFile;
	$objFileUp->MakeSpec($this,$objFile->SpecRel());
      }
      echo '</ul>';
    }
  }
 
  public function Finish() {
    global $db;
    $sqlDone = 'UPDATE '.TABLE_CUSTOM_UPLOADS.' SET when_finished='.FieldDate().' WHERE id="'.$this->ID.'"';
    $db->Execute($sqlDone);
    $this->status = mysql_info();
  }
  public function FileSpec() {
    return clsUploads::PathToBulkUpload().$this->filename;
  }
}
 
class clsUploadFiles {
  public function File_fromID($iID) {
    global $db;
 
    $idSafe = sprintf('%u',$iID);
    $sql = 'SELECT * FROM '.TABLE_CUSTOM_UPLOAD_FILES.' WHERE id='.$idSafe;
    $qry = $db->Execute($sql);
    if ($qry->RecordCount()) {
      $obj = new clsUploadFile;
      $obj->LoadFields($qry);
      return $obj;
    }
  }
  public function File_isKnown($iName) {
    global $db;
 
    $sql = 'SELECT * FROM '.TABLE_CUSTOM_UPLOAD_FILES.' WHERE filespec="'.$iName.'"';
    $qry = $db->Execute($sql);
    return ($qry->RecordCount());
  }
}
 
class clsUploadFile {
  public $ID;
  public $ID_Upload;
  public $filespec;
  public $ID_Prod;
  private $strAutoDescr;
  public $width, $height;
  public $status;
 
  private $objUpload;
 
  public function MakeSpec($iUpload,$iSpec) {
    global $db;
 
    $this->objUpload = $iUpload;
    $this->filespec = $iSpec;
    $strFileSpec = $this->FileSpec();
// echo 'ISPEC='.$iSpec.' FULL SPEC='.$strFileSpec.'<br>';
 
    $imgArr = getimagesize($strFileSpec);
    $sqlFSpec = mysql_real_escape_string($this->filespec);
    $this->width = $imgArr[0];
    $this->height = $imgArr[1];
    echo '<li>'.$this->filespec;
    if ($this->width && $this->height) {
      $sql = 'SELECT * FROM '.TABLE_CUSTOM_UPLOAD_FILES.' WHERE filespec="'.$sqlFSpec.'"';
      $qryFile = $db->Execute($sql);
      if ($qryFile->RecordCount()) {
      // existing record found; is it a deleted file?
        if ($qryFile->fields['when_deleted']) {
        // previously deleted file has just been uploaded again; un-delete it from the table:
          $sql = 'UPDATE '.TABLE_CUSTOM_UPLOAD_FILES.' SET '
	    .'when_deleted=NULL,'
	    .'size_x='.$this->width.','
            .'size_y='.$this->height.' WHERE id='.$qryFile->id;
          $db->Execute($sql);
          $this->status = mysql_info();
          echo ' ...<b>re-uploaded</b>; was previously deleted by admin #'.$qryFile->fields['who_deleted'].' at '.$qryFile->fields['when_deleted'];
        } else {
        // existing record has not been deleted, so just report the duplication
        // Later: should probably update the record as above, since the existing file gets overwritten
          echo ' ...duplicate; ID='.$qryFile->fields['id'];
        }
      } else {
      // existing record not found; create it:
        $sql = 'INSERT INTO '.TABLE_CUSTOM_UPLOAD_FILES.' (id_upload,filespec,size_x,size_y) VALUES('
          .$this->objUpload->ID.','
          .'"'.$sqlFSpec.'",'
          .$this->width.','
          .$this->height.');';
        $db->Execute($sql);
        $this->status = mysql_info();
        if ($this->status) {
          echo ' ...ID='.mysql_insert_id().' <b>status='.$this->status.'</b>';
        } else {
          echo ' ...ID='.mysql_insert_id().' (ok)';
        }
      }
    } else {
      // imagesize returned zero pixels for width or height, so file is not an image
      echo ' ...<b>not an image</b>';
    }
  }
 
  public function LoadFields($iData) {
    $this->ID = $iData->fields['id'];
    $this->ID_Upload = $iData->fields['id_upload'];
    $this->filespec = $iData->fields['filespec'];
    $this->ID_Prod = $iData->fields['id_prod'];
  }
  public function Save() {
    global $db;
 
    $sql = 'UPDATE '.TABLE_CUSTOM_UPLOAD_FILES.' SET '
      .'when_deleted=NULL,'
      .'filespec="'.mysql_real_escape_string($this->filespec).'",'
      .'size_x='.(int)$this->width.','
      .'size_y='.(int)$this->height.','
      .'id_prod='.(int)$this->ID_Prod
      .' WHERE id='.$this->ID;
    $db->Execute($sql);
  }
  public function FileSpec() {
    return clsUploads::PathToBulkUpload().$this->filespec;
  }
  public function FileExt() {
    $path_parts = pathinfo($this->filespec);
    return $path_parts['extension'];
  }
  public function MakeThumb($iWidth,$iHeight) {
    $objThumb = new clsUploadThumb;
    $objThumb->Create($this, $iWidth,$iHeight);
    return $objThumb;
  }
  public function AutoDescr() {
    if ($strAutoDescr == '') {
      $strFileSpec = wfEscapeShellArg($this->FileSpec());
      $cmd = 'identify -format "%f ... %ww x %hh (x %q bits) ... %b" '.$strFileSpec;
      $strAutoDescr = exec($cmd);
    }
    return $strAutoDescr;
  }
  public function AutoDescrHTML($iSep) {
    $strFileSpec = wfEscapeShellArg($this->FileSpec());
    $cmd = 'identify -format "<b>file:</b> %f'.$iSep.'%ww x %hh (x %q bits)'.$iSep.'%b" '.$strFileSpec;
    $strDescr = exec($cmd);
    return $strDescr;
  }
  public function URL() {
    return clsUploads::URLToBulkUpload().$this->filespec;
  }
  public function HTML($iHTMLAttr) {
    return '<img '.$iHTMLAttr.' src="'.$this->URL().'" title="'.$this->AutoDescr().'">';
  }
  public function Delete() {
  // ACTION: Deletes the current image file and all associated thumbnails
    global $db;
 
    $fn = $this->filespec;
    $fs = $this->FileSpec();
    echo '<br>Deleting thumbnails for ['.$fn.']';
    // Delete the thumbnails:
    clsUploadThumbs::DelImgThumbs($this->ID);
    // Delete the master image file:
    echo '<br>Deleting file ['.$fn.']';
    if (is_file($fs)) {
      unlink($fs);
      echo '...ok';
    } else {
      echo '...<font color=red>FILE NOT FOUND</font>';
    }
    // Mark the file as deleted:
    $sql = 'UPDATE '.TABLE_CUSTOM_UPLOAD_FILES.' SET'
      .' when_deleted='.FieldDate()
      .',who_deleted='.$_SESSION['admin_id']
      .' WHERE id='.$this->ID;
    $db->Execute($sql);
  }
}
 
class clsFile {
  public $name;
  public $path;
  public $pathRel;
 
  public function Init($iPath,$iName) {
    $this->name = $iName;
    $this->path = $iPath;
    $this->pathRel = $iPathRel;
  }
  public function InitSpec($iSpec,$iPathRel) {
    $arrPath = pathinfo($iSpec);
    $this->name = $arrPath['basename'];
    $this->path = $arrPath['dirname'];
    $this->pathRel = $iPathRel;
  }
  public function Spec() {
    return $this->path.$this->name;
  }
  public function SpecRel() {
    if ($this->pathRel) {
      $strPath = $this->pathRel.'/';
    }
    return $strPath.$this->name;
  }
}
 
function dirlist($iDir,$iPathRel='') {
//  foreach(scandir($dir) as $entry) {
  $d = dir($iDir);
  while (false !== ($entry = $d->read())) {
    if($entry != '.' && $entry != '..')
    {
      $entry  = $iDir.'/'.$entry;
      if(is_dir($entry))
      {
        $path = pathinfo($entry);
        $subDir = dirlist($entry,$iPathRel.$path['basename']);
        if (is_array($listarray)) {
          if (is_array($subDir)) {
            $listarray = array_merge($listarray,$subDir);
          }
        } else {
          $listarray = $subDir;
        }
      } else {
        $path = pathinfo($entry);
        $objFile = new clsFile;
//        $objFile->Init($path['basename'],$entry);
        $objFile->InitSpec($entry,$iPathRel);
//        $listarray[] = $ipath.'/'.$path['basename'];
        $listarray[] = $objFile;
      }
    }
  }
  $d->close();
  return($listarray);
}
 
class clsUploadThumbs {
  public function Path() {
    return DIR_FS_CATALOG_IMAGES.'thumbs/';
//    return '../images/thumbs/';
  }
  public function URL() {
    return DIR_WS_CATALOG_IMAGES.'thumbs/';
  }
  public function ImgThumbs($iImgID) {
    global $db;
 
    $sql = 'SELECT * FROM '.TABLE_CUSTOM_UPLOAD_THUMBS.' WHERE id_file='.$iImgID;
    $qry = $db->Execute($sql);
    if ($qry->RecordCount()) {
      while (!$qry->EOF) {
        $obj = new clsUploadThumb;
        $obj->LoadFields($qry);
        $arr[$obj->ID]=$obj;
//        $arr[]=$obj;
        $qry->MoveNext();
      }
      return $arr;
    }
  }
  public function DelImgThumbs($iImgID) {
    $arrThumbs = self::ImgThumbs($iImgID);
    if (is_array($arrThumbs)) {
      foreach ($arrThumbs as $objThumb) {
        $fn = $objThumb->filename;
        $fs = $objThumb->FileSpec();
        echo '<br> - deleting thumbnail ['.$fn.']';
        if (is_file($fs)) {
          $objThumb->Delete();
          if ($objThumb->status) {
            echo '...ok';
          } else {
            echo '...<font color=red>ERROR</font>';
          }
        } else {
          echo '...<font color=red>FILE NOT FOUND</font>';
        }
      }
    } else {
      echo '<br>No thumbnails to delete.';
    }
  }
}
 
class clsUploadThumb {
  public $ID;
  public $ID_File;
  public $error;
  public $filename;
  public $width;
  public $height;
  public $request;
  public $status;
  public $when_made;
 
  private $objFile;
  private $pxReqX,$pxReqY;
 
  public function LoadFields($iData) {
    $this->ID = $iData->fields['id'];
    $this->ID_file = $iData->fields['id_file'];
    $this->filename = $iData->fields['filename'];
    $this->width = $iData->fields['size_x'];
    $this->height = $iData->fields['size_y'];
    $this->request = $iData->fields['request'];
    $this->when_made = $iData->fields['when_made'];
  }
  public function Make($iFile, $iWidth, $iHeight) {
// ACTION: Initializes the object and, if necessary, creates the thumb file
    global $db;
    global $wgImageMagickConvertCommand;
    $kTempFile = clsUploadThumbs::Path().'temp.tmp';
 
    $this->objFile = $iFile;
    $this->filename = $this->FileName();
    $this->pxReqX = $iWidth;
    $this->pxReqY = $iHeight;
 
// check database for a matching thumbnail
//    $sql = 'SELECT * FROM '.TABLE_CUSTOM_UPLOAD_THUMBS.' WHERE filename="'.$this->FileName().'"';
    $sql = 'SELECT * FROM '.TABLE_CUSTOM_UPLOAD_THUMBS.' WHERE request="'.$this->MatchStr().'"';
//echo 'SQL=['.$sql.']<br>';
    $qry = $db->Execute($sql);
    if ($qry->RecordCount()) {
// found; load record
      $this->status = 'found';
      $this->LoadFields($qry);
//echo " - FOUND";
    } else {
// not found; create record and thumbnail
      $strFileSpec = wfEscapeShellArg($this->objFile->FileSpec());
      $strThumbSpec = wfEscapeShellArg($this->FileSpec());
//    $cmd = $wgImageMagickConvertCommand.' '.$strFileSpec.' -quality 80 -thumbnail "'.$iOption.'" -depth 8 '.$strThumbSpec;
      $cmd = 'convert '.$strFileSpec.' -quality 80 -thumbnail "'.$this->GeomStrReq().'>" -depth 8 '.$kTempFile;
      system ( $cmd,$retval );
      $this->error = $retval;
      if ($retval) {
        $this->status = '<br>Command ['.$cmd.'] failed; error code = '.$retval;
      } else {
        $imgArr = getimagesize($kTempFile);
//echo 'Getting size of ['.$this->FileSpec().']';
        $this->width = $imgArr[0];
        $this->height = $imgArr[1];
        $this->filename = $this->FileName();
        rename($kTempFile,$this->FileSpec());
 
        $sql = 'INSERT INTO '.TABLE_CUSTOM_UPLOAD_THUMBS.' (id_file,filename,size_x,size_y,request,when_made) VALUES('
          .$this->objFile->ID.', '
          .'"'.$this->filename.'", '
          .$this->width.', '
          .$this->height.', '
          .'"'.$this->MatchStr().'", '
          .FieldDate().')';
        $qry = $db->Execute($sql);
        $this->ID = mysql_insert_id();
        $this->status = 'ok';
      }
    }
    return $retval;
  }
  public function HTML() {
    return '<a href="?set='.CUSTOM_MODULE_SET_BULK_ASSIGN.'&img-id='.$this->objFile->ID.'"><img src="'.$this->FileURL($iAffix).'" title="'.$this->objFile->AutoDescr().'"></a>';
  }
  public function FileName() {
    return $this->objFile->ID.'-'.$this->GeomStrReal().'.'.$this->objFile->FileExt();
  }
  public function FileSpec() {
    return clsUploadThumbs::Path().$this->filename;
  }
  public function FileURL() {
    return clsUploadThumbs::URL().$this->filename;
  }
  private function GeomStrReal() {
    return GeomStr($this->width,$this->height);
  }
  private function GeomStrReq() {
    return GeomStr($this->pxReqX,$this->pxReqY);
  }
  private function MatchStr() {
    return $this->objFile->ID.'-'.$this->pxReqX.'x'.$this->pxReqY;
  }
  public function Delete() {
  // ACTION: Deletes the thumbnail file and the associated record
    global $db;
 
    // remove the record
    $sql = 'DELETE FROM '.TABLE_CUSTOM_UPLOAD_THUMBS.' WHERE id='.$this->ID;
    $db->Execute($sql);
    // delete the file
    $this->status = unlink($this->FileSpec());
  }
}
 
function GeomStr($iWidth,$iHeight) {
  if ($iWidth) {
    $strOut = $iWidth;
  }
  $strOut .= 'x';
  if ($iHeight) {
    $strOut .= $iHeight;
  }
  return $strOut;
}
 
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 SaveImport($iCommit) {
    global $db;
    $result = '<ul>';
    foreach (self::Records()->List as $obj) {
      $result .= $obj->SaveImport($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;
    }
  }
  public function Item($iID) {
    global $db;
 
    $sql = 'SELECT * FROM '.TABLE_PRODUCTS.' WHERE products_id='.(int)$iID;
    $qry = $db->Execute($sql);
    if ($qry->RecordCount()) {
      $objItem = new clsTitle();
      $objItem->LoadFields($qry);
      return $objItem;
    }
  }
}
 
class clsTitle {
  private $intID;
  public $price;
  public $supplier;
  public $category;	// master category
// import fields
  public $ImportKey;
  public $Name;
  public $SuppImp;
  public $CatgImp;
  public $isCatg;
// -- calculated fields
  public $ISBN;
  public $ISBN_URL;
  public $HtmlName;
// -- status fields
  public $Status;
  public $isFound;
// stuff for catalog viewing:
  public $model;
  public $image;
// -- object cache
  private $objDescr;
 
  public function ID() {
    if (!isset($this->intID)) {
      $this->UpdateName();
    }
//echo 'TITLE ID='.$this->intID;
    return $this->intID;
  }
// == DISPLAY FUNCTIONS
  public function Load() {
    global $db;
 
    $sql = 'SELECT * FROM '.TABLE_PRODUCTS.' WHERE products_id='.$this->intID;
    $qry = $db->Execute($sql);
    if ($qry->RecordCount()) {
      $this->LoadFields($qry);
    }
  }
  public function Save() {
    global $db;
 
    $sql = 'UPDATE '.TABLE_PRODUCTS.' SET '
      .'products_model="'.mysql_real_escape_string($this->model).'"'
      .',products_image="'.mysql_real_escape_string($this->image).'"'
      .',products_price="'.mysql_real_escape_string($this->price).'"'
      .',manufacturers_id='.(int)$this->supplier
      .',master_categories_id='.(int)$this->category
      .' WHERE products_id='.(int)$this->intID;
    $db->Execute($sql);
//echo 'SQL=[<b>'.$sql.'</b>]';
  }
  public function LoadFields($iData) {
    $this->isFound = true;
    $this->intID = $iData->fields['products_id'];
    $this->model = $iData->fields['products_model'];
    $this->image = $iData->fields['products_image'];
    $this->price = $iData->fields['products_price'];
    $this->supplier = $iData->fields['manufacturers_id'];;
    $this->category = $iData->fields['master_categories_id'];
echo 'LOADING: Price='.$this->price;
  }
  public function DescrObj() {
    if (is_null($objDescr)) {
      $objDescr = clsProdDescrs::Item($this->intID);
    }
    return $objDescr;
  }
  public function HTML_Links() {
    $id = $this->intID;
    $out = '[<a href="/shop/admin/product.php?read=only&action=new_product_preview&pID='.$id.'">preview</a>]';
    $out .= ' [<a href="/shop/admin/product.php?action=new_product&pID='.$id.'">edit</a>]';
    $out .= ' [<a href="/shop/index.php?main_page=product_info&products_id='.$id.'">shop</a>]';
    return $out;
  }
  public function HTML() {
    global $db;
 
// make HTML for basic product info:
    if ($this->image) {
      $out = '<img src="'.DIR_WS_CATALOG_IMAGES.$this->image.'" align=left>';
    }
    $id = $this->intID;
    $out = '<b>Product ID</b>: '.$id;
    $out .= ' '.$this->HTML_Links();
    $out .= '<br>';
 
// add HTML for current language-description:
    $objDescr = clsProdDescrs::Item($this->intID);
    $out .= $objDescr->HTML();
    return $out;
  }
// == IMPORT FUNCTIONS
  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 SaveImport($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 clsProdDescrs {
  public function Item($iProd) {
    global $db;
 
    $idLang = clsLanguages::Current()->id;
    $sql = 'SELECT * FROM '.TABLE_PRODUCTS_DESCRIPTION.' WHERE products_id='.(int)$iProd.' AND language_id='.(int)$idLang;
    $qry = $db->Execute($sql);
    if ($qry->RecordCount()) {
      $objItem = new clsProdDescr();
      $objItem->LoadFields($qry);
      return $objItem;
    }
  }
}
 
class clsProdDescr {
  public $id_prod;
  private $objProd;
  public $id_lang;
  public $name;
  public $descr;
  public $URL;
 
  public function LoadFields($iData) {
    $this->id_prod = $iData->fields['products_id'];
    $this->id_lang = $iData->fields['language_id'];
    $this->name = $iData->fields['products_name'];
    $this->descr = $iData->fields['products_description'];
    $this->URL = $iData->fields['products_url'];
  }
  public function HTML() {
    $out = '<b>Name</b>: '.$this->name.'<br>';
    if ($this->descr) {
      $out .= '<b>Description</b>: '.$this->descr.'<br>';
    } else {
      $out .= '<b><font color=#6f6f6f>No description</font></b><br>';
    }
    return $out; 
  }
}
 
class clsLanguages {
 
  public function Current() {
    global $db;
 
    $strLang = $_SESSION['language'];
    $sql = 'SELECT * FROM '.TABLE_LANGUAGES.' WHERE directory="'.$strLang.'"';
    $qry = $db->Execute($sql);
    if ($qry->RecordCount()) {
      $obj = new clsLanguage;
      $obj->LoadFields($qry);
      return $obj;
    }
  }
}
 
class clsLanguage {
  public $id;
  public $name;
 
  public function LoadFields($iData) {
    $this->id = $iData->fields['languages_id'];
    $this->name = $iData->fields['name'];
  }
}
 
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 SaveImport($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 SaveImport($iCommit) {
    foreach (self::$Records->List as $obj) {
      if (!$obj->isFound) {
        $sqlOut .= $obj->SaveImport($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 SaveImport($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;
      }
    }
  }
}
 
?>
Personal tools