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
(→‎Code - store.php: oops, wrong code (non-working dev code); this is the right one)
imported>Woozle
(basically working... totally different: is an actual class library now)
Line 8: Line 8:
==Code - store.php==
==Code - store.php==
<php><?php
<php><?php
# PURPOSE: vbz page generator
/*
# VERSION: /topics/
FILE: store.php
PURPOSE: vbz class library - should eventually be subdivided
HISTORY:
  2009-07-11 (Wzl) Lots of cleanup; added types and methods needed for shopping cart page
*/
//define('kfpHostAcctRoot','/hsphere/local/home/hypertwi/');
//define('kfpMediaWiki',kfpHostAcctRoot.'wiki.vbz.net/');
define('kEmbeddedPagePrefix','embed:');
 
if (defined( '__DIR__' )) {
  $fpThis = __DIR__;
} else {
  $fpThis = dirname(__FILE__);
}
if (!defined('LIBMGR')) {
    require('libmgr.php');
}
clsLibMgr::Add('datamgr',$fpThis.'/datamgr.php');
clsLibMgr::Load('datamgr');
 
define('EN_PGTYPE_NOTFND',-1); // requested item (supp/dept/title) not found
define('EN_PGTYPE_HOME',1); // catalog home page
define('EN_PGTYPE_SUPP',2); // supplier page
define('EN_PGTYPE_DEPT',3); // department page, or possibly title for keyless dept
define('EN_PGTYPE_TITLE',4); // title page
// table names
// - caching
define('ksTbl_cache_tables','data_tables');
define('ksTbl_cache_procs','data_procs');
define('ksTbl_cache_flow','data_flow');
define('ksTbl_cache_log','data_log');
// - stock
define('ksTbl_stock_places','stk_places');
define('ksTbl_stock_bins','stk_bins');
define('ksQry_stock_bins_wInfo','qryStk_Bins_w_info');
define('ksTbl_stock_items','stk_items');
define('ksTbl_stock_hist_items','stk_history');
define('ksTbl_stock_hist_bins','stk_bin_history');
 
$vbgImgSize = array(
    'th' => 'thumbnail',
    'sm' => 'small',
    'big' => 'large',
    'huge' => 'huge',
    'zoom' => 'detail');
 
// shipping charge adjustment factors by destination zone:
$listShipListDesc['US'] = 'United States';
$listShipListDesc['CA'] = 'Canada';
$listShipListDesc['INT'] = 'International';
$listPkgFactors['US'] = 1.0;
$listItmFactors['US'] = 1.0;
$listPkgFactors['CA'] = 2.0;
$listItmFactors['CA'] = 2.0;
$listPkgFactors['INT'] = 4.0;
$listItmFactors['INT'] = 4.0;
// The above is just until we have something more exact and dynamic
 
$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) {
  $fpTools = $fwpAbsTools;
  $fpPages = $fwpAbsPages;
}
*/
$fwpLogo = $fpTools.'/img/logos/v/';
 
class clsVbzData extends clsDatabase {
  private $objPages;
 
  public function __construct($iSpec) {
    global $objDataMgr;
 
    parent::__construct($iSpec);
    $objDataMgr = new clsDataMgr($this,ksTbl_cache_tables,ksTbl_cache_procs,ksTbl_cache_flow,ksTbl_cache_log);
    $this->Open();
  }
// generic object-creation function
  protected function Make($iName) {
    if (!isset($this->$iName)) {
      $this->$iName = new $iName($this);
    }
    return $this->$iName;
  }
// table-specific functions
  public function Pages() {
    return $this->Make('clsCatPages');
  }
  public function Suppliers() {
    return $this->Make('clsSuppliers');
  }
  public function Depts() {
    return $this->Make('clsDepts');
  }
  public function Titles() {
    return $this->Make('clsTitles');
  }
  public function TitlesExt() {
    return $this->Make('clsTitlesExt');
  }
  public function Items() {
    return $this->Make('clsItems');
  }
  public function Items_Stock() {
    return $this->Make('clsItems_Stock');
  }
  public function ItTyps() {
    return $this->Make('clsItTyps');
  }
  public function ItOpts() {
    return $this->Make('clsItOpts');
  }
  public function ShipCosts() {
    return $this->Make('clsShipCosts');
  }
  public function Images() {
    return $this->Make('clsImages');
  }
  public function StkItems() {
    return $this->Make('clsStkItems');
  }
  public function Topics() {
    return $this->Make('clsTopics');
  }
  public function Events() {
    return $this->Make('clsEvents');
  }
  public function LogEvent($iWhere,$iParams,$iDescr,$iCode,$iIsError,$iIsSevere) {
    return $this->Events()->LogEvent($iWhere,$iParams,$iDescr,$iCode,$iIsError,$iIsSevere);
  }
// Page output routines
  public function SectionHdr($iTitle) {
    $out = '<p class=main><big>'.$iTitle.'</big></p>';
    return $out;
  }
  public function ShowTitles($iHdrText,$iList,$objNoImgSect) {
    $cntImgs = 0;
    $outImgs = '';
    foreach ($iList as $i => $objTitleData) {
      $objTitle = $this->Titles()->GetItem($objTitleData->ID);
      $objImgs = $objTitle->ListImages('th');
      $currMinPrice = $objTitleData->currMinPrice;
      $currMaxPrice = $objTitleData->currMaxPrice;
      $strPrice = DataCurr($currMinPrice);
      if ($currMinPrice != $currMaxPrice) {
        $strPrice .= '-'.DataCurr($currMaxPrice);
      }
      assert('is_resource($objImgs->Res)');
      if ($objImgs->RowCount()) {
        $cntImgs++;
$strCatNum = $objTitleData->CatNum;
        $strTitleTag = '&quot;'.$objTitle->Name.'&quot; ('.$strCatNum.')';
        $strTitleLink = $objTitle->Link();
        while ($objImgs->NextRow()) {
          $strImgTag = $strTitleTag.' - '.$strPrice;
  $qtyStk = $objTitleData->qtyForSale;
          if ($qtyStk) {
            $strImgTag .= ' - '.$qtyStk.' in stock';
          }
          $outImgs .= $strTitleLink.'<img class="thumb" src="'.KWP_IMG_MERCH.'/'.$objImgs->Spec.'" title="'.$strImgTag.'"></a>';
        }
      } 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>'.$objTitleData->CatNum.'</b>');
        $objNoImgSect->ColAdd($objTitle->Name);
        $objNoImgSect->ColAdd($strPrice);
        $objNoImgSect->ColAdd('<b>[</b>'.$objTitle->Link().'order</a><b>]</b>');
        $qtyStk = $objTitleData->qtyForSale;
        if ($qtyStk) {
          $strStock = '<b>'.$qtyStk.'</b> in stock';
          $objNoImgSect->ColAdd($strStock);
          if ($objTitleData->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();
      }
    }
    $out = '';
    if ($cntImgs) {
      $out .= $this->SectionHdr($iHdrText);
      $out .= $outImgs;
    }
    return $out;
  }
}
 
class clsList {
  public $List;
 
  public function Add($iName, $iValue=NULL) {
    $objItem = new clsListItem($iName,$iValue);
    $this->List[] = $objItem;
    return $objItem;
  }
  public function Output($iPfx, $iSep, $iSfx) {
    $out = NULL;
    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) {
    $this->name = $iName;
    $this->value = $iValue;
  }
}
 
/* ===================
  CLASS: clsPage
  PURPOSE: Handles display of different page types
*/
class clsPage extends clsVbzData {
// query
  protected $strReq; // requested page
// page definition
  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 $strWikiPg; // name of wiki page to embed, if any (blank = suppress embedding)
  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;
 
  public function __construct($iSpec) {
    parent::__construct($iSpec);
    $this->lstTop = new clsList();
  }
 
