VbzCart/docs/archive/code/files/store.php: Difference between revisions

From Woozle Writes Code
< VbzCart‎ | docs‎ | archive‎ | code‎ | files
Jump to navigation Jump to search
imported>Woozle
(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...)
 
imported>Woozle
(→‎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>