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
// 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++;
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.)
';
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('');
$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;
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.' ');
}
}