Difference between revisions of "VbzCart/archive/code/files/store.php"

from HTYP, the free directory anyone can edit if they can prove to me that they're not a spambot
< VbzCart‎ | archive‎ | code‎ | files
Jump to navigation Jump to search
(New page: ==About== * '''Purpose''': Classes for displaying different types of catalog display pages * '''History''': ** '''2009-03-07''' Transcribed from working code at vbz.net * '''To Do''': ** s...)
 
(→‎Code - store.php: oops, wrong code (non-working dev code); this is the right one)
Line 8: Line 8:
 
==Code - store.php==
 
==Code - store.php==
 
<php><?php
 
<php><?php
# PURPOSE: vbz class library
+
# PURPOSE: vbz page generator
 +
# VERSION: /topics/
  
define('kfpHostAcctRoot','/hsphere/local/home/hypertwi/');
+
// CONSTANTS
define('kfpMediaWiki',kfpHostAcctRoot.'wiki.vbz.net/');
+
// -- KF = boolean flag
define('kEmbeddedPagePrefix','embed:');
+
// -- KS = string
 
+
// -- KWP = web path (URL including protocol)
require('datamgr.php');
+
// -- KFP = file path
if (KF_USE_WIKI) {
+
// -- KRP = relative path
  define(KW_WIKI_ROOT,'http://wiki.vbz.net/');
+
$fltStart = microtime(true);
  include('extract.php');
+
// debugging activation
}
+
define('KDO_DEBUG',0);
 
+
define('KDO_DEBUG_STACK',0);
define('EN_PGTYPE_NOTFND',-1); // requested item (supp/dept/title) not found
+
// debugging options
define('EN_PGTYPE_HOME',1); // catalog home page
+
define('KDO_DEBUG_HTML',1);
define('EN_PGTYPE_SUPP',2); // supplier page
+
define('KDO_DEBUG_IMMED',1);
define('EN_PGTYPE_DEPT',3); // department page, or possibly title for keyless dept
+
define('KDO_DEBUG_DARK',0);
define('EN_PGTYPE_TITLE',4); // title page
+
define('KF_USE_WIKI',true);
 
+
// 2008-06-07 force absolute URL for cart until we fix the domain-cookie problem
$imgSize['th'] = 'thumbnail';
+
define('KF_CART_ABSOLUTE',true);
$imgSize['sm'] = 'small';
 
$imgSize['big'] = 'large';
 
$imgSize['huge'] = 'huge';
 
$imgSize['zoom'] = 'detail';
 
 
 
$intCallDepth = 0;
 
 
 
// CALCULATED GLOBALS
 
$fpTools = '/tools';
 
$fpPages = '';
 
$fwpAbsPages = 'http://'.KS_PAGE_SERVER.$fpPages;
 
$fwpAbsTools = 'http://'.KS_TOOLS_SERVER.$fpTools;
 
$fwpCart = $fwpAbsPages.'/cart/';
 
$strCurServer = $_ENV['SERVER_NAME'];
 
 
 
// SET UP DEPENDENT VALUES
 
 
/*
 
/*
if ($strCurServer != KS_TOOLS_SERVER) {
+
GET CONNECTED TO LIBRARIES
  $fpTools = $fwpAbsTools;
 
  $fpPages = $fwpAbsPages;
 
}
 
 
*/
 
*/
$fwpLogo = $fpTools.'/img/logos/v/';
 
 
 
function InitData($iSpec) {
 
  global $objFactory,$objDataMgr;
 
 
  $objDb = new clsDatabase($iSpec);
 
  $objFactory = new clsFactory($objDb);
 
  $objDataMgr = new clsDataMgr($objDb,'data_tables','data_procs','v_data_flow','data_log');
 
  return $objDb;
 
}
 
 
class clsFactory {
 
  protected $objDB;
 
  private $objPages;
 
  private $objSupps;
 
  private $objDepts;
 
  private $objTitles;
 
  private $objTitlesExt;
 
  private $objItems;
 
  private $objItTyps;
 
  private $objImages;
 
  private $objStkItems;
 
  private $objTopics;
 
 
  public function __construct($iDB) {
 
    $this->objDB = $iDB;
 
  }
 
// generic functions
 
  public function DB() {
 
    return $this->objDB;
 
  }
 
  public function Table($iName) {
 
    return new clsDataTable($this->objDB,$iName);
 
  }
 
  public function Query($iSQL) {
 
    return new clsDataQuery($this->objDB,$iSQL);
 
  }
 
// table-specific functions
 
  public function Pages() {
 
    if (!is_object($this->objPages)) {
 
      $this->objPages = new clsCatPages($this->objDB);
 
    }
 
    return $this->objPages;
 
  }
 
  public function Suppliers() {
 
    if (!is_object($this->objSupps)) {
 
      $this->objSupps = new clsSuppliers($this->objDB);
 
    }
 
    return $this->objSupps;
 
  }
 
  public function Depts() {
 
    if (!is_object($this->objDepts)) {
 
      $this->objDepts = new clsDepts($this->objDB);
 
    }
 
    return $this->objDepts;
 
  }
 
  public function Titles() {
 
    if (!is_object($this->objTitles)) {
 
      $this->objTitles = new clsTitles($this->objDB);
 
    }
 
    return $this->objTitles;
 
  }
 
  public function TitlesExt() {
 
    if (!is_object($this->objTitlesExt)) {
 
      $this->objTitlesExt = new clsTitlesExt($this->objDB);
 
    }
 
    return $this->objTitlesExt;
 
  }
 
  public function Items() {
 
    if (!is_object($this->objItems)) {
 
      $this->objItems = new clsItems($this->objDB);
 
    }
 
    return $this->objItems;
 
  }
 
  public function ItTyps() {
 
    if (!is_object($this->objItTyps)) {
 
      $this->objItTyps = new clsItTyps($this->objDB);
 
    }
 
    return $this->objItTyps;
 
  }
 
  public function Images() {
 
    if (!is_object($this->objImages)) {
 
      $this->objImages = new clsImages($this->objDB);
 
    }
 
    return $this->objImages;
 
  }
 
  public function StkItems() {
 
    if (!is_object($this->objStkItems)) {
 
      $this->objStkItems = new clsStkItems($this->objDB);
 
    }
 
    return $this->objStkItems;
 
  }
 
  public function Topics() {
 
    if (!is_object($this->objTopics)) {
 
      $this->objTopics = new clsTopics($this->objDB);
 
    }
 
    return $this->objTopics;
 
  }
 
  public function Table_noID($iName) {
 
    return new clsDataTable_noID($objDb,$iName);
 
  }
 
}
 
 
class clsList {
 
  public $List;
 
  
  public function Add($iName, $iValue=NULL) {
+
require('../local.php');
    $objItem = new clsListItem($iName,$iValue);
+
require('site.php');
    $this->List[] = $objItem;
+
$strLibs .= ':'.KFP_WIKI.':'.KFP_WIKI.'includes/';
    return $objItem;
+
ini_set('include_path',$strLibs);
  }
+
require('store.php');
  public function Output($iPfx, $iSep, $iSfx) {
 
    if (is_array($this->List)) {
 
      foreach ($this->List as $objItem) {
 
        if (is_null($objItem->value)) {
 
          $out .= $iPfx.$iSep.$objItem->name.$iSfx;
 
        } else {
 
          $out .= $iPfx.$objItem->name.$iSep.$objItem->value.$iSfx;
 
        }
 
      }
 
    }
 
    return $out;
 
  }
 
}
 
class clsListItem {
 
  public $name;
 
  public $value;
 
  
  public function __construct($iName, $iValue=NULL) {
+
// PROCESS PAGE REQUEST
    $this->name = $iName;
+
$page_uri = $_ENV['REQUEST_URI'];
    $this->value = $iValue;
+
// prepare data objects
  }
+
InitData(KS_DB_VBZCART);
}
+
//$objFactory = new clsFactory_Carts($objFactory->DB()); // this is an ugly kluge
 
+
// clsFactory can be done away with when the data.php and carts.php are rewritten to use a single class for each type
/* ===================
+
// - static methods for the whole-table functions, regular methods for individual rows
  CLASS: clsPage
 
  PURPOSE: Handles display of different page types
 
*/
 
class clsPage {
 
// query
 
  protected $strReq; // requested page
 
// page definition
 
  protected $strAbbr; // page's abbreviation for wiki embedding lookups (if blank, suppress embedding)
 
  protected $strName; // short title: {item name} (goes into html title, prefixed with store name)
 
  protected $strTitle; // longer, descriptive title: {"item name" by Supplier} (goes at top of page)
 
  protected $strSheet; // name of style sheet to use (without the .css)
 
  protected $strTitleContext; // context of short title, in HTML: {Supplier: Department:} (goes above title, in small print)
 
  protected $strHdrXtra; // any extra stuff (HTML) for the header
 
  protected $strSideXtra; // any extra stuff for the sidebar
 
  protected $lstTop; // stuff listed at the top of the sidebar
 
// calculated fields
 
  protected $strCalcTitle;
 
  protected $strContText;
 
// flags set by wiki contents
 
  protected $hideImgs;
 
/* OLD
 
// query parsing
 
  public $CatNum;
 
// status
 
  var $enPgType;
 
/**/
 
  public function __construct() {
 
    $this->lstTop = new clsList();
 
  }
 
 
 
  public function GetQuery() {
 
// ACTION: Retrieves request from URL and parses it
 
    $this->strSheet = 'browse'; // default
 
    $strReq = $_SERVER['PATH_INFO'];
 
    $this->strReq = $strReq;
 
//    $pathinfo = $_SERVER['REQUEST_URI'];
 
    if (strrpos($strReq,'/')+1 < strlen($strReq)) {
 
      $strRedir = KWP_CAT_REL.substr($strReq,1).'/';
 
      header('Location: '.$strRedir);
 
      exit; // retry with new URL
 
    }
 
    $this->ParseQuery();
 
  }
 
  public function ParseQuery() {
 
// This is essentially an abstract function
 
// Define any additional parsing of the query (store member vars etc.)
 
 
 
//    global $objFactory;
 
 
 
//    $strReq = $this->strReq;
 
 
 
 
 
//   $this->objCatPage = $objFactory->Pages()->GetItem_byKey($strReq);
 
//print 'REQ='.$strReq.' ABBR='.$this->objCatPage->AB;
 
  }
 
// DIFFERENT TYPES OF PAGES
 
  protected function DoNotFound() {
 
//    $this->Setup('','Unknown Title','unknown title in catalog','browse','Tomb of the...');
 
    $this->strAbbr = '';
 
    $this->strTitle = 'Unknown Page';
 
    $this->strName = 'unknown title in catalog';
 
    $this->strTitleContext = 'Tomb of the...';
 
    $this->strHdrXtra = '';
 
    $this->strSideXtra = '<dt><b>Cat #</b>: '.$this->strReq;
 
  }
 
// UTILITY
 
