About
- Purpose: Classes for displaying different types of catalog display pages
- History:
- 2009-03-07 Transcribed from working code at vbz.net
- 2009-10-06 Latest code - large chunks working, focus of development no longer on this module
- 2011-12-18 long-overdue update
- 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
2009-10-06 (Wzl) Changed most clsTitle* classes to clsVbzTitle* (conflict with something - w3tpl?)
Additional changes needed so it would work on Rizzo
2010-06-12 (Wzl) A little cleanup; clsTopic::Titles()
2010-06-14 (Wzl) clsVbzTable::GetItem() handles non-numeric IDs by creating new object and passing along ID
2011-01-18 (Wzl) moved clsTopic(s) to topic.php
define('kEmbeddedPagePrefix','embed:');
/*
if (defined( '__DIR__' )) {
$fpThis = __DIR__;
} else {
$fpThis = dirname(__FILE__);
}
if (!defined('LIBMGR')) {
require(KFP_LIB.'/libmgr.php');
}
clsLibMgr::Add('strings', KFP_LIB.'/strings.php',__FILE__,__LINE__);
clsLibMgr::Add('string.tplt', KFP_LIB.'/StringTemplate.php',__FILE__,__LINE__);
clsLibMgr::Add('cache' , KFP_LIB.'/cache.php',__FILE__,__LINE__);
clsLibMgr::Add('dtree', KFP_LIB.'/dtree.php',__FILE__,__LINE__);
clsLibMgr::Add('events', KFP_LIB.'/events.php',__FILE__,__LINE__);
clsLibMgr::Add('vbz.data', KFP_LIB_VBZ.'/vbz-data.php',__FILE__,__LINE__);
clsLibMgr::Add('topic', KFP_LIB_VBZ.'/topic.php',__FILE__,__LINE__);
clsLibMgr::Load('strings',__FILE__,__LINE__);
clsLibMgr::Load('string.tplt',__FILE__,__LINE__);
clsLibMgr::Load('cache',__FILE__,__LINE__);
clsLibMgr::Load('dtree',__FILE__,__LINE__);
clsLibMgr::Load('events',__FILE__,__LINE__);
clsLibMgr::Load('vbz.data',__FILE__,__LINE__);
clsLibMgr::Load('topic',__FILE__,__LINE__);
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
// - 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');
// - browsing
define('ksTbl_title_topics','brs_titles_x_topics');
global $vbgImgSize;
$vbgImgSize = array(
'th' => 'thumbnail',
'sm' => 'small',
'big' => 'large',
'huge' => 'huge',
'zoom' => 'detail');
// shipping zone data:
global $listShipListDesc,$listItmFactors,$listPkgFactors; // there's got to be a better way to do this...
$listShipListDesc['US'] = 'United States';
$listShipListDesc['CA'] = 'Canada';
$listShipListDesc['INT'] = 'International';
// -- shipping charge adjustment factors:
$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 = $_SERVER['SERVER_NAME'];
// SET UP DEPENDENT VALUES
/*
if ($strCurServer != KS_TOOLS_SERVER) {
$fpTools = $fwpAbsTools;
$fpPages = $fwpAbsPages;
}
$fwpLogo = $fpTools.'/img/logos/v/';
/*====
NOTES:
2011-02-02 This could use some rewriting. A lot of it is kind of pointless,
and other parts duplicate RichText objects.
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 is specifically duplicated
$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 .= '
<tbody></tbody>
<tbody></tbody>No Images Available for this item :-( |
|
';
return $this->out;
}
}
class clsCacheFile_vbz extends clsCacheFile {
public function __construct() {
parent::__construct(KFP_CACHE);
}
}
class clsVbzData extends clsDatabase {
protected $objPages;
public function __construct($iSpec) {
parent::__construct($iSpec);
$this->Open();
}
// cache manager
protected function CacheMgr_empty() {
return new clsCacheMgr($this);
}
public function CacheMgr() {
if (empty($this->objCacheMgr)) {
$objCache = $this->CacheMgr_empty();
$objCache->SetTables('cache_tables','cache_queries','cache_flow','cache_log');
$this->objCacheMgr = $objCache;
}
return $this->objCacheMgr;
}
// 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($iID=NULL) {
return $this->Make('clsVbzTitles',$iID);
}
public function Items() {
return $this->Make('clsItems');
}
public function Items_Stock() {
return $this->Make('clsItems_Stock');
}
public function Items_Cat() {
return $this->Make('clsItems_info_Cat');
}
public function ItTyps() {
return $this->Make('clsItTyps');
}
public function ItOpts() {
return $this->Make('clsItOpts');
}
public function ShipCosts() {
return $this->Make('clsShipCosts');
}
public function Folders() {
return $this->Make('clsVbzFolders');
}
public function Images() {
return $this->Make('clsImages');
}
public function StkItems() {
return $this->Make('clsStkItems');
}
public function Topics($iID=NULL) {
return $this->Make('clsTopics',$iID);
}
public function TitleTopic_Titles() {
return $this->Make('clsTitleTopic_Titles');
}
public function TitleTopic_Topics() {
return $this->Make('clsTitleTopic_Topics');
}
public function VarsGlobal() {
return $this->Make('clsGlobalVars');
}
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 Formatter() {
if (!isset($this->objFmt)) {
$this->objFmt = new clsPageOutput();
}
return $this->objFmt;
}
public function SectionHdr($iTitle) {
/*
$out = '
'.$iTitle.'
';
return $out;
$this->Formatter()->Clear();
return $this->Formatter()->SectionHdr($iTitle);
}
/*----
NOTES:
2011-02-02 This really should somehow provide a more general service. Right now, it's only used for displaying
department pages -- but topic pages and searches could make use of it as well, if there were some tidy way
to abstract the collecting of the price and stock data. This will probably necessitate adding hi/low price
data to _titles and possibly _dept_ittyps (it's already in _title_ittyps).
HISTORY:
2011-02-02
* Removed assertion that $objImgs->Res is a resource, because if there are no thumbnails for this title,
then apparently it isn't, and apparently RowCount() handles this properly.
* Also fixed references to qtyForSale -- should be qtyInStock.
*/
public function ShowTitles($iHdrText,$iList,$objNoImgSect) {
$cntImgs = 0;
$outImgs = ;
foreach ($iList as $i => $row) {
$objTitle = $this->Titles()->GetItem($row['ID']);
$objImgs = $objTitle->ListImages('th');
//assert('is_resource($objImgs->Res); /* TYPE='.get_class($objImgs).' SQL='.$objImgs->sqlMake.' */');
$currMinPrice = $row['currMinPrice'];
$currMaxPrice = $row['currMaxPrice'];
$strPrice = DataCurr($currMinPrice);
if ($currMinPrice != $currMaxPrice) {
$strPrice .= '-'.DataCurr($currMaxPrice);
}
if ($objImgs->RowCount()) {
$cntImgs++;
$strCatNum = $objTitle->CatNum();
$strTitleTag = '"'.$objTitle->Name.'" ('.$strCatNum.')';
$strTitleLink = $objTitle->Link();
while ($objImgs->NextRow()) {
$strImgTag = $strTitleTag.' - '.$strPrice;
$qtyStk = $row['qtyInStock'];
if ($qtyStk) {
$strImgTag .= ' - '.$qtyStk.' in stock';
}
$outImgs .= $strTitleLink.'<img class="thumb" src="'.$objImgs->WebSpec().'" title="'.$strImgTag.'"></a>';
}
} else {
if (!$objNoImgSect->inTbl) {
$objNoImgSect->StartTable('titles without images:');
$objNoImgSect->AddText('Cat. #TitlePrice
Rangeto
orderstatus');
}
$objNoImgSect->RowStart();
$objNoImgSect->ColAdd(''.$objTitle->CatNum().'');
$objNoImgSect->ColAdd($objTitle->Name);
$objNoImgSect->ColAdd($strPrice);
$objNoImgSect->ColAdd('['.$objTitle->Link().'order</a>]');
$qtyStk = $row['qtyInStock'];
if ($qtyStk) {
$strStock = ''.$qtyStk.' in stock';
if ($row['cntInPrint'] == 0) {
$strStock .= ' - OUT OF PRINT!';
}
$objNoImgSect->ColAdd($strStock);
} else {
$objNoImgSect->ColAdd('<a title="explanation..." href="'.KWP_HELP_NO_STOCK_BUT_AVAIL.'">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: clsVbzSkin
PURPOSE: Abstract skin class
abstract class clsVbzSkin extends clsVbzData {
/*-----
USAGE: Normal main entry point -- should be called from index.php
*/
public function DoPage() {
try {
$this->DoPreContent();
$this->DoContent();
$this->DoPostContent();
} catch(exception $e) {
$this->EmailException($e);
}
}
/*----
HISTORY:
2011-03-31 added Page and Cookie to list of reported variables
*/
protected function EmailException(exception $e) {
$msg = $e->getMessage();
$out = 'Description: '.($e->getMessage());
$out .= "\nStack trace:\n".($e->getTraceAsString());
$guest_ip = $_SERVER['REMOTE_ADDR'];
$guest_browser = $_SERVER['HTTP_USER_AGENT'];
$guest_referer = NzArray($_SERVER,'HTTP_REFERER');
$guest_page = $_SERVER['REQUEST_URI'];
$guest_cookie = $_SERVER['HTTP_COOKIE'];
$out .= <<<__END__
Client information:
- IP Addr: $guest_ip
- Browser: $guest_browser
- Page : $guest_page
- Cookie : $guest_cookie
- Referer: $guest_referer
__END__;
$subj = 'vbz error from IP '.$guest_ip;
$ok = mail(KS_TEXT_EMAIL_ADDR_ERROR,$subj,$out);
echo <<<__END__
Ack! We seem to have a small problem here. (If it was a large problem, you wouldn't be seeing this message.)
The webmaster is being alerted about this.
Meanwhile, you might try reloading the page -- a lot of errors are transient,
which makes them hard to fix, which is why there are more of them than the other kind.
We apologize for the nuisance.
Error Message: $msg
__END__;
// FUTURE: log the error and whether the email was successful
}
/*-----
ACTION: Displays everything *before* the main page contents
*/
protected function DoPreContent() {
$this->ParseInput();
$this->HandleInput();
$this->RenderHdrBlocks();
}
/*-----
ACTION: Displays everything *after* the main page contents
*/
protected function DoPostContent() {
$this->RenderFtrBlocks();
}
// ABSTRACT section //
/*-----
ACTION: Displays the main page contents
*/
protected abstract function DoContent();
/*-----
ACTION: Grab any expected input and interpret it
*/
protected abstract function ParseInput();
/*-----
ACTION: Take the parsed input and do any needed processing (e.g. looking up data)
*/
protected abstract function HandleInput();
/*-----
ACTION: Render any output that appears *before* the main content
*/
protected abstract function RenderHdrBlocks();
/*-----
ACTION: Render any output that appears *after* the main content
*/
protected abstract function RenderFtrBlocks();
}
/* ===================
CLASS: clsVbzSkin_Standard
PURPOSE: Standard skin class
Will later be replaceable with other skins
abstract class clsVbzSkin_Standard extends clsVbzSkin {
/*
protected function DoContent() {
}
protected function ParseInput() {
}
protected function HandleInput() {
}
protected function RenderHdrBlocks() {
$this->RenderHtmlStart();
$this->RenderContentHdr();
$this->DoSidebar();
}
protected function RenderFtrBlocks() {
$this->RenderContentFtr();
$this->RenderHtmlStop();
}
protected function RenderContentFtr() {
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 '
';
$didPage = true;
}
protected function RenderHtmlStop() {
echo "\n</body>\n</html>";
}
// NEW METHODS for this class //
protected function DoSidebar() {
$objCache = $this->CacheMgr();
// TO DO: these should be pulled from the [stats] table
/*
if ($objCache->dtNewest) {
$timeSidebarBuild=$objCache->dtNewest;
} else {
$timeSidebarBuild = NULL;
}
$timeSidebarBuild = NULL;
$statsQtyTitlesAvail = 2245;
$statsQtyStockPieces = 1395;
$statsQtyStockItems = 753;
$statsQtyArtists = 136;
$statsQtyTopics = 1048;
//---------
echo '
';
}
protected function DoSepBar() {
echo $this->Render_HLine();
}
public function Render_HLine($iHeight=NULL) {
global $fpTools;
$htHt = is_null($iHeight)?:('height='.$iHeight);
return '<img src="'.$fpTools.'/img/bg/hlines/"'.$htHt.' 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_HELP_HOME,'help','help!','help');
}
// NEW METHODS for this class //
/*----
PURPOSE: Renders HTML inside <head></head> section
HISTORY:
2011-01-11 Created
*/
protected function RenderHtmlHeaderSection() {
$strTitle = KS_STORE_NAME.' - '.$this->strName;
$out = "\n<title>$strTitle</title>";
$arVars = array('sheet' => $this->strSheet);
$objStrTplt = new clsStringTemplate_array(NULL,NULL,$arVars);
$objStrTplt->MarkedValue(KHT_PAGE_STYLE);
$out .= $objStrTplt->Replace();
//$out .= KHT_PAGE_STYLE;
if (!empty($this->strName)) {
$ftName = ': '.htmlspecialchars($this->strName);
} else {
$ftName = ;
}
$strContent = KS_STORE_NAME_META.$ftName;
$out .= "\n<meta name=description content=\"$strContent\">";
return $out;
}
/*----
PURPOSE: Renders HTML up to beginning of BODY.
HISTORY:
2011-01-11 Extracted everything between <head> and </head> into RenderHtmlHeaderSection()
*/
protected function RenderHtmlStart() {
//$this->strCalcTitle = KS_STORE_NAME.' - '.$this->strName;
$out = KHT_PAGE_DOCTYPE;
$out .= "\n\n";
$out .= $this->RenderHtmlHeaderSection();
$out .= "\n";
$out .= KHT_PAGE_BODY_TAG;
echo $out;
}
protected function RenderContentHdr() {
global $fwpLogo;
//$strWikiPg = $this->strWikiPg;
// begin content header
echo '
';
echo '';
// === LEFT HEADER: Title ===
echo '';
// === END LEFT HEADER ===
// === RIGHT HEADER: nav icons ===
echo '';
// === END RIGHT HEADER ===
echo "\n';
echo '';
if ($this->strTitleContext) {
echo ''.KS_STORE_NAME.': '.$this->strTitleContext.' ';
}
echo ''.$this->strTitle.' | ';
$this->DoToolbar();
echo ' | \n |
";
}
}
/* ===================
CLASS: clsPage
PURPOSE: Handles display of different page types
TO DO: These classes (clsPage and descendants) need to be reorganized (they're a mess)
and also set up so we can create different skins.
*/
abstract class clsPage extends clsVbzSkin_Standard {
// 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();
}
protected function HandleInput() {
$this->strSheet = 'browse'; // default
}
/*-----
IMPLEMENTATION: Retrieves request from URL and parses it
URL data identifies page, keyed to cat_pages data
*/
protected function ParseInput() {
if (isset($_SERVER['PATH_INFO'])) {
$strReq = $_SERVER['PATH_INFO'];
} else {
$strReq = '';
}
$this->strReq = $strReq;
if (strrpos($strReq,'/')+1 < strlen($strReq)) {
$strRedir = KWP_CAT_REL.substr($strReq,1).'/';
header('Location: '.$strRedir);
exit; // retry with new URL
}
}
// DIFFERENT TYPES OF PAGES
protected function DoNotFound() {
$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;
}
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) {
echo '';
}
}
}
}
class clsPageCat extends clsPage {
private $objCatPage; // object for identifying page to display
protected function RenderHdrBlocks() {
if ($this->useSkin) {
parent::RenderHdrBlocks();
}
}
protected function RenderFtrBlocks() {
if ($this->useSkin) {
parent::RenderFtrBlocks();
}
}
protected function HandleInput() {
parent::HandleInput();
$strReq = $this->strReq;
$this->objCatPage = $this->Pages()->GetItem_byKey($strReq);
$objPage = $this->objCatPage;
$this->useSkin = TRUE;
if ($this->strReq) {
if (is_object($objPage)) {
switch ($objPage->Type) {
case 'S':
$this->DoCatSupp();
break;
case 'D':
$this->DoCatDept();
break;
case 'T':
$this->DoCatTitle();
break;
case 'I':
$this->useSkin = FALSE;
$this->DoCatImage();
break;
}
} else {
$this->DoNotFound();
}
} else {
$this->DoCatHome();
}
}
public function DoContent() {
echo $this->strContText;
}
// 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() {
$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() {
$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());
}
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();
$idRow = $this->objCatPage->ID_Row;
$objTitle = $objTitleTbl->GetItem($idRow);
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()');
}
}
/* ===========================
*** CATALOG DATA CLASSES ***
*/
class clsCatPages extends clsVbzTable {
public function __construct($iDB) {
parent::__construct($iDB);
$this->Name('cat_pages'); // cache
//$this->Name('qryCat_pages'); // live data
$this->KeyName('AB');
$this->ClassSng('clsCatPage');
}
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 function is named wrong, and needs to be rewritten anyway
// $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 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');
$this->ActionKey('supp');
}
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;
}
/*----
HISTORY
2010-11-12 disabled automatic cache update
*/
protected function DataSet_forStore($iClass=NULL) {
//$objCache = $this->objDB->CacheMgr();
//$objCache->Update_byName('_supplier_ittyps','clsSuppliers.DoHomePage()');
$sql = 'SELECT * FROM _supplier_ittyps ORDER BY Name, ItemCount DESC';
$objRows = $this->objDB->DataSet($sql,$iClass);
return $objRows;
}
public function DoHomePage() {
$out = '';
$objRec = $this->DataSet_forStore();
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 {
/*----
ACTION: Finds the Item for this Supplier with the given supplier CatNum
RETURNS: object of type requested by user; defaults to clsItem. NULL if not found.
DEPRECATED -- use GetItem_bySCatNum()
*/
public function GetItem_bySuppCatNum($iCatNum,$iClass=NULL) {
return $this->GetItem_bySCatNum($iCatNum);
}
/*----
ACTION: Checks the given catalog number to see if it corresponds to a given item for the current supplier
INPUT: supplier catalog number
OUTPUT: item object (if found) or NULL (if not found)
HISTORY:
2011-01-09 Moved here from VbzAdminSupplier; replaces GetItem_bySuppCatNum()
*/
public function GetItem_bySCatNum($iSCat) {
$objTblItems = $this->objDB->Items();
$sqlFind = '(ID_Supp='.$this->ID.') AND (Supp_CatNum="'.$iSCat.'")';
$objItem = $objTblItems->GetData($sqlFind);
if ($objItem->HasRows()) {
$objItem->NextRow();
return $objItem;
} else {
return NULL;
}
}
/*----
ACTION: Finds the Title for this Supplier with the given CatKey
RETURNS: object of type requested by user; defaults to clsVbzTitle. NULL if not found.
HISTORY:
2010-11-07 Created for Title editing page -- need to check for duplicate CatKey before saving.
*/
public function GetTitle_byCatKey($iCatKey,$iClass='clsVbzTitle') {
$sqlCatKey = $this->objDB->SafeParam($iCatKey);
$sqlFilt = '(ID_Supplier='.$this->ID.') AND (CatKey="'.$sqlCatKey.'")';
$objTitle = $this->objDB->Titles_Cat()->GetData($sqlFilt,$iClass);
if ($objTitle->HasRows()) {
$objTitle->NextRow();
return $objTitle;
} else {
return NULL;
}
}
/*----
ACTION: Searches for Titles whose CatKeys include the given string
PURPOSE: used during renaming of supplier-recycled catalog numbers, so we can see if that number
has been recycled before and avoid having to repeatedly try new names
HISTORY:
2010-11-08 Created for title editing page
*/
public function GetTitles_byCatKey($iCatKey,$iClass='clsVbzTitle') {
$sqlCatKey = $this->objDB->SafeParam($iCatKey);
$sqlFilt = '(ID_Supplier='.$this->ID.') AND (CatKey LIKE "%'.$sqlCatKey.'%")';
$objTitle = $this->objDB->Titles_Cat()->GetData($sqlFilt,$iClass);
if ($objTitle->HasRows()) {
$objTitle->NextRow();
return $objTitle;
} else {
return NULL;
}
}
protected function DeptsData_forCount($iClass='clsDept') {
$objTbl = $this->objDB->Depts();
$objRows = $objTbl->GetData('isActive AND (ID_Supplier='.$this->ID.')',$iClass,'Sort');
return $objRows;
}
/*----
USED BY: $this->DeptsPage_forStore()
RETURNS: array of data for the current supplier
array[rows] = source dataset -- each row is an ItTyp within a Department
array[depts][ID_Dept][ID_ItTyp] = count of items for sale by department and item type
array[supp][ID_ItTyp] = count of items for sale by item type
HISTORY:
2011-02-02 switched data source from qryItTypsDepts_ItTyps to _dept_ittyps
Page was not displaying at all. Some additional changes were necessary.
*/
protected function DeptsData_forStore() {
if (is_null($this->arDeptsData)) {
//$objRows = $this->objDB->DataSet('SELECT * FROM qryItTypsDepts_ItTyps WHERE ID_Supplier='.$this->ID);
$objRows = $this->objDB->DataSet('SELECT * FROM _dept_ittyps WHERE ID_Supp='.$this->ID);
while ($objRows->NextRow()) {
$idItTyp = $objRows->ID_ItTyp;
$intCntForSale = $objRows->cntForSale;
if (!isset($arObjs[$idItTyp])) {
$objItTyp = $this->Engine()->ItTyps()->SpawnItem();
$arObjs[$idItTyp] = $objItTyp;
$objItTyp->Row['NameSng'] = $objRows->Value('ItTypNameSng');
$objItTyp->Row['NamePlr'] = $objRows->Value('ItTypNamePlr');
$objItTyp->Row['cntForSale'] = 0; // initialize the count
}
// accumulate the list of everything this supplier has:
$idSupp = $objRows->ID_Supplier;
$objItTyp->Row['cntForSale'] += $intCntForSale;
// accumulate the department listing:
$idDept = $objRows->Value('ID_Dept');
$arDeptCntForSale[$idDept][$idItTyp] = $intCntForSale;
}
$arOut['rows'] = $objRows;
$arOut['depts'] = $arDeptCntForSale;
$arOut['supp'] = $arObjs;
$this->arDeptsData = $arOut;
}
return $this->arDeptsData;
}
/*----
ACTION: Generates the item-type-count summary for the Supplier's index page
*/
public function DoPiece_ItTyp_Summary() {
$arData = $this->DeptsData_forStore();
$arObjs = $arData['supp'];
$outRow = '';
foreach ($arObjs as $id=>$obj) {
$objTyp = $obj;
$cnt = $objTyp->Value('cntForSale');
if ($cnt > 0) {
$strType = $objTyp->Name($cnt);
if ($outRow != '') {
$outRow .= ', ';
}
$outRow .= ''.$cnt.' '.$strType;
}
}
$out = ''.$outRow.'';
return $out;
}
/*----
ACTION: Generates the table of departments and the summary of items available for each
*/
public function DoPiece_Dept_ItTyps() {
$arData = $this->DeptsData_forStore();
$arObjs = $arData['supp'];
$arDeptCntForSale = $arData['depts'];
$out = '';
$isOdd = FALSE;
$fpSupp = KWP_CAT_REL.strtolower($this->Value('CatKey')).'/';
foreach ($arDeptCntForSale as $idDept=>$arCnts) {
$isOdd = !$isOdd;
if ($isOdd) {
$cellOpen = ''.$cellOpen.''.$strName.'';
$out .= $cellOpen.$outRow.'';
}
}
$out .= '';
} else {
$cellOpen = ' | ';
}
$outRow = '';
foreach ($arCnts as $id=>$cnt) {
if ($cnt > 0) {
$objTyp = $arObjs[$id];
$strType = $objTyp->Name($cnt);
if ($outRow != '') {
$outRow .= ', ';
}
$outRow .= ''.$cnt.' '.$strType;
}
}
if ($outRow != '') {
$objDept = $this->objDB->Depts()->GetItem($idDept);
$strPageKey = $objDept->PageKey();
$strName = $objDept->Name;
$out .= ' |
|
';
return $out;
}
protected function DeptsPage_forStore() {
$out = $this->DoPiece_ItTyp_Summary();
$out .= $this->Engine()->SectionHdr('Departments:');
$out .= $this->DoPiece_Dept_ItTyps();
return $out;
}
public function 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');
$objDepts = $this->DeptsData_forCount();
$intRows = $objDepts->RowCount();
if ($intRows == 1) {
// if there's only one department, display that instead of a department listing
$objDepts->NextRow(); // get the first/only dept
$out = $objDepts->DoPage();
} else {
$out .= $this->DeptsPage_forStore();
}
return $out;
}
public function ShopLink($iText=NULL) {
if (is_null($iText)) {
$strText = $this->Name;
} else {
$strText = $iText;
}
$out = ''.$strText.'';
return $out;
}
public function Link() { return $this->ShopLink(); }
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');
$this->ActionKey('dept');
}
protected function _newItem() {
CallStep('clsDepts._newItem()');
return new clsDept($this);
}
// THIS FUNCTION IS DEPRECATED
/*
public function DoListing_forSupp($iSuppID) {
CallEnter($this,__LINE__,'clsDepts.DoListing_forSupp('.$iSuppID.')');
//$objRows = $this->objDB->DataSet('SELECT * FROM qryItTypsDepts_ItTyps WHERE ID_Supplier='.$iSuppID);
$objRows = $this->Data_forStore();
while ($objRows->NextRow()) {
$idItTyp = $objRows->ID_ItTyp;
$intCntForSale = $objRows->cntForSale;
$arTypSng[$idItTyp] = $objRows->ItTyp_Sng;
$arTypPlr[$idItTyp] = $objRows->ItTyp_Plr;
// accumulate the list of everything this supplier has:
$idSupp = $objRows->ID_Supplier;
if (isset($arSuppCntForSale[$idItTyp])) {
$arSuppCntForSale[$idItTyp] += $intCntForSale;
} else {
$arSuppCntForSale[$idItTyp] = $intCntForSale;
}
// accumulate the department listing:
$idDept = $objRows->ID_Dept;
$arDeptCntForSale[$idDept][$idItTyp] = $intCntForSale;
}
// Now present the accumulated data:
// - SUPPLIER:
$outRow = '';
foreach ($arSuppCntForSale as $idType=>$cnt) {
if ($cnt == 1) {
$strType = $arTypSng[$idType];
} else {
$strType = $arTypPlr[$idType];
}
if ($outRow != '') {
$outRow .= ', ';
}
$outRow .= ''.$cnt.' '.$strType;
}
$out = ''.$outRow.'';
// - DEPARTMENTS:
$out .= 'Departments:
';
$isOdd = FALSE;
foreach ($arDeptCntForSale as $idDept=>$arCnts) {
$isOdd = !$isOdd;
if ($isOdd) {
$cellOpen = ''.$cellOpen.''.$strName.'';
$outRow = '';
foreach ($arCnts as $idType=>$cnt) {
if ($cnt == 1) {
$strType = $arTypSng[$idType];
} else {
$strType = $arTypPlr[$idType];
}
if ($outRow != '') {
$outRow .= ', ';
}
$outRow .= ''.$cnt.' '.$strType;
}
$out .= $cellOpen.$outRow.'';
}
$out .= '';
} else {
$cellOpen = ' | ';
}
$objDept = $this->objDB->Depts()->GetItem($idDept);
$strPageKey = $objDept->PageKey();
$strName = $objDept->Name;
$out .= ' |
|
';
CallExit('clsDepts.DoListing_forSupp()');
return $out;
}
/**/
}
class clsDept extends clsDataSet {
// object cache
private $objSupp;
public function SuppObj() {
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;
}
}
}
// DEPRECATED -- use SuppObj()
public function Supplier() {
return $this->SuppObj();
}
public function PageKey() {
if ($this->PageKey) {
return $this->PageKey;
} else {
return $this->CatKey;
}
}
/*----
PURPOSE: loads data needed to display catalog views for this department
HISTORY
2010-11-12 disabled automatic cache update
2010-11-16 changed sorting field from cntInPrint to cntForSale
2011-02-02 using _dept_ittyps now instead of qryItTypsDepts_ItTyps
Also added "AND (cntForSale)" to WHERE clause -- not listing titles with nothing to sell
*/
protected function Data_forStore() { // was GetDeptData()
//$objCache = $this->objDB->CacheMgr();
//$objCache->Update_byName('_dept_ittyps','clsDept.DoListing() for ID='.$this->ID);
//$sql = 'SELECT * FROM qryItTypsDepts_ItTyps WHERE (ID_Dept='.$this->ID.') ORDER BY cntForSale DESC';
$sql = 'SELECT * FROM _dept_ittyps WHERE (ID_Dept='.$this->ID.') AND (cntForSale) ORDER BY cntForSale DESC';
$objItTyps = $this->objDB->DataSet($sql,'clsItTyp');
return $objItTyps;
}
/*-----
PURPOSE: Print this department's information as part of department list
HISTORY:
2010-11-16 $cntAvail is now cntForSale, not cntInPrint+qtyInStock
*/
public function DoListing() {
assert('$this->ID');
$objItTyps = $this->Data_forStore();
$isFirst = true;
$out = '';
while ($objItTyps->NextRow()) {
if ($isFirst) {
$isFirst = false;
} else {
$out .= ', ';
}
$cntInPrint = $objItTyps->cntInPrint;
$qtyInStock = $objItTyps->qtyForSale;
//$cntAvail = $cntInPrint + $qtyInStock;
$cntForSale = $objItTyps->cntForSale;
if ($cntAvail == 1) {
$strName = $objItTyps->ItTyp_Sng;
} else {
$strName = $objItTyps->ItTyp_Plr;
}
$out .= ' '.$cntAvail.' '.$strName;
}
return $out;
}
/*----
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.
HISTORY:
2010-11-?? Started using cached table _title_ittyps instead of qryTitles_ItTyps_Titles
2010-11-16 $cntAvail is now cntForSale, not cntInPrint+qtyInStock
2011-02-02 $qtyInStock now set to Row['qtyInStock'], not Row['qtyForSale'] which didn't make sense anyway
*/
public function DoPage() {
$out = '';
$idDept = $this->ID;
if (empty($idDept)) {
throw new exception('Department object has no ID');
}
$objSection = new clsPageOutput();
// calculate the list of item types available in this department
$objItTyps = $this->Data_forStore();
$objTitles = new clsVbzTitle($this->objDB);
$objNoImgSect = new clsPageOutput();
$cntSections = 0;
while ($objItTyps->NextRow()) {
$cntInPrint = $objItTyps->Row['cntInPrint'];
$qtyInStock = $objItTyps->Row['qtyInStock'];
$cntAvail = $objItTyps->Row['cntForSale'];
if ($cntAvail) {
$cntSections++;
$idItTyp = $objItTyps->Row['ID_ItTyp'];
$sql = 'SELECT *, ID_Title AS ID, TitleName AS Name, cntInStock 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.');';
$objTitles->Query($sql);
$arTitles = NULL;
if ($objTitles->hasRows()) {
while ($objTitles->NextRow()) {
// add title to display list
$arTitles[] = $objTitles->Values(); // save it in a list
}
assert('is_array($arTitles)');
// We've generated the list of titles for this section; now display the section header and titles:
$out .= $this->objDB->ShowTitles($objItTyps->Row['ItTypNamePlr'].':',$arTitles,$objNoImgSect);
} else {
echo 'ERROR: No titles found! SQL='.$sql;
}
$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 URL_Rel() {
$strURL = $this->Supplier()->URL();
$strKey = $this->PageKey();
if ($strKey) {
$strURL .= strtolower($strKey).'/';
}
return $strURL;
}
public function URL_Abs() {
return KWP_ROOT.$this->URL_Rel();
}
public function LinkName() {
$strURL = $this->URL_Rel();
return ''.$this->Name.'';
}
/*-----
RETURNS: The string which, when prepended to a Title's CatKey, would form the Title's catalog number
*/
public function CatPfx() {
$strFull = strtoupper($this->Supplier()->CatKey);
if ($this->AffectsCatNum()) {
$strFull .= '-'.strtoupper($this->CatKey);
}
return $strFull.'-';
}
/*-----
RETURNS: TRUE if this department affects the catalog number (i.e. if CatKey is non-blank)
*/
public function AffectsCatNum() {
return ($this->CatKey != '');
}
}
class clsVbzTitles extends clsVbzTable {
public function __construct($iDB) {
parent::__construct($iDB);
$this->Name('cat_titles');
$this->KeyName('ID');
$this->ClassSng('clsVbzTitle');
}
public function Search_forText_SQL($iFind) {
return '(Name LIKE "%'.$iFind.'%") OR (`Desc` LIKE "%'.$iFind.'%")';
}
public function Search_forText($iFind) {
$sqlFilt = $this->Search_forText_SQL($iFind);
$rs = $this->GetData($sqlFilt);
return $rs;
}
/*
ACTION: Finds a Title from a CatNum and returns an object for it
TO DO:
Rename to Get_byCatNum()
Stop using v_titles
*/
/* 2010-11-07 Is anything actually using this?
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 clsVbzTitleExt($this);
$objTitle = new clsVbzTitle($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('clsVbzTitles.GetItem_byCatNum() -> ok');
return $objTitle;
} else {
CallExit('clsVbzTitles.GetItem_byCatNum() -> NULL');
return NULL;
}
}
*/
}
class clsVbzTitle extends clsDataSet {
// object cache
private $objDept;
private $objSupp;
// options
public $hideImgs;
public function Dept() {
$doLoad = FALSE;
if (empty($this->objDept)) {
$doLoad = TRUE;
} else if (is_object($this->objDept)) {
if ($this->ID_Dept != $this->objDept->ID) {
$doLoad = TRUE;
}
} else {
$doLoad = TRUE;
}
if ($doLoad) {
$idDept = $this->ID_Dept;
if (empty($idDept)) {
$objDept = NULL;
} else {
$objDept = $this->objDB->Depts()->GetItem($idDept);
assert('is_object($objDept)');
}
$this->objDept = $objDept;
}
return $this->objDept;
}
/*----
RETURNS: ID of this title's supplier
HISTORY:
2011-09-28 revised to get ID directly from the new ID_Supp field
instead of having to look up the Dept and get it from there.
*/
public function Supplier_ID() {
/*
$objDept = $this->Dept();
$idSupp = $objDept->ID_Supplier;
*/
$idSupp = $this->Value('ID_Supp');
return $idSupp;
}
// DEPRECATED -- use SuppObj()
public function Supplier() {
return $this->SuppObj();
}
public function SuppObj() {
$doLoad = FALSE;
if (empty($this->objSupp)) {
$doLoad = TRUE;
} else if (is_object($this->objSupp)) {
if ($this->ID_Supplier != $this->objSupp->ID) {
$doLoad = TRUE;
}
} else {
$doLoad = TRUE;
}
if ($doLoad) {
$idSupp = $this->Supplier_ID();
if (empty($idSupp)) {
$objSupp = NULL;
} else {
$objSupp = $this->objDB->Suppliers()->GetItem($idSupp);
assert('is_object($objSupp)');
}
$this->objSupp = $objSupp;
}
return $this->objSupp;
}
public function Items() {
$sqlFilt = 'ID_Title='.$this->ID;
$objTbl = $this->objDB->Items();
$objRows = $objTbl->GetData($sqlFilt);
return $objRows;
}
public function Topics() {
$objTbl = $this->Engine()->TitleTopic_Topics();
$objRows = $objTbl->GetTitle($this->KeyValue());
return $objRows;
}
public function DoPage() {
$idTitle = $this->KeyValue();
assert('$idTitle');
$objSection = new clsPageOutput();
// show "small" images
if (!$this->hideImgs) {
$objImgs = $this->ListImages('sm');
if ($objImgs->hasRows()) {
while ($objImgs->NextRow()) {
$strImgTag = $objImgs->AttrDispl;
$urlRel = $objImgs->Spec;
$idImg = $objImgs->ID;
//$strImg = 'WebSpec().'"';
if ($strImgTag) {
$strImg .= ' title="'.$strImgTag.'"';
}
$strImg .= '>';
$objImgBig = $objImgs->ImgForSize('big');
if (is_object($objImgBig)) {
if ($objImgBig->FirstRow()) {
$strImg = $objImgBig->Href().$strImg.'';
}
}
$objSection->AddText($strImg);
}
} else {
$objSection->ShowImgUnavail();
}
}
// list topics for this title
$db = $this->Engine();
$tbl = $db->TitleTopic_Topics();
$tbl->doBranch(TRUE);
$rs = $tbl->GetTitle($idTitle);
if ($rs->hasRows()) {
$txt = '';
$txt .= ''.$db->Topics()->IndexLink('Topics').':';
while ($rs->NextRow()) {
$txt .= ' - '.$rs->ShopLink();
}
$txt .= ' |
';
$objSection->AddText($txt);
}
// now list available items as table
//$sql = 'SELECT * FROM qryTitles_ItTyps_ItTyps WHERE (ID_Title='.$idTitle.') ORDER BY ItTyp_Sort IS NULL, ItTyp_Sort;';
$sql = 'SELECT * FROM _title_ittyps WHERE (ID_Title='.$idTitle.') ORDER BY ItTypSort IS NULL, ItTypSort;';
$rsTypes = $this->Engine()->DataSet($sql);
$isItem = FALSE;
if ($rsTypes->hasRows()) {
if (KF_CART_ABSOLUTE) {
$urlCart = KWP_CART_ABS;
} else {
$urlCart = KWP_CART_REL;
}
$objSection->AddText('