  public function GetQuery() {
// ACTION: Retrieves request from URL and parses it
    if (isset($_SERVER['PATH_INFO'])) {
$strReq = $_SERVER['PATH_INFO'];
    } else {
$strReq = '';
    }
    $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->strWikiPg = '';
    $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;
 
    echo '<div style="clear: both;" align=right>';
    $this->DoSepBar();
    echo '<table width=100%><tr><td align=right><small><i>';
    $fltExecTime = microtime(true)-$fltStart;
    $dat = getrusage();
    $fltUserTime = $dat["ru_utime.tv_usec"]/1000000;
    $strServer = $_SERVER['SERVER_SOFTWARE'];
    echo $strServer.' .. ';
    echo 'PHP '.phpversion().' .. Generated in <b>'.$fltUserTime.'</b> seconds (script execution '.$fltExecTime.' sec.) .. ';
    $strWikiPg = $this->strWikiPg;
    if ($strWikiPg) {
echo 'wiki: <a href="'.KWP_WIKI.kEmbeddedPagePrefix.$this->strWikiPg.'">'.$strWikiPg.'</a> .. ';
    }
    echo date('Y-m-d H:i:s');
    echo '</i></small></td></tr></table>';
    echo '</div></body></html>';
    $didPage = true;
  }
  private function DoWikiContent() {
# WIKI CONTENTS
# $txtPage = GetEmbedPage('cat');
    if (KF_USE_WIKI) {
      $txtWiki = GetWikiPage($this->strWikiPg);
      if ($txtWiki) {
        if (strpos($txtWiki,'__NOIMG__') != -1) {
          $txtWiki = str_replace('__NOIMG__','',$txtWiki);
          $this->hideImgs = true;
        }
      }
      if ($txtWiki) {
//        print '<span class=main>'.$txtPage.'</span><br>';
        echo '<table class=main><tr><td>'.$txtWiki.'</td></tr></table>';
      }
    }
  }
  protected function DoSidebar() {
    global $fpTools,$objDataMgr;
 
// TO DO: these should be pulled from the [stats] table
if ($objDataMgr->dtNewest) {
    $timeSidebarBuild=$objDataMgr->dtNewest;
} else {
    $timeSidebarBuild = NULL;
}
$statsQtyTitlesAvail = 2245;
$statsQtyStockPieces = 1395;
$statsQtyStockItems = 753;
$statsQtyArtists = 136;
$statsQtyTopics = 1048;
//---------
 
    echo '<table class=border align=left cellpadding=3 bgcolor="#000000"><tr><td>';
?>
<table class=sidebar bgcolor="#ffffff" cellpadding=5><tr><td>
<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
 
    echo '<br> ...<a href="/stock/" title="'.$statsQtyStockPieces.' pieces, '.$statsQtyStockItems.'. items"><b>S</b>tock</a> ('.$statsQtyStockPieces.')';
    echo '<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.')';
    echo '<p>';
    echo '[[ <a href="'.KWP_WIKI.'" title="vbz wiki homepage"><b>wiki</b></a> ]]<br>';
    echo '-- [[ <a href="'.KWP_WIKI.'help" title="help-related pages on the wiki"><b>Help</b></a> ]]<br>';
    echo '-- [[ <a href="'.KWP_WIKI.'about" title="about vbz.net (probably more than you want to know)"><b>About</b></a> ]]<br>';
    echo '-- [[ <a href="'.KWP_WIKI.'contact" title="contact vbz.net (several different methods)"><b>Contact</b></a> ]]<br>';
    echo '<p>';
    echo '<a href="/email/" title="web form for sending us email">email form</a><br>';
    echo '<a href="/cart/" title="your shopping cart">shopping cart</a><p>';
# == END Sidebar B ==
/*
    print '<table class=border 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>';
*/
    echo '</span></td></tr></table></td></tr></table>';
  }
  private function DoSepBar() {
    global $fpTools;
 
    echo '<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;
 
    echo $this->ToolbarItem($fpPages.'/','home',KS_STORE_NAME.' home page','home page');
    echo $this->ToolbarItem($fpPages.'/search/','search','search page','search page');
    echo $this->ToolbarItem($fwpCart,'cart','shopping cart','shopping cart');
    echo $this->ToolbarItem(KWP_WIKI.'help','help','help!','help');
  }
// -- HEADER
  protected function DoHeader() {
    global $fpTools, $fwpLogo;
 
    $strWikiPg = $this->strWikiPg;
    $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>';
    echo $htmlHead;
?><body
bgcolor=000044
TEXT=CCFFFF
LINK=33FF33
VLINK=33CCFF
ALINK=FFCC00
TOPMARGIN=0
LEFTMARGIN=0
MARGINWIDTH=0
MARGINHEIGHT=0
>
<?
// begin content header
    echo '<table width="100%" class=border cellpadding=5><tr><td>';
    echo '<table width="100%" class=hdr cellpadding=2><tr>';
// === LEFT HEADER: Title ===
    echo '<td>';
    echo '<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) {
      echo '<span class=pretitle><b><a href="/">'.KS_STORE_NAME.'</a></b>: '.$this->strTitleContext.'</span><br>';
    }
    echo '<span class=page-title>'.$this->strTitle.'</span></td>';
// === END LEFT HEADER ===
 
// === RIGHT HEADER: nav icons ===
    echo '<td align=right>';
    $this->DoToolbar();
    echo '</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() {
    $strReq = $this->strReq;
    $this->objCatPage = $this->Pages()->GetItem_byKey($strReq);
 
//print 'REQ='.$strReq.' ABBR='.$this->objCatPage->AB;
  }
 
  public function DoRequest() {
    $doRawHTML = FALSE;
    $this->strSheet = 'browse'; // default
    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.$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() {
//    $objSuppTbl = VbzClasses::Suppliers();
//    $this->Setup('cat','Catalog Home','Catalog main page','browse','hello and welcome to the...');
    $this->DoCatIndicia();
    $this->strWikiPg = 'cat';
    $this->strTitle = 'Catalog Home';
    $this->strName = 'Catalog main page';
    $this->strTitleContext = 'hello and welcome to the...';
    $this->AddText($this->Suppliers()->DoHomePage());
  }
  private function DoCatSupp() {
    CallEnter($this,__LINE__,'clsPage.DoCatSupp()');
 
//    $objSuppTbl = VbzClasses::Suppliers();
    $objSuppTbl = $this->Suppliers();
    $objSupp = $objSuppTbl->GetItem($this->objCatPage->ID_Row);
    assert('is_object($objSupp)');
    $strSuppName = $objSupp->Name;
 
    $this->DoSuppIndicia($objSupp);
    $this->strWikiPg = 'supp:'.strtoupper($objSupp->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() {
    CallEnter($this,__LINE__,'clsPage.DoCatDept()');
 
//    $objDeptTbl = VbzClasses::Depts();
    $objDeptTbl = $this->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->strWikiPg = 'dept:'.strtoupper($objDept->PageKey);
 
    $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() {
    CallEnter($this,__LINE__,'clsPage.DoCatTitle()');
 
    $strPageKey = $this->objCatPage->Path;
//    $objTitleTbl = VbzClasses::Titles();
    $objTitleTbl = $this->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->strWikiPg = 'title:'.$objTitle->CatNum();
//print 'ABBR='.$this->strAbbr;
    $this->strTitle = $strTitleName;
    $this->strName = $strPageKey.' "'.$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() {
    CallEnter($this,__LINE__,'clsPage.DoCatImage()');
//    $objImageTbl = VbzClasses::Images();
    $objImageTbl = $this->Images();
    $objImage = $objImageTbl->GetItem($this->objCatPage->ID_Row);
    $objImage->DoPage();
    CallExit('clsPage.DoCatImage()');
  }
}
 
class clsPageTopic extends clsPage {
  public function DoRequest() {
    $this->strSheet = 'browse'; // default
    $strReq = $this->strReq;
    if (is_numeric($strReq)) {
      $idTopic = (int)$strReq;
      $objTopic = $this->Topics()->GetItem($idTopic);
      $this->strWikiPg = 'topic.'.$objTopic->WebName();
      $this->strTitle = 'Topic Index';
      $this->strName = 'catalog topic index';
      $this->AddText($objTopic->DoPage());
    } else {
      $this->strWikiPg = 'topics';
      $this->strTitle = 'Topic Index';
      $this->strName = 'catalog topic index';
      $this->AddText($this->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 class=content>';
      $this->inTbl++;
    }
  }
  function RowStart($iClass='') {
    if ($iClass) {
      $this->out .= '<tr class="'.$iClass.'">';
    } 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 ShowImgUnavail() {
    $this->out .= '<table class=border 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 clsVbzTable extends clsTable {
  protected function Touch($iCaller) {
    global $objDataMgr;
 
    $objDataMgr->Update_byName($this->Name(),$iCaller);
  }
}
 
class clsCatPages extends clsVbzTable {
  public function __construct($iDB) {
    parent::__construct($iDB);
      $this->Name('cat_pages');
      $this->KeyName('AB');
      $this->ClassSng('clsCatPage');
  }
/*
  protected function _newItem() {
    return new clsCatPage($this);
  }
*/
  public function GetItem_byKey($iKey) {
 
    CallEnter($this,__LINE__,__CLASS__.'.GetItem_byKey('.$iKey.')');
    $strKey = trim($iKey,'/');
    $strKey = str_replace('-','/',$strKey);
    $sqlCatKey = $this->objDB->SafeParam($strKey);
    $this->Touch('clsCatPages.GetItem_byKey('.$iKey.')');
    $objItem = $this->GetData('Path="'.$sqlCatKey.'"');
//    $objRec = $this->objDB->Query($sql);
    assert('is_object($objItem)');
    if ($objItem->NextRow()) {
      DumpValue('objItem NumRows',$objItem->hasRows());
      CallExit('clsCatPages.GetItem_byKey('.$iKey.') -> Page '.$objItem->AB);
    } else {
      CallExit('clsCatPages.GetItem_byKey('.$iKey.') -> no data');
    }
    return $objItem;
  }
}
 
class clsCatPage extends clsDataSet {
// == STATIC SECTION
//  const cksTblName = 'cat_pages';
//  const cksIDName = 'AB';
 
}
 
class clsSuppliers extends clsVbzTable {
// ==== STATIC SECTION
 
// ==== DYNAMIC SECTION
  public function __construct($iDB) {
    parent::__construct($iDB);
      $this->Name('cat_supp');
      $this->KeyName('ID');
      $this->ClassSng('clsSupplier');
  }
  public function GetItem_byKey($iKey) {
    CallEnter($this,__LINE__,__CLASS__.'.GetItem_byKey('.$iKey.')');
    $sqlCatKey = $this->objDB->SafeParam($iKey);
    $objItem = $this->GetData('CatKey="'.$sqlCatKey.'"');
    CallExit(__CLASS__.'.GetItem_byKey('.$iKey.') -> new supplier');
    return $objItem;
  }
  public function DoHomePage() {
    global $objDataMgr;
 
    $objDataMgr->Update_byName('_supplier_ittyps','clsSuppliers.DoHomePage()');
    $sql = 'SELECT * FROM _supplier_ittyps ORDER BY Name, ItemCount DESC';
    $objRec = $this->objDB->DataSet($sql);
    $out = '';
    if ($objRec->hasRows()) {
      $objTbl = new clsPageOutput;
      $objTbl->StartTable('Suppliers');
      $strKeyLast = $outCell = '';
      while ($objRec->NextRow()) {
        $strKey = $objRec->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->Name.'</a></b>');
          $isFirst = true;
        }
        if ($isFirst) {
          $isFirst = false;
        } else {
          $outCell .= ', ';
        }
$strItType = $objRec->ItemType;
if ($strItType == '') {
    $strItType = '?id'.$objRec->ID;
}
        $outCell .= ' <b>'.$objRec->ItemCount.'</b> '.$strItType;
      }
      $objTbl->ColAdd($outCell);
      $objTbl->RowStop();
      $out .= $objTbl->EndTable();
    }
    return $out;
  }
}
 
class clsSupplier extends clsDataSet {
  public function DoPage() {
    global $objDataMgr;
 
    CallEnter($this,__LINE__,'clsSupplier.DoPage()');
    $out = '';
    assert('$this->ID');
// first, check how many departments supplier has:
    $objDeptTbl = $this->objDB->Depts();
    $objDepts = $objDeptTbl->GetData('isActive AND (ID_Supplier='.$this->ID.')','clsDept','Sort');
 
    if ($objDepts->RowCount() == 1) {
// if there's only one department, display that instead of a department listing
      $out = $objDepts->DoPage();
    } else {
      $objDataMgr->Update_byName('_supplier_ittyps','clsSupplier.DoPage() for '.$this->CatKey);
      $sql = 'SELECT * FROM _supplier_ittyps WHERE ID='.$this->ID.' ORDER BY Name, ItemCount DESC';
      $objItTyps = $this->objDB->DataSet($sql,'clsItTyp');
      $isFirst = true;
      $out .= '<span class=catalog-summary>';
      while ($objItTyps->NextRow()) {
        if ($isFirst) {
          $isFirst = false;
        } else {
          $out .= ', ';
        }
        $out .= ' <b>'.$objItTyps->ItemCount.'</b> '.$objItTyps->ItemType;
      }
      $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 clsVbzTable {
  public function __construct($iDB) {
    parent::__construct($iDB);
      $this->Name('cat_depts');
      $this->KeyName('ID');
      $this->ClassSng('clsDept');
  }
  protected function _newItem() {
    CallStep('clsDepts._newItem()');
    return new clsDept($this);
  }
  public function DoListing_forSupp($iSuppID) {
    CallEnter($this,__LINE__,'clsDepts.DoListing_forSupp('.$iSuppID.')');
   
    $out = '<p class=main><big>Departments:</big></p><table class=depts>';
    $objDepts = $this->GetData('ID_Supplier='.$iSuppID,'clsDept');
    $isFirst = true;
 
    $isOdd = FALSE;
    while ($objDepts->NextRow()) {
      $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>';
      }
    }
    $out .= '</table>';
    CallExit('clsDepts.DoListing_forSupp()');
    return $out;
/**/
  }
}
class clsDept extends clsDataSet {
// object cache
  private $objSupp;
 
  public function Supplier() {
    if (is_object($this->objSupp)) {
      return $this->objSupp;
    } else {
      $idSupp = $this->ID_Supplier;
      if ($idSupp) {
        $this->objSupp = $this->objDB->Suppliers()->GetItem($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;
 
    $objDataMgr->Update_byName('_dept_ittyps','clsDept.DoListing() for ID='.$this->ID);
    $sql = 'SELECT * FROM qryItTypsDepts_ItTyps WHERE (ID_Dept='.$this->ID.') ORDER BY cntInPrint DESC';
    $objItTyps = $this->objDB->DataSet($sql,'clsItTyp');
    return $objItTyps;
  }
  public function DoListing() {
// PURPOSE: Print this department's information as part of department list
 
    assert('$this->ID');
    $objItTyps = $this->GetDeptData();
    $isFirst = true;
    $out = '';
    while ($objItTyps->NextRow()) {
      if ($isFirst) {
        $isFirst = false;
      } else {
        $out .= ', ';
      }
      $cntInPrint = $objItTyps->cntInPrint;
      $qtyInStock = $objItTyps->qtyForSale;
// TO FIX: This is wrong. Need cntForSale field
      $cntAvail = $cntInPrint + $qtyInStock;
      if ($cntAvail == 1) {
        $strName = $objItTyps->ItTyp_Sng;
      } else {
        $strName = $objItTyps->ItTyp_Plr;
      }
      $out .= ' <b>'.$cntAvail.'</b> '.$strName;
    }
    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');
    $out = '';
    $idDept = $this->ID;
    $objSection = new clsPageOutput();
    $objItTyps = $this->GetDeptData();
    $objTitles = new clsTitleExt($this->objDB);
    $objNoImgSect = new clsPageOutput();
    $cntSections = 0;
    while ($objItTyps->NextRow()) {
      $cntInPrint = $objItTyps->cntInPrint;
      $qtyInStock = $objItTyps->qtyForSale;
// 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_byName('_title_ittyps','clsDept.DoPage() for ID_ItTyp='.$idItTyp.', ID_Dept='.$idDept);
        $objTitles->Query($sql);
//        $idTitle = $objTitles->GetValue('ID_Title');
//        $objTitles->ID = $idTitle;
        if ($objTitles->hasRows()) {
          while ($objTitles->NextRow()) {
    // make a copy with current row's data
            $objTitle = new clsDataSet(NULL,$objTitles->Res,$objTitles->Row);
    //$objTitle = clone $objTitles;
            $lstTitles[] = $objTitle; // save it in a list
          }
          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->ItTyp_Plr.':',$lstTitles,$objNoImgSect);
          $out .= $this->objDB->ShowTitles($objItTyps->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
      }
    }
    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 clsVbzTable {
  public function __construct($iDB) {
    parent::__construct($iDB);
      $this->Name('cat_titles');
      $this->KeyName('ID');
      $this->ClassSng('clsTitle');
  }
/*
ACTION: Finds a Title from a CatNum and returns an object for it
TO DO: Rename to Get_byCatNum()
*/
  public function GetItem_byCatNum($iCatNum) {
    global $objDataMgr;
 
    CallEnter($this,__LINE__,__CLASS__.'.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_byName('_titles','GetItem_byCatNum('.$iCatNum.')');
    $objDataMgr->Update_byName('_depts','GetItem_byCatNum('.$iCatNum.')');
    // get data from v_titles
    $objTitle->Query($sql);
    $idTitle = $objTitle->ID;
    assert('is_resource($objTitle->Res)');
    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 clsDataSet {
// == STATIC SECTION ==
  const cksTblName = 'cat_titles';
  const cksIDName = 'ID';
 
  public static function GetItem($iID) {
    $sql = 'SELECT * FROM '.self::cksTblName.' WHERE '.self::cksIDName.'="'.$iID.'"';
    $objItem = new self;
    $objItem->Query($sql);
    return $objItem;
  }
 
// == DYNAMIC SECTION ==
// object cache
  private $objDept;
// options
  public $hideImgs;
 
  public function Dept() {
    if (is_object($this->objDept)) {
      return $this->objDept;
    } else {
      $idDept = $this->ID_Dept;
      if ($idDept) {
        $objDept = $this->objDB->Depts()->GetItem($idDept);
        $this->objDept = $objDept;
        assert('is_object($objDept)');
        return $objDept;
      } else {
        return NULL;
      }
    }
  }
  public function IsActive() {
      if (is_null($this->DateUnavail)) {
  $out = TRUE;
      } else {
  $out = ($this->DateUnavail > time());
      }
      return $out;
  }
  public function DoPage() {
    global $objDataMgr;
 
    $idTitle = $this->ID;
    assert('$idTitle');
    $objSection = new clsPageOutput();
 
// show small-size images
    if (!$this->hideImgs) {
      $objImgs = $this->ListImages('sm');
      if ($objImgs->hasRows()) {
        while ($objImgs->NextRow()) {
          $strImgTag = $objImgs->AttrDispl;
          $urlRel = $objImgs->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->hasRow()) {
              $strImg = $objImgBig->Href().$strImg.'</a>';
            }
          }
          $objSection->AddText($strImg);
        }
      } else {
        $objSection->ShowImgUnavail();
      }
    }
 
// now list available items as table
    $sql = 'SELECT * FROM qryTitles_ItTyps_ItTyps WHERE (ID_Title='.$idTitle.') ORDER BY ItTyp_Sort IS NULL, ItTyp_Sort;';
    $objTypes = $this->objDB->DataSet($sql);
    if ($objTypes->hasRows()) {
      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->NextRow()) {
        $idItTyp = $objTypes->ID_ItTyp;
        assert('$idItTyp');
$sqlFilt = '(ID_Title='.$idTitle.') AND (ID_ItTyp='.$idItTyp.')';
$sqlSort = 'GrpSort,GrpDescr,ItOpt_Sort';
$objStk = $this->objDB->Items_Stock();
$objItems = $objStk->GetData($sqlFilt,'clsItem',$sqlSort);
        $idItType = 0;
 
        $txtLine = '<tr class=typeHdr><td colspan=3><b>'.$objTypes->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->cntStkForSale;
          $cntForSale = $objTypes->cntForSale;
          $cntOutStock = $cntForSale - $cntInStock;
 
  $txtInStock = $txtOutStock = '';
          if ($cntInStock > 0) {
            $txtInStock .= $txtLine;
          }
          if ($cntOutStock > 0) {
            $txtOutStock .= $txtLine;
          }
        }
 
// iterate through items for this type:
        $strGrpLast = '';
        while ($objItems->NextRow()) {
          $strGrp = $objItems->GrpDescr;
  $qtyStk = $objItems->qtyForSale;
          if ($strGrp != $strGrpLast) {
            $strGrpLast = $strGrp;
            $strGrpCode = $objItems->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 ($qtyStk > 0) {
                $txtInStock .= $out;
              } else {
                $txtOutStock .= $out;
              }
            }
          }
          if ($objItems->isForSale) {
            $txtLine = $objItems->Print_TableRow();
 
            if ($flagDisplayTogether) {
              $txtBoth .= $txtLine;
            } else {
              if ($qtyStk > 0) {
                $txtInStock .= $txtLine;
              } else {
                $txtOutStock .= $txtLine;
              }
            }
          }
        }
      }
 
// 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>';


// CONSTANTS
      if ($flagDisplayTogether) {
// -- KF = boolean flag
// Display in-stock and backordered items together
// -- KS = string
        $objSection->AddText($txtTblOpen);
// -- KWP = web path (URL including protocol)
        $objSection->AddText($txtTblHdr);
// -- KFP = file path
        $objSection->AddText($txtBoth);
// -- KRP = relative path
        $objSection->AddText($txtTblFtr);
$fltStart = microtime(true);
        $objSection->AddText($txtTblShut);
// debugging activation
      } else {
define('KDO_DEBUG',0);
        if ($txtInStock != '') {
define('KDO_DEBUG_STACK',0);
          $txtClause = Pluralize($cntInStock,'This item is','These items are');
// debugging options
          $objSection->AddText($txtTblOpen);
define('KDO_DEBUG_HTML',1);
          $objSection->AddText('<tr class=inStock><td colspan=5>'.$txtClause.' in stock:</td></tr>');
define('KDO_DEBUG_IMMED',1);
          $objSection->AddText($txtTblHdr);
define('KDO_DEBUG_DARK',0);
          $objSection->AddText($txtInStock);
define('KF_USE_WIKI',true);
          $objSection->AddText($txtTblFtr);
// 2008-06-07 force absolute URL for cart until we fix the domain-cookie problem
          $objSection->AddText($txtTblShut);
define('KF_CART_ABSOLUTE',true);
        }
 
        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) {
    $sqlFilt = '(ID_Title='.$this->ID.') AND (Ab_Size="'.$iSize.'")';
    $objImgs = $this->objDB->Images()->GetData($sqlFilt,'clsImage','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 URL_part() {
    return strtolower($this->CatNum('/'));
  }
  public function URL() {
    return KWP_CAT_REL.$this->URL_part();
  }
  public function Link() {
    $strURL = $this->URL();
    return '<a href="'.$strURL.'">';
  }
  public function LinkName() {
    return $this->Link().$this->Name.'</a>';
  }
  public function LinkName_wt() {
// TO DO: make this more configurable
    $out = '[[vbznet:cat/'.$this->URL_part().'|'.$this->Name.']]';
    return $out;
  }
}
// extended Title data from v_titles
class clsTitlesExt extends clsTitles {
  public function __construct($iDB) {
    parent::__construct($iDB);
      $this->Name('v_titles');
      $this->KeyName('ID');
  }
  protected function _newItem() {
    CallStep('clsTitlesExt._newItem()');
    return new clsTitleExt($this);
  }
}
// this encapsulates [_titles] instead of [titles]
class clsTitleExt extends clsTitle {
/*
/*
GET CONNECTED TO LIBRARIES
  public $CatNum;
  public $CatWeb;
  public $curMinPrice;
  public $curMaxPrice;
  public $idItTyp;
  public $qtyInStock;
*/
*/
// action flags
  public $dontLoadBasic;
/*
  protected function LoadResults() {
    CallEnter($this,__LINE__,'clsTitleExt.LoadResults()');
    if (!$this->dontLoadBasic) {
      parent::LoadResults();
    }


require('../local.php');
    $this->CatNum = $this->GetValue('CatNum');
require('site.php');
    $this->CatWeb = $this->GetValue('CatWeb');
$strLibs .= ':'.KFP_WIKI.':'.KFP_WIKI.'includes/';
    $this->currMinPrice = $this->GetValue('currMinPrice');
ini_set('include_path',$strLibs);
    $this->currMaxPrice = $this->GetValue('currMaxPrice');
require('store.php');
    $this->idItTyp = $this->GetValue('ID_ItTyp');
    $this->qtyInStock = $this->GetValue('qtyInStock');


// PROCESS PAGE REQUEST
    CallExit('clsTitle.LoadResults()');
$page_uri = $_ENV['REQUEST_URI'];
  }
// prepare data objects
*/
InitData(KS_DB_VBZCART);
  public function Link() {
//$objFactory = new clsFactory_Carts($objFactory->DB()); // this is an ugly kluge
    $out = '<a class="thumb" href="'.$this->URL().'">';
// clsFactory can be done away with when the data.php and carts.php are rewritten to use a single class for each type
    return $out;
// - static methods for the whole-table functions, regular methods for individual rows
  }
  public function URL() {
    return KWP_CAT_REL.$this->CatWeb.'/';
  }
}
/* -------------------- *\
    TITLE/ITTYP hybrid
\* -------------------- */
class clsTitleIttyp extends clsDataSet {
/*
  public $ID_ItTyp;
  //public $ID_Dept;
  public $cntForSale;
  public $cntInPrint;
  public $cntInStock;
  public $qtyInStock;
  public $ItTypSng;
  public $ItTypPlr;
*/
// object cache
  private $objIttyp;


// process the request
/*
$objPage = new clsPageCat();
  protected function LoadResults() {
$objPage->GetQuery();
    CallEnter($this,__LINE__,'clsTitleIttyp.LoadResults()');
$objPage->DoRequest();
    $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->ItTypSng = $this->GetValue('ItTyp_Sng');
    $this->ItTypPlr = $this->GetValue('ItTyp_Plr');
    if ($this->ID_ItTyp) { } else {
      echo 'ERROR: ID_ItTyp has no value! data = ';
      DumpArray($this->Row,TRUE);
    }
    CallExit('clsTitleIttyp.LoadResults()');
  }
*/
  public function Ittyp() {
    if (is_null($this->objIttyp)) {
      $this->objIttyp = VbzClasses::ItTyps()->GetItem($this->ID_ItTyp);
    }
    return $this->objIttyp;
  }
}
/* -------------------- *\
    ITEM classes
\* -------------------- */
class clsItems extends clsVbzTable {


if (!$didPage) {
  public function __construct($iDB) {
//  $objPage->Init('','Unknown page','something is messed up','browse','Houston, we have a problem...');
    parent::__construct($iDB);
//  $objPage->DoError();
      $this->Name('cat_items');
      $this->KeyName('ID');
      $this->ClassSng('clsItem');
  }
/*
ACTION: Finds the Item with the given CatNum, and returns a clsItem object
*/
  public function Get_byCatNum($iCatNum) {
      $sqlCatNum = $this->objDB->SafeParam($iCatNum);
      $objItem = $this->GetData('CatNum="'.$sqlCatNum.'"');
      if ($objItem->HasRows()) {
  $objItem->NextRow();
  return $objItem;
      } else {
  return NULL;
      }
  }
}
}
if (KDO_DEBUG) {
/* ===============
print "DEBUG:<p>".$debug;
CLASS: clsItem
NOTE: "in stock" always refers to stock for sale, not stock which has already been purchased
*/
class clsItem extends clsDataSet {
// object cache
  private $objTitle;
 
  public function Print_TableRow() {
/*
  ASSUMES:
      This item is ForSale, so isForSale = true and (qtyForSale>0 || isInPrint) = true
      This item's data was generated by clsItems_Stock
  TO DO: create a separate clsItem_Stock class and move this method there.
*/
    $qtyInStock = $this->qtyForSale;
    if ($qtyInStock) {
      $strClass = 'inStock';
      $strStock = $qtyInStock.' in stock';
    } else {
      $strClass = 'noStock';
    }
    $out = '<tr class='.$strClass.'><!-- ID='.$this->ID.' -->';
    $out .= '<td>&emsp;'.$this->ItOpt_Descr;
    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 Title() {
    $doLoad = TRUE;
    if (is_object($this->objTitle)) {
      if ($this->objTitle->ID == $this->ID_Title) {
        $doLoad = FALSE;
      }
    }
    if ($doLoad) {
      $this->objTitle = $this->objDB->Titles()->GetItem($this->ID_Title);
    }
    return $this->objTitle;
  }
  public function ItTyp() {
    $doLoad = TRUE;
    if (is_object($this->objItTyp)) {
      if ($this->objItTyp->ID == $this->ID_ItTyp) {
        $doLoad = FALSE;
      }
    }
    if ($doLoad) {
      $this->objItTyp = $this->objDB->ItTyps()->GetItem($this->ID_ItTyp);
    }
    return $this->objItTyp;
  }
  public function ItOpt() {
    $doLoad = TRUE;
    if (is_object($this->objItOpt)) {
      if ($this->objItOpt->ID == $this->ID_ItOpt) {
        $doLoad = FALSE;
      }
    }
    if ($doLoad) {
      $this->objItOpt = $this->objDB->ItOpts()->GetItem($this->ID_ItOpt);
    }
    return $this->objItOpt;
  }
  public function ShCost() {
    $doLoad = TRUE;
    if (is_object($this->objShCost)) {
      if ($this->objShCost->ID == $this->ID_ShipCost) {
        $doLoad = FALSE;
      }
    }
    if ($doLoad) {
      $this->objShCost = $this->objDB->ShipCosts()->GetItem($this->ID_ShipCost);
    }
    return $this->objShCost;
  }
  public function ShipPriceItem($iZone) {
      global $listItmFactors;
      $this->ShCost(); // get the shipping cost object
      $fltZoneFactor = $listItmFactors[$iZone];
      return $this->objShCost->PerItem * $fltZoneFactor;
  }
  public function ShipPricePkg($iZone) {
      global $listPkgFactors;
      $this->ShCost(); // get the shipping cost object
      $fltZoneFactor = $listPkgFactors[$iZone];
      return $this->objShCost->PerPkg * $fltZoneFactor;
  }
}
 
/* -------------------- *\
    ITEM TYPE classes
\* -------------------- */
class clsItTyps extends clsVbzTable {
  public function __construct($iDB) {
    parent::__construct($iDB);
      $this->Name('cat_ittyps');
      $this->KeyName('ID');
      $this->ClassSng('clsItTyp');
  }
}
class clsItTyp extends clsDataSet {
  public function Name($iCount=-1) {
    if ($iCount == -1) {
      $iCount = $this->cntInPrint;
    }
    if ($iCount == 1) {
      return $this->NameSng;
    } else {
      return $this->NamePlr;
    }
  }
}
/* -------------------- *\
    ITEM OPTION classes
\* -------------------- */
class clsItOpts extends clsVbzTable {
  public function __construct($iDB) {
    parent::__construct($iDB);
      $this->Name('cat_ioptns');
      $this->KeyName('ID');
      $this->ClassSng('clsItOpt');
  }
}
class clsItOpt extends clsDataSet {
}
/* -------------------- *\
    SHIP COST classes
\* -------------------- */
class clsShipCosts extends clsVbzTable {
  public function __construct($iDB) {
    parent::__construct($iDB);
      $this->Name('cat_ship_cost');
      $this->KeyName('ID');
      $this->ClassSng('clsShipCost');
  }
}
class clsShipCost extends clsDataSet {
}
/* -------------------- *\
    STOCK ITEM classes
\* -------------------- */
// TO DO: explain the difference between clsItems_Stock and clsStkItems
class clsItems_Stock extends clsItems {
  public function __construct($iDB) {
    parent::__construct($iDB);
      $this->Name('qryCat_Items_Stock');
      $this->KeyName('ID');
  }
}
 
class clsStkItems extends clsVbzTable {
  public function __construct($iDB) {
    parent::__construct($iDB);
      $this->Name('stk_items');
      $this->KeyName('ID');
  }
  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->NextRow()) {
      assert('is_resource($objStock->Res)');
      if ($objStock->RowCount()) {
        assert('$objStock->RowCount() == 1');
        return $objStock->Qty;
      }
    } else {
      return NULL;
    }
  }
}
/* -------------------- *\
    IMAGE classes
\* -------------------- */
class clsImages extends clsVbzTable {
  public function __construct($iDB) {
    parent::__construct($iDB);
      $this->Name('cat_images');
      $this->KeyName('ID');
      $this->ClassSng('clsImage');
  }
}
class clsImage extends clsDataSet {
// == STATIC SECTION ==
  const cksTblName = 'cat_images';
 
// == DYNAMIC SECTION ==
// object cache
  private $objTitle;
 
  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';
    }
    $sqlFilt = '(ID_Title='.$this->ID_Title.') AND (AttrFldr'.$sqlAttr.') AND (Ab_Size="'.$iSize.'")';
    $objImgOut = $this->objDB->Images()->GetData($sqlFilt);
    return $objImgOut;
  }
  public function Title() {
    if (!is_object($this->objTitle)) {
$this->objTitle = $this->objDB->Titles()->GetItem($this->ID_Title);
    }
    return $this->objTitle;
  }
  public function DoPage() {
    global $vbgImgSize;
 
    $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><small>'.$strCatNum.' - title ID #'.$this->ID_Title.'</small>';
    echo '<table border=1><tr><td><table>';
// show list of available image sizes (except th and sm)
 
    $objImgs = $this->ListImages_sameAttr();
    $strOut = NULL;
    if ($objImgs->hasRows()) {
      $strImgCount = 0;
      while ($objImgs->NextRow()) {
        $strImgType = $objImgs->Ab_Size;
        if (($strImgType != 'th') && ($strImgType != 'sm')) {
          $strImgCount++;
  $strDesc = $vbgImgSize[$strImgType];
  if ($objImgs->ID == $this->ID) {
      $strImgTag = '<b>'.$strDesc.'</b>';
  } else {
      $strImgTag = $objImgs->Href(TRUE).$strDesc.'</a>';
  }
          if ($strOut) {
            $strOut .= ' .. ';
          }
          $strOut .= $strImgTag;
        }
      }
      if ($strImgCount > 1) {
echo '<tr><td><font color=#aaaaaa>sizes</font> :</td><td align=center>'.$strOut.'</td><td>: <font color=#aaaaaa>sizes</font></td></tr>';
      }
    }
    $strOut = NULL;
 
// show list of available images for this title at this size
    $objImgs = $this->ListImages_sameSize();
    if ($objImgs->NextRow()) {
      $strImgCount = 0;
      $strOut .= '';
      if ($objImgs->hasRows()) {
        while ($objImgs->NextRow()) {
          $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>';
          }
        }
        if ($strImgCount > 1) {
          echo '<tr><td><font color=#aaaaaa>views</font> :</td><td align=center>'.$strOut.'</td><td>: <font color=#aaaaaa>views</font></td></tr>';
        }
      }
    }
    echo '</table></td></tr></table>';
    echo $objTitle->Link().'ordering page</a><br>';
    echo $this->ImgSrc();
    echo '</body></html>';
  }
  public function ListImages_sameAttr() {
    if ($this->AttrFldr) {
      $sqlFilt = '(ID_Title='.$this->ID_Title.') AND (AttrFldr="'.$this->AttrFldr.'")';
    } else {
      $sqlFilt = '(ID_Title='.$this->ID_Title.')';
    }
    $objImgOut = $this->objDB->Images()->GetData($sqlFilt);
 
    return $objImgOut;
  }
  public function ListImages_sameSize() {
    $sqlFilt = '(ID_Title='.$this->ID_Title.') AND (Ab_Size="'.$this->Ab_Size.'")';
    $objImgOut = $this->objDB->Images()->GetData($sqlFilt);
    return $objImgOut;
  }
  public function Href($iAbs=false) {
    $strFldrRel = $this->AttrFldr;
    if ($strFldrRel) {
      $strFldrRel .= '-';
    }
    $strFldrRel .= $this->Ab_Size;
 
    if ($iAbs) {
      $strFldr = $this->Title()->URL().'/'.$strFldrRel;
    } else {
      $strFldr = $strFldrRel;
    }
 
    return '<a href="'.$strFldr.'/">';
  }
  public function ImgSrc() {
    return '<img src="'.KWP_IMG_MERCH.$this->Spec.'">';
  }
}
 
/* ------------------ *\
    CATALOG BROWSING
\* ------------------ */
class clsTopics extends clsVbzTable {
  public function __construct($iDB) {
    parent::__construct($iDB);
      $this->Name('brs_topics');
      $this->KeyName('ID');
      $this->ClassSng('clsTopic');
  }
  public function DoIndex() {
    global $objDataMgr;
 
    CallEnter($this,__LINE__,'clsTopics.DoIndex()');
    $objSection = new clsPageOutput();
 
    $objTopics = $this->GetData('ID_Parent IS NULL',NULL,'Sort,Name,NameTree');
    while ($objTopics->NextRow()) {
      if ($isFirst) {
        $isFirst = false;
        $objSection->SectionHdr('Root Topics');
      } else {
        $objSection->AddText($objTopics->Name.'<br>');
      }
    }
 
    CallExit('clsTopic.DoIndex()');
    return $objSection->out;
  }
}
class clsTopic extends clsDataSet {
/*
  public $ID_Parent;
  public $Name;
  public $NameTree;
  public $NameFull;
  public $Variants;
  public $Mispeled;
 
  protected function LoadResults() {
    CallEnter($this,__LINE__,'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 $objDataMgr;
 
    CallEnter($this,__LINE__,'clsTopic.DoPage()');
    assert('$this->ID');
    $objSection = new clsPageOutput();
 
    $objTitles = $this->objDB->DataSet('SELECT * FROM brs_titles_x_topics WHERE ID_Topic='.$this->ID);
    while ($objTitles->NextRow()) {
      if ($isFirst) {
        $isFirst = false;
        $objSection->SectionHdr('Titles');
      } else {
        $objSection->AddText($objTitles->Name.'<br>');
      }
    }
 
    CallExit('clsTopic.DoPage()');
    return $out;
  }
  public function WebName() {
    return sprintf(KS_FMT_TOPICID,$this->ID);
  }
}
 
/* ------------------ *\
    EVENT LOGGING
\* ------------------ */
class clsEvents extends clsVbzTable {
  public function __construct($iDB) {
    assert('is_object($iDB)');
    parent::__construct($iDB);
      $this->Name('event_log');
      $this->KeyName('ID');
  }
 
  public function LogEvent($iWhere,$iParams,$iDescr,$iCode,$iIsError,$iIsSevere) {
    global $sql, $vgUserName;
 
    $sql = 'INSERT INTO `'.$this->Name().'` (EvWhen,EvWhere,Params,Descr,Code,VbzUser,SysUser,Machine,isError,isSevere)'.
'VALUES(NOW(),"'.$iWhere.'","'.$iParams.'","'.$iDescr.'",'.SQLValue($iCode).','.SQLValue($vgUserName).
',NULL,"'.
$_ENV['REMOTE_ADDR'].'",'.
($iIsError?'TRUE':'FALSE').','.
($iIsSevere?'TRUE':'FALSE').');';
    $this->objDB->Exec($sql); 
  }
}
 
/* ==================== *\
    UTILITY FUNCTIONS
\* ==================== */
 
function DataCents($iCents,$iPfx='$') {
  $out = $iPfx.sprintf("%01.2f",$iCents/100);
  return $out;
}
function DataCurr($iCurr,$iPfx='$') {
  $out = $iPfx.sprintf("%01.2f",$iCurr);
  return $out;
}
function DataDate($iDate) {
    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;
}
function DataDateTime($iDate) {
    if (is_string($iDate)) {
if ($iDate == '') {
    $out = '-';
} else {
    $objDate = new DateTime($iDate);
    $out = $objDate->format('Y-m-d H:i');
}
    } else {
      $out = '';
    }
    return $out;
}
function IsEmail($iAddr) {
    $ok = preg_match('/.{1}.*[\@].{1}.*[\.][a-z]{2}.*/i', $iAddr );
    return $ok;
}
 
/* ==================== *\
    MISSING FUNCTIONS
\* ==================== */
if (!function_exists('http_redirect')) {
    function http_redirect($iURL) {
header('Status: 301 Moved Permanently',TRUE);
header('Location: '.$iURL,TRUE);
    }
}
}
</php>
</php>

Revision as of 12:21, 6 October 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 /*

FILE: store.php
PURPOSE: vbz class library - should eventually be subdivided
HISTORY:
 2009-07-11 (Wzl) Lots of cleanup; added types and methods needed for shopping cart page
  • /

//define('kfpHostAcctRoot','/hsphere/local/home/hypertwi/'); //define('kfpMediaWiki',kfpHostAcctRoot.'wiki.vbz.net/'); define('kEmbeddedPagePrefix','embed:');

if (defined( '__DIR__' )) {

 $fpThis = __DIR__;

} else {

 $fpThis = dirname(__FILE__);

} if (!defined('LIBMGR')) {

   require('libmgr.php');

} clsLibMgr::Add('datamgr',$fpThis.'/datamgr.php'); clsLibMgr::Load('datamgr');

define('EN_PGTYPE_NOTFND',-1); // requested item (supp/dept/title) not found define('EN_PGTYPE_HOME',1); // catalog home page define('EN_PGTYPE_SUPP',2); // supplier page define('EN_PGTYPE_DEPT',3); // department page, or possibly title for keyless dept define('EN_PGTYPE_TITLE',4); // title page // table names // - caching define('ksTbl_cache_tables','data_tables'); define('ksTbl_cache_procs','data_procs'); define('ksTbl_cache_flow','data_flow'); define('ksTbl_cache_log','data_log'); // - stock define('ksTbl_stock_places','stk_places'); define('ksTbl_stock_bins','stk_bins'); define('ksQry_stock_bins_wInfo','qryStk_Bins_w_info'); define('ksTbl_stock_items','stk_items'); define('ksTbl_stock_hist_items','stk_history'); define('ksTbl_stock_hist_bins','stk_bin_history');

$vbgImgSize = array(

   'th'	=> 'thumbnail',
   'sm'	=> 'small',
   'big' 	=> 'large',
   'huge'	=> 'huge',
   'zoom'	=> 'detail');

// shipping charge adjustment factors by destination zone: $listShipListDesc['US'] = 'United States'; $listShipListDesc['CA'] = 'Canada'; $listShipListDesc['INT'] = 'International'; $listPkgFactors['US'] = 1.0; $listItmFactors['US'] = 1.0; $listPkgFactors['CA'] = 2.0; $listItmFactors['CA'] = 2.0; $listPkgFactors['INT'] = 4.0; $listItmFactors['INT'] = 4.0; // The above is just until we have something more exact and dynamic

$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) {

 $fpTools = $fwpAbsTools;
 $fpPages = $fwpAbsPages;

}

  • /

$fwpLogo = $fpTools.'/img/logos/v/';

class clsVbzData extends clsDatabase {

 private $objPages;
 public function __construct($iSpec) {
   global $objDataMgr;
   parent::__construct($iSpec);
   $objDataMgr = new clsDataMgr($this,ksTbl_cache_tables,ksTbl_cache_procs,ksTbl_cache_flow,ksTbl_cache_log);
   $this->Open();
 }

// generic object-creation function

 protected function Make($iName) {
   if (!isset($this->$iName)) {
     $this->$iName = new $iName($this);
   }
   return $this->$iName;
 }

// table-specific functions

 public function Pages() {
   return $this->Make('clsCatPages');
 }
 public function Suppliers() {
   return $this->Make('clsSuppliers');
 }
 public function Depts() {
   return $this->Make('clsDepts');
 }
 public function Titles() {
   return $this->Make('clsTitles');
 }
 public function TitlesExt() {
   return $this->Make('clsTitlesExt');
 }
 public function Items() {
   return $this->Make('clsItems');
 }
 public function Items_Stock() {
   return $this->Make('clsItems_Stock');
 }
 public function ItTyps() {
   return $this->Make('clsItTyps');
 }
 public function ItOpts() {
   return $this->Make('clsItOpts');
 }
 public function ShipCosts() {
   return $this->Make('clsShipCosts');
 }
 public function Images() {
   return $this->Make('clsImages');
 }
 public function StkItems() {
   return $this->Make('clsStkItems');
 }
 public function Topics() {
   return $this->Make('clsTopics');
 }
 public function Events() {
   return $this->Make('clsEvents');
 }
 public function LogEvent($iWhere,$iParams,$iDescr,$iCode,$iIsError,$iIsSevere) {
   return $this->Events()->LogEvent($iWhere,$iParams,$iDescr,$iCode,$iIsError,$iIsSevere);
 }

// Page output routines

 public function SectionHdr($iTitle) {

$out = '

'.$iTitle.'

';

   return $out;
 }
 public function ShowTitles($iHdrText,$iList,$objNoImgSect) {
   $cntImgs = 0;
   $outImgs = ;
   foreach ($iList as $i => $objTitleData) {
     $objTitle = $this->Titles()->GetItem($objTitleData->ID);
     $objImgs = $objTitle->ListImages('th');
     $currMinPrice = $objTitleData->currMinPrice;
     $currMaxPrice = $objTitleData->currMaxPrice;
     $strPrice = DataCurr($currMinPrice);
     if ($currMinPrice != $currMaxPrice) {
       $strPrice .= '-'.DataCurr($currMaxPrice);
     }
     assert('is_resource($objImgs->Res)');
     if ($objImgs->RowCount()) {
       $cntImgs++;

$strCatNum = $objTitleData->CatNum;

       $strTitleTag = '"'.$objTitle->Name.'" ('.$strCatNum.')';
       $strTitleLink = $objTitle->Link();
       while ($objImgs->NextRow()) {
         $strImgTag = $strTitleTag.' - '.$strPrice;

$qtyStk = $objTitleData->qtyForSale;

         if ($qtyStk) {
           $strImgTag .= ' - '.$qtyStk.' in stock';
         }
         $outImgs .= $strTitleLink.'<img class="thumb" src="'.KWP_IMG_MERCH.'/'.$objImgs->Spec.'" title="'.$strImgTag.'"></a>';
       }
     } else {
       if (!$objNoImgSect->inTbl) {
         $objNoImgSect->StartTable('titles without images:');

$objNoImgSect->AddText('Cat. #TitlePrice
Rangeto
orderstatus');

       }
       $objNoImgSect->RowStart();
       $objNoImgSect->ColAdd(''.$objTitleData->CatNum.'');
       $objNoImgSect->ColAdd($objTitle->Name);
       $objNoImgSect->ColAdd($strPrice);
       $objNoImgSect->ColAdd('['.$objTitle->Link().'order</a>]');
       $qtyStk = $objTitleData->qtyForSale;
       if ($qtyStk) {
         $strStock = ''.$qtyStk.' in stock';
         $objNoImgSect->ColAdd($strStock);
         if ($objTitleData->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();
     }
   }
   $out = ;
   if ($cntImgs) {
     $out .= $this->SectionHdr($iHdrText);
     $out .= $outImgs;
   }
   return $out;
 }

}

class clsList {

 public $List;
 public function Add($iName, $iValue=NULL) {
   $objItem = new clsListItem($iName,$iValue);
   $this->List[] = $objItem;
   return $objItem;
 }
 public function Output($iPfx, $iSep, $iSfx) {
   $out = NULL;
   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) {
   $this->name = $iName;
   $this->value = $iValue;
 }

}

/* ===================

 CLASS: clsPage
 PURPOSE: Handles display of different page types
  • /

class clsPage extends clsVbzData { // query

 protected $strReq;	// requested page

// page definition

 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 $strWikiPg;	// name of wiki page to embed, if any (blank = suppress embedding)
 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;
 public function __construct($iSpec) {
   parent::__construct($iSpec);
   $this->lstTop = new clsList();
 }
 public function GetQuery() {

// ACTION: Retrieves request from URL and parses it

   if (isset($_SERVER['PATH_INFO'])) {

$strReq = $_SERVER['PATH_INFO'];

   } else {

$strReq = ;

   }
   $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->strWikiPg	= ;
   $this->strTitle	= 'Unknown Page';
   $this->strName	= 'unknown title in catalog';
   $this->strTitleContext	= 'Tomb of the...';
   $this->strHdrXtra	= ;

$this->strSideXtra = '

Cat #: '.$this->strReq; } // UTILITY protected function AddText($iText) { $this->strContText .= $iText; } // PAGE COMPONENTS // -- HEADER COMPONENTS protected function DoPreamble() {
  1. Framework
$this->DoHeader(); $this->DoSidebar(); $this->DoWikiContent(); } protected function DoPostamble() { global $didPage,$fltStart; echo '
';
   $this->DoSepBar();
echo '
';
   $fltExecTime = microtime(true)-$fltStart;
   $dat = getrusage();
   $fltUserTime = $dat["ru_utime.tv_usec"]/1000000;
   $strServer = $_SERVER['SERVER_SOFTWARE'];
   echo $strServer.' .. ';
   echo 'PHP '.phpversion().' .. Generated in '.$fltUserTime.' seconds (script execution '.$fltExecTime.' sec.) .. ';
   $strWikiPg = $this->strWikiPg;
   if ($strWikiPg) {

echo 'wiki: <a href="'.KWP_WIKI.kEmbeddedPagePrefix.$this->strWikiPg.'">'.$strWikiPg.'</a> .. ';

   }
   echo date('Y-m-d H:i:s');
echo '
'; echo '
</body></html>';
   $didPage = true;
 }
 private function DoWikiContent() {
  1. WIKI CONTENTS
  2. $txtPage = GetEmbedPage('cat');
   if (KF_USE_WIKI) {
     $txtWiki = GetWikiPage($this->strWikiPg);
     if ($txtWiki) {
       if (strpos($txtWiki,'__NOIMG__') != -1) {
         $txtWiki = str_replace('__NOIMG__',,$txtWiki);
         $this->hideImgs = true;
       }
     }
     if ($txtWiki) {

// print ''.$txtPage.'
';

echo '
'.$txtWiki.'
';
     }
   }
 }
 protected function DoSidebar() {
   global $fpTools,$objDataMgr;

// TO DO: these should be pulled from the [stats] table if ($objDataMgr->dtNewest) {

   $timeSidebarBuild=$objDataMgr->dtNewest;

} else {

   $timeSidebarBuild = NULL;

} $statsQtyTitlesAvail = 2245; $statsQtyStockPieces = 1395; $statsQtyStockItems = 753; $statsQtyArtists = 136; $statsQtyTopics = 1048; //---------

echo '
';

?>

';
 }
 private function DoSepBar() {
   global $fpTools;
   echo '<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;
   echo $this->ToolbarItem($fpPages.'/','home',KS_STORE_NAME.' home page','home page');
   echo $this->ToolbarItem($fpPages.'/search/','search','search page','search page');
   echo $this->ToolbarItem($fwpCart,'cart','shopping cart','shopping cart');
   echo $this->ToolbarItem(KWP_WIKI.'help','help','help!','help');
 }

// -- HEADER

 protected function DoHeader() {
   global $fpTools, $fwpLogo;
   $strWikiPg = $this->strWikiPg;
   $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 .= ''.$this->strCalcTitle.'';
    if ($this->strSheet) {
      $htmlHead .= '';
    }
# remove any quotes from $pageName:
    $htmlName = str_replace('"','"',$this->strName);
    if ($htmlName) {
      $htmlName = ': '.$htmlName;
    }
    $htmlHead .= '';
    $htmlHead .= '';
    echo $htmlHead;
?>
';
    echo '';
// === LEFT HEADER: Title ===
    echo '';
// === END LEFT HEADER ===

// === RIGHT HEADER: nav icons ===
    echo '';
// === END RIGHT HEADER ===
?>
'; echo ''.KS_SMALL_LOGO_ALT.''; if ($this->strTitleContext) { echo ''.KS_STORE_NAME.': '.$this->strTitleContext.'
'; } echo ''.$this->strTitle.'
'; $this->DoToolbar(); echo '
strReq; $this->objCatPage = $this->Pages()->GetItem_byKey($strReq); //print 'REQ='.$strReq.' ABBR='.$this->objCatPage->AB; } public function DoRequest() { $doRawHTML = FALSE; $this->strSheet = 'browse'; // default 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','by supplier'); } private function DoSuppIndicia($iSupp,$isFinal=true) { $this->DoCatIndicia(); if ($isFinal) { $this->lstTop->Add('Supplier',$iSupp->Name); $this->lstTop->Add('more info'); } 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() { // $objSuppTbl = VbzClasses::Suppliers(); // $this->Setup('cat','Catalog Home','Catalog main page','browse','hello and welcome to the...'); $this->DoCatIndicia(); $this->strWikiPg = 'cat'; $this->strTitle = 'Catalog Home'; $this->strName = 'Catalog main page'; $this->strTitleContext = 'hello and welcome to the...'; $this->AddText($this->Suppliers()->DoHomePage()); } private function DoCatSupp() { CallEnter($this,__LINE__,'clsPage.DoCatSupp()'); // $objSuppTbl = VbzClasses::Suppliers(); $objSuppTbl = $this->Suppliers(); $objSupp = $objSuppTbl->GetItem($this->objCatPage->ID_Row); assert('is_object($objSupp)'); $strSuppName = $objSupp->Name; $this->DoSuppIndicia($objSupp); $this->strWikiPg = 'supp:'.strtoupper($objSupp->CatKey); $this->strTitle = $strSuppName; $this->strName = 'listing for '.$strSuppName; $this->strTitleContext = 'Suppliers: '.$strSuppName.':'; $this->AddText($objSupp->DoPage()); CallExit('clsPage.DoCatSupp()'); } private function DoCatDept() { CallEnter($this,__LINE__,'clsPage.DoCatDept()'); // $objDeptTbl = VbzClasses::Depts(); $objDeptTbl = $this->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->strWikiPg = 'dept:'.strtoupper($objDept->PageKey); $this->strTitle = $strSuppName; $this->strName = $strDeptName.' dept. of '.$strSuppName; $this->strTitleContext = 'items supplied by '.$strSuppLink.'\'s '.$strDeptName.' department:'; $this->AddText($objDept->DoPage()); CallExit('clsPage.DoCatDept()'); } private function DoCatTitle() { CallEnter($this,__LINE__,'clsPage.DoCatTitle()'); $strPageKey = $this->objCatPage->Path; // $objTitleTbl = VbzClasses::Titles(); $objTitleTbl = $this->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->strWikiPg = 'title:'.$objTitle->CatNum(); //print 'ABBR='.$this->strAbbr; $this->strTitle = $strTitleName; $this->strName = $strPageKey.' "'.$strTitleName.'" from '.$objSupp->Name; $this->strTitleContext = 'items supplied by '.$objSupp->Link().'\'s '. $objDept->LinkName().' department:'; $objTitle->hideImgs = $this->hideImgs; $this->AddText($objTitle->DoPage()); CallExit('clsPage.DoCatTitle()'); } private function DoCatImage() { CallEnter($this,__LINE__,'clsPage.DoCatImage()'); // $objImageTbl = VbzClasses::Images(); $objImageTbl = $this->Images(); $objImage = $objImageTbl->GetItem($this->objCatPage->ID_Row); $objImage->DoPage(); CallExit('clsPage.DoCatImage()'); } } class clsPageTopic extends clsPage { public function DoRequest() { $this->strSheet = 'browse'; // default $strReq = $this->strReq; if (is_numeric($strReq)) { $idTopic = (int)$strReq; $objTopic = $this->Topics()->GetItem($idTopic); $this->strWikiPg = 'topic.'.$objTopic->WebName(); $this->strTitle = 'Topic Index'; $this->strName = 'catalog topic index'; $this->AddText($objTopic->DoPage()); } else { $this->strWikiPg = 'topics'; $this->strTitle = 'Topic Index'; $this->strName = 'catalog topic index'; $this->AddText($this->Topics()->DoIndex()); } $this->DoPreamble(); // everything before the contents echo ''.$this->strContText.''; $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 .= '

'.$iTitle.'

'; return $this->out; } function StartTable($iTitle) { if ($iTitle) { $this->SectionHdr($iTitle); $this->out .= ''; $this->inTbl++; } } function RowStart($iClass='') { if ($iClass) { $this->out .= ''; } else { $this->out .= ''; } } function RowStop() { $this->out .= ''; $this->isOdd = !$this->isOdd; } function ColAdd($iText) { if ($this->isOdd) { $cellOpen = ''; } function EndTable() { if ($this->inTbl) { $this->out .= '
'; } else { $cellOpen = ''; } $this->out .= $cellOpen.$iText.'
'; $this->inTbl--; } return $this->out; } function ShowImgUnavail() { $this->out .= '
No Images
Available
for this item
:-(
'; return $this->out; } } /* =========================== *** CATALOG DATA CLASSES *** */ class clsVbzTable extends clsTable { protected function Touch($iCaller) { global $objDataMgr; $objDataMgr->Update_byName($this->Name(),$iCaller); } } class clsCatPages extends clsVbzTable { public function __construct($iDB) { parent::__construct($iDB); $this->Name('cat_pages'); $this->KeyName('AB'); $this->ClassSng('clsCatPage'); } /* protected function _newItem() { return new clsCatPage($this); } */ public function GetItem_byKey($iKey) { CallEnter($this,__LINE__,__CLASS__.'.GetItem_byKey('.$iKey.')'); $strKey = trim($iKey,'/'); $strKey = str_replace('-','/',$strKey); $sqlCatKey = $this->objDB->SafeParam($strKey); $this->Touch('clsCatPages.GetItem_byKey('.$iKey.')'); $objItem = $this->GetData('Path="'.$sqlCatKey.'"'); // $objRec = $this->objDB->Query($sql); assert('is_object($objItem)'); if ($objItem->NextRow()) { DumpValue('objItem NumRows',$objItem->hasRows()); CallExit('clsCatPages.GetItem_byKey('.$iKey.') -> Page '.$objItem->AB); } else { CallExit('clsCatPages.GetItem_byKey('.$iKey.') -> no data'); } return $objItem; } } class clsCatPage extends clsDataSet { // == STATIC SECTION // const cksTblName = 'cat_pages'; // const cksIDName = 'AB'; } class clsSuppliers extends clsVbzTable { // ==== STATIC SECTION // ==== DYNAMIC SECTION public function __construct($iDB) { parent::__construct($iDB); $this->Name('cat_supp'); $this->KeyName('ID'); $this->ClassSng('clsSupplier'); } public function GetItem_byKey($iKey) { CallEnter($this,__LINE__,__CLASS__.'.GetItem_byKey('.$iKey.')'); $sqlCatKey = $this->objDB->SafeParam($iKey); $objItem = $this->GetData('CatKey="'.$sqlCatKey.'"'); CallExit(__CLASS__.'.GetItem_byKey('.$iKey.') -> new supplier'); return $objItem; } public function DoHomePage() { global $objDataMgr; $objDataMgr->Update_byName('_supplier_ittyps','clsSuppliers.DoHomePage()'); $sql = 'SELECT * FROM _supplier_ittyps ORDER BY Name, ItemCount DESC'; $objRec = $this->objDB->DataSet($sql); $out = ''; if ($objRec->hasRows()) { $objTbl = new clsPageOutput; $objTbl->StartTable('Suppliers'); $strKeyLast = $outCell = ''; while ($objRec->NextRow()) { $strKey = $objRec->CatKey; if ($strKey != $strKeyLast) { $strKeyLast = $strKey; $strKeyLink = strtolower($strKey).'/'; if ($outCell) { $objTbl->ColAdd($outCell); $objTbl->RowStop(); $outCell = ''; } $objTbl->RowStart(); $objTbl->ColAdd(''.$objRec->Name.''); $isFirst = true; } if ($isFirst) { $isFirst = false; } else { $outCell .= ', '; } $strItType = $objRec->ItemType; if ($strItType == '') { $strItType = '?id'.$objRec->ID; } $outCell .= ' '.$objRec->ItemCount.' '.$strItType; } $objTbl->ColAdd($outCell); $objTbl->RowStop(); $out .= $objTbl->EndTable(); } return $out; } } class clsSupplier extends clsDataSet { public function DoPage() { global $objDataMgr; CallEnter($this,__LINE__,'clsSupplier.DoPage()'); $out = ''; assert('$this->ID'); // first, check how many departments supplier has: $objDeptTbl = $this->objDB->Depts(); $objDepts = $objDeptTbl->GetData('isActive AND (ID_Supplier='.$this->ID.')','clsDept','Sort'); if ($objDepts->RowCount() == 1) { // if there's only one department, display that instead of a department listing $out = $objDepts->DoPage(); } else { $objDataMgr->Update_byName('_supplier_ittyps','clsSupplier.DoPage() for '.$this->CatKey); $sql = 'SELECT * FROM _supplier_ittyps WHERE ID='.$this->ID.' ORDER BY Name, ItemCount DESC'; $objItTyps = $this->objDB->DataSet($sql,'clsItTyp'); $isFirst = true; $out .= ''; while ($objItTyps->NextRow()) { if ($isFirst) { $isFirst = false; } else { $out .= ', '; } $out .= ' '.$objItTyps->ItemCount.' '.$objItTyps->ItemType; } $out .= ''; $out .= $objDeptTbl->DoListing_forSupp($this->ID); } CallExit('clsSupplier.DoPage()'); return $out; } public function Link() { $out = ''.$this->Name.''; return $out; } public function URL() { return KWP_CAT_REL.strtolower($this->CatKey).'/'; } } class clsDepts extends clsVbzTable { public function __construct($iDB) { parent::__construct($iDB); $this->Name('cat_depts'); $this->KeyName('ID'); $this->ClassSng('clsDept'); } protected function _newItem() { CallStep('clsDepts._newItem()'); return new clsDept($this); } public function DoListing_forSupp($iSuppID) { CallEnter($this,__LINE__,'clsDepts.DoListing_forSupp('.$iSuppID.')'); $out = '

Departments:

'; $objDepts = $this->GetData('ID_Supplier='.$iSuppID,'clsDept'); $isFirst = true; $isOdd = FALSE; while ($objDepts->NextRow()) { $outDept = $objDepts->DoListing(); if ($outDept) { // only show departments with something in them if ($isOdd) { $cellOpen = ''.$cellOpen.''.$objDepts->Name.''; $isOdd = !$isOdd; $out .= $cellOpen.$outDept.''; } } $out .= '
'; } else { $cellOpen = ''; } $keyDept = $objDepts->PageKey(); $out .= '
'; CallExit('clsDepts.DoListing_forSupp()'); return $out; /**/ } } class clsDept extends clsDataSet { // object cache private $objSupp; public function Supplier() { if (is_object($this->objSupp)) { return $this->objSupp; } else { $idSupp = $this->ID_Supplier; if ($idSupp) { $this->objSupp = $this->objDB->Suppliers()->GetItem($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; $objDataMgr->Update_byName('_dept_ittyps','clsDept.DoListing() for ID='.$this->ID); $sql = 'SELECT * FROM qryItTypsDepts_ItTyps WHERE (ID_Dept='.$this->ID.') ORDER BY cntInPrint DESC'; $objItTyps = $this->objDB->DataSet($sql,'clsItTyp'); return $objItTyps; } public function DoListing() { // PURPOSE: Print this department's information as part of department list assert('$this->ID'); $objItTyps = $this->GetDeptData(); $isFirst = true; $out = ''; while ($objItTyps->NextRow()) { if ($isFirst) { $isFirst = false; } else { $out .= ', '; } $cntInPrint = $objItTyps->cntInPrint; $qtyInStock = $objItTyps->qtyForSale; // TO FIX: This is wrong. Need cntForSale field $cntAvail = $cntInPrint + $qtyInStock; if ($cntAvail == 1) { $strName = $objItTyps->ItTyp_Sng; } else { $strName = $objItTyps->ItTyp_Plr; } $out .= ' '.$cntAvail.' '.$strName; } 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'); $out = ''; $idDept = $this->ID; $objSection = new clsPageOutput(); $objItTyps = $this->GetDeptData(); $objTitles = new clsTitleExt($this->objDB); $objNoImgSect = new clsPageOutput(); $cntSections = 0; while ($objItTyps->NextRow()) { $cntInPrint = $objItTyps->cntInPrint; $qtyInStock = $objItTyps->qtyForSale; // 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_byName('_title_ittyps','clsDept.DoPage() for ID_ItTyp='.$idItTyp.', ID_Dept='.$idDept); $objTitles->Query($sql); // $idTitle = $objTitles->GetValue('ID_Title'); // $objTitles->ID = $idTitle; if ($objTitles->hasRows()) { while ($objTitles->NextRow()) { // make a copy with current row's data $objTitle = new clsDataSet(NULL,$objTitles->Res,$objTitles->Row); //$objTitle = clone $objTitles; $lstTitles[] = $objTitle; // save it in a list } 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->ItTyp_Plr.':',$lstTitles,$objNoImgSect); $out .= $this->objDB->ShowTitles($objItTyps->ItTyp_Plr.':',$lstTitles,$objNoImgSect); } else { echo 'ERROR: No titles found! SQL='.$sql; } unset($lstTitles); $objSection->Clear(); } else { $out .= 'Small coding error: this line should never happen.'; // TO DO: log an error } } if (!$cntSections) { $out .= '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.)'; } 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 ''.$this->Name.''; return ''.$this->Name.''; } } class clsTitles extends clsVbzTable { public function __construct($iDB) { parent::__construct($iDB); $this->Name('cat_titles'); $this->KeyName('ID'); $this->ClassSng('clsTitle'); } /* ACTION: Finds a Title from a CatNum and returns an object for it TO DO: Rename to Get_byCatNum() */ public function GetItem_byCatNum($iCatNum) { global $objDataMgr; CallEnter($this,__LINE__,__CLASS__.'.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_byName('_titles','GetItem_byCatNum('.$iCatNum.')'); $objDataMgr->Update_byName('_depts','GetItem_byCatNum('.$iCatNum.')'); // get data from v_titles $objTitle->Query($sql); $idTitle = $objTitle->ID; assert('is_resource($objTitle->Res)'); 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 clsDataSet { // == STATIC SECTION == const cksTblName = 'cat_titles'; const cksIDName = 'ID'; public static function GetItem($iID) { $sql = 'SELECT * FROM '.self::cksTblName.' WHERE '.self::cksIDName.'="'.$iID.'"'; $objItem = new self; $objItem->Query($sql); return $objItem; } // == DYNAMIC SECTION == // object cache private $objDept; // options public $hideImgs; public function Dept() { if (is_object($this->objDept)) { return $this->objDept; } else { $idDept = $this->ID_Dept; if ($idDept) { $objDept = $this->objDB->Depts()->GetItem($idDept); $this->objDept = $objDept; assert('is_object($objDept)'); return $objDept; } else { return NULL; } } } public function IsActive() { if (is_null($this->DateUnavail)) { $out = TRUE; } else { $out = ($this->DateUnavail > time()); } return $out; } public function DoPage() { global $objDataMgr; $idTitle = $this->ID; assert('$idTitle'); $objSection = new clsPageOutput(); // show small-size images if (!$this->hideImgs) { $objImgs = $this->ListImages('sm'); if ($objImgs->hasRows()) { while ($objImgs->NextRow()) { $strImgTag = $objImgs->AttrDispl; $urlRel = $objImgs->Spec; $idImg = $objImgs->ID; $strImg = 'ImgForSize('big'); if (is_object($objImgBig)) { if ($objImgBig->hasRow()) { $strImg = $objImgBig->Href().$strImg.''; } } $objSection->AddText($strImg); } } else { $objSection->ShowImgUnavail(); } } // now list available items as table $sql = 'SELECT * FROM qryTitles_ItTyps_ItTyps WHERE (ID_Title='.$idTitle.') ORDER BY ItTyp_Sort IS NULL, ItTyp_Sort;'; $objTypes = $this->objDB->DataSet($sql); if ($objTypes->hasRows()) { if (KF_CART_ABSOLUTE) { $urlCart = KWP_CART_ABS; } else { $urlCart = KWP_CART_REL; } $objSection->AddText('
'); $flagDisplayTogether = false; // hard-coded for now while ($objTypes->NextRow()) { $idItTyp = $objTypes->ID_ItTyp; assert('$idItTyp'); $sqlFilt = '(ID_Title='.$idTitle.') AND (ID_ItTyp='.$idItTyp.')'; $sqlSort = 'GrpSort,GrpDescr,ItOpt_Sort'; $objStk = $this->objDB->Items_Stock(); $objItems = $objStk->GetData($sqlFilt,'clsItem',$sqlSort); $idItType = 0; $txtLine = ''.$objTypes->ItTyp_Plr.':'; if ($flagDisplayTogether) { // displaying all items in a single listing $txtBoth .= $txtLine; } else { // set flags to determine which stock-status sections to show $cntInStock = $objTypes->cntStkForSale; $cntForSale = $objTypes->cntForSale; $cntOutStock = $cntForSale - $cntInStock; $txtInStock = $txtOutStock = ''; if ($cntInStock > 0) { $txtInStock .= $txtLine; } if ($cntOutStock > 0) { $txtOutStock .= $txtLine; } } // iterate through items for this type: $strGrpLast = ''; while ($objItems->NextRow()) { $strGrp = $objItems->GrpDescr; $qtyStk = $objItems->qtyForSale; if ($strGrp != $strGrpLast) { $strGrpLast = $strGrp; $strGrpCode = $objItems->GrpCode; $out = ''; $out .= ' — '.$strGrp; if ($strGrpCode) { $out .= ' ('.$strGrpCode.')'; } $out .= ''; $out .= ''; // this should probably be a subroutine... if ($flagDisplayTogether) { $txtBoth .= $out; } else { if ($qtyStk > 0) { $txtInStock .= $out; } else { $txtOutStock .= $out; } } } if ($objItems->isForSale) { $txtLine = $objItems->Print_TableRow(); if ($flagDisplayTogether) { $txtBoth .= $txtLine; } else { if ($qtyStk > 0) { $txtInStock .= $txtLine; } else { $txtOutStock .= $txtLine; } } } } } // DO the actual display of the accumulated text $txtTblOpen = ''; $txtTblHdr = ''; $txtTblFtr = ''; $txtTblShut = '
OptionStatusPriceOrder
Qty.
list
price
'; 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(''.$txtClause.' in stock:'); $objSection->AddText($txtTblHdr); $objSection->AddText($txtInStock); $objSection->AddText($txtTblFtr); $objSection->AddText($txtTblShut); } if ($txtOutStock != '') { if ($txtInStock != '') { $objSection->AddText('

'); } $txtClause = Pluralize($cntOutStock,'This item is','These items are'); $objSection->AddText($txtTblOpen); $objSection->AddText(''.$txtClause.' not in stock'); $txtClause = Pluralize($cntOutStock,'it','them'); $objSection->AddText(', but we can (probably) get '.$txtClause.':'); $objSection->AddText($txtTblHdr); $objSection->AddText($txtOutStock); $objSection->AddText($txtTblFtr); $objSection->AddText($txtTblShut); } /**/ } // $objSection->AddText('

'); $objSection->AddText(''); } else { $objSection->SectionHdr('This title is currently unavailable'); } return $objSection->out; } public function ListImages($iSize) { $sqlFilt = '(ID_Title='.$this->ID.') AND (Ab_Size="'.$iSize.'")'; $objImgs = $this->objDB->Images()->GetData($sqlFilt,'clsImage','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 URL_part() { return strtolower($this->CatNum('/')); } public function URL() { return KWP_CAT_REL.$this->URL_part(); } public function Link() { $strURL = $this->URL(); return ''; } public function LinkName() { return $this->Link().$this->Name.''; } public function LinkName_wt() { // TO DO: make this more configurable $out = '[[vbznet:cat/'.$this->URL_part().'|'.$this->Name.']]'; return $out; } } // extended Title data from v_titles class clsTitlesExt extends clsTitles { public function __construct($iDB) { parent::__construct($iDB); $this->Name('v_titles'); $this->KeyName('ID'); } 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($this,__LINE__,'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 = ''; return $out; } public function URL() { return KWP_CAT_REL.$this->CatWeb.'/'; } } /* -------------------- *\ TITLE/ITTYP hybrid \* -------------------- */ class clsTitleIttyp extends clsDataSet { /* public $ID_ItTyp; //public $ID_Dept; public $cntForSale; public $cntInPrint; public $cntInStock; public $qtyInStock; public $ItTypSng; public $ItTypPlr; */ // object cache private $objIttyp; /* protected function LoadResults() { CallEnter($this,__LINE__,'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->ItTypSng = $this->GetValue('ItTyp_Sng'); $this->ItTypPlr = $this->GetValue('ItTyp_Plr'); if ($this->ID_ItTyp) { } else { echo 'ERROR: ID_ItTyp has no value! data = '; DumpArray($this->Row,TRUE); } CallExit('clsTitleIttyp.LoadResults()'); } */ public function Ittyp() { if (is_null($this->objIttyp)) { $this->objIttyp = VbzClasses::ItTyps()->GetItem($this->ID_ItTyp); } return $this->objIttyp; } } /* -------------------- *\ ITEM classes \* -------------------- */ class clsItems extends clsVbzTable { public function __construct($iDB) { parent::__construct($iDB); $this->Name('cat_items'); $this->KeyName('ID'); $this->ClassSng('clsItem'); } /* ACTION: Finds the Item with the given CatNum, and returns a clsItem object */ public function Get_byCatNum($iCatNum) { $sqlCatNum = $this->objDB->SafeParam($iCatNum); $objItem = $this->GetData('CatNum="'.$sqlCatNum.'"'); if ($objItem->HasRows()) { $objItem->NextRow(); return $objItem; } else { return NULL; } } } /* =============== CLASS: clsItem NOTE: "in stock" always refers to stock for sale, not stock which has already been purchased */ class clsItem extends clsDataSet { // object cache private $objTitle; public function Print_TableRow() { /* ASSUMES: This item is ForSale, so isForSale = true and (qtyForSale>0 || isInPrint) = true This item's data was generated by clsItems_Stock TO DO: create a separate clsItem_Stock class and move this method there. */ $qtyInStock = $this->qtyForSale; if ($qtyInStock) { $strClass = 'inStock'; $strStock = $qtyInStock.' in stock'; } else { $strClass = 'noStock'; } $out = ''; $out .= ' '.$this->ItOpt_Descr; if ($this->isInPrint) { if ($qtyInStock) { $strStatus = $strStock.'; more available'; } else { $strStatus = 'available, not in stock'; } } else { $strStatus = ''.$strStock.' - out of print!'; } $out .= ''.$strStatus.''; $out .= ''.DataCurr($this->PriceSell).''; $out .= ''.''; if ($this->PriceList) { $out .= ''.DataCurr($this->PriceList).''; } $out .= ''; return $out; } public function Title() { $doLoad = TRUE; if (is_object($this->objTitle)) { if ($this->objTitle->ID == $this->ID_Title) { $doLoad = FALSE; } } if ($doLoad) { $this->objTitle = $this->objDB->Titles()->GetItem($this->ID_Title); } return $this->objTitle; } public function ItTyp() { $doLoad = TRUE; if (is_object($this->objItTyp)) { if ($this->objItTyp->ID == $this->ID_ItTyp) { $doLoad = FALSE; } } if ($doLoad) { $this->objItTyp = $this->objDB->ItTyps()->GetItem($this->ID_ItTyp); } return $this->objItTyp; } public function ItOpt() { $doLoad = TRUE; if (is_object($this->objItOpt)) { if ($this->objItOpt->ID == $this->ID_ItOpt) { $doLoad = FALSE; } } if ($doLoad) { $this->objItOpt = $this->objDB->ItOpts()->GetItem($this->ID_ItOpt); } return $this->objItOpt; } public function ShCost() { $doLoad = TRUE; if (is_object($this->objShCost)) { if ($this->objShCost->ID == $this->ID_ShipCost) { $doLoad = FALSE; } } if ($doLoad) { $this->objShCost = $this->objDB->ShipCosts()->GetItem($this->ID_ShipCost); } return $this->objShCost; } public function ShipPriceItem($iZone) { global $listItmFactors; $this->ShCost(); // get the shipping cost object $fltZoneFactor = $listItmFactors[$iZone]; return $this->objShCost->PerItem * $fltZoneFactor; } public function ShipPricePkg($iZone) { global $listPkgFactors; $this->ShCost(); // get the shipping cost object $fltZoneFactor = $listPkgFactors[$iZone]; return $this->objShCost->PerPkg * $fltZoneFactor; } } /* -------------------- *\ ITEM TYPE classes \* -------------------- */ class clsItTyps extends clsVbzTable { public function __construct($iDB) { parent::__construct($iDB); $this->Name('cat_ittyps'); $this->KeyName('ID'); $this->ClassSng('clsItTyp'); } } class clsItTyp extends clsDataSet { public function Name($iCount=-1) { if ($iCount == -1) { $iCount = $this->cntInPrint; } if ($iCount == 1) { return $this->NameSng; } else { return $this->NamePlr; } } } /* -------------------- *\ ITEM OPTION classes \* -------------------- */ class clsItOpts extends clsVbzTable { public function __construct($iDB) { parent::__construct($iDB); $this->Name('cat_ioptns'); $this->KeyName('ID'); $this->ClassSng('clsItOpt'); } } class clsItOpt extends clsDataSet { } /* -------------------- *\ SHIP COST classes \* -------------------- */ class clsShipCosts extends clsVbzTable { public function __construct($iDB) { parent::__construct($iDB); $this->Name('cat_ship_cost'); $this->KeyName('ID'); $this->ClassSng('clsShipCost'); } } class clsShipCost extends clsDataSet { } /* -------------------- *\ STOCK ITEM classes \* -------------------- */ // TO DO: explain the difference between clsItems_Stock and clsStkItems class clsItems_Stock extends clsItems { public function __construct($iDB) { parent::__construct($iDB); $this->Name('qryCat_Items_Stock'); $this->KeyName('ID'); } } class clsStkItems extends clsVbzTable { public function __construct($iDB) { parent::__construct($iDB); $this->Name('stk_items'); $this->KeyName('ID'); } 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->NextRow()) { assert('is_resource($objStock->Res)'); if ($objStock->RowCount()) { assert('$objStock->RowCount() == 1'); return $objStock->Qty; } } else { return NULL; } } } /* -------------------- *\ IMAGE classes \* -------------------- */ class clsImages extends clsVbzTable { public function __construct($iDB) { parent::__construct($iDB); $this->Name('cat_images'); $this->KeyName('ID'); $this->ClassSng('clsImage'); } } class clsImage extends clsDataSet { // == STATIC SECTION == const cksTblName = 'cat_images'; // == DYNAMIC SECTION == // object cache private $objTitle; 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'; } $sqlFilt = '(ID_Title='.$this->ID_Title.') AND (AttrFldr'.$sqlAttr.') AND (Ab_Size="'.$iSize.'")'; $objImgOut = $this->objDB->Images()->GetData($sqlFilt); return $objImgOut; } public function Title() { if (!is_object($this->objTitle)) { $this->objTitle = $this->objDB->Titles()->GetItem($this->ID_Title); } return $this->objTitle; } public function DoPage() { global $vbgImgSize; $objTitle = $this->Title(); $strCatNum = $objTitle->CatNum(); $strTitle = $objTitle->Name; $htmlTitle = KS_STORE_NAME.' - '.$strCatNum.' “'.$strTitle.'”'; echo ''.$htmlTitle.''; echo ''; echo '
'; echo ''.$strTitle.'
'.$strCatNum.' - title ID #'.$this->ID_Title.''; echo '
'; // show list of available image sizes (except th and sm) $objImgs = $this->ListImages_sameAttr(); $strOut = NULL; if ($objImgs->hasRows()) { $strImgCount = 0; while ($objImgs->NextRow()) { $strImgType = $objImgs->Ab_Size; if (($strImgType != 'th') && ($strImgType != 'sm')) { $strImgCount++; $strDesc = $vbgImgSize[$strImgType]; if ($objImgs->ID == $this->ID) { $strImgTag = ''.$strDesc.''; } else { $strImgTag = $objImgs->Href(TRUE).$strDesc.''; } if ($strOut) { $strOut .= ' .. '; } $strOut .= $strImgTag; } } if ($strImgCount > 1) { echo ''; } } $strOut = NULL; // show list of available images for this title at this size $objImgs = $this->ListImages_sameSize(); if ($objImgs->NextRow()) { $strImgCount = 0; $strOut .= ''; if ($objImgs->hasRows()) { while ($objImgs->NextRow()) { $strImgFldr = $objImgs->AttrFldr; $strImgDescr = $objImgs->AttrDispl; $strImgCount++; if ($strOut) { $strOut .= ' .. '; } if ($objImgs->ID == $this->ID) { $strOut .= ''.$strImgDescr.''; } else { $strOut .= $objImgs->Href(TRUE).$strImgDescr.''; } } if ($strImgCount > 1) { echo ''; } } } echo '
sizes :'.$strOut.': sizes
views :'.$strOut.': views
'; echo $objTitle->Link().'ordering page
'; echo $this->ImgSrc(); echo ''; } public function ListImages_sameAttr() { if ($this->AttrFldr) { $sqlFilt = '(ID_Title='.$this->ID_Title.') AND (AttrFldr="'.$this->AttrFldr.'")'; } else { $sqlFilt = '(ID_Title='.$this->ID_Title.')'; } $objImgOut = $this->objDB->Images()->GetData($sqlFilt);
   return $objImgOut;
 }
 public function ListImages_sameSize() {
   $sqlFilt = '(ID_Title='.$this->ID_Title.') AND (Ab_Size="'.$this->Ab_Size.'")';
   $objImgOut = $this->objDB->Images()->GetData($sqlFilt);
   return $objImgOut;
 }
 public function Href($iAbs=false) {
   $strFldrRel = $this->AttrFldr;
   if ($strFldrRel) {
     $strFldrRel .= '-';
   }
   $strFldrRel .= $this->Ab_Size;
   if ($iAbs) {
     $strFldr = $this->Title()->URL().'/'.$strFldrRel;
   } else {
     $strFldr = $strFldrRel;
   }
   return '<a href="'.$strFldr.'/">';
 }
 public function ImgSrc() {
   return '<img src="'.KWP_IMG_MERCH.$this->Spec.'">';
 }

}

/* ------------------ *\

   CATALOG BROWSING

\* ------------------ */ class clsTopics extends clsVbzTable {

 public function __construct($iDB) {
   parent::__construct($iDB);
     $this->Name('brs_topics');
     $this->KeyName('ID');
     $this->ClassSng('clsTopic');
 }
 public function DoIndex() {
   global $objDataMgr;
   CallEnter($this,__LINE__,'clsTopics.DoIndex()');
   $objSection = new clsPageOutput();
   $objTopics = $this->GetData('ID_Parent IS NULL',NULL,'Sort,Name,NameTree');
   while ($objTopics->NextRow()) {
     if ($isFirst) {
       $isFirst = false;
       $objSection->SectionHdr('Root Topics');
     } else {
       $objSection->AddText($objTopics->Name.'
'); } }
   CallExit('clsTopic.DoIndex()');
   return $objSection->out;
 }

} class clsTopic extends clsDataSet { /*

 public $ID_Parent;
 public $Name;
 public $NameTree;
 public $NameFull;
 public $Variants;
 public $Mispeled;
 protected function LoadResults() {
   CallEnter($this,__LINE__,'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 $objDataMgr;
   CallEnter($this,__LINE__,'clsTopic.DoPage()');
   assert('$this->ID');
   $objSection = new clsPageOutput();
   $objTitles = $this->objDB->DataSet('SELECT * FROM brs_titles_x_topics WHERE ID_Topic='.$this->ID);
   while ($objTitles->NextRow()) {
     if ($isFirst) {
       $isFirst = false;
       $objSection->SectionHdr('Titles');
     } else {
       $objSection->AddText($objTitles->Name.'
'); } }
   CallExit('clsTopic.DoPage()');
   return $out;
 }
 public function WebName() {
   return sprintf(KS_FMT_TOPICID,$this->ID);
 }

}

/* ------------------ *\

   EVENT LOGGING

\* ------------------ */ class clsEvents extends clsVbzTable {

 public function __construct($iDB) {
   assert('is_object($iDB)');
   parent::__construct($iDB);
     $this->Name('event_log');
     $this->KeyName('ID');
 }
 public function LogEvent($iWhere,$iParams,$iDescr,$iCode,$iIsError,$iIsSevere) {
   global $sql, $vgUserName;
   $sql = 'INSERT INTO `'.$this->Name().'` (EvWhen,EvWhere,Params,Descr,Code,VbzUser,SysUser,Machine,isError,isSevere)'.

'VALUES(NOW(),"'.$iWhere.'","'.$iParams.'","'.$iDescr.'",'.SQLValue($iCode).','.SQLValue($vgUserName). ',NULL,"'. $_ENV['REMOTE_ADDR'].'",'. ($iIsError?'TRUE':'FALSE').','. ($iIsSevere?'TRUE':'FALSE').');';

   $this->objDB->Exec($sql);  
 }

}

/* ==================== *\

   UTILITY FUNCTIONS

\* ==================== */

function DataCents($iCents,$iPfx='$') {

 $out = $iPfx.sprintf("%01.2f",$iCents/100);
 return $out;

} function DataCurr($iCurr,$iPfx='$') {

 $out = $iPfx.sprintf("%01.2f",$iCurr);
 return $out;

} function DataDate($iDate) {

   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;

} function DataDateTime($iDate) {

   if (is_string($iDate)) {

if ($iDate == ) { $out = '-'; } else { $objDate = new DateTime($iDate); $out = $objDate->format('Y-m-d H:i'); }

   } else {
     $out = ;
   }
   return $out;

} function IsEmail($iAddr) {

   $ok = preg_match('/.{1}.*[\@].{1}.*[\.][a-z]{2}.*/i', $iAddr );
   return $ok;

}

/* ==================== *\

   MISSING FUNCTIONS

\* ==================== */ if (!function_exists('http_redirect')) {

   function http_redirect($iURL) {

header('Status: 301 Moved Permanently',TRUE); header('Location: '.$iURL,TRUE);

   }

} </php>