  protected function AddText($iText) {
 
    $this->strContText .= $iText;
 
  }
 
 
 
// PAGE COMPONENTS
 
// -- HEADER COMPONENTS
 
  protected function DoPreamble() {
 
# Framework
 
    $this->DoHeader();
 
    $this->DoSidebar();
 
    $this->DoWikiContent();
 
  }
 
  protected function DoPostamble() {
 
    global $didPage,$fltStart,$strPageAbbr;
 
    print '<div style="clear: both;" align=right>';
 
    $this->DoSepBar();
 
    print '<table width=100%><tr><td><small>'.$txtFooter.'</small></td><td align=right><small><i>';
 
    $fltExecTime = microtime(true)-$fltStart;
 
    $dat = getrusage();
 
    $fltUserTime = $dat["ru_utime.tv_usec"]/1000000;
 
    $strServer = $_SERVER['SERVER_SOFTWARE'];
 
    print $strServer.' .. ';
 
    print 'PHP '.phpversion().' .. Generated in <b>'.$fltUserTime.'</b> seconds (script execution '.$fltExecTime.' sec.) .. ';
 
    if ($strPageAbbr) {
 
      print 'wiki: <a href="'.KWP_WIKI_ROOT.kEmbeddedPagePrefix.$strPageAbbr.'">'.$strPageAbbr.'</a> .. ';
 
    }
 
    print date('Y-m-d H:i:s');
 
    print '</i></small></td></tr></table>';
 
    print '</i></small></div></body></html>';
 
    $didPage = true;
 
  }
 
  private function DoWikiContent() {
 
# WIKI CONTENTS
 
# $txtPage = GetEmbedPage('cat');
 
    if (KF_USE_WIKI) {
 
      $txtWiki = GetWikiPage($this->strAbbr);
 
      if ($txtWiki) {
 
        if (strpos($txtWiki,'__NOIMG__') != -1) {
 
          $txtWiki = str_replace('__NOIMG__','',$txtWiki);
 
          $this->hideImgs = true;
 
        }
 
      }
 
      if ($txtWiki) {
 
//        print '<span class=main>'.$txtPage.'</span><br>';
 
        print '<table class=main><tr><td>'.$txtWiki.'</td></tr></table>';
 
      }
 
    }
 
  }
 
  protected function DoSidebar() {
 
    global $fpTools,$objDataMgr;
 
// later: these will be pulled from the [stats] table
 
if ($objDataMgr->dtNewest) {
 
  $timeSidebarBuild=$objDataMgr->dtNewest;
 
}
 
$statsQtyTitlesAvail = 2245;
 
$statsQtyStockPieces = 1395;
 
$statsQtyStockItems = 753;
 
$statsQtyArtists = 136;
 
$statsQtyTopics = 1048;
 
 
 
    print '<table align=left background="'.$fpTools.'/img/bg/lines/" cellpadding=3 bgcolor="#000000"><tr><td>';
 
?>
 
<table bgcolor="#ffffff" cellpadding=5><tr><td class=xxmenu>
 
<table border=0 class=menu-title width="100%"><tr><td class=menu-title><a href="/">Home</a></td></tr></table>
 
<span class=menu-text><dl>
 
<?php
 
/*
 
<span class=menu-text><p style="background: #eeeeee;"><dl>
 
*/
 
  echo $this->lstTop->Output('<dt><b>','</b>: ','');
 
//  echo '</p></span></dl>';
 
  echo '</dl>';
 
  if ($this->strSideXtra) {
 
    echo '<dl style="background: #eeeeee;">'.$this->strSideXtra.'</dl>';
 
  }
 
  echo '<form action="/search/">';
 
  echo 'Search '.$statsQtyTitlesAvail.' items:<br>';
 
?>
 
<input size=10 name=search><input type=submit value="Go"><br>
 
<small><a href="/search/">advanced</a></small>
 
</form>
 
<b>Indexes</b>
 
<br> ...<a href="/cat/"><b>C</b>atalog <b>H</b>ome</a>
 
<?php
 
 
 
    print '<br> ...<a href="/stock/" title="'.$statsQtyStockPieces.' pieces, '.$statsQtyStockItems.'. items"><b>S</b>tock</a> ('.$statsQtyStockPieces.')';
 
    print '<br> ...<a href="/artists/" title="'.$statsQtyArtists.'.artists"><b>A</b>rtists</a> ('.$statsQtyArtists.')';
 
    print '<br> ...<a href="/topics/" title="'.$statsQtyTopics.'.topics"><b>T</b>opics</a> ('.$statsQtyTopics.')';
 
    print '<p>';
 
    print '[[ <a href="'.KWP_WIKI.'/" title="vbz wiki homepage"><b>wiki</b></a> ]]<br>';
 
    print '-- [[ <a href="'.KWP_WIKI.'/help" title="help-related pages on the wiki"><b>Help</b></a> ]]<br>';
 
    print '-- [[ <a href="'.KWP_WIKI.'/about" title="about vbz.net (probably more than you want to know)"><b>About</b></a> ]]<br>';
 
    print '-- [[ <a href="'.KWP_WIKI.'/contact" title="contact vbz.net (several different methods)"><b>Contact</b></a> ]]<br>';
 
    print '<p>';
 
    print '<a href="/email/" title="web form for sending us email">email form</a><br>';
 
    print '<a href="/cart/" title="your shopping cart">shopping cart</a><p>';
 
# == END Sidebar B ==
 
    print '<table background="'.$fpTools.'/img/bg/hdr/" width="100%"><tr><td>';
 
    print '<table width="100%"><tr><td valign=top class=menu-status>Updated:</td><td>';
 
    print '<td align=right class=menu-status><b>'.$timeSidebarBuild.'</b>';
 
    print '</td></tr></table>';
 
    print '</td></tr></table></span></td></tr></table></td></tr></table>';
 
  }
 
  private function DoSepBar() {
 
    global $fpTools;
 
 
 
    print '<img src="'.$fpTools.'/img/bg/hlines/" alt="-----" width="100%">';
 
  }
 
  private function ToolbarItem($iURL,$iIcon,$iTitle,$iAlt) {
 
    global $fpTools;
 
    return '<a href="'.$iURL.'"><img border=0 src="'.$fpTools.'/img/icons/'.$iIcon.'.050pxh.png" title="'.$iTitle.'" alt="'.$iAlt.'"></a>';
 
  }
 
  protected function DoToolbar() {
 
    global $fpPages,$fwpCart;
 
    print $this->ToolbarItem($fpPages.'/','home',KS_STORE_NAME.' home page','home page');
 
    print $this->ToolbarItem($fpPages.'/search/','search','search page','search page');
 
    print $this->ToolbarItem($fwpCart,'cart','shopping cart','shopping cart');
 
    print $this->ToolbarItem(KWP_WIKI.'/help','help','help!','help');
 
  }
 
// -- HEADER
 
  protected function DoHeader() {
 
    global $fpTools, $fwpLogo,$strPageAbbr;;
 
 
 
    $strPageAbbr = $this->strAbbr;
 
    $this->strCalcTitle = KS_STORE_NAME.' - '.$this->strName;
 
    $htmlHead = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">';
 
    $htmlHead .= '<html><head><title>'.$this->strCalcTitle.'</title>';
 
    if ($this->strSheet) {
 
      $htmlHead .= '<link rel="StyleSheet" href="'.$fpTools.'/styles/'.$this->strSheet.'.css">';
 
    }
 
# remove any quotes from $pageName:
 
    $htmlName = str_replace('"','&quot;',$this->strName);
 
    if ($htmlName) {
 
      $htmlName = ': '.$htmlName;
 
    }
 
    $htmlHead .= '<meta name=description content="'.KS_STORE_NAME_META.$htmlName.'">';
 
    $htmlHead .= '</head>';
 
    print $htmlHead;
 
?><body
 
bgcolor=000044
 
TEXT=CCFFFF
 
LINK=33FF33
 
VLINK=33CCFF
 
ALINK=FFCC00
 
TOPMARGIN=0
 
LEFTMARGIN=0
 
MARGINWIDTH=0
 
MARGINHEIGHT=0
 
>
 
<?
 
// begin content header
 
    print '<table width="100%" background="'.$fpTools.'/img/bg/lines/" cellpadding=5 bgcolor=000000><tr><td>';
 
    print '<table width="100%" class=hdr cellpadding=2><tr>';
 
// === LEFT HEADER: Title ===
 
    print '<td>';
 
    print '<a href="'.KWP_HOME_ABS.'"><img align=left border=0 src="'.$fwpLogo.'" title="'.KS_STORE_NAME.' home" alt="'.KS_SMALL_LOGO_ALT.'"></a>';
 
    if ($this->strTitleContext) {
 
      print '<span class=pretitle><b><a href="/">'.KS_STORE_NAME.'</a></b>: '.$this->strTitleContext.'</span><br>';
 
    }
 
    print '<span class=page-title>'.$this->strTitle.'</span></td>';
 
// === END LEFT HEADER ===
 
 
 
// === RIGHT HEADER: nav icons ===
 
    print '<td align=right>';
 
    $this->DoToolbar();
 
    print '</td>';
 
// === END RIGHT HEADER ===
 
?>
 
</tr></table>
 
</td></tr></table>
 
<!-- end html header -->
 
<?
 
  }
 
}
 
 
 
class clsPageCat extends clsPage {
 
  private $objCatPage; // object for identifying page to display
 
 
 
  public function ParseQuery() {
 
    global $objFactory;
 
 
 
    $strReq = $this->strReq;
 
    $this->objCatPage = $objFactory->Pages()->GetItem_byKey($strReq);
 
//print 'REQ='.$strReq.' ABBR='.$this->objCatPage->AB;
 
  }
 
 
 
  public function DoRequest() {
 
    if ($this->strReq) {
 
      if (is_object($this->objCatPage)) {
 
        switch ($this->objCatPage->Type) {
 
        case 'S':
 
          $this->DoCatSupp();
 
          break;
 
        case 'D':
 
          $this->DoCatDept();
 
          break;
 
        case 'T':
 
          $this->DoCatTitle();
 
          break;
 
        case 'I':
 
          $doRawHTML = TRUE;
 
          $this->DoCatImage();
 
          break;
 
        }
 
      } else {
 
        $this->DoNotFound();
 
      }
 
    } else {
 
      $this->DoCatHome();
 
    }
 
    if ($doRawHTML) {
 
      echo $this->strContText;
 
    } else {
 
      $this->DoPreamble(); // everything before the contents
 
      echo $this->strContText;
 
      $this->DoPostamble(); // everything after the contents
 
    }
 
  }
 
// SIDEBAR INFO for different types of pages
 
  private function DoCatIndicia() {
 
    $this->lstTop->Add('Section','<a href="'.KWP_CAT_REL.'">by supplier</a>');
 
  }
 
  private function DoSuppIndicia($iSupp,$isFinal=true) {
 
    $this->DoCatIndicia();
 
    if ($isFinal) {
 
      $this->lstTop->Add('Supplier',$iSupp->Name);
 
      $this->lstTop->Add('<a href="'.KWP_WIKI_ROOT.$iSupp->Name.'">more info</a>');
 
    } else {
 
      $this->lstTop->Add('Supplier',$iSupp->Link());
 
    }
 
  }
 
  private function DoDeptIndicia($iDept,$isFinal=true) {
 
    $this->DoSuppIndicia($iDept->Supplier(),false);
 
    if ($isFinal) {
 
      $this->lstTop->Add('Dept.',$iDept->Name);
 
    } else {
 
      $this->lstTop->Add('Dept.',$iDept->LinkName());
 
    }
 
  }
 
  private function DoTitleIndicia($iTitle) {
 
    $this->DoDeptIndicia($iTitle->Dept(),false);
 
    $this->lstTop->Add('Title',$iTitle->Name);
 
    $this->lstTop->Add(' - catalog #',$iTitle->CatNum());
 
  }
 
 
 
 
 
  private function DoCatHome() {
 
    global $objFactory;
 
 
 
    $objSuppTbl = $objFactory->Suppliers();
 
//    $this->Setup('cat','Catalog Home','Catalog main page','browse','hello and welcome to the...');
 
    $this->DoCatIndicia();
 
    $this->strAbbr = 'cat';
 
    $this->strTitle = 'Catalog Home';
 
    $this->strName = 'Catalog main page';
 
    $this->strTitleContext = 'hello and welcome to the...';
 
    $this->AddText($objSuppTbl->DoHomePage());
 
  }
 
  private function DoCatSupp() {
 
    global $objFactory;
 
    CallEnter('clsPage.DoCatSupp()');
 
 
 
    $objSuppTbl = $objFactory->Suppliers();
 
    $objSupp = $objSuppTbl->GetItem($this->objCatPage->ID_Row);
 
    assert(is_object($objSupp));
 
    $strSuppName = $objSupp->GetValue('Name');
 
 
 
    $this->DoSuppIndicia($objSupp);
 
    $this->strAbbr = 'supp:'.strtoupper($this->CatKey);
 
    $this->strTitle = $strSuppName;
 
    $this->strName = 'listing for '.$strSuppName;
 
    $this->strTitleContext = '<a href="'.KWP_CAT_REL.'">Suppliers</a>: <b>'.$strSuppName.'</b>:';
 
    $this->AddText($objSupp->DoPage());
 
 
 
    CallExit('clsPage.DoCatSupp()');
 
  }
 
  private function DoCatDept() {
 
    global $objFactory;
 
    CallEnter('clsPage.DoCatDept()');
 
 
 
    $objDeptTbl = $objFactory->Depts();
 
    $objDept = $objDeptTbl->GetItem($this->objCatPage->ID_Row);
 
    assert(is_object($objDept));
 
    $objSupp = $objDept->Supplier();
 
    assert(is_object($objSupp));
 
    $strDeptName = $objDept->Name;
 
    $strSuppName = $objSupp->Name;
 
    $strDeptLink = $objDept->LinkName();
 
    $strSuppLink = $objSupp->Link();
 
 
 
    $this->DoDeptIndicia($objDept);
 
    $this->strAbbr = 'dept:'.strtoupper($this->CatNum);
 
    $this->strTitle = $strSuppName;
 
    $this->strName = $strDeptName.' dept. of '.$strSuppName;
 
    $this->strTitleContext = 'items <a href="'.KWP_CAT_REL.'">supplied</a> by '.$strSuppLink.'\'s <b>'.$strDeptName.'</b> department:';
 
    $this->AddText($objDept->DoPage());
 
    CallExit('clsPage.DoCatDept()');
 
  }
 
  private function DoCatTitle() {
 
    global $objFactory;
 
    CallEnter('clsPage.DoCatTitle()');
 
 
 
    $strCatNum = $this->CatNum;
 
    $objTitleTbl = $objFactory->Titles();
 
 
 
    $objTitle = $objTitleTbl->GetItem($this->objCatPage->ID_Row);
 
    assert(is_object($objTitle));
 
    $objDept = $objTitle->Dept();
 
    assert(is_object($objDept));
 
    $objSupp = $objDept->Supplier();
 
    assert(is_object($objSupp));
 
    $strTitleName = $objTitle->Name;
 
 
 
    $this->DoTitleIndicia($objTitle);
 
 
 
//    $this->strAbbr = 'title:'.strtoupper($strCatNum);
 
    $this->strAbbr = 'title:'.$objTitle->CatNum();
 
//print 'ABBR='.$this->strAbbr;
 
    $this->strTitle = $strTitleName;
 
    $this->strName = $strCatNum.' "'.$strTitleName.'" from '.$objSupp->Name;
 
    $this->strTitleContext =
 
      'items <a href="'.KWP_CAT_REL.
 
      '">supplied</a> by '.$objSupp->Link().'\'s '.
 
      $objDept->LinkName().' department:';
 
    $objTitle->hideImgs = $this->hideImgs;
 
    $this->AddText($objTitle->DoPage());
 
    CallExit('clsPage.DoCatTitle()');
 
  }
 
  private function DoCatImage() {
 
    global $objFactory;
 
    CallEnter('clsPage.DoCatImage()');
 
    $objImageTbl = $objFactory->Images();
 
    $objImage = $objImageTbl->GetItem($this->objCatPage->ID_Row);
 
    $objImage->DoPage();
 
    CallExit('clsPage.DoCatImage()');
 
  }
 
}
 
 
 
class clsPageTopic extends clsPage {
 
  public function DoRequest() {
 
    global $objFactory;
 
 
 
    $strReq = $this->strReq;
 
    if (is_numeric($strReq)) {
 
      $idTopic = (int)$strReq;
 
      $objTopic = $objFactory->Topics()->GetItem($idTopic);
 
      $this->strAbbr = 'topic.'.$objTopic->WebName();
 
      $this->strTitle = 'Topic Index';
 
      $this->strName = 'catalog topic index';
 
      $this->AddText($objTopic->DoPage());
 
    } else {
 
      $this->strAbbr = 'topics';
 
      $this->strTitle = 'Topic Index';
 
      $this->strName = 'catalog topic index';
 
      $this->AddText($objFactory->Topics()->DoIndex());
 
    }
 
    $this->DoPreamble(); // everything before the contents
 
    echo '<span class=main>'.$this->strContText.'</span>';
 
    $this->DoPostamble(); // everything after the contents
 
  }
 
}
 
 
 
class clsPageOutput {
 
  public $out;
 
  private $isOdd;
 
  public $inTbl;
 
 
 
  function __construct() {
 
    $this->out = '';
 
    $this->isOdd = false;
 
    $this->inTbl = 0;
 
  }
 
  function Clear() {
 
    $this->out = '';
 
  }
 
  function AddText($iText) {
 
    $this->out .= $iText;
 
  }
 
  function SectionHdr($iTitle) {
 
    $this->out .= '<p class=main><big>'.$iTitle.'</big></p>';
 
    return $this->out;
 
  }
 
  function StartTable($iTitle) {
 
    if ($iTitle) {
 
      $this->SectionHdr($iTitle);
 
      $this->out .= '<table>';
 
      $this->inTbl++;
 
    }
 
  }
 
  function RowStart($iClass='') {
 
    if ($iAttr) {
 
      $this->out .= '<tr class="'.$iAttr.'">';
 
    } else {
 
      $this->out .= '<tr>';
 
    }
 
  }
 
  function RowStop() {
 
    $this->out .= '</tr>';
 
    $this->isOdd = !$this->isOdd;
 
  }
 
  function ColAdd($iText) {
 
    if ($this->isOdd) {
 
      $cellOpen = '<td class=catalog-stripe valign=top>';
 
    } else {
 
      $cellOpen = '<td class=catalog valign=top>';
 
    }
 
    $this->out .= $cellOpen.$iText.'</td>';
 
  }
 
  function EndTable() {
 
    if ($this->inTbl) {
 
      $this->out .= '</table>';
 
      $this->inTbl--;
 
    }
 
    return $this->out;
 
  }
 
  function ShowTitles($iHdrText,$iList,$objNoImgSect) {
 
    foreach ($iList as $i => $objTitle) {
 
      $objImgs = $objTitle->ListImages('th');
 
      $currMinPrice = $objTitle->currMinPrice;
 
      $currMaxPrice = $objTitle->currMaxPrice;
 
      $strPrice = DataCurr($currMinPrice);
 
      if ($currMinPrice != $currMaxPrice) {
 
        $strPrice .= '-'.DataCurr($currMaxPrice);
 
      }
 
      if ($objImgs->RowCount()) {
 
        $cntImgs++;
 
        $strTitleTag = '&quot;'.$objTitle->Name.'&quot; ('.$objTitle->CatNum.')';
 
        $strTitleLink = $objTitle->Link();
 
        while ($objImgs->HasData()) {
 
          $strImgTag = $strTitleTag.' - '.$strPrice;
 
          if ($objTitle->qtyInStock) {
 
            $strImgTag .= ' - '.$objTitle->qtyInStock.' in stock';
 
          }
 
          $outImgs .= $strTitleLink.'<img class="thumb" src="'.KWP_IMG_MERCH.'/'.$objImgs->GetValue('Spec').'" title="'.$strImgTag.'"></a>';
 
          $objImgs->NextRow();
 
        }
 
      } else {
 
        if (!$objNoImgSect->inTbl) {
 
          $objNoImgSect->StartTable('titles without images:');
 
          $objNoImgSect->AddText('<tr class=main><th>Cat. #</th><th>Title</th><th>Price<br>Range</th><th>to<br>order</th><th>status</th></tr>');
 
        }
 
        $objNoImgSect->RowStart();
 
        $objNoImgSect->ColAdd('<b>'.$objTitle->CatNum.'</b>');
 
        $objNoImgSect->ColAdd($objTitle->Name);
 
        $objNoImgSect->ColAdd($strPrice);
 
        $objNoImgSect->ColAdd('<b>[</b>'.$objTitle->Link().'order</a><b>]</b>');
 
        $qtyInStock = $objTitle->GetValue('qtyInStock');
 
        if ($qtyInStock) {
 
          $strStock = '<b>'.$qtyInStock.'</b> in stock';
 
          $objNoImgSect->ColAdd($strStock);
 
          if ($objTitle->GetValue('cntInPrint') == 0) {
 
            $objNoImgSect->ColAdd('OUT OF PRINT!');
 
          }
 
        } else {
 
          $objNoImgSect->ColAdd('<a title="explanation..." href="'.KWP_WIKI.'/Available_but_not_in_stock">available, not in stock</a>');
 
// Debugging:
 
//          $objNoImgSect->ColAdd('ID_Title='.$objTitle->ID.' ID_ItTyp='.$objTitle->idItTyp);
 
        }
 
        $objNoImgSect->RowStop();
 
      }
 
    }
 
    if ($cntImgs) {
 
      $this->SectionHdr($iHdrText);
 
      $this->AddText($outImgs);
 
    }
 
    return $this->out;
 
  }
 
  function ShowImgUnavail() {
 
    $this->out .= '<table background="/tools/img/bg/lines/" bgcolor="000000" cellpadding="5"><tbody><tr><td><table class="hdr" cellpadding="2"><tbody><tr><td align="center"><span class="page-title">No Images<br>Available<br></span>for this item<br><b>:-(</b></td></tr></tbody></table></td></tr></tbody></table>';
 
    return $this->out;
 
  }
 
}
 
 
 
/* ===========================
 
*** CATALOG DATA CLASSES ***
 
*/
 
 
 
class clsCatPages extends clsDataTable {
 
  public function __construct($iDB) {
 
    parent::__construct($iDB,'cat_pages','AB');
 
  }
 
  protected function _newItem() {
 
    return new clsCatPage($this);
 
  }
 
  public function GetItem_byKey($iKey) {
 
    global $objDataMgr;
 
 
 
    CallEnter('clsCatPages.GetItem_byKey('.$iKey.')');
 
    $strKey = trim($iKey,'/');
 
    $strKey = str_replace('-','/',$strKey);
 
    $sqlCatKey = $this->objDB->SafeParam($strKey);
 
//    $sql = 'SELECT * FROM '.$this->strName.' WHERE CatKey="'.$sqlCatKey.'"';
 
    $objDataMgr->Update($this->Name(),'clsCatPages.GetItem_byKey('.$iKey.')');
 
    $objItem = $this->GetData('Path="'.$sqlCatKey.'"');
 
//    $objRec = $this->objDB->Query($sql);
 
    DumpValue('objItem NumRows',$objItem->Res->num_rows);
 
    CallExit('clsCatPages.GetItem_byKey('.$iKey.') -> Page '.$this->strAbbr);
 
    return $objItem;
 
  }
 
}
 
class clsCatPage extends clsDataItem {
 
  public $AB;
 
  public $Type;
 
  public $ID_Row;
 
 
 
  protected function LoadResults() {
 
    CallEnter('clsCatPage.LoadResults()');
 
    parent::LoadResults();
 
    $this->AB = $this->GetValue('AB');
 
    $this->Type = $this->GetValue('Type');
 
    $this->ID_Row = $this->GetValue('ID_Row');
 
    assert($this->AB);
 
    CallExit('clsCatPage.LoadResults()');
 
  }
 
}
 
 
 
class clsSuppliers extends clsDataTable {
 
  public function __construct($iDB) {
 
    parent::__construct($iDB,'suppliers');
 
  }
 
  protected function _newItem() {
 
    return new clsSupplier($this);
 
  }
 
/*
 
  public function GetItem($iID) {
 
    CallEnter('clsSuppliers.GetItem('.$iID.')');
 
    $objItem = parent::GetItem($iID,$objItem);
 
    CallExit('clsSuppliers.GetItem('.$iID.')');
 
    return $objItem;
 
  }
 
/**/
 
  public function GetItem_byKey($iKey) {
 
    CallEnter('clsSuppliers.GetItem_byKey('.$iKey.')');
 
    $sqlCatKey = $this->objDB->SafeParam($iKey);
 
//    $sql = 'SELECT * FROM '.$this->strName.' WHERE CatKey="'.$sqlCatKey.'"';
 
    $objItem = $this->GetData('CatKey="'.$sqlCatKey.'"');
 
//    $objRec = $this->objDB->Query($sql);
 
    CallExit('clsSuppliers.GetItem_byKey('.$iKey.') -> new supplier');
 
    return $objItem;
 
  }
 
  public function DoHomePage() {
 
    global $objDataMgr;
 
 
 
    $sql = 'SELECT * FROM _supplier_ittyps ORDER BY Name, ItemCount DESC';
 
    $objRec = new clsDataItem($this);
 
    $objDataMgr->Update('_supplier_ittyps','clsSuppliers.DoHomePage()');
 
    $objRec->Query($sql);
 
    if ($objRec->RowCount()) {
 
      $objTbl = new clsPageOutput;
 
      $objTbl->StartTable('Suppliers');
 
      while ($objRec->HasData()) {
 
        $strKey = $objRec->GetValue('CatKey');
 
        if ($strKey != $strKeyLast) {
 
          $strKeyLast = $strKey;
 
          $strKeyLink = strtolower($strKey).'/';
 
          if ($outCell) {
 
            $objTbl->ColAdd($outCell);
 
            $objTbl->RowStop();
 
            $outCell = '';
 
          }
 
          $objTbl->RowStart();
 
          $objTbl->ColAdd('<b><a href="'.$strKeyLink.'">'.$objRec->GetValue('Name').'</a></b>');
 
          $isFirst = true;
 
        }
 
        if ($isFirst) {
 
          $isFirst = false;
 
        } else {
 
          $outCell .= ', ';
 
        }
 
        $outCell .= ' <b>'.$objRec->GetValue('ItemCount').'</b> '.$objRec->GetValue('ItemType');
 
        $objRec->NextRow();
 
      }
 
      $objTbl->ColAdd($outCell);
 
      $objTbl->RowStop();
 
      $out .= $objTbl->EndTable();
 
    }
 
    return $out;
 
  }
 
}
 
 
 
class clsSupplier extends clsDataItem {
 
  public $ID;
 
  public $Name;
 
  public $CatKey;
 
 
 
  protected function LoadResults() {
 
    CallEnter('clsSupplier.LoadResults()');
 
    parent::LoadResults();
 
    $this->ID = $this->GetValue('ID');
 
    $this->Name = $this->GetValue('Name');
 
    $this->CatKey = $this->GetValue('CatKey');
 
    assert($this->ID);
 
    CallExit('clsSupplier.LoadResults()');
 
  }
 
  public function DoPage() {
 
    global $objFactory,$objDataMgr;
 
 
 
    CallEnter('clsSupplier.DoPage()');
 
    assert($this->ID);
 
// first, check how many departments supplier has:
 
    $objDeptTbl = $objFactory->Depts();
 
    $objDepts = new clsDept($objDeptTbl);
 
    $sql = 'SELECT * FROM _depts WHERE (cntForSale>0) AND (ID_Supp='.$this->ID.')';
 
    $objDataMgr->Update('_depts','clsSupplier.DoPage() for '.$this->CatKey);
 
    $objDepts->Query($sql);
 
    if ($objDepts->RowCount() == 1) {
 
// if there's only one department, display that instead of a department listing
 
      $out = $objDepts->DoPage();
 
    } else {
 
      $sql = 'SELECT * FROM _supplier_ittyps WHERE ID='.$this->ID.' ORDER BY Name, ItemCount DESC';
 
      $objDataMgr->Update('_supplier_ittyps','clsSupplier.DoPage() for '.$this->CatKey);
 
      $objItTyps = new clsDataItem($this->Table);
 
      $objItTyps->Query($sql);
 
      $isFirst = true;
 
      $out .= '<span class=catalog-summary>';
 
      while ($objItTyps->HasData()) {
 
        if ($isFirst) {
 
          $isFirst = false;
 
        } else {
 
          $out .= ', ';
 
        }
 
        $out .= ' <b>'.$objItTyps->GetValue('ItemCount').'</b> '.$objItTyps->GetValue('ItemType');
 
        $objItTyps->NextRow();
 
      }
 
      $out .= '</span>';
 
      $out .= $objDeptTbl->DoListing_forSupp($this->ID);
 
    }
 
 
 
    CallExit('clsSupplier.DoPage()');
 
    return $out;
 
  }
 
  public function Link() {
 
    $out = '<a href="'.$this->URL().'">'.$this->Name.'</a>';
 
    return $out;
 
  }
 
  public function URL() {
 
    return KWP_CAT_REL.strtolower($this->CatKey).'/';
 
  }
 
}
 
class clsDepts extends clsDataTable {
 
  public function __construct($iDB) {
 
    parent::__construct($iDB,'depts');
 
  }
 
  protected function _newItem() {
 
    CallStep('clsDepts._newItem()');
 
    return new clsDept($this);
 
  }
 
  public function DoListing_forSupp($iSuppID) {
 
    CallEnter('clsDepts.DoListing_forSupp('.$iSuppID.')');
 
 
 
    $out .= '<p class=main><big>Departments:</big></p><table>';
 
    $objDepts = $this->GetData('ID_Supplier='.$iSuppID,'Name');
 
    $isFirst = true;
 
 
 
    while ($objDepts->HasData()) {
 
      $outDept = $objDepts->DoListing();
 
      if ($outDept) { // only show departments with something in them
 
        if ($isOdd) {
 
          $cellOpen = '<td class=catalog-stripe valign=top>';
 
        } else {
 
          $cellOpen = '<td class=catalog valign=top>';
 
        }
 
        $keyDept = $objDepts->PageKey();
 
        $out .= '<tr>'.$cellOpen.'<a href="'.strtolower($keyDept).'/">'.$objDepts->Name.'</a></td>';
 
        $isOdd = !$isOdd;
 
        $out .= $cellOpen.$outDept.'</td></tr>';
 
      }
 
      $objDepts->NextRow();
 
    }
 
    $out .= '</table>';
 
    CallExit('clsDepts.DoListing_forSupp()');
 
    return $out;
 
/**/
 
  }
 
  public function GetItem_byCatPage($iCatPage) {
 
    global $objDataMgr;
 
 
 
    CallEnter('clsDepts.GetItem_byCatPage('.$iCatPage.')');
 
    assert(is_object($this->objDB));
 
    $sqlCatPage = strtolower(str_replace('.','/',$iCatPage));
 
    $sqlCatPage = $this->objDB->SafeParam($sqlCatPage);
 
    $sql = 'SELECT * FROM _depts WHERE CatWeb_Dept="'.$sqlCatPage.'"';
 
    $objRec = new clsDataItem($this);
 
    $objDataMgr->Update('_depts','clsDepts.GetItem_byCatPage('.$iCatPage.')');
 
    $objRec->Query($sql);
 
    if ($objRec->HasData()) {
 
      assert($objRec->RowCount() == 1);
 
      $idDept = $objRec->GetValue('ID');
 
      $objDept = $this->GetData('ID='.$idDept);
 
      assert($objDept);
 
      return $objDept;
 
    } else {
 
      return NULL;
 
    }
 
    CallExit('clsDepts.GetItem_byCatPage()');
 
  }
 
}
 
class clsDept extends clsDataItem {
 
  public $ID;
 
  public $Name;
 
  public $CatKey;
 
  public $PageKey;
 
  public $idSupp;
 
  public $isActive;
 
// object cache
 
  private $objSupp;
 
 
 
  protected function LoadResults() {
 
    CallEnter('clsDept.LoadResults()');
 
    $this->ID = $this->GetValue('ID');
 
    $this->Name = $this->GetValue('Name');
 
    $this->CatKey = $this->GetValue('CatKey');
 
    $this->PageKey = $this->GetValue('PageKey');
 
    $this->idSupp = $this->GetValue('ID_Supplier');
 
    $this->isActive = $this->GetValue('isActive');
 
    $objSupp = NULL;
 
    assert($this->ID);
 
    CallExit('clsDept.LoadResults()');
 
  }
 
  public function Supplier() {
 
    global $objFactory;
 
 
 
    if (is_object($this->objSupp)) {
 
      return $this->objSupp;
 
    } else {
 
      if ($this->idSupp) {
 
        $this->objSupp = $objFactory->Suppliers()->GetItem($this->idSupp);
 
        return $this->objSupp;
 
      } else {
 
        return NULL;
 
      }
 
    }
 
  }
 
  public function PageKey() {
 
    if ($this->PageKey) {
 
      return $this->PageKey;
 
    } else {
 
      return $this->CatKey;
 
    }
 
  }
 
  protected function GetDeptData() {
 
    global $objDataMgr;
 
 
 
//    $sql = 'SELECT * FROM _dept_ittyps WHERE (ID_Dept='.$this->ID.') AND cntForSale ORDER BY cntInPrint DESC';
 
    $sql = 'SELECT * FROM qryItTypsDepts_ItTyps WHERE (ID_Dept='.$this->ID.') ORDER BY cntInPrint DESC';
 
    $objItTyps = new clsTitleIttyp($this->Table);
 
    $objDataMgr->Update('_dept_ittyps','clsDept.DoListing() for ID='.$this->ID);
 
    $objItTyps->Query($sql);
 
    return $objItTyps;
 
  }
 
  public function DoListing() {
 
// PURPOSE: Print this department's information as part of department list
 
 
 
    assert($this->ID);
 
    $objItTyps = $this->GetDeptData();
 
 
 
    $isFirst = true;
 
    while ($objItTyps->HasData()) {
 
      if ($isFirst) {
 
        $isFirst = false;
 
      } else {
 
        $out .= ', ';
 
      }
 
      $cntInPrint = $objItTyps->cntInPrint;
 
      $qtyInStock = $objItTyps->qtyInStock;
 
// TO FIX: This is wrong. Need cntForSale field
 
      $cntAvail = $cntInPrint + $qtyInStock;
 
      if ($cntAvail == 1) {
 
        $strName = $objItTyps->ItTypNameSng;
 
      } else {
 
        $strName = $objItTyps->ItTypNamePlr;
 
      }
 
      $out .= ' <b>'.$cntAvail.'</b> '.$strName;
 
      $objItTyps->NextRow();
 
    }
 
    return $out;
 
  }
 
  public function DoPage() {
 
// PURPOSE: Print page for current department
 
// ACTION:
 
// * Iterates through item types available for this department.
 
// * For each item type, prints header and then a list of titles.
 
    global $objDataMgr;
 
 
 
    assert($this->ID);
 
    $idDept = $this->ID;
 
    $objSection = new clsPageOutput();
 
    $objItTyps = $this->GetDeptData();
 
    $objTitles = new clsTitleExt($this->Table);
 
//    $objTitles = new clsDataItem($this->Table);  TRY THIS NEXT
 
    $objNoImgSect = new clsPageOutput();
 
    while ($objItTyps->HasData()) {
 
      $cntInPrint = $objItTyps->cntInPrint;
 
      $qtyInStock = $objItTyps->qtyInStock;
 
// TO FIX: This is wrong. Need cntForSale field
 
      $cntAvail = $cntInPrint + $qtyInStock;
 
      if ($cntAvail) {
 
        $cntSections++;
 
        $idItTyp = $objItTyps->ID_ItTyp;
 
//        $objSection->SectionHdr();
 
//        $sql = 'SELECT *, ID_Title AS ID, TitleName AS Name FROM _title_ittyps WHERE ((cntForSale) AND (ID_ItTyp='.$idItTyp.') AND (ID_Dept='.$idDept.'));';
 
        $sql = 'SELECT t.ID_Title AS ID, t.* FROM qryTitles_ItTyps_Titles AS t WHERE (ID_ItTyp='.$idItTyp.') AND (ID_Dept='.$idDept.');';
 
//        $objDataMgr->Update('_title_ittyps','clsDept.DoPage() for ID_ItTyp='.$idItTyp.', ID_Dept='.$idDept);
 
        $objTitles->Query($sql);
 
        $idTitle = $objTitles->ID;
 
//        $idTitle = $objTitles->GetValue('ID_Title');
 
//        $objTitles->ID = $idTitle;
 
 
        if ($objTitles->HasData()) {
 
          while ($objTitles->HasData()) {
 
            $objTitle = clone $objTitles; // get a copy with current values
 
            $objTitle->Res = NULL;
 
            $lstTitles[] = $objTitle; // save it in a list
 
            $objTitles->NextRow();
 
          }
 
          assert(is_array($lstTitles));
 
 
 
// We've generated the list of titles for this section; now display the section header and titles:
 
 
 
//          $out .= $objSection->ShowTitles($objItTyps->ItTypNamePlr.':',$lstTitles,$objNoImgSect);
 
          $out .= $objSection->ShowTitles($objItTyps->GetValue('ItTyp_Plr').':',$lstTitles,$objNoImgSect);
 
        } else {
 
  echo 'ERROR: No titles found! SQL='.$sql;
 
        }
 
        unset($lstTitles);
 
        $objSection->Clear();
 
      } else {
 
        $out .= '<span class=main>Small coding error: this line should never happen.</span>'; // TO DO: log an error
 
      }
 
      $objItTyps->NextRow();
 
    }
 
    if (!$cntSections) {
 
        $out .= '<span class=main>This department appears to have been emptied of all leftover stock. (Eventually there will be a way to see what items used to be here.)</span>';
 
    }
 
    if ($objNoImgSect->inTbl) {
 
      $objNoImgSect->EndTable();
 
      $objSection->AddText($objNoImgSect->out);
 
      $objSection->EndTable();
 
      $out .= $objSection->out;
 
    }
 
    return $out;
 
  }
 
  public function LinkName() {
 
    $strURL = $this->Supplier()->URL();
 
    if ($this->PageKey) {
 
      $strURL .= strtolower($this->PageKey).'/';
 
    }
 
//    return '<a href="'.KWP_CAT_REL.$strURL.'">'.$this->Name.'</a>';
 
    return '<a href="'.$strURL.'">'.$this->Name.'</a>';
 
  }
 
}
 
 
 
class clsTitles extends clsDataTable {
 
  public function __construct($iDB,$iTable='titles') {
 
    parent::__construct($iDB,$iTable);
 
  }
 
  protected function _newItem() {
 
    CallStep('clsTitles._newItem()');
 
    return new clsTitle($this);
 
  }
 
  public function GetItem_byCatNum($iCatNum) {
 
    global $objDataMgr;
 
 
 
    CallEnter('clsTitles.GetItem_byCatNum('.$iCatNum.')');
 
    assert(is_object($this->objDB));
 
    $sqlCatNum = strtoupper(str_replace('.','-',$iCatNum));
 
    $sqlCatNum = $this->objDB->SafeParam($sqlCatNum);
 
    $sql = 'SELECT * FROM v_titles WHERE CatNum="'.$sqlCatNum.'"';
 
    $objTitle = new clsTitleExt($this);
 
    // make sure _titles (part of v_titles) is up-to-date
 
    $objDataMgr->Update('_titles','GetItem_byCatNum('.$iCatNum.')');
 
    // get data from v_titles
 
    $objTitle->Query($sql);
 
    $idTitle = $objTitle->ID;
 
    if ($objTitle->RowCount()) {
 
      assert($idTitle);
 
      $sql = 'SELECT * FROM titles WHERE ID='.$idTitle;
 
      $objTitle->dontLoadBasic = true;
 
      $objTitle->Query($sql);
 
      CallExit('clsTitles.GetItem_byCatNum() -> ok');
 
      return $objTitle;
 
    } else {
 
      CallExit('clsTitles.GetItem_byCatNum() -> NULL');
 
      return NULL;
 
    }
 
  }
 
}
 
class clsTitle extends clsDataItem {
 
  public $ID;
 
  public $Name;
 
  public $CatKey;
 
  public $idDept;
 
// object cache
 
  private $objDept;
 
// options
 
  public $hideImgs;
 
 
 
  protected function LoadResults() {
 
    CallEnter('clsTitle.LoadResults()');
 
    $this->ID = $this->GetValue('ID');
 
    $this->Name = $this->GetValue('Name');
 
    $this->CatKey = $this->GetValue('CatKey');
 
    $this->idDept = $this->GetValue('ID_Dept');
 
    assert($this->ID);
 
    CallExit('clsTitle.LoadResults()');
 
  }
 
  protected function LoadResStandard() {
 
  }
 
  protected function LoadResExtended() {
 
// extended fields
 
  }
 
  public function Dept() {
 
    global $objFactory;
 
 
 
    if (is_object($this->objDept)) {
 
      return $this->objDept;
 
    } else {
 
      if ($this->idDept) {
 
        $objDept = $objFactory->Depts()->GetItem($this->idDept);
 
        $this->objDept = $objDept;
 
        assert(is_object($objDept));
 
        return $objDept;
 
      } else {
 
        return NULL;
 
      }
 
    }
 
  }
 
  public function DoPage() {
 
    global $objFactory,$objDataMgr;
 
 
 
    $idTitle = $this->ID;
 
    assert($idTitle);
 
    $objSection = new clsPageOutput();
 
// show small-size images
 
    if (!$this->hideImgs) {
 
      $objImgs = $this->ListImages('sm');
 
      if ($objImgs->HasData()) {
 
        while ($objImgs->HasData()) {
 
          $strImgTag = $objImgs->GetValue('AttrDispl');
 
          $urlRel = $objImgs->GetValue('Spec');
 
          $idImg = $objImgs->ID;
 
          $strImg = '<img src="'.KWP_IMG_MERCH.$urlRel.'"';
 
          if ($strImgTag) {
 
            $strImg .= ' title="'.$strImgTag.'"';
 
          }
 
          $strImg .= '>';
 
          $objImgBig = $objImgs->ImgForSize('big');
 
          if (is_object($objImgBig)) {
 
            if ($objImgBig->HasData()) {
 
              $strImg = $objImgBig->Href().$strImg.'</a>';
 
            }
 
          }
 
          $objSection->AddText($strImg);
 
          $objImgs->NextRow();
 
        }
 
      } else {
 
        $objSection->ShowImgUnavail();
 
      }
 
    }
 
// now list available items as table
 
//    $sql = 'SELECT * FROM _title_ittyps WHERE (ID_Title='.$idTitle.') AND cntForSale ORDER BY IFNULL(ItTypSort,"ZZ")';
 
    $sql = 'SELECT * FROM qryTitles_ItTyps_ItTyps WHERE (ID_Title='.$idTitle.') ORDER BY ItTyp_Sort IS NULL, ItTyp_Sort';
 
// echo '<!-- SQL for grouping: '.$sql.' -->';
 
    $objTypes = new clsTitleIttyp($this->Table);
 
//    $objDataMgr->Update('_title_ittyps','clsTitle.DoPage()');
 
    $objTypes->Query($sql); // list of all item types available for this title
 
    if ($objTypes->HasRows()) {
 
// $objSection->AddText('<br>Found '.$objTypes->RowCount().' item(s):');
 
      if (KF_CART_ABSOLUTE) {
 
        $urlCart = KWP_CART_ABS;
 
      } else {
 
        $urlCart = KWP_CART_REL;
 
      }
 
      $objSection->AddText('<form method=post action="'.$urlCart.'"><input type=hidden name=from value=browse-multi>');
 
 
 
      $flagDisplayTogether = false; // hard-coded for now
 
 
 
      while ($objTypes->HasData()) {
 
        $idItTyp = $objTypes->ID_ItTyp;
 
        assert($idItTyp);
 
$sql = '(ID_Title='.$idTitle.') AND (ID_ItTyp='.$idItTyp.')';
 
// $strGrpCode = $objTypes->GetValue('GrpCode');
 
// $strGrpDescr = $objTypes->GetValue('GrpDescr');
 
        $objItems = $objFactory->Items()->GetData($sql,'GrpSort,GrpDescr,ItOpt_Sort');
 
        assert($objItems->HasData());
 
        $idItType = 0;
 
//        $txtLine = '<tr class=typeHdr><td colspan=3><b>'.$objTypes->Ittyp()->Name().'</b>:</td></tr>';
 
 
 
        $txtLine = '<tr class=typeHdr><td colspan=3><b>'.$objTypes->GetValue('ItTyp_Plr').'</b>:</td></tr>';
 
 
 
        if ($flagDisplayTogether) {
 
// displaying all items in a single listing
 
          $txtBoth .= $txtLine;
 
        } else {
 
// set flags to determine which stock-status sections to show
 
          $cntInStock = $objTypes->cntInStock;
 
          $cntForSale = $objTypes->cntForSale;
 
          $cntOutStock = $cntForSale - $cntInStock;
 
// DEBUG:
 
//$objSection->AddText("<!--\n\nfor sale: $cntForSale .. in stock: $cntInStock .. outta stock: $cntOutStock\n\n-->");
 
          if ($cntInStock > 0) {
 
            $txtInStock .= $txtLine;
 
          }
 
          if ($cntOutStock > 0) {
 
            $txtOutStock .= $txtLine;
 
          }
 
        }
 
 
 
// iterate through items for this type:
 
        $strGrpLast = '';
 
        while ($objItems->HasData()) {
 
          $strGrp = $objItems->GetValue('GrpDescr');
 
          if ($strGrp != $strGrpLast) {
 
            $strGrpLast = $strGrp;
 
            $strGrpCode = $objItems->GetValue('GrpCode');
 
            $out = '<tr class="group">';
 
            $out .= '<td colspan=5> &mdash; '.$strGrp;
 
            if ($strGrpCode) {
 
              $out .= ' <font color=#666666>(<font color=#666699>'.$strGrpCode.'</font>)</font>';
 
            }
 
            $out .= '</td>';
 
            $out .= '</tr>';
 
// this should probably be a subroutine...
 
            if ($flagDisplayTogether) {
 
              $txtBoth .= $out;
 
            } else {
 
              if ($objItems->qtyInStock > 0) {
 
                $txtInStock .= $out;
 
              }
 
              if ($objItems->qtyInStock == 0) {
 
                $txtOutStock .= $out;
 
              }
 
            }
 
          }
 
          if ($objItems->isForSale) {
 
            $txtLine = $objItems->Print_TableRow();
 
 
 
            if ($flagDisplayTogether) {
 
              $txtBoth .= $txtLine;
 
            } else {
 
              if ($objItems->qtyInStock > 0) {
 
                $txtInStock .= $txtLine;
 
              }
 
              if ($objItems->qtyInStock == 0) {
 
                $txtOutStock .= $txtLine;
 
              }
 
            }
 
          }
 
          $objItems->NextRow();
 
        }
 
        $objTypes->NextRow();
 
      }
 
 
 
// DO the actual display of the accumulated text
 
 
 
      $txtTblOpen = '<table class=main><tbody>';
 
      $txtTblHdr = '<tr><th align=left>Option</th><th>Status</th><th align=right class=title-price>Price</th><th align=center class=orderQty>Order<br>Qty.</th><th><i>list<br>price</th></tr>';
 
      $txtTblFtr = '<tr><td colspan="4" align="right"><input value="Add to Cart" type="submit"></td></tr>';
 
      $txtTblShut = '</tbody></table>';
 
 
 
      if ($flagDisplayTogether) {
 
// Display in-stock and backordered items together
 
        $objSection->AddText($txtTblOpen);
 
        $objSection->AddText($txtTblHdr);
 
        $objSection->AddText($txtBoth);
 
        $objSection->AddText($txtTblFtr);
 
        $objSection->AddText($txtTblShut);
 
      } else {
 
        if ($txtInStock != '') {
 
          $txtClause = Pluralize($cntInStock,'This item is','These items are');
 
          $objSection->AddText($txtTblOpen);
 
          $objSection->AddText('<tr class=inStock><td colspan=5>'.$txtClause.' in stock:</td></tr>');
 
          $objSection->AddText($txtTblHdr);
 
          $objSection->AddText($txtInStock);
 
          $objSection->AddText($txtTblFtr);
 
          $objSection->AddText($txtTblShut);
 
        }
 
        if ($txtOutStock != '') {
 
          if ($txtInStock != '') {
 
            $objSection->AddText('<p>');
 
          }
 
          $txtClause = Pluralize($cntOutStock,'This item is','These items are');
 
          $objSection->AddText($txtTblOpen);
 
          $objSection->AddText('<tr><td colspan=5>'.$txtClause.' <a href='.'"http://wiki.vbz.net/Available_but_not_in_stock"><b>not in stock</b></a>');
 
          $txtClause = Pluralize($cntOutStock,'it','them');
 
          $objSection->AddText(', but we can (probably) <a href='.'"http://wiki.vbz.net/Shipping_Policies">get '.$txtClause.'</a>:</td></tr>');
 
          $objSection->AddText($txtTblHdr);
 
          $objSection->AddText($txtOutStock);
 
          $objSection->AddText($txtTblFtr);
 
          $objSection->AddText($txtTblShut);
 
        } /**/
 
      }
 
//      $objSection->AddText('<tr><td colspan="4" align="right"><input value="Add to Cart" type="submit"></td></tr></tbody></table></form>');
 
      $objSection->AddText('</form>');
 
    } else {
 
      $objSection->SectionHdr('This title is currently unavailable');
 
    }
 
    return $objSection->out;
 
  }
 
  public function ListImages($iSize) {
 
    global $objFactory;
 
 
 
    $objImgs = $objFactory->Images()->GetData('(ID_Title='.$this->ID.') AND (Ab_Size="'.$iSize.'")','AttrSort');
 
    return $objImgs;
 
  }
 
  public function CatNum($iSep='-') {
 
    $objDept = $this->Dept();
 
    $objSupp = $objDept->Supplier();
 
    $strDeptKey = $objDept->CatKey;
 
    $strOut = $objSupp->CatKey;
 
    if ($strDeptKey) {
 
      $strOut .= $iSep.$strDeptKey;
 
    }
 
    $strOut .= $iSep.$this->CatKey;
 
    return strtoupper($strOut);
 
  }
 
  public function Link() {
 
    $strRel = $this->CatNum('/');
 
    return '<a href="'.$strURL.'">';
 
  }
 
  public function LinkName() {
 
    return $this->Link().$this->Name.'</a>';
 
  }
 
}
 
// extended Title data from v_titles
 
class clsTitlesExt extends clsTitles {
 
  public function __construct($iDB,$iTable='v_titles') {
 
    parent::__construct($iDB,$iTable);
 
  }
 
  protected function _newItem() {
 
    CallStep('clsTitlesExt._newItem()');
 
    return new clsTitleExt($this);
 
  }
 
}
 
// this encapsulates [_titles] instead of [titles]
 
class clsTitleExt extends clsTitle {
 
  public $CatNum;
 
  public $CatWeb;
 
  public $curMinPrice;
 
  public $curMaxPrice;
 
  public $idItTyp;
 
  public $qtyInStock;
 
// action flags
 
  public $dontLoadBasic;
 
  protected function LoadResults() {
 
    CallEnter('clsTitleExt.LoadResults()');
 
    if (!$this->dontLoadBasic) {
 
      parent::LoadResults();
 
    }
 
 
 
    $this->CatNum = $this->GetValue('CatNum');
 
    $this->CatWeb = $this->GetValue('CatWeb');
 
    $this->currMinPrice = $this->GetValue('currMinPrice');
 
    $this->currMaxPrice = $this->GetValue('currMaxPrice');
 
    $this->idItTyp = $this->GetValue('ID_ItTyp');
 
    $this->qtyInStock = $this->GetValue('qtyInStock');
 
 
 
    CallExit('clsTitle.LoadResults()');
 
  }
 
  public function Link() {
 
    $out = '<a class="thumb" href="'.$this->URL().'">';
 
    return $out;
 
  }
 
  public function URL() {
 
    return KWP_CAT_REL.$this->CatWeb.'/';
 
  }
 
}
 
/* -------------------- *\
 
    TITLE/ITTYP hybrid
 
\* -------------------- */
 
class clsTitleIttyp extends clsDataItem_noID {
 
  public $ID_ItTyp;
 
  public $ID_Dept;
 
  public $cntForSale;
 
  public $cntInPrint;
 
  public $cntInStock;
 
  public $qtyInStock;
 
  public $ItTypNameSng;
 
  public $ItTypNamePlr;
 
// object cache
 
  private $objIttyp;
 
 
 
  protected function LoadResults() {
 
    CallEnter('clsTitleIttyp.LoadResults()');
 
    $idItTyp = $this->GetValue('ID_ItTyp');
 
    if ($idItTyp != $this->ID_ItTyp) {
 
      $this->ID_ItTyp = $this->GetValue('ID_ItTyp');
 
      $this->objIttyp = NULL;
 
    }
 
    $this->ID_Title = $this->GetValue('ID_Title');
 
    $this->ID_Dept = $this->GetValue('ID_Dept');
 
    $this->cntForSale = $this->GetValue('cntForSale');
 
    $this->cntInPrint = $this->GetValue('cntInPrint');
 
    $this->cntInStock = $this->GetValue('cntInStock');
 
    $this->qtyInStock = $this->GetValue('qtyInStock');
 
    $this->ItTypNameSng = $this->GetValue('ItTypNameSng');
 
    $this->ItTypNamePlr = $this->GetValue('ItTypNamePlr');
 
    if ($this->ID_ItTyp) { } else {
 
      echo 'ERROR: ID_ItTyp has no value! data = ';
 
      DumpArray($this->Row,TRUE);
 
    }
 
    CallExit('clsTitleIttyp.LoadResults()');
 
  }
 
  public function Ittyp() {
 
    global $objFactory;
 
 
 
    if (is_null($this->objIttyp)) {
 
      $this->objIttyp = $objFactory->ItTyps()->GetItem($this->ID_ItTyp);
 
    }
 
    return $this->objIttyp;
 
  }
 
}
 
/* -------------------- *\
 
    ITEM classes
 
\* -------------------- */
 
class clsItems extends clsDataTable {
 
  public function __construct($iDB,$iTable='cat_items') {
 
    global $objDataMgr;
 
    $objDataMgr->Update('cat_items','clsItems()');
 
    parent::__construct($iDB,$iTable);
 
  }
 
  protected function _newItem() {
 
    CallStep('clsTitles._newItem()');
 
    return new clsItem($this);
 
  }
 
}
 
class clsItem extends clsDataItem {
 
// NOTE: "in stock" always refers to stock for sale, not stock which has already been purchased
 
  public $CatNum;
 
  public $isForSale;
 
  public $isInPrint;
 
  public $qtyInStock;
 
  public $idTitle;
 
  public $idItTyp;
 
  public $idItOpt;
 
  public $ItOptDescr;
 
  public $PriceSell;
 
  public $PriceList;
 
// object cache
 
  private $objTitle;
 
 
 
  protected function LoadResults() {
 
    CallEnter('clsItem.LoadResults()');
 
    $this->ID = $this->GetValue('ID');
 
    $this->CatNum = $this->GetValue('CatNum');
 
    $this->isForSale = $this->GetValue('isForSale');
 
    $this->isInPrint = $this->GetValue('isInPrint');
 
    $this->qtyInStock = $this->GetValue('qtyInStock');
 
    $this->idTitle = $this->GetValue('ID_Title');
 
    $this->idItTyp = $this->GetValue('ID_ItTyp');
 
    $this->idItOpt = $this->GetValue('ID_ItOpt');
 
    $this->ItOptDescr = $this->GetValue('ItOpt_Descr');
 
    $this->PriceSell = $this->GetValue('PriceSell');
 
    $this->PriceList = $this->GetValue('PriceList');
 
    assert($this->ID);
 
    CallExit('clsItem.LoadResults()');
 
  }
 
  public function Print_TableRow() {
 
// ASSUMES: This item is ForSale, so isForSale = true and (qtyForSale>0 || isInPrint) = true
 
    $qtyInStock = $this->QtyInStock(true);
 
    if ($qtyInStock) {
 
      $strClass = 'inStock';
 
      $strStock = $qtyInStock.' in stock';
 
    } else {
 
      $strClass = 'noStock';
 
    }
 
    $out = '<tr class='.$strClass.'><!-- ID='.$this->ID.' -->';
 
    $out .= '<td>&emsp;'.$this->ItOptDescr;
 
    if ($this->isInPrint) {
 
      if ($qtyInStock) {
 
        $strStatus = $strStock.'; more available';
 
      } else {
 
        $strStatus = '<a title="explanation..." href="'.KWP_WIKI.'/Available_but_not_in_stock">available, not in stock</a>';
 
      }
 
    } else {
 
      $strStatus = '<b>'.$strStock.'</b> - <i>out of print!</i>';
 
    }
 
    $out .= '<td>'.$strStatus.'</td>';
 
    $out .= '<td>'.DataCurr($this->PriceSell).'</td>';
 
    $out .= '<td>'.'<input size=3 name="qty-'.$this->CatNum.'"></td>';
 
    if ($this->PriceList) {
 
      $out .= '<td><i>'.DataCurr($this->PriceList).'</i></td>';
 
    }
 
    $out .= '</tr>';
 
    return $out;
 
  }
 
  public function QtyInStock($iNeedQty) {
 
// DEPRECATED
 
// Originally, this field might have contained a "-1" to indicate
 
// that some items were in stock but the number hadn't been
 
// calculated. We're not doing that anymore.
 
/*
 
    if (is_null($this->qtyInStock)) {
 
      $doFigure = true;
 
    } else {
 
      if ($this->qtyInStock == -1) {
 
        if ($iNeedQty) {
 
          $doFigure = true;
 
        }
 
      }
 
    }
 
    if ($doFigure) {
 
      $this->DoFigureStock();
 
    }
 
*/
 
    return $this->qtyInStock;
 
  }
 
  public function Title() {
 
    global $objFactory;
 
 
 
    $doLoad = TRUE;
 
    if (is_object($this->objTitle)) {
 
      if ($this->objTitle == $this->idTitle) {
 
        $doLoad = FALSE;
 
      }
 
    }
 
    if ($doLoad) {
 
      $this->objTitle = $objFactory->Titles()->GetItem($this->idTitle);
 
    }
 
    return $this->objTitle;
 
  }
 
  public function StoreLink() {
 
/*
 
RETURNS: HTML suitable for use within the store
 
NOTE: Since the store doesn't yet have pages for each item,
 
this returns the store's Title link
 
*/
 
    return $this->Title-Link();
 
  }
 
  public function AdminLink() {
 
    return '<a href="item='.$this->ID.'">';
 
  }
 
/*
 
  private function DoFigureStock() {
 
    global $objFactory;
 
 
 
    $qtyInStock = $objFactory->StkItems()->QtyInStock_forItem($this->ID);
 
//    assert(!is_null($qtyInStock));
 
//    $sql = 'UPDATE cat_items SET qtyInStock='.$qtyInStock.' WHERE ID='.$this->ID;
 
    assert(is_object($this->Table));
 
    assert(is_object($this->Table->DB()));
 
    $this->Table->DB()->Exec($sql);
 
    $this->qtyInStock = $qtyInStock;
 
  }
 
*/
 
}
 
class clsItemsExt extends clsItems {
 
  public function __construct($iDB,$iTable='v_items') {
 
    parent::__construct($iDB,$iTable);
 
  }
 
  protected function _newItem() {
 
    CallStep('clsItemsExt._newItem()');
 
    return new clsItemExt($this);
 
  }
 
}
 
class clsItemExt extends clsItem {
 
  public $OptSort;
 
 
 
  protected function LoadResults() {
 
    CallEnter('clsItemExt.LoadResults()');
 
    parent::LoadResults();
 
 
 
    $this->OptSort = $this->GetValue('OptSort');
 
    $this->CatWeb = $this->GetValue('CatWeb');
 
    $this->currMinPrice = $this->GetValue('currMinPrice');
 
    $this->currMaxPrice = $this->GetValue('currMaxPrice');
 
    $this->idItTyp = $this->GetValue('ID_ItTyp');
 
    $this->qtyInStock = $this->GetValue('qtyInStock');
 
 
 
    CallExit('clsItemExt.LoadResults()');
 
  }
 
}
 
 
 
/* -------------------- *\
 
    ITEM TYPE classes
 
\* -------------------- */
 
class clsItTyps extends clsDataTable {
 
  public function __construct($iDB) {
 
    global $objDataMgr;
 
    $objDataMgr->Update('cat_ittyps','clsItems()');
 
    parent::__construct($iDB,'cat_ittyps');
 
  }
 
  protected function _newItem() {
 
    CallStep('clsItTyps._newItem()');
 
    return new clsItTyp($this);
 
  }
 
}
 
class clsItTyp extends clsDataItem {
 
  public $ID;
 
  public $NameSng;
 
  public $NamePlr;
 
//  public $cntInPrint;
 
//  public $qtyInStock;
 
//  public $usePrefix;
 
 
 
  protected function LoadResults() {
 
    CallEnter('clsItTyp.LoadResults()');
 
/*
 
    if ($this->usePrefix) {
 
      $this->ID = $this->GetValue('ID_ItTyp');
 
      $this->NameSng = $this->GetValue('ItTypNameSng');
 
      $this->NamePlr = $this->GetValue('ItTypNamePlr');
 
      $this->cntInPrint = $this->GetValue('cntInPrint');
 
    } else {
 
/**/
 
      $this->ID = $this->GetValue('ID');
 
      $this->NameSng = $this->GetValue('NameSng');
 
      $this->NamePlr = $this->GetValue('NamePlr');
 
//    }
 
    assert($this->ID);
 
    CallExit('clsItTyp.LoadResults()');
 
  }
 
  public function Name($iCount=-1) {
 
    if ($iCount == -1) {
 
      $iCount = $this->cntInPrint;
 
    }
 
    if ($iCount == 1) {
 
      return $this->NameSng;
 
    } else {
 
      return $this->NamePlr;
 
    }
 
  }
 
}
 
/* -------------------- *\
 
    STOCK ITEM classes
 
\* -------------------- */
 
class clsStkItems extends clsDataTable {
 
  public function __construct($iDB) {
 
    parent::__construct($iDB,'stk_items');
 
  }
 
  public function QtyInStock_forItem($iItemID) {
 
    $sql = 'SELECT SUM(s.Qty) AS Qty FROM stk_items AS s LEFT JOIN stk_bins AS sb ON s.ID_Bin=sb.ID WHERE (s.ID_Item='.$iItemID.') AND (s.WhenRemoved IS NULL) AND (sb.WhenVoided IS NULL) AND (sb.isForSale) GROUP BY s.ID_Item';
 
// ** TO DO: maybe this can use a view or one of the calculated tables now?
 
 
 
    $objStock = new clsDataItem($this);
 
    $objStock->Query($sql);
 
    if ($objStock->HasData()) {
 
      if ($objStock->RowCount()) {
 
        assert($objStock->RowCount() == 1);
 
        return $objStock->GetValue('Qty');
 
      }
 
    }
 
  }
 
/*
 
  protected function _newItem() {
 
    CallStep('clsStkItems._newItem()');
 
    return new clsStkItem($this);
 
  }
 
*/
 
}
 
/* -------------------- *\
 
    IMAGE classes
 
\* -------------------- */
 
class clsImages extends clsDataTable {
 
  public function __construct($iDB) {
 
    parent::__construct($iDB,'cat_images');
 
  }
 
  protected function _newItem() {
 
    CallStep('clsImages._newItem()');
 
    return new clsImage($this);
 
  }
 
}
 
class clsImage extends clsDataItem {
 
  public $idTitle;
 
  public $Ab_Size;
 
  public $AttrFldr;
 
  public $Spec;
 
// object cache
 
  private $objTitle;
 
 
 
  protected function LoadResults() {
 
    CallEnter('clsImage.LoadResults()');
 
    $this->ID = $this->GetValue('ID');
 
    $this->idTitle = $this->GetValue('ID_Title');
 
    $this->AbSize = $this->GetValue('Ab_Size');
 
    $this->AttrFldr = $this->GetValue('AttrFldr');
 
    $this->AttrDispl = $this->GetValue('AttrDispl');
 
    $this->Spec = $this->GetValue('Spec');
 
    assert($this->ID);
 
    CallExit('clsImage.LoadResults()');
 
  }
 
  public function ImgForSize($iSize) {
 
// ACTION: Get the image with the same title and attribute but with the given size
 
    if ($this->AttrFldr) {
 
      $sqlAttr = '="'.$this->AttrFldr.'"';
 
    } else {
 
      $sqlAttr = ' IS NULL';
 
    }
 
    $sql = 'SELECT * FROM cat_images WHERE (ID_Title='.$this->idTitle.') AND (AttrFldr'.$sqlAttr.') AND (Ab_Size="'.$iSize.'");';
 
    $objImgOut = new clsImage($this->Table);
 
    $objImgOut->Query($sql);
 
    return $objImgOut;
 
  }
 
  public function Title() {
 
    global $objFactory;
 
 
 
    if (!is_object($this->objTitle)) {
 
      $objTitleTbl = $objFactory->TitlesExt();
 
      $this->objTitle = $objTitleTbl->GetItem($this->idTitle);
 
    }
 
    return $this->objTitle;
 
  }
 
  public function DoPage() {
 
    global $objFactory;
 
 
 
    $objTitle = $this->Title();
 
    $strCatNum = $objTitle->CatNum;
 
    $strTitle = $objTitle->Name;
 
    $htmlTitle = KS_STORE_NAME.' - '.$strCatNum.' &ldquo;'.$strTitle.'&rdquo;';
 
    echo '<html><head><title>'.$htmlTitle.'</title></head>';
 
    echo '<body
 
bgcolor=000044
 
TEXT=CCFFFF
 
LINK=33FF33
 
VLINK=33CCFF
 
ALINK=FFCC00
 
TOPMARGIN=0
 
LEFTMARGIN=0
 
MARGINWIDTH=0
 
MARGINHEIGHT=0
 
>';
 
    echo '<center>';
 
    echo '<big>'.$strTitle.'</big><br>';
 
 
 
// show list of available image sizes (except th and sm)
 
    $objImgs = $this->ListImages_sameAttr();
 
    if ($objImgs->HasData()) {
 
      $strImgCount = 0;
 
      while ($objImgs->HasData()) {
 
        $strImgType = $objImgs->AbSize;
 
        if (($strImgType != 'th') && ($strImgType != 'sm')) {
 
          $strImgCount++;
 
          $strImgTag = $imgSize[$strImgType];
 
          if ($strOut) {
 
            $strOut .= ' .. ';
 
          }
 
          $strOut .= $strImgTag;
 
        }
 
        $objImgs->NextRow();
 
      }
 
      if ($strImgCount > 1) {
 
        echo $strOut.'<br>';
 
      }
 
    }
 
// show list of available images for this title at this size
 
    $objImgs = $this->ListImages_sameSize();
 
    if ($objImgs->HasData()) {
 
      $strImgCount = 0;
 
      $strOut .= '';
 
      if ($objImgs->HasData()) {
 
        while ($objImgs->HasData()) {
 
          $strImgFldr = $objImgs->AttrFldr;
 
          $strImgDescr = $objImgs->AttrDispl;
 
          $strImgCount++;
 
          if ($strOut) {
 
            $strOut .= ' .. ';
 
          }
 
          if ($objImgs->ID == $this->ID) {
 
            $strOut .= '<b>'.$strImgDescr.'</b>';
 
          } else {
 
            $strOut .= $objImgs->Href(TRUE).$strImgDescr.'</a>';
 
          }
 
          $objImgs->NextRow();
 
        }
 
        if ($strImgCount > 1) {
 
          echo $strOut.'<br>';
 
        }
 
      }
 
    }
 
    echo $objTitle->Link().'ordering page</a><br>';
 
    echo $this->ImgSrc();
 
    echo '</body></html>';
 
  }
 
  public function ListImages_sameAttr() {
 
    if ($this->AttrFldr) {
 
      $sqlFilt = '(ID_Title='.$this->idTitle.') AND (AttrFldr="'.$this->AttrFldr.'")';
 
    } else {
 
      $sqlFilt = '(ID_Title='.$this->idTitle.')';
 
    }
 
    $objImgOut = $this->Table->GetData($sqlFilt);
 
    return $objImgOut;
 
  }
 
  public function ListImages_sameSize() {
 
    $sqlFilt = '(ID_Title='.$this->idTitle.') AND (Ab_Size="'.$this->AbSize.'")';
 
    $objImgOut = $this->Table->GetData($sqlFilt);
 
    return $objImgOut;
 
  }
 
  public function Href($iAbs=false) {
 
    if ($iAbs) {
 
      $strFldr = $this->Title()->URL();
 
    }
 
    $strFldr .= $this->AttrFldr;
 
    if ($strFldr) {
 
      $strFldr .= '-';
 
    }
 
    $strFldr .= $this->AbSize;
 
    return '<a href="'.$strFldr.'/">';
 
  }
 
  public function ImgSrc() {
 
    return '<img src="'.KWP_IMG_MERCH.$this->Spec.'">';
 
  }
 
}
 
 
 
/* ------------------ *\
 
    CATALOG BROWSING
 
\* ------------------ */
 
class clsTopics extends clsDataTable {
 
  public function __construct($iDB) {
 
    parent::__construct($iDB,'brs_topics');
 
  }
 
  protected function _newItem() {
 
    CallStep('clsTopics._newItem()');
 
    return new clsTopic($this);
 
  }
 
  public function DoIndex() {
 
    global $objFactory,$objDataMgr;
 
 
 
    CallEnter('clsTopics.DoIndex()');
 
    $objSection = new clsPageOutput();
 
 
 
    $objTopics = $this->GetData('ID_Parent IS NULL','Sort,Name,NameTree');
 
    while ($objTopics->HasData()) {
 
      if ($isFirst) {
 
        $isFirst = false;
 
        $objSection->SectionHdr('Root Topics');
 
      } else {
 
        $objSection->AddText($objTopics->Name.'<br>');
 
      }
 
      $objTopics->NextRow();
 
    }
 
 
 
    CallExit('clsTopic.DoIndex()');
 
    return $objSection->out;
 
  }
 
}
 
class clsTopic extends clsDataItem {
 
  public $ID_Parent;
 
  public $Name;
 
  public $NameTree;
 
  public $NameFull;
 
  public $Variants;
 
  public $Mispeled;
 
 
 
  protected function LoadResults() {
 
    CallEnter('clsTopic.LoadResults()');
 
    $this->ID = $this->GetValue('ID');
 
    $this->ID_Parent = $this->GetValue('ID_Parent');
 
    $this->Name = $this->GetValue('Name');
 
    $this->NameTree = $this->GetValue('NameTree');
 
    $this->NameFull = $this->GetValue('NameFull');
 
    $this->Variants = $this->GetValue('Variants');
 
    $this->Mispeled = $this->GetValue('Mispeled');
 
    assert($this->ID);
 
    CallExit('clsTopic.LoadResults()');
 
  }
 
 
 
  public function DoPage() {
 
    global $objFactory,$objDataMgr;
 
 
 
    CallEnter('clsTopic.DoPage()');
 
    assert($this->ID);
 
    $objSection = new clsPageOutput();
 
 
 
    $objTbl = $objFactory->Table_noID('brs_titles_x_topics');
 
    $objTitles = $objTbl->GetData('ID_Topic='.$this->ID);
 
    while ($objTitles->HasData()) {
 
      if ($isFirst) {
 
        $isFirst = false;
 
        $objSection->SectionHdr('Titles');
 
      } else {
 
        $objSection->AddText($objTitles->Name.'<br>');
 
      }
 
      $objTitles->NextRow();
 
    }
 
 
 
    CallExit('clsTopic.DoPage()');
 
    return $out;
 
  }
 
  public function WebName() {
 
    return sprintf(KS_FMT_TOPICID,$this->ID);
 
  }
 
}
 
  
/* ==================== *\
+
// process the request
    UTILITY FUNCTIONS
+
$objPage = new clsPageCat();
\* ==================== */
+
$objPage->GetQuery();
 +
$objPage->DoRequest();
  
function DataCents($iCents,$iPfx='$') {
+
if (!$didPage) {
  $out = $iPfx.sprintf("%01.2f",$iCents/100);
+
//  $objPage->Init('','Unknown page','something is messed up','browse','Houston, we have a problem...');
  return $out;
+
//  $objPage->DoError();
 
}
 
}
function DataCurr($iCurr,$iPfx='$') {
+
if (KDO_DEBUG) {
  $out = $iPfx.sprintf("%01.2f",$iCurr);
+
print "DEBUG:<p>".$debug;
  return $out;
 
 
}
 
}
function DataDate($iDate) {
+
</php>
    if (is_string($iDate)) {
 
      $objDate = new DateTime($iDate);
 
//  if ($iDate == 0) {
 
//    $out = '';
 
//  } else {
 
//    $out = date('Y-m-d',$iDate);
 
      $out = $objDate->format('Y-m-d');
 
    } else {
 
      $out = '';
 
    }
 
  return $out;
 
}</php>
 

Revision as of 14:23, 7 March 2009

About

  • Purpose: Classes for displaying different types of catalog display pages
  • History:
    • 2009-03-07 Transcribed from working code at vbz.net
  • To Do:
    • should be split up into auto-loadable class files, e.g. vbz.title.php, vbz.dept.php, etc.
    • "clsFactory" should be eliminated in favor of static functions for each class

Code - store.php

<php><?php

  1. PURPOSE: vbz page generator
  2. VERSION: /topics/

// CONSTANTS // -- KF = boolean flag // -- KS = string // -- KWP = web path (URL including protocol) // -- KFP = file path // -- KRP = relative path $fltStart = microtime(true); // debugging activation define('KDO_DEBUG',0); define('KDO_DEBUG_STACK',0); // debugging options define('KDO_DEBUG_HTML',1); define('KDO_DEBUG_IMMED',1); define('KDO_DEBUG_DARK',0); define('KF_USE_WIKI',true); // 2008-06-07 force absolute URL for cart until we fix the domain-cookie problem define('KF_CART_ABSOLUTE',true); /*

GET CONNECTED TO LIBRARIES
  • /

require('../local.php'); require('site.php'); $strLibs .= ':'.KFP_WIKI.':'.KFP_WIKI.'includes/'; ini_set('include_path',$strLibs); require('store.php');

// PROCESS PAGE REQUEST $page_uri = $_ENV['REQUEST_URI']; // prepare data objects InitData(KS_DB_VBZCART); //$objFactory = new clsFactory_Carts($objFactory->DB()); // this is an ugly kluge // clsFactory can be done away with when the data.php and carts.php are rewritten to use a single class for each type // - static methods for the whole-table functions, regular methods for individual rows

// process the request $objPage = new clsPageCat(); $objPage->GetQuery(); $objPage->DoRequest();

if (!$didPage) { // $objPage->Init(,'Unknown page','something is messed up','browse','Houston, we have a problem...'); // $objPage->DoError(); } if (KDO_DEBUG) {

print "DEBUG:

".$debug; } </php>