Difference between revisions of "VbzCart/archive/code/SpecialVbzAdmin"

from HTYP, the free directory anyone can edit if they can prove to me that they're not a spambot
< VbzCart‎ | archive‎ | code
Jump to navigation Jump to search
(2009-10-04 version)
(long-overdue update)
Line 1: Line 1:
 
<php><?php
 
<php><?php
 
/*
 
/*
NAME: SpecialVbzAdmin
+
  NAME: SpecialVbzAdmin
PURPOSE: Special page for administering VbzCart
+
  PURPOSE: Special page for administering VbzCart
AUTHOR: Woozle (Nick) Staddon
+
  AUTHOR: Woozle (Nick) Staddon
VERSION:
+
  REQUIRES:
2009-03-10 0.0 (Wzl) Started writing
+
    Tabber extension for tabs on Supplier admin page
  had a few functions implemented by June or so, but not enough to process anything
+
    TreeAndMenu extension (tentatively) for category management
2009-07-09 (Wzl)
+
  VERSION:
  rewrote menu functions as classes
+
    2009-03-10 0.0 (Wzl) Started writing
  started on Shipments
+
      had a few functions implemented by June or so, but not enough to process anything
2009-10-04 (Wzl)
+
    2009-07-09 (Wzl)
  menu classes now in separate file; removed from here
+
      rewrote menu functions as classes
  added 'orders' and 'order' pages/classes
+
      started on Shipments
 +
    2009-10-04 (Wzl)
 +
      menu classes now in separate file; removed from here
 +
      added 'orders' and 'order' pages/classes
 +
    2009-10-06 (Wzl) clsTitles -> clsVbzTitles, clsTitle -> clsVbzTitle
 +
    2010-06-27 (Wzl) new functionality in Bins, Images; moved catalog rebuild out to standalone script
 +
    2010-09-22 (Wzl) working on email confirmation of orders (finally)
 +
    2011-02-06 (Wzl) extensive work since 9/22... most features usable
 +
    2011-12-21 (Wzl) extracted clsVbzAdminData into base.admin.php so it could be used from command line
 
*/
 
*/
 
$wgSpecialPages['VbzAdmin'] = 'SpecialVbzAdmin'; # Let MediaWiki know about your new special page.
 
$wgSpecialPages['VbzAdmin'] = 'SpecialVbzAdmin'; # Let MediaWiki know about your new special page.
Line 20: Line 28:
 
         'description' => 'special page for VbzCart administration',
 
         'description' => 'special page for VbzCart administration',
 
         'author' => 'Woozle (Nick) Staddon',
 
         'author' => 'Woozle (Nick) Staddon',
'version' => '0.0 2009-10-04 alpha'
+
'version' => '2011-12-21 unreleased'
 
);
 
);
 
global $dbgShowLibs;
 
global $dbgShowLibs;
 
$dbgShowLibs = TRUE;
 
$dbgShowLibs = TRUE;
  
//require_once KFP_LIB_VBZ.'site.php';
 
//require_once KFP_VBZ_LIBS.'store.php'; // normal location
 
//require_once kfpLib.'/dev/data.php'; // development
 
 
if (!defined('LIBMGR')) {
 
if (!defined('LIBMGR')) {
 
     require('libmgr.php');
 
     require('libmgr.php');
 
}
 
}
 
//clsLibMgr::$doDebug = TRUE;
 
//clsLibMgr::$doDebug = TRUE;
clsLibMgr::Add('vbz.store', kfpLib.'/dev/store.php'); // development
+
clsLibMgr::Add('vbz.site', KFP_LIB_VBZ.'/site.php',__FILE__,__LINE__);
clsLibMgr::Add('vbz.shop', kfpLib.'/dev/shop.php'); // development
+
clsLibMgr::Add('vbz.shop', KFP_LIB_VBZ.'/shop.php',__FILE__,__LINE__);
clsLibMgr::Add('forms', kfpLib.'/dev/forms.php'); // development
+
clsLibMgr::Add('vbz.ckout', KFP_LIB_VBZ.'/ckout.php',__FILE__,__LINE__);
clsLibMgr::Add('menus', 'menu.php');
+
clsLibMgr::Add('vbz.topic', KFP_LIB_VBZ.'/topic.php',__FILE__,__LINE__);
clsLibMgr::Load('vbz.store');
+
clsLibMgr::Add('admin.events', KFP_MW_PLUGINS.'/lib/admin.events.php',__FILE__,__LINE__);
clsLibMgr::Load('vbz.shop');
+
clsLibMgr::Add('admin.forms', KFP_MW_PLUGINS.'/lib/admin.forms.php',__FILE__,__LINE__);
clsLibMgr::Load('forms');
+
clsLibMgr::Add('vbz.admin.base', KFP_LIB_VBZ.'/base.admin.php',__FILE__,__LINE__);
clsLibMgr::Load('menus');
+
clsLibMgr::Add('vbz.admin.cache', KFP_LIB_VBZ.'/admin.cache.php',__FILE__,__LINE__);
 +
clsLibMgr::Add('vbz.admin.cat', KFP_LIB_VBZ.'/admin.cat.php',__FILE__,__LINE__);
 +
clsLibMgr::Add('vbz.admin.sess',KFP_LIB_VBZ.'/admin.sess.php',__FILE__,__LINE__);
 +
clsLibMgr::Add('vbz.admin.cart',KFP_LIB_VBZ.'/admin.cart.php',__FILE__,__LINE__);
 +
clsLibMgr::Add('vbz.admin.ord', KFP_LIB_VBZ.'/admin.ord.php',__FILE__,__LINE__);
 +
clsLibMgr::Add('vbz.admin.pkg', KFP_LIB_VBZ.'/admin.pkg.php',__FILE__,__LINE__);
 +
clsLibMgr::Add('vbz.admin.cust',KFP_LIB_VBZ.'/admin.cust.php',__FILE__,__LINE__);
 +
clsLibMgr::Add('vbz.admin.rstk',KFP_LIB_VBZ.'/admin.rstk.php',__FILE__,__LINE__);
 +
clsLibMgr::Add('vbz.admin.stock',KFP_LIB_VBZ.'/admin.stock.php',__FILE__,__LINE__);
 +
clsLibMgr::Add('richtext', KFP_MW_PLUGINS.'/richtext.php',__FILE__,__LINE__);
 +
clsLibMgr::Add('menus', KFP_MW_PLUGINS.'/menu.php',__FILE__,__LINE__);
 +
clsLibMgr::Load('vbz.site' ,__FILE__,__LINE__);
 +
clsLibMgr::Load('vbz.shop' ,__FILE__,__LINE__);
 +
clsLibMgr::Load('vbz.ckout' ,__FILE__,__LINE__);
 +
clsLibMgr::Load('vbz.topic' ,__FILE__,__LINE__);
 +
clsLibMgr::Load('admin.events' ,__FILE__,__LINE__);
 +
clsLibMgr::Load('admin.forms' ,__FILE__,__LINE__);
 +
clsLibMgr::Load('vbz.admin.base' ,__FILE__,__LINE__);
 +
clsLibMgr::Load('vbz.admin.cache' ,__FILE__,__LINE__);
 +
clsLibMgr::Load('vbz.admin.cat' ,__FILE__,__LINE__);
 +
clsLibMgr::Load('vbz.admin.sess' ,__FILE__,__LINE__);
 +
clsLibMgr::Load('vbz.admin.ord' ,__FILE__,__LINE__);
 +
clsLibMgr::Load('vbz.admin.pkg' ,__FILE__,__LINE__);
 +
clsLibMgr::Load('vbz.admin.cart' ,__FILE__,__LINE__);
 +
clsLibMgr::Load('vbz.admin.cust' ,__FILE__,__LINE__);
 +
clsLibMgr::Load('vbz.admin.rstk' ,__FILE__,__LINE__);
 +
clsLibMgr::Load('vbz.admin.stock' ,__FILE__,__LINE__);
 +
clsLibMgr::Load('richtext' ,__FILE__,__LINE__);
 +
clsLibMgr::Load('menus' ,__FILE__,__LINE__);
  
define('kwp_DocTblPfx','htyp:VbzCart/tables/');
+
define('kwp_DocPfx','htyp:VbzCart/');
 +
define('kwp_DocTblPfx',kwp_DocPfx.'tables/');
 +
define('kwp_DocPrcPfx',kwp_DocPfx.'procs/');
 +
define('kwp_DocTermPfx',kwp_DocPfx.'ui/terms/');
 +
//echo 'LIB LOG:'.clsLibMgr::$Log;
  
/*
+
if (!defined('KS_CHAR_URL_ASSIGN')) {
//require_once KFP_LIB.'libmgr.php';
+
    define('KS_CHAR_URL_ASSIGN',':'); // character used for encoding values in wiki-internal URLs
 
+
}
clsLibMgr::AddLib('datamgr',KFP_LIB.'dev/datamgr.php');
 
clsLibMgr::AddLib('data',KFP_LIB.'dev/data.php');
 
clsLibMgr::AddLib('store',KFP_LIB.'dev/store.php');
 
 
 
//clsLibMgr::UseLib('datamgr');
 
clsLibMgr::UseLib('store');
 
*/
 
 
 
define('KS_CHAR_URL_ASSIGN',':'); // character used for encoding values in wiki-internal URLs
 
  
 
// data source names -- these are used only by admin functions; general tables are in store.php
 
// data source names -- these are used only by admin functions; general tables are in store.php
 
define('KSQL_DS_ITEMS_TO_SHIP','qryStock_forOpenOrders');
 
define('KSQL_DS_ITEMS_TO_SHIP','qryStock_forOpenOrders');
 +
 +
function Date_DefaultYear($iDate,$iYear,$iSmallerPfx='<small>',$iSmallerSfx='</small>') {
 +
    if (empty($iDate)) {
 +
return NULL;
 +
    } else {
 +
$dtIn = strtotime($iDate);
 +
$yrIn = date('Y',$dtIn);
 +
$doYr = ($yrIn != $iYear);
 +
$out = '';
 +
if ($doYr) {
 +
    $out .= $iSmallerPfx;
 +
}
 +
$ftIn = date('m/d',$dtIn);
 +
$out .= $ftIn;
 +
if ($doYr) {
 +
    $out .= '<br>'.$yrIn;
 +
    $out .= $iSmallerSfx;
 +
}
 +
return $out;
 +
    }
 +
}
  
 
function wfSpecialVbzAdmin() {
 
function wfSpecialVbzAdmin() {
Line 64: Line 113:
  
 
$app = new SpecialVbzAdmin($wgRequest);
 
$app = new SpecialVbzAdmin($wgRequest);
 +
}
 +
function NextSeq($iData) {
 +
    if ($iData->HasRows()) {
 +
$intMax = 0;
 +
while ($iData->NextRow()) {
 +
    if ($iData->Seq > $intMax) {
 +
$intMax = $iData->Seq;
 +
    }
 +
}
 +
return $intMax+1;
 +
    } else {
 +
return 1;
 +
    }
 
}
 
}
  
require_once( $wgScriptPath.'includes/SpecialPage.php' );
+
/* DEACTIVATED 2010-11-08
 
 
 
function VbzDb() {
 
function VbzDb() {
 
   static $objDb;
 
   static $objDb;
Line 77: Line 138:
 
     return $objDb;
 
     return $objDb;
 
}
 
}
class SpecialVbzAdmin extends SpecialPage {
+
*/
//=======
+
class SpecialVbzAdmin extends SpecialPageApp {
// STATIC
+
    protected $args;
 +
    protected $objDB;
  
//=======
+
    public function __construct() {
// DYNAMIC
 
 
 
  protected $args;
 
 
 
  public function __construct() {
 
 
global $wgMessageCache,$wgUser;
 
global $wgMessageCache,$wgUser;
global $vgUsername;
+
global $vgUserName,$vgPage;
  
 
parent::__construct( 'VbzAdmin' );
 
parent::__construct( 'VbzAdmin' );
$this->includable( false );
+
$this->includable( TRUE );
         $wgMessageCache->addMessage('vbzadmin', 'VbzCart administration');
+
         $this->SetTitle('VbzAdmin');
$vgUsername = 'wiki:'.$wgUser->getName();
+
$vgUserName = 'wiki:'.$wgUser->getName();
  }
+
$vgPage = $this;
  function execute( $par ) {
+
    }
 +
    /*----
 +
      USAGE: Must be called before parent::SetHeaders()
 +
    */
 +
    public function SetTitle($iText) {
 +
global $wgMessageCache;
 +
 
 +
        $wgMessageCache->addMessage('vbzadmin',$iText);
 +
    }
 +
    protected function DB() {
 +
if (!isset($this->objDB)) {
 +
    $this->objDB = new clsVbzAdminData(KS_DB_VBZCART);
 +
    $this->objDB->Open();
 +
}
 +
return $this->objDB;
 +
    }
 +
    function execute( $par ) {
 
global $wgUser;
 
global $wgUser;
 +
 +
$doAdmin = $wgUser->isAllowed('editinterface');
 +
$this->GetArgs($par);
 +
 +
if ($doAdmin) {
 +
    $this->RegObjs($this->ClassList());
 +
    $this->HandlePageArgs();
 +
}
  
 
$this->setHeaders();
 
$this->setHeaders();
$this->GetArgs($par);
 
  
if ($wgUser->isAllowed('editinterface')) {
+
$this->doMenu($doAdmin);
 +
 
 +
if ($doAdmin) {
 
$this->doAdmin();
 
$this->doAdmin();
 
} else {
 
} else {
 
$this->doUser();
 
$this->doUser();
}
 
  }
 
  private function GetArgs($par) {
 
 
/*
 
PURPOSE: Parses variable arguments from the URL
 
  The URL is formatted as a series of arguments /arg=val/arg=val/..., so that we can always refer directly
 
    to any particular item as a wiki page title while also not worrying about hierarchy/order.
 
*/
 
    $args_raw = split('/',$par);
 
    foreach($args_raw as $arg_raw) {
 
if (strpos($arg_raw,KS_CHAR_URL_ASSIGN) !== FALSE) {
 
    list($key,$val) = split(KS_CHAR_URL_ASSIGN,$arg_raw);
 
    $this->args[$key] = $val;
 
 
}
 
}
 
     }
 
     }
  }
+
    protected function doMenu($iAdmin) {
  public function doAdmin() {
 
 
global $wgOut;
 
global $wgOut;
/*
+
 
PURPOSE: do stuff that only admins are allowed to do
 
*/
 
if (isset($this->args['page'])) {
 
    $page = $this->args['page'];
 
} else {
 
    $page = NULL;
 
}
 
// display menu
 
 
$wtSelf = 'Special:'.$this->name();
 
$wtSelf = 'Special:'.$this->name();
 
 
 
$objMenu = new clsMenu($wtSelf);
 
$objMenu = new clsMenu($wtSelf);
$objMenu->Add($objRow = new clsMenuRow('Stock','menu.stock'));
+
if ($iAdmin) {
  $objRow->Add(new clsMenuItem('stock places','places'));
+
    $objMenu->Add($objRow = new clsMenuRow('Stock','menu.stock'));
  $objRow->Add(new clsMenuItem('stock bins','bins'));
+
      $objRow->Add(new clsMenuItem('stock places','place'));
  $objRow->Add(new clsMenuItem('cache tables','cache'));
+
      $objRow->Add(new clsMenuItem('stock bins','bin'));
  $objRow->Add(new clsMenuItem('suppliers','supp'));
+
    $objMenu->Add($objRow = new clsMenuRow('Catalog','menu.cat'));
$objMenu->Add($objRow = new clsMenuRow('Ship','menu.ship'));
+
      $objRow->Add(new clsMenuItem('suppliers','supp'));
  $objRow->Add(new clsMenuItem('items to ship','toship'));
+
      $objRow->Add(new clsMenuItem('images','cat.img'));
  $objRow->Add(new clsMenuItem('shipments','shmpts'));
+
      $objRow->Add(new clsMenuItem('topics','topic'));
$objMenu->Add($objRow = new clsMenuRow('Orders','menu.orders'));
+
      $objRow->Add(new clsMenuItem('search','cat.search'));
  $objRow->Add(new clsMenuItem('carts','carts'));
+
    $objMenu->Add($objRow = new clsMenuRow('Restocks','menu.rstk'));
  $objRow->Add(new clsMenuItem('orders','orders'));
+
      $objRow->Add(new clsMenuItem('needed','rstk.need'));
 +
      $objRow->Add(new clsMenuItem('expected','rstk.wait'));
 +
      $objRow->Add(new clsMenuItem('past','rstk.past'));
 +
    $objMenu->Add($objRow = new clsMenuRow('Orders','menu.orders'));
 +
      $objRow->Add(new clsMenuItem('carts','cart'));
 +
      $objRow->Add(new clsMenuItem('orders',KS_URL_PAGE_ORDER));
 +
      $objRow->Add(new clsMenuItem('charges','chg'));
 +
    $objMenu->Add($objRow = new clsMenuRow('Ship','menu.ship'));
 +
      $objRow->Add(new clsMenuItem('items to ship','toship'));
 +
      $objRow->Add(new clsMenuItem('shipments','shpmt'));
 +
    $objMenu->Add($objRow = new clsMenuRow('Utilities','menu.utils'));
 +
      $objRow->Add(new clsMenuItem('cache tables','cache'));
 +
      $objRow->Add(new clsMenuItem('ccard encryption','migr.encr'));
 +
      $objRow->Add(new clsMenuItem('update stats','util.stats'));
 +
      $objRow->Add(new clsMenuItem('price list','util.plist'));
 +
      $objRow->Add(new clsMenuItem('inventory','util.inv'));
 +
    $objMenu->Add($objRow = new clsMenuRow('Logs','menu.logs'));
 +
      $objRow->Add(new clsMenuItem('general','log.misc'));
 +
      $objRow->Add(new clsMenuItem('carts','log.cart'));
 +
}
 
 
$out = $objMenu->WikiText($page);
+
$wgOut->addHTML('<table style="background: #ccffcc;"><tr><td>');
 +
$out = $objMenu->WikiText($this->page);
 
$out .= $objMenu->Execute();
 
$out .= $objMenu->Execute();
 
$wgOut->addHTML('<table style="background: #ccffcc;"><tr><td>');
 
 
$wgOut->addWikiText($out,TRUE); $out = '';
 
$wgOut->addWikiText($out,TRUE); $out = '';
 
$wgOut->addHTML('</td></tr></table>');
 
$wgOut->addHTML('</td></tr></table>');
  
if (!is_null($page)) {
+
// a little diagnostic info
    $dbVBZ = VbzDb();
+
$isFnd = FALSE;
    $id = isset($this->args['id'])?$this->args['id']:NULL;
+
$out .= '<small>';
    switch ($page) {
+
if (is_object($this->tbl)) {
      case 'places':
+
    $out .= 'table class: <b>'.get_class($this->tbl).'</b>';
$objPlaces = $dbVBZ->Places();
+
    $isFnd = TRUE;
$objPlaces->ListPage();
+
}
break;
+
if (is_object($this->obj)) {
      case 'place':
+
    $out .'record class: <b>'.get_class($this->obj).'</b>';
$objPlaces = $dbVBZ->Places();
+
    $isFnd = TRUE;
$objPlace = $objPlaces->GetItem($id);
+
}
$objPlace->InfoPage();
+
if (!$isFnd) {
break;
+
    $out .= 'No classes found for page ['.$this->page.'].';
      case 'bins':
+
}
$objBins = $dbVBZ->Bins();
+
$out .= '</small>';
$objBins->ListPage();
+
$wgOut->addHTML($out); $out = '';
break;
+
 
      case 'bin':
+
    }
$objBins = $dbVBZ->Bins();
+
    protected function ClassList() {
$objBin = $objBins->GetItem($id);
+
$ar = array(
$objBin->InfoPage();
+
  //'clsAdminCacheFlows',
break;
+
  //'clsAdminCacheProc',
      case 'cache':
+
  //'clsAdminCacheTables',
$this->doCacheTables();
+
  //'VbzAdminCartLines',
break;
+
  //'VbzAdminCartLog',
      case 'supp':
+
  'VbzAdminCarts',
if (is_null($id)) {
+
  'VbzAdminCatalogs',
    $this->doSuppliers();
+
  'clsAdminCustAddrs',
} else {
+
  'VbzAdminCustCards',
    $this->doSupplier($id);
+
  'clsAdminCustEmails',
 +
  'clsAdminCustNames',
 +
  'clsAdminCustPhones',
 +
  'VbzAdminCusts',
 +
  'VbzAdminDepts',
 +
  'clsAdminEvents',
 +
  'clsAdminImages',
 +
  'VbzAdminItems',
 +
  //'clsAdminItems_info_Cat',
 +
  'VbzAdminOrderChgs',
 +
  'VbzAdminOrderItems',
 +
  //'VbzAdminOrderPulls',
 +
  'VbzAdminOrders',
 +
  'VbzAdminOrderTrxacts',
 +
  //'VbzAdminOrderTrxTypes',
 +
  'VbzAdminOrderMsgs',
 +
  //'clsAdminRstkReqItems',
 +
  'clsAdminRstkReqs',
 +
  //'VbzAdminSessions',
 +
  'VbzAdminStkItems',
 +
  'VbzAdminSuppliers',
 +
  'VbzAdminTitles',
 +
  //'VbzAdminTitles_info_Cat',
 +
  //'VbzAdminTitles_info_Item',
 +
  //'clsAdminTitleTopic_Titles',
 +
  //'clsAdminTitleTopic_Topics',
 +
  'clsAdminTopics',
 +
 
 +
  //'clsCMITems',
 +
  'clsCtgGroups',
 +
  //'clsCtgTitles',
 +
  //'clsOrderPullTypes',
 +
  'clsPackages',
 +
  //'clsPkgLines',
 +
  'clsShipments',
 +
  //'clsStkLog',
 +
  //'clsTitleTopics_base',
 +
  //'clsRstkRcdLines',
 +
  'clsRstkRcds',
 +
  //'VbzStockBinLog',
 +
  'VbzStockBins',
 +
  'VbzStockPlaces',
 +
  );
 +
return $ar;
 +
    }
 +
    /*-----
 +
      PURPOSE: do stuff that only admins are allowed to do
 +
    */
 +
    public function doAdmin() {
 +
global $wgOut;
 +
$obj = $this->obj;
 +
$tbl = $this->tbl;
 +
 
 +
$out =NULL;
 +
$didPage = FALSE;
 +
 
 +
if (is_object($obj)) {
 +
    $out = $obj->AdminPage();
 +
    $didPage = TRUE;
 +
} elseif (is_object($tbl)) {
 +
    $out = $tbl->AdminPage();
 +
    $didPage = TRUE;
 +
}
 +
 
 +
if (!$didPage) {
 +
    $page = $this->page;
 +
    $idObj = $this->idObj;
 +
    $doObj = $this->doObj;
 +
 
 +
    if (!is_null($page)) {
 +
$dbVBZ = $this->DB();
 +
 
 +
$out = NULL;
 +
switch ($page) {
 +
  case 'cache':
 +
  case 'cache.tbl':
 +
  case 'cache.proc':
 +
    $this->DB()->CacheMgr()->MenuDispatch($page,$idObj);
 +
    break;
 +
  case 'cat.search':
 +
    $tbl = $dbVBZ->Titles_Cat();
 +
    $out = $tbl->SearchPage();
 +
    break;
 +
  case 'log.cart':
 +
    $objTbl = new VbzAdminCartLog($dbVBZ);
 +
    $out = $objTbl->AdminPage();
 +
    break;
 +
  case 'log.misc':
 +
    $objLog = new clsAdminEvents($dbVBZ);
 +
    $objLog->ListPage();
 +
    break;
 +
  case 'migr.encr':
 +
    $objCards = $dbVBZ->CustCards();
 +
    $objCards->EncryptAdmin();
 +
    break;
 +
  case 'rstk.need':
 +
    $objTbl = $dbVBZ->RstkReqs();
 +
    $objTbl->AdminItemsNeeded();
 +
    break;
 +
  case 'rstk.past':
 +
    $objTbl = $dbVBZ->RstkReqs();
 +
    $objRows = $objTbl->RowsInactive();
 +
    $out = $objRows->AdminList();
 +
    break;
 +
  case 'rstk-rcd':
 +
    $objTbl = $dbVBZ->RstkRcds();
 +
    $objRow = $objTbl->GetItem($idObj);
 +
    $out = $objRow->AdminPage();
 +
    break;
 +
  case 'rstk-req':
 +
    $objTbl = $dbVBZ->RstkReqs();
 +
    $objRow = $objTbl->GetItem($idObj);
 +
    $out = $objRow->AdminPage();
 +
    break;
 +
  case 'rstk.wait':
 +
    $objTbl = $dbVBZ->RstkReqs();
 +
    $objRows = $objTbl->RowsActive();
 +
    $out = $objRows->AdminList();
 +
    break;
 +
  case 'toship':
 +
    $this->doStockToShip();
 +
    break;
 +
  case 'util.stats':
 +
    $this->DoUpdateStats();
 +
    break;
 +
  case 'util.plist':
 +
    $this->DoPriceList();
 +
    break;
 +
  case 'util.inv':
 +
    $this->DoInvCompare();
 +
    break;
 +
  default:
 +
    $out = 'Select from the menu above.';
 
}
 
}
break;
+
    }
      case 'dept':
+
}
$this->doDept($id);
+
if (!is_null($out)) {
break;
+
    $wgOut->AddWikiText($out,TRUE);
      case 'title':
+
}
$this->doTitle($id);
+
    }
break;
+
    public function doCharges() {
      case 'toship':
+
global $wgOut;
$this->doStockToShip();
+
global $vgPage;
break;
 
      case 'shmpts':
 
$objShpmts = new clsShipments($dbVBZ);
 
$objShpmts->ListPage();
 
break;
 
      case 'shipmt':
 
$objShpmts = new clsShipments($dbVBZ);
 
$objShipmt = $objShpmts->GetItem($id);
 
$objShipmt->InfoPage();
 
break;
 
      case 'carts':
 
$objCarts = new VbzAdminCarts($dbVBZ);
 
$objCarts->ListPage();
 
break;
 
      case 'cart':
 
$objCarts = new VbzAdminCarts($dbVBZ);
 
$objCart = $objCarts->GetItem($id);
 
$objCart->InfoPage();
 
break;
 
      case 'orders':
 
$objOrders = new VbzAdminOrders($dbVBZ);
 
$objOrders->ListPage();
 
break;
 
      case 'order':
 
$objOrders = new VbzAdminOrders($dbVBZ);
 
$objOrder = $objOrders->GetItem($id);
 
$objOrder->InfoPage();
 
break;
 
  
    }
+
$doAll = $vgPage->Arg('all');
 +
$strMnuAll = $this->SelfLink_WT(array('all' => TRUE),'all');
 +
$strMnuUnp = $this->SelfLink_WT(array('all' => FALSE),'to process');
 +
 
 +
$objTbl = new VbzAdminOrderChgs($this->DB());
 +
if ($doAll) {
 +
    $strMenu = "$strMnuUnp .. '''$strMnuAll'''";
 +
    $strDescr = ' in database';
 +
    $sqlFilt = NULL;
 +
} else {
 +
    $strMenu = "'''$strMnuUnp''' .. $strMnuAll";
 +
    $strDescr = ' to be processed';
 +
    $sqlFilt = '(WhenDecided IS NULL) AND ((WhenXmitted IS NULL) OR isSuccess) AND (WhenVoided IS NULL) AND (WhenHeldUp IS NULL)';
 
}
 
}
  }
+
$objRows = $objTbl->GetData($sqlFilt,NULL,'ID DESC');
  public function doUser() {
+
$wgOut->AddWikiText("'''Show Charges''': $strMenu", TRUE);
 +
$arArgs['descr'] = $strDescr;
 +
$wgOut->AddWikiText($objRows->AdminTable($arArgs),TRUE);
 +
    }
 +
    public function doUser() {
 
global $wgOut;
 
global $wgOut;
 
/*
 
/*
Line 236: Line 433:
  
 
// individual admin functions
 
// individual admin functions
  public function doStockToShip() {
+
    public function doStockToShip() {
 
global $wgOut;
 
global $wgOut;
  
$dbVBZ = VbzDb();
+
$dbVBZ = $this->DB();
 
$out = '==Stock to Ship=='."\n";
 
$out = '==Stock to Ship=='."\n";
 
$wgOut->addWikiText($out,TRUE); $out = '';
 
$wgOut->addWikiText($out,TRUE); $out = '';
Line 250: Line 447:
 
$idBin = $objRows->ID_Bin;
 
$idBin = $objRows->ID_Bin;
 
$strOrd = $objRows->OrdText?$objRows->OrdText:'?ord#?';
 
$strOrd = $objRows->OrdText?$objRows->OrdText:'?ord#?';
$wtItem = '{{faint|'.$idItem.'}} '.SelfLink('item','id',$idItem,$objRows->ItemText);
+
$wtItem = '{{faint|'.$idItem.'}} '.SelfLink_Page('item','id',$idItem,$objRows->ItemText);
$wtOrder = '{{faint|'.$idOrd.'}} '.SelfLink('ord','id',$idOrd,$strOrd);
+
$wtOrder = '{{faint|'.$idOrd.'}} '.SelfLink_Page(KS_URL_PAGE_ORDER,'id',$idOrd,$strOrd);
$wtBin = '{{faint|'.$idBin.'}} '.SelfLink('bin','id',$idBin,$objRows->BinText);
+
$wtBin = '{{faint|'.$idBin.'}} '.SelfLink_Page('bin','id',$idBin,$objRows->BinText);
 
$wtQtyNeed = $objRows->QtyOpen;
 
$wtQtyNeed = $objRows->QtyOpen;
 
$intQtyForShip = $objRows->QtyForSale;
 
$intQtyForShip = $objRows->QtyForSale;
Line 263: Line 460:
 
    }
 
    }
 
    $out .= "\n|}\n(Retrieval complete.)";
 
    $out .= "\n|}\n(Retrieval complete.)";
      } else {
+
} else {
 
    $out = 'No stock items available for open orders.';
 
    $out = 'No stock items available for open orders.';
      }
+
}
      $wgOut->addWikiText($out,TRUE); $out = '';
+
$wgOut->addWikiText($out,TRUE); $out = '';
 
     }
 
     }
 +
/*
 
     public function doCacheTables() {
 
     public function doCacheTables() {
global $wgRequest, $wgOut;
+
$this->DB()->CacheMgr()->AdminPage();
global $objDataMgr;
 
 
 
$out = '==Cache Tables=='."\n";
 
$wgOut->addWikiText($out,TRUE); $out = '';
 
 
 
$dbVBZ = VbzDb();
 
 
 
// check for action requests
 
$strDo = $wgRequest->getVal('do');
 
$strTbls = $wgRequest->getVal('table-info');
 
$objDataMgr = new clsDataMgr($dbVBZ,ksTbl_cache_tables,ksTbl_cache_procs,ksTbl_cache_flow,ksTbl_cache_log);
 
if ($strDo != '') {
 
    $idTbl = $wgRequest->getVal('table');
 
    switch ($strDo) {
 
      case 'table-update':
 
$out = $dbVBZ->UpdateTable($idTbl,'Special:VbzAdmin');
 
break;
 
      case 'table-stamp';
 
$out = $dbVBZ->StampTable($idTbl,'Special:VbzAdmin');
 
break;
 
    }
 
    $wgOut->addWikiText($out,TRUE); $out = '';
 
}
 
 
 
// display the current status
 
$out = $dbVBZ->ShowTables($strTbls);
 
$wgOut->addWikiText($out,TRUE); $out = '';
 
$dbVBZ->Shut();
 
 
 
// $wgOut->addHTML($out);
 
 
     }
 
     }
 +
*/
 
     public function doSuppliers() {
 
     public function doSuppliers() {
$dbVBZ = VbzDb();
+
$objSupps = $this->DB()->Suppliers();
$objSupps = $dbVBZ->Suppliers();
 
 
$objSupps->ListPage();
 
$objSupps->ListPage();
 
     }
 
     }
 
     public function doSupplier($iID) {
 
     public function doSupplier($iID) {
$dbVBZ = VbzDb();
+
$objSupps = $this->DB()->Suppliers();
$objSupps = $dbVBZ->Suppliers();
 
 
$objSupp = $objSupps->GetItem($iID);
 
$objSupp = $objSupps->GetItem($iID);
$objSupp->InfoPage();
+
return $objSupp->AdminPage();
 
     }
 
     }
 
     public function doDept($iID) {
 
     public function doDept($iID) {
$dbVBZ = VbzDb();
+
$objDepts = $this->DB()->Depts();
$objDepts = $dbVBZ->Depts();
 
 
$objDept = $objDepts->GetItem($iID);
 
$objDept = $objDepts->GetItem($iID);
$objDept->InfoPage();
+
return $objDept->InfoPage();
 
     }
 
     }
 
     public function doTitle($iID) {
 
     public function doTitle($iID) {
$dbVBZ = VbzDb();
+
$objTitles = $this->DB()->Titles();
$objTitles = $dbVBZ->Titles();
 
 
$objTitle = $objTitles->GetItem($iID);
 
$objTitle = $objTitles->GetItem($iID);
$objTitle->InfoPage();
+
return $objTitle->InfoPage();
 
     }
 
     }
}
+
     public function doItem($iID) {
 
+
$objTbl = $this->DB()->Items();
class clsVbzAdminData extends clsVbzData {
+
$objRow = $objTbl->GetItem($iID);
     public function Suppliers() {
+
return $objRow->InfoPage();
return $this->Make('VbzAdminSuppliers');
 
 
     }
 
     }
     public function Depts() {
+
     public function doImgAdmin() {
return $this->Make('VbzAdminDepts');
+
$objTbl = $this->DB()->Images();
 +
return $objTbl->AdminPage_Unassigned();
 
     }
 
     }
     public function Titles() {
+
     /*----
return $this->Make('VbzAdminTitles');
+
      TO DO: This really should be rewritten as a method of clsContactNode
    }
+
      USED BY: VbzAdminOrder::DoSetupCart() in admin.ord.php
    public function Items() {
+
      HISTORY:
return $this->Make('VbzAdminItems');
+
2011-04-17 using AdminLink() on customer object instead of hand-building the links
    }
+
    */
    public function Places() {
+
    function CheckPersonMatches(clsPerson $iPerson,VbzAdminCart $iCart) {
return $this->Make('VbzStockPlaces');
+
$objDB = $this->DB();
    }
+
$objPage = $this;
     public function Bins() {
+
$objPerson = $iPerson;
return $this->Make('VbzStockBins');
+
$objCart = $iCart;
    }
+
//$arLink = $iLinkArr;
    public function StkLines() {
+
 
return $this->Make('VbzAdminStkItems');
+
$strName = $objPerson->FormName();
    }
+
$strDescr = $objPerson->Descr();
    public function CartLines() {
+
 
return $this->Make('clsShopCartLines');
+
$objName = $iPerson->Node('name');
    }
+
if (!is_object($objName)) {
    public function UpdateTable($iID,$iCaller) {
+
    echo $iPerson->DumpHTML();
/*
+
    throw new exception('Internal error: missing object in tree.');
ACTION: Update the table by running all the procs which target it
+
}
*/
+
$strCustName = $objName->Value();
global $objDataMgr;
+
 
 +
$out = "\n<hr>Contact information for <b>$strDescr</b>:";
 +
 
 +
$out .= "\n<li> <b>Customer</b>: ".$strCustName;
 +
$out .= "\n<ul>";
 +
if ($objCart->DataItem(KSI_SHIP_IS_CARD)) {
 +
    $strAddrShip = 'Address';
 +
} else {
 +
//     $strCardAddr = $objPerson->Card->Addr->AsSingleLine();
 +
    $objPay = $objPerson->Payment();
 +
    if (is_null($objPay)) {
 +
/*
 +
  2011-10-04 this isn't a problem as long as _one_ of the calls has payment in iPerson
 +
echo 'Person object tree:';
 +
echo $objPerson->DumpHTML();
 +
throw new exception('Payment object is NULL');
 +
*/
 +
$strCardAddr = NULL; // so later code knows not to try using it
 +
    } else {
 +
$strCardAddr = $objPay->Addr()->AsSingleLine();
 +
$out .= "\n<li> <b>Card Address</b>: ".$strCardAddr.'</li>';
 +
$strAddrShip = 'Shipping Address';
 +
    }
 +
}
 +
if ($objPerson->HasContact()) {
 +
    $objAddr = $objPerson->Contact()->Addr();
 +
    if ($objAddr) {
 +
$strShipAddr = $objAddr->AsSingleLine();
 +
$out .= "\n<li> <b>$strAddrShip</b>: ".$strShipAddr.'</li>';
 +
$out .= "\n<ul><li><b>Searching as</b>: ".clsCustAddrs::Searchable($strShipAddr).'</li></ul>';
 +
    }
 +
    if ($objPerson->Contact()->HasEmail()) {
 +
$strEmail = $objPerson->Contact()->Email()->Value();
 +
$out .= "\n<li> <b>Email</b>: ".$strEmail.'</li>';
 +
    }
 +
    if ($objPerson->Contact()->HasPhone()) {
 +
$strPhone = $objPerson->Contact()->Phone()->Value();
 +
$out .= "\n<li> <b>Phone</b>: ".$strPhone.'</li>';
 +
    }
 +
}
 +
$out .= "\n</ul>";
  
$out = '';
+
// Look for matches to existing contacts
$arDone = $objDataMgr->Update_byID($iID,$iCaller);
+
$out .= "\nChecking <b>$strDescr</b> for matches to existing customers...";
$out .= $objDataMgr->strMsgs;
+
// -- name
if (is_array($arDone)) {
+
// --- customer
    foreach($arDone AS $ID=>$obj) {
+
$objRows = $objDB->CustNames()->Find($strCustName);
$out .= "\n* ".$obj->Name;
+
if ($objRows->HasRows()) {
 +
    while ($objRows->NextRow()) {
 +
$idCont = $objRows->ID_Cust;
 +
$idName = $objRows->ID;
 +
$arSame[$idCont]['name'] = $objRows->RowCopy();
 +
    }
 +
}
 +
// --- destination (if different)
 +
if (isset($strDestName)) {
 +
    $objRows = $objDB->CustNames()->Find($strDestName);
 +
    if ($objRows->HasRows()) {
 +
while ($objRows->NextRow()) {
 +
    $idCont = $objRows->ID_Cust;
 +
    $idName = $objRows->ID;
 +
    $arSame[$idCont]['name'] = $objRows->RowCopy();
 +
}
 
    }
 
    }
 +
}
 +
 +
// -- address
 +
// --- card
 +
if ($objCart->DataItem(KSI_SHIP_IS_CARD)) {
 +
    $strAddrShip = 'addr';
 
} else {
 
} else {
    $out .= '<br>No tables updated.';
+
    $strAddrShip = 'addr-ship';
 +
    if (!is_null($strCardAddr)) {
 +
$objRows = $objDB->CustAddrs()->Find($strCardAddr);
 +
if ($objRows->HasRows()) {
 +
    while ($objRows->NextRow()) {
 +
$idCont = $objRows->ID_Cust;
 +
$idName = $objRows->ID;
 +
$arSame[$idCont]['addr-card'] = $objRows->RowCopy();
 +
    }
 +
}
 +
    }
 +
}
 +
// --- shipping
 +
if (isset($strCardAddr)) {
 +
    $objRows = $objDB->CustAddrs()->Find($strCardAddr);
 +
    if ($objRows->HasRows()) {
 +
while ($objRows->NextRow()) {
 +
    $idCont = $objRows->ID_Cust;
 +
    $idName = $objRows->ID;
 +
    $arSame[$idCont][$strAddrShip] = $objRows->RowCopy();
 +
}
 +
    }
 
}
 
}
/*
+
if (isset($objPerson->Contact)) {
  $sql =
+
    // -- phone
'SELECT df.ID_Dest, dp.Name, dp.doesClear'.
+
    if (isset($strPhone)) {
' FROM data_flow AS df LEFT JOIN data_procs AS dp ON df.ID_Proc=dp.ID'.
+
$objRows = $objDB->CustPhones()->Find($strPhone);
' WHERE ID_Dest='.$this->SafeParam($iID).
+
if ($objRows->HasRows()) {
' ORDER BY df.ID_Dest, IF(dp.doesClear,0,1)';
+
    while ($objRows->NextRow()) {
// $out = $sql;
+
$idCont = $objRows->ID_Cust;
 +
$idName = $objRows->ID;
 +
$arSame[$idCont]['phone'] = $objRows->RowCopy();
 +
    }
 +
}
 +
    }
  
  $objProcs = $this->DataSet($sql);
+
    // -- email
  if ($objProcs->hasRows()) {
+
    if (isset($strEmail)) { // sometimes this isn't set; this may be a bug. figure out why later.
      $out = 'Running update procedures:';
+
$objRows = $objDB->CustEmails()->Find($strEmail);
      while ($objProcs->hasRow()) {
+
if ($objRows->HasRows()) {
  $out .= "\n* ".$objProcs->Name.'()';
+
    while ($objRows->NextRow()) {
  $objProcs->NextRow();
+
$idCont = $objRows->ID_Cust;
      }
+
$idName = $objRows->ID;
 +
$arSame[$idCont]['email'] = $objRows->RowCopy();
 +
    }
 +
}
 +
    }
 +
}
 +
// -- credit card
 +
$strCard = $objCart->DataItem(KSI_CUST_CARD_NUM);
 +
$objRows = $objDB->CustCards()->Find($strCard);
 +
if ($objRows->HasRows()) {
 +
    while ($objRows->NextRow()) {
 +
$idCont = $objRows->ID_Cust;
 +
$idName = $objRows->ID;
 +
$arSame[$idCont]['card'] = $objRows->RowCopy();
 +
    }
 +
}
 +
// Report any matches found:
 +
if (isset($arSame)) {
 +
    $out .= "\nChoose how to resolve the match:";
 +
    $out .= "\n<ul>";
 +
    foreach ($arSame as $idCont=>$val) {
 +
$objCust = $objDB->Custs($idCont);
 +
$htLink = $objCust->AdminLink_status();
  
  } else {
+
$out .= "\n<li><input type=radio name=\"$strName\" value=\"$idCont\">Use contact #$htLink</a>:";
      $out = 'Nothing to update.';
+
$out .= "\n<ul>";
  }
+
foreach($val as $vkey=>$vval) {
*/
+
    $strDescr = $vval->ShortDescr();
  return $out;
+
    $out .= "\n<li> <b>$vkey</b>: $strDescr</li>";
 +
}
 +
$out .= "\n</ul></li>";
 +
    }
 +
    $out .= "\n<li><input type=radio name=\"$strName\" value=\"new\">Create new contact record</li>";
 +
    $out .= "\n</ul>";
 +
} else {
 +
// 2011-07-28 removing "create new records" link; should be created on import if none found
 +
//     $htURL = $objPage->SelfURL(array('allnew'=>TRUE));
 +
//     $htLink = '<a href="'.$htURL.'">create new records</a>';
 +
    $out .= "\n<br>No matches found; new contact records will be created.";
 +
    $out .= '<input type=hidden name="cust" value=new /><input type=hidden name="ship" value=new />';
 +
}
 +
return $out;
 
     }
 
     }
     public function StampTable($iID,$iCaller) {
+
     protected function DoUpdateStats() {
/*
+
$objVars = $this->objDB->VarsGlobal();
ACTION: Update the table's timestamp so that dependent tables will get updated as needed
+
 
*/
+
$sqlStkQty = 'SELECT SUM(QtyForSale) AS Qty FROM qryStkItms_for_sale';
 +
$intStkQty = 0;
  
$sql = 'UPDATE '.ksTbl_cache_tables.' SET WhenUpdated=NOW() WHERE ID='.$iID;
+
$objVars->Val('stat.stock.qty',$intStkQty); // total stock quantity
$this->Open();
 
$this->Exec($sql);
 
 
 
$objLogger = VbzDb()->Events();
 
$objLogger->LogEvent(__CLASS__.'.'.__METHOD__,'ID='.$iID,'stamp table',NULL,FALSE,FALSE);
 
$this->Shut();
 
 
     }
 
     }
     public function ShowTables($iTbls) {
+
     protected function DoPriceList() {
global $objDataMgr;
+
global $wgOut,$wgRequest;
 +
global $vgPage;
  
assert('is_object($objDataMgr)');
+
$vgPage->UseHTML();
assert('is_object($objDataMgr->Tables)');
 
  
$objTbls = $this->DataSet('SELECT * FROM '.ksTbl_cache_tables.' WHERE Name != "" ORDER BY Name');
+
$doCheck = $wgRequest->GetBool('btnCheck');
  
// convert table info string-list to an array:
+
$out = NULL;
$tok = substr ( $iTbls, 0, 1); // token for splitting
+
$out .= 'Enter <s>catalog numbers or</s> item IDs:';
if ($tok) {
+
 
$tks = substr ( $iTbls, 1 ); // tokenized string
+
if ($doCheck) {
$tkl = explode ( $tok, $tks ); // split the string
+
    $txt = $wgRequest->GetText('list');
foreach ($tkl as $value) {
+
    $xts = new xtString($txt);
if ($value) {
+
    $xts->ReplaceSequence("\n\t ", ' ',0);
    $lstTbls[$value] = $value;
+
    $ar = explode (' ',$xts->Value);
}
+
 
}
+
    $pos = strpos ($txt,':'); // colon means there are quantities
 +
    $hasQtys = is_numeric($pos);
 +
 
 +
    $htTxt = htmlspecialchars($txt);
 +
    $htTxtRows = 3;
 
} else {
 
} else {
$lstTbls = NULL;
+
    $htTxt = '';
 +
    $htTxtRows = 30;
 
}
 
}
  
if ($objTbls->hasRows()) {
+
if ($doCheck) {
    $out = "{| class=sortable \n|-\n! table name || last update || targets || sources || notes";
+
    $out .= '<table width=100%><tr><td width=10%>';
    while ($objTbls->NextRow()) {
+
    if ($hasQtys) {
if ($objTbls->isActive) {
+
$htQtyCol = '<th>Qty</th>';
    $strTbl = $objTbls->Name;
+
    } else {
    $idTbl =  $objTbls->ID;
+
$htQtyCol = '';
 +
    }
  
    $objSrces = $this->DataSet('SELECT * FROM '.ksTbl_cache_flow.' WHERE ID_Dest='.$objTbls->ID);
+
    $objDB = $this->DB();
    $objTargs = $this->DataSet('SELECT * FROM '.ksTbl_cache_flow.' WHERE ID_Srce='.$objTbls->ID);
+
    $out .= '</td><td valign=top>';
    $cntSrces = $objSrces->RowCount();
+
    $out .= '<table><tr><th>ID</th>'.$htQtyCol.'<th>Cat #</th><th>Name</th><th>Exact</th><th>Rounded</th></tr>';
    $cntTargs = $objTargs->RowCount();
+
    $arItems = array();
 +
    $arQtys = array();
 +
    foreach ($ar as $word) {
 +
// if word contains a colon, ignore it and everything after (so we can use that format here even though qty is irrelevant):
 +
$pos = strpos ($word,':');
 +
if ($pos) {
 +
    $qty = substr($word,$pos+1);
 +
    $word = substr($word,0,$pos);
 +
} else {
 +
    $qty = NULL;
 +
}
 +
if (is_numeric($word)) {
 +
    $id = $word;
 +
    $objItem = $objDB->Items($id);
 +
 
 +
    if (is_object($objItem)) {
 +
$id = $objItem->Value('ID');
 +
if (!array_key_exists($id,$arItems)) {
 +
    $arItems[$id] = $objItem->Values();
 +
    $arCatNums[$objItem->Value('CatNum')] = $id;
 +
}
 +
$arQtys[$id] = NzArray($arQtys,$id)+$qty;
  
// table info open/shut calculations
 
    $doInfo = isset($lstTbls[$idTbl]);
 
    $lstTblsThis = $lstTbls;
 
    if ($doInfo) {
 
    // remove this table from the list
 
unset($lstTblsThis[$idTbl]);
 
 
    } else {
 
    } else {
    // add this table to the list
+
$out .= "\n<tr>"
$lstTblsThis[$idTbl] = $idTbl;
+
  .'<td>'.$id.'</td><td colspan=2>not found</td></tr>';
 
    }
 
    }
    // rebuild the string-list
+
} else {
    if (count($lstTblsThis) > 0) {
+
    // to be written
$strTbls = ':'.implode(':',$lstTblsThis);
+
}
$htTblName = WikiSelfLink('table-info='.$strTbls,$strTbl);
+
    }
 +
 
 +
    ksort($arCatNums);
 +
 
 +
    foreach ($arCatNums as $catnum => $id) {
 +
//echo '<br>CATNUM=['.$catnum.'] ID=['.$id.']';
 +
$arVals = $arItems[$id];
 +
$objItem->Values($arVals); // load the row into the object
 +
 
 +
$mnSellExact = $objItem->Value('PriceSell');
 +
$mnSellRound = round($mnSellExact) + 1.00;
 +
 
 +
$out .= "\n<tr>"
 +
  .'<td>'.$objItem->AdminLink().'</td>';
 +
if ($hasQtys) {
 +
    $qty = $arQtys[$id];
 +
    if (is_null($qty)) {
 +
$out .= '<td></td>';
 
    } else {
 
    } else {
$strTbls = NULL;
+
$out .= "<td align=right>$qty</td>";
$htTblName = WikiSelfLink('',$strTbl);
 
    }
 
    // build the table name HTML
 
    if ($doInfo) {
 
$htTblName = '<b>'.$htTblName.'</b>';
 
 
    }
 
    }
 +
}
 +
$out .=
 +
  '<td>'.$objItem->Value('CatNum').'</td>'
 +
  .'<td>'.$objItem->FullDescr_HTML().'</td>'
 +
  .'<td>'.$mnSellExact.'</td>'
 +
  .'<td>'.$mnSellRound.'</td>'
 +
  .'</tr>';
 +
    }
 +
    $out .= '</tr></table>'; // item listing table
 +
    $out .= '</td></tr></table>'; // outer table
 +
}
 +
 +
$out .= '<form method=post>';
 +
$out .= '<textarea name=list rows='.$htTxtRows.'>'.$htTxt.'</textarea>';
 +
$out .= '<input type=submit name=btnCheck value="Check" />';
 +
$out .= '</form>';
 +
 +
$wgOut->AddHTML($out);
 +
return NULL; // caller expects wikitext
 +
    }
 +
    private function DoInvCompare() {
 +
global $vgPage;
 +
global $wgOut,$wgRequest;
 +
 +
$txtStart = $wgRequest->GetText('txtStart');
 +
$txtFinish = $wgRequest->GetText('txtFinish');
 +
 +
$vgPage->UseHTML();
 +
 +
$htStart = htmlspecialchars($txtStart);
 +
$htFinish = htmlspecialchars($txtFinish);
 +
 +
$fxParse = function($iText) {
 +
    $ar = preg_split('/ /',$iText);
 +
    foreach ($ar as $item) {
 +
list($id,$qty) = preg_split('/:/',$item);
 +
$arOut[$id] = $qty;
 +
    }
 +
    return $arOut;
 +
};
  
    $txtSrces = '';
+
$arStart = $fxParse($txtStart);
    $htTblLink = '&table='.$idTbl;
+
$arFinish = $fxParse($txtFinish);
  
    if ($cntSrces) {
+
$arDiff = array();
$txtSrces .= WikiSelfLink('do=table-update'.$htTblLink,'update').' ('.$cntSrces.')';
+
foreach ($arStart as $id => $qty) {
    }
+
    $qtyFinish = nzArray($arFinish,$id);
    $txtTargs = '';
+
    if ($qty != $qtyFinish) {
    if ($cntTargs) {
+
$arDiff[$id] = 'old:'.$qty.' new:'.$qtyFinish;
$txtTargs .= WikiSelfLink('do=table-stamp'.$htTblLink,'stamp').' ('.$cntTargs.')';
+
    }
    }
+
}
   
+
foreach ($arFinish as $id => $qty) {
    $out .= "\n|-\n| ".$htTblName. ' || ' . $objTbls->WhenUpdated .  
+
    $qtyStart = nzArray($arStart,$id);
      ' || '.$txtTargs.
+
    if (!array_key_exists($id,$arStart)) {
      ' || '.$txtSrces.
+
$arDiff[$id] = 'new:'.$qty;
      ' || '.$objTbls->Notes;
+
    }
 +
}
 +
 
 +
$out = '<form method=post action="'.$vgPage->SelfURL().'">';
 +
$out .= 'Display difference between two inventory counts:';
 +
$out .= '<table width=100%><tr>';
 +
$out .= "<td>Starting inventory:<textarea rows=10 name=txtStart>$txtStart</textarea></td>";
 +
$out .= "<td>Ending inventory:<textarea rows=10 name=txtFinish>$txtFinish</textarea></td>";
 +
$out .= '<tr><td colspan=2 align=center><input type=submit name=btnCalc value="Compare"></td></tr>';
 +
$out .= '</tr></table>';
 +
$out .= '</form>';
  
    // if table is selected to show info, add a row for that:
+
if (count($arDiff) > 0) {
    if ($doInfo) {
+
    $tbl = $this->DB()->Items();
$out .= "\n|-\n| colspan=5 |";
+
    $out .= '<table>';
if ($objSrces->hasRows()) {
+
    foreach ($arDiff as $id => $txt) {
    $out .= "\n* '''Sources''':";
+
$obj = $tbl->GetItem($id);
    while ($objSrces->NextRow()) {
+
$out .= '<tr><td>'.$obj->AdminLink_friendly().'</td><td>'.$txt.'</td></tr>';
$objSrce = $objDataMgr->Tables->GetItem($objSrces->ID_Srce);
 
if ($objSrce->isActive) {
 
    $strName = $objSrce->Name;
 
    $out .= ' [['.kwp_DocTblPfx.$strName.'|'.$strName.']]';
 
} else {
 
    $out .= " ''N/A id=".$objSrces->ID_Srce."''";
 
}
 
    }
 
}
 
if ($objTargs->hasRows()) {
 
    $out .= "\n* '''Targets''':";
 
    while ($objTargs->NextRow()) {
 
$objTarg = $objDataMgr->Tables->GetItem($objTargs->ID_Dest);
 
if ($objTarg->isActive) {
 
    $strName = $objTarg->Name;
 
    $out .= ' [['.kwp_DocTblPfx.$strName.'|'.$strName.']]';
 
} else {
 
    $out .= " ''N/A id=".$objTargs->ID_Dest."''";
 
}
 
    }
 
}
 
    }
 
}
 
 
    }
 
    }
    $out .= "\n|}";
+
    $out .= '</table>';
 
} else {
 
} else {
    $out .= 'ERROR: Mysterious lack of data';
+
    $cnt = count($arStart);
 +
    $out .= $cnt.' item'.Pluralize($cnt).' compared - inventories are identical.';
 
}
 
}
return $out;
 
    }
 
}
 
function SelfLink($iPage,$iKey,$iVal,$iText=NULL) {
 
    $strText = (is_null($iText))?$iVal:$iText;
 
    if (is_null($strText)) {
 
return NULL;
 
    } else {
 
return '[[{{FULLPAGENAME}}/page'.KS_CHAR_URL_ASSIGN.$iPage.'/'.$iKey.KS_CHAR_URL_ASSIGN.$iVal.'|'.$strText.']]';
 
    }
 
}
 
function WikiSelfLink($iArgs,$iText) {
 
// this function is deprecated; gradually convert to SelfLink and then rename it
 
  return '[{{fullurl:{{FULLPAGENAME}}|'.$iArgs.'}} '.$iText.']';
 
}
 
function TimeStamp_HideTime($iStamp) {
 
  
    if (is_string($iStamp)) {
+
$wgOut->AddHTML($out);
$intStamp = strtotime($iStamp);
+
return NULL; // caller expects wikitext
    } else if (is_int($iStamp)) {
 
$intStamp = $iStamp;
 
    } else {
 
$intStamp = NULL;
 
    }
 
    if (!is_null($intStamp)) {
 
return date('Y-m-d',$intStamp);
 
    } else {
 
return NULL;
 
 
     }
 
     }
 
}
 
}
  
class VbzStockPlaces extends clsTable {
+
/* *****
 +
* CATALOG DATA
 +
*/
 +
class VbzAdminSuppliers extends clsSuppliers {
 
     public function __construct($iDB) {
 
     public function __construct($iDB) {
 
parent::__construct($iDB);
 
parent::__construct($iDB);
  $this->Name(ksTbl_stock_places);
+
  $this->ClassSng('VbzAdminSupplier');
  $this->KeyName('ID');
 
  $this->ClassSng('VbzStockPlace');
 
 
     }
 
     }
     public function ListPage() {
+
     public function AdminPage() {
 
global $wgOut;
 
global $wgOut;
 +
global $vgPage;
  
$out = '==Stock Locations=='."\n";
+
$vgPage->UseWiki();
$wgOut->addWikiText($out,TRUE); $out = '';
 
  
$out = $this->Listing();
+
$out = '==Suppliers==';
 
$wgOut->addWikiText($out,TRUE); $out = '';
 
$wgOut->addWikiText($out,TRUE); $out = '';
    }
+
$objRecs = $this->GetData();
    public function Listing($iParent=0) {
+
if ($objRecs->HasRows()) {
$dbVBZ = VbzDb();
+
    $out = "{| class=sortable\n|-\n! ID || A? || Code || Actions || Name";
 
+
    $isOdd = TRUE;
// if (!is_null($iParent)) {
+
    while ($objRecs->NextRow()) {
//     $sqlFilt = ' WHERE ID_Parent='.$iParent;
+
$strCatKey = $objRecs->CatKey;
// } else {
+
$id = $objRecs->ID;
    $sqlFilt = '';
+
$wtActions =
// }
+
  '['.KWP_CAT.strtolower($strCatKey)." shop] "
$sql = 'SELECT * FROM '.ksTbl_stock_places.' ORDER BY Name';
+
  .$objRecs->AdminLink('manage');
$objRow = $dbVBZ->DataSet($sql);
+
$wtCatNum = $strCatKey;
if ($objRow->hasRows()) {
+
$wtStyle = $isOdd?'background:#ffffff;':'background:#cccccc;';
    while ($objRow->NextRow()) {
+
$isActive = $objRecs->isActive;
//$arRows[$objRow->ID] = $objRow->Row;
+
if ($isActive) {
$idParent = $objRow->ID_Parent;
+
    $wtName = '[['.$objRecs->Name.']]';
$idRow = $objRow->ID;
 
$arData[$idRow] = $objRow->Row;
 
if (is_null($idParent)) {
 
    $arTree[0][] = $idRow;
 
 
} else {
 
} else {
    $arTree[$idParent][] = $idRow;
+
    $wtName = $objRecs->Name;
 +
    $wtStyle .= ' color: #888888;';
 
}
 
}
 +
$out .= "\n|- style=\"$wtStyle\"\n| ".$id
 +
  .' || '.($isActive?'&radic;':'')
 +
  .' || '.$wtCatNum
 +
  .' || '.$wtActions
 +
  .' || '.$wtName;
 +
$isOdd = !$isOdd;
 
    }
 
    }
    $out = "{| class=sortable \n|-\n! ID || name || description";
 
    $out .= $this->ListSubStkPlaces($arData,$arTree,$iParent);
 
 
    $out .= "\n|}";
 
    $out .= "\n|}";
 
} else {
 
} else {
    $out = NULL;
+
    $out = 'No suppliers have been created yet.';
 +
}
 +
$wgOut->addWikiText($out,TRUE); $out = '';
 +
    }
 +
}
 +
class VbzAdminSupplier extends clsSupplier {
 +
    /*====
 +
      HISTORY:
 +
2010-12-05 boilerplate event logging added to VbzAdminSupplier
 +
    */
 +
    protected function Log() {
 +
if (!is_object($this->logger)) {
 +
    $this->logger = new clsLogger_DataSet($this,$this->objDB->Events());
 
}
 
}
return $out;
+
return $this->logger;
 +
    }
 +
    public function StartEvent(array $iArgs) {
 +
return $this->Log()->StartEvent($iArgs);
 +
    }
 +
    public function FinishEvent(array $iArgs=NULL) {
 +
return $this->Log()->FinishEvent($iArgs);
 +
    }
 +
    public function EventListing() {
 +
return $this->Log()->EventListing();
 +
    }
 +
    //====
 +
    /*----
 +
      HISTORY:
 +
2010-10-11 Replaced existing code with call to static function
 +
    */
 +
    public function AdminLink($iText=NULL,$iPopup=NULL,array $iarArgs=NULL) {
 +
return clsAdminData::_AdminLink($this,$iText,$iPopup,$iarArgs);
 +
    }
 +
    public function AdminLink_name() {
 +
return $this->AdminLink($this->Name);
 +
    }
 +
    /*----
 +
      HISTORY:
 +
2010-11-04 Created so AdminPage() can use HTML
 +
2011-02-16 Disabled until I figure out why it isn't redundant
 +
    */
 +
/*
 +
    public function ShopLink($iText=NULL) {
 +
return '<a href="'.KWP_CAT.strtolower($this->CatKey).'">'.$iText.'</a>';
 
     }
 
     }
     private function ListSubStkPlaces($iData, $iTree, $iBranch=0, $iInd=0) {
+
*/
      $ind = $iInd+1;
+
     public function PageTitle() {
      $out = '';
+
global $vgPage;
  
      if (isset($iTree[$iBranch])) {
+
$doShow = $vgPage->Arg('show');
  foreach($iTree[$iBranch] AS $key=>$ID) {
+
return $this->Value('CatKey').':'.$doShow;
      $row = $iData[$ID];
 
      $htPlacePfx = '[[{{FULLPAGENAME}}/page'.KS_CHAR_URL_ASSIGN.'place/id'.KS_CHAR_URL_ASSIGN.$ID.'|';
 
      $htPlaceName = $htPlacePfx.$row['Name'].']]';
 
      $out .= "\n|-\n| ".$ID.' || <font style="color: grey;">'.str_repeat('+&nbsp;',$iInd).'</font>'.$htPlaceName.' || '.$row['Descr'];
 
      $out .= $this->ListSubStkPlaces($iData,$iTree,$ID,$ind);
 
  }
 
      }
 
      return $out;
 
 
     }
 
     }
}
+
    /*----
class VbzStockPlace extends clsDataSet {
+
      RETURNS: object for Supplier's Topic
     public function HasParent() {
+
      HISTORY:
return !is_null($this->ID_Parent);
+
2011-10-01 written -- replacing Departments with Topics
 +
    */
 +
     public function TopicObj() {
 +
$id = $this->Value('ID_Topic');
 +
if (is_null($id)) {
 +
    return NULL;
 +
} else {
 +
    $row = $this->Engine()->Topics($id);
 +
    return $row;
 +
}
 
     }
 
     }
     public function ParentObj() {
+
    /*----
if ($this->HasParent()) {
+
      RETURNS: nicely-formatted link to Supplier's Topic
    $objPlaces = new VbzStockPlaces($this->objDB);
+
      HISTORY:
    $obj = $objPlaces->GetItem($this->ID_Parent);
+
2011-10-01 written -- replacing Departments with Topics
 +
    */
 +
     public function TopicLink($iNone='<i>n/a</i>') {
 +
$row = $this->TopicObj();
 +
if (is_object($row)) {
 +
    return $row->AdminLink_name();
 
} else {
 
} else {
    $obj = NULL;
+
    return $iNone;
 
}
 
}
return $obj;
 
 
     }
 
     }
     public function InfoPage() {
+
    /*----
global $wgOut;
+
    */
 +
     public function AdminPage() {
 +
global $wgOut,$wgRequest;
 +
global $vgPage,$vgOut;
 +
 
 +
$vgPage->UseHTML();
 +
$out = NULL;
 +
 
 +
$doEdit = $vgPage->Arg('edit');
 +
$doSave = $wgRequest->GetBool('btnSave');
 +
 
 +
// save edits before showing events
 +
$ftSaveStatus = NULL;
 +
if ($doEdit || $doSave) {
 +
    $this->BuildEditForm();
 +
    if ($doSave) {
 +
$ftSaveStatus = $this->AdminSave();
 +
    }
 +
}
 +
 
 +
$strCatKey = $this->CatKey;
 +
$strName = $this->Name;
 +
 
 +
$doDeptAdd = $vgPage->Arg('add.dept');
 +
 
 +
$objPage = new clsWikiFormatter($vgPage);
 +
$objSection = new clsWikiSection($objPage,$strName.' ('.$strCatKey.')');
 +
$out = $objSection->Generate();
 +
$wgOut->AddHTML($out); $out = '';
 +
 
 +
$objSection = new clsWikiSection($objPage,'Current Record (ID '.$this->ID.')',NULL,3);
 +
$objSection->ToggleAdd('edit');
 +
$out = $objSection->Generate();
 +
 
 +
if ($doEdit) {
 +
    $out .= $objSection->FormOpen();
 +
 
 +
    $objForm = $this->objForm;
 +
    $ftName = $objForm->Render('Name');
 +
    $ftCatKey = $objForm->Render('CatKey');
 +
    $ftTopic = $objForm->Render('ID_Topic');
 +
    $ftActive = $objForm->Render('isActive');
 +
} else {
 +
    $ftName = $vgOut->InternalLink($strName);
 +
    $ftCatKey = $this->ShopLink($strCatKey);
 +
    $ftTopic = $this->TopicLink();
 +
    $ftActive = NoYes($this->isActive);
 +
}
 +
 
 +
$ftID = $this->AdminLink();
 +
 
 +
$out .= $vgOut->TableOpen();
 +
 
 +
$out .= $vgOut->TblRowOpen();
 +
$out .= $vgOut->TblCell('<b>ID</b>:','align=right');
 +
$out .= $vgOut->TblCell($ftID);
 +
$out .= $vgOut->TblRowShut();
 +
 
 +
$out .= $vgOut->TblRowOpen();
 +
$out .= $vgOut->TblCell('<b>Name</b>:','align=right');
 +
$out .= $vgOut->TblCell($ftName);
 +
$out .= $vgOut->TblRowShut();
 +
 
 +
$out .= $vgOut->TblRowOpen();
 +
$out .= $vgOut->TblCell('<b>CatKey</b>:','align=right');
 +
$out .= $vgOut->TblCell($ftCatKey);
 +
$out .= $vgOut->TblRowShut();
 +
 
 +
$out .= $vgOut->TblRowOpen();
 +
$out .= $vgOut->TblCell('<b>Topic</b>:','align=right');
 +
$out .= $vgOut->TblCell($ftTopic);
 +
$out .= $vgOut->TblRowShut();
 +
 
 +
$out .= $vgOut->TblRowOpen();
 +
$out .= $vgOut->TblCell('<b>Active</b>:','align=right');
 +
$out .= $vgOut->TblCell($ftActive);
 +
$out .= $vgOut->TblRowShut();
 +
 
 +
$out .= $vgOut->TableShut();
  
$out = '==Stock Location '.$this->ID.'=='."\n";
+
if ($doEdit) {
$out .= "\n* '''Name''': ".$this->InfoLink();
+
    $out .= '<b>Edit notes</b>: <input type=text name="EvNotes" size=40><br>';
if (!is_null($this->Descr)) {
+
    $out .= '<input type=submit name="btnSave" value="Save">';
    $out .= "\n* '''Description''': ".$this->Descr;
+
    $out .= '<input type=submit name="btnCancel" value="Cancel">';
 +
    $out .= '<input type=reset value="Reset">';
 +
    $out .= '</form>';
 
}
 
}
if ($this->HasParent()) {
+
 
    $out .= "\n* '''Parent''': ".$this->ParentObj()->InfoLink();
+
$vgOut->addText($out,TRUE); $out = '';
 +
 
 +
// show submenu
 +
$arMnu = array(
 +
  'dept' => '.departments.'.$strName.' departments',
 +
  'cat' => '.catalogs.'.$strName.' wholesale catalogs',
 +
  'rreq' => '.restocks.'.$strName.' restock requests',
 +
  'ctg' => '.catalog groups.groups for organizing '.$strName.' catalog items'
 +
  );
 +
$out = '<b>Manage</b>: '.$vgPage->SelfLinkMenu('show',$arMnu);
 +
$vgOut->AddText($out); $out = '';
 +
 
 +
$doShow = $vgPage->Arg('show');
 +
 
 +
//$vgPage->UseWiki();
 +
switch ($doShow) {
 +
/* Some remediation needed here. Some of these output in wikitext, others in HTML.
 +
All of them seem to output directly, rather than returning rendered text.
 +
*/
 +
  case 'dept':
 +
    $objSection = new clsWikiSection($objPage,'Departments',NULL,3);
 +
    $objSection->ToggleAdd('add','add a department to '.$strName,'add.dept');
 +
    $out = $objSection->Generate();
 +
    $wgOut->addHTML($out,TRUE); $out = '';
 +
    $out .= $this->DeptsListing();
 +
    break;
 +
  case 'cat':
 +
    $objSection = new clsWikiSection($objPage,'Catalogs',NULL,3);
 +
    $arLink = array(
 +
      'page' => $this->objDB->CtgSrcs()->ActionKey(),
 +
      'id' => 'new',
 +
      'supp' => $this->ID
 +
      );
 +
    $objSection->ActionAdd('add','add a catalog to '.$strName,FALSE,$arLink);
 +
    $out = $objSection->Generate();
 +
    $wgOut->addHTML($out,TRUE); $out = '';
 +
    $out .= $this->CatalogAdmin();
 +
    break;
 +
  case 'rreq':
 +
    $objSection = new clsWikiSection($objPage,'Restock Requests',NULL,3);
 +
    $out = $objSection->Generate();
 +
    $wgOut->addHTML($out,TRUE); $out = '';
 +
    $out .= $this->RstkReqAdmin();
 +
    break;
 +
  case 'ctg':
 +
    $objSection = new clsWikiSection($objPage,'Catalog Groups','catalog management groups',3);
 +
    $objSection->ArgsToKeep(array('show','page','id'));
 +
    $objSection->ToggleAdd('edit','edit the list of groups','edit.ctg');
 +
    $out = $objSection->Generate();
 +
    $wgOut->addHTML($out,TRUE); $out = '';
 +
    $doEdit = $vgPage->Arg('edit.ctg');
 +
    $out .= $this->CtgGrpAdmin($doEdit);
 +
    break;
 +
  default:
 +
    $out = '';
 
}
 
}
$wgOut->addWikiText($out,TRUE); $out = '';
+
$vgOut->addText($out);
$out = "===Sub-Locations===\n";
+
    }
$out .= $this->SubsList();
+
    /*----
$wgOut->addWikiText($out,TRUE); $out = '';
+
      ACTION: Save user changes to the record
$out = "\n===Bins===\n";
+
      HISTORY:
$out .= $this->BinsList();
+
2010-11-06 copied from VbzStockBin to VbzAdminItem
$wgOut->addWikiText($out,TRUE); $out = '';
+
2011-01-26 copied from VbzAdminItem to clsAdminTopic
 +
2011-10-02 copied from clsAdminTopic to VbzAdminSupplier
 +
    */
 +
    public function AdminSave() {
 +
global $vgOut;
 +
 
 +
$out = $this->objForm->Save();
 +
$vgOut->AddText($out);
 
     }
 
     }
     public function InfoLink() {
+
     /*----
return '[[{{FULLPAGENAME}}/page'.KS_CHAR_URL_ASSIGN.'place/id'.KS_CHAR_URL_ASSIGN.$this->ID.'|'.$this->Name.']]';
+
      HISTORY:
 +
2010-11-06 adapted from VbzStockBin for VbzAdminTitle
 +
2011-10-01 adapted from VbzAdminTitle for VbzAdminSupplier
 +
    */
 +
    private function BuildEditForm() {
 +
global $vgOut;
 +
 
 +
if (is_null($this->objForm)) {
 +
    // create fields & controls
 +
    $objForm = new clsForm_DataSet($this,$vgOut);
 +
    //$objCtrls = new clsCtrls($objForm->Fields());
 +
    //$objCtrls = $objForm;
 +
 
 +
    $objForm->AddField(new clsField('Name'), new clsCtrlHTML(array('size'=>25)));
 +
    $objForm->AddField(new clsFieldNum('ID_Topic'), new clsCtrlHTML());
 +
    $objForm->AddField(new clsField('CatKey'), new clsCtrlHTML(array('size'=>8)));
 +
    $objForm->AddField(new clsFieldBool('isActive'), new clsCtrlHTML_CheckBox());
 +
    $objForm->AddField(new clsField('Notes'), new clsCtrlHTML_TextArea(array('height'=>3,'width'=>50)));
 +
 
 +
    $this->objForm = $objForm;
 +
    //$this->objCtrls = $objCtrls;
 +
}
 
     }
 
     }
     public function SubsList() {
+
     public function DeptsListing() {
$objPlaces = new VbzStockPlaces($this->objDB);
+
$out = $this->objDB->Depts()->Listing_forSupp($this->ID,$this);
$out = $objPlaces->Listing($this->ID);
 
 
return $out;
 
return $out;
 
     }
 
     }
     public function BinsList() {
+
  /*%%%%
$objBins = new VbzStockBins($this->objDB);
+
    SECTION: Data Entry Management
$out = $objBins->Listing($this->ID);
+
     PROCESS:
 +
      * User enters a list of Titles or Items in a textarea box, one per line.
 +
      * Each line is checked against Supplier catalog #s
 +
      * if found, shows details for the title/item and provides option to approve it in the final resultset
 +
      * if not found, gives user the option to give more information identifying the Title/Item, such as
 +
our catalog # (or what our catalog # would be if the Title/Item existed in the database)
 +
  */
 +
    /*----
 +
      PURPOSE: renders form for reconciliation of a user-entered list of Titles from a Supplier source document
 +
      INPUT:
 +
$iTitles[line #] = array of title information, format to be determined
 +
  ['id'] = ID of Title record to be approved as matching the input
 +
  ['scat'] = supplier's catalog number
 +
  ['ocat'] = our catalog number (may be hypothetical)
 +
  ['$buy'] = cost to us
 +
  ['$sell'] = our selling price (to customer)
 +
  ['name'] = descriptive name for the Title
 +
      RETURNS: HTML code for reconciliation form. Does not include <form> tags or buttons.
 +
    */
 
/*
 
/*
$objRow = $objBins->GetData('ID_Place='.$this->ID,'VbzStockBin','code');
+
    public function AdminTitles_form_entry(array $iTitles) {
if ($objRow->hasRows()) {
+
die('This function is not ready yet!');
    $out = "{| class=sortable \n|-\n! ID || code || description";
+
 
    while ($objRow->NextRow()) {
+
if (count($iTitles) > 0) {
$id = $objRow->ID;
+
    $isOdd = TRUE;
$out .= "\n|-\n| $id || ".$objRow->Code." || ".$objRow->Descr;
+
    $isReady = TRUE; // ready to enter - all items have been identified
 +
    $out .= '<table><tr><th>ID</th><th>Cat#</th><th>Title</th><th>Qty</th><th>Price</th></tr>';
 +
    foreach ($iTitles as $cnt => $data) {
 +
$ftStyle = $isOdd?'background:#ffffff;':'background:#eeeeee;';
 +
$htAttr = ' style="'.$ftStyle.'"';
 +
$isOdd = !$isOdd;
 +
 
 +
$strScat = nz($data['scat']);
 +
$strInvTitle = nz($data['title']);
 +
$strPrBuy = nz($data['$buy']);
 +
$strPrSell = nz($data['$sell']);
 +
$strQty = nz($arOut['qty']);
 +
$out .= "<tr$htAttr><td></td><td>$strScat</td><td>$strInvTitle</td><td align=center>$strQty</td><td align=right>$strPrice</td></tr>";
 +
 
    }
 
    }
    $out .= "\n|}";
 
 
} else {
 
} else {
    $out = 'This stock location does not contain any bins.';
+
    $out = 'No titles entered.';
 
}
 
}
 +
    }
 
*/
 
*/
return $out;
+
    /*----
    }
+
      PURPOSE: renders form for reconciliation of a user-entered list of Items from a Supplier source document
}
+
(same as AdminTitles_form_entry() but for Items instead of Titles)
class VbzStockBins extends clsTable {
+
      ACTION: Renders an Item-reconciliation form
     public function __construct($iDB) {
+
      INPUT: output from AdminItems_data_check()
parent::__construct($iDB);
+
      OUTPUT: returned data
  $this->Name(ksTbl_stock_bins);
+
      RETURNS: HTML of form containing data AdminItems_form_receive() is expecting to see
  $this->KeyName('ID');
+
    */
  $this->ClassSng('VbzStockBin');
+
     public function AdminItems_form_entry(array $iData) {
    }
+
$cntItems = count($iData);
    public function ListPage() {
+
 
global $wgOut;
+
if ($cntItems > 0) {
 +
    $strPfx = $this->Value('CatKey');
 +
    $isOdd = TRUE;
 +
    $out = '<table><tr>'
 +
      .'<th></th>'
 +
      .'<th>status</th>'
 +
      .'<th>ID</th>'
 +
      .'<th>Our Cat#</th>'
 +
      .'<th>SCat#</th>'
 +
      .'<th>What</th>'
 +
      .'<th>Qty</th>'
 +
      .'<th>$buy</th>'
 +
      .'<th>$sell</th>'
 +
      .'</tr>';
 +
    foreach ($iData as $idx => $row) {
 +
$ftStyle = $isOdd?'background:#ffffff;':'background:#eeeeee;';
 +
$htAttr = ' style="'.$ftStyle.'"';
 +
$isOdd = !$isOdd;
 +
   
 +
$idItem = nz($row['id']);
 +
$strOCat = nz($row['ocat']);
 +
$strSCat = nz($row['scat']);
 +
$strInvTitle = nz($row['name']);
 +
$strPrBuy = nz($row['$buy']);
 +
$strPrSell = nz($row['$sell']);
 +
$strQty = nz($row['qty']);
 +
$objItem = $row['@obj'];
 +
 
 +
$htOCat = $strOCat;
 +
$htItem = NULL;
 +
 
 +
$cnOCat = "ocat[$idx]";
 +
 
 +
$canUpdSCat = FALSE;
 +
$canUpdDescr = FALSE;
 +
 
 +
if (is_null($objItem)) {
 +
    //$cntNoItem++;
 +
    if (!empty($strOCat)) {
 +
$arOkAdd[$idx] = $data;
 +
    }
 +
    // let user enter our catalog #
 +
    $htOCat = $strPfx.'-<input name="'.$cnOCat.'" size=15 value="'.htmlspecialchars($strOCat).'">';
 +
} else {
 +
    $data['obj'] = $objItem;
 +
    $arOkFnd[$idx] = $data;
 +
    $strOCat = $objItem->Value('CatNum');
 +
    $idItem = $objItem->KeyValue();
 +
 
 +
    $htOCat = $strOCat.'<input type=hidden name="'.$cnOCat.'" value="'.htmlspecialchars($strOCat).'">';
 +
    $htItem = $objItem->AdminLink().'<input type=hidden name="id['.$idx.']" value="'.$idItem.'">';
 +
    $htOCat = $strOCat;
 +
 
 +
    // compare entered values with recorded values
 +
    // -- supplier catalog #
 +
    $strSCatEnt = $strSCat; // entered
 +
    $strSCatRec = $objItem->Supp_CatNum; // recorded
 +
    if ($strSCatEnt != $strSCatRec) {
 +
$canUpdSCat = TRUE;
 +
    }
 +
    // -- title
 +
    $strDescrEnt = $strInvTitle; // entered
 +
    $strDescrRec = $objItem->Descr; // recorded
 +
    if ($strDescrEnt != $strDescrRec) {
 +
$canUpdDescr = TRUE;
 +
    }
 +
}
  
$out = '==Stock Bins=='."\n";
+
$htSCat = $strSCat.'<input type=hidden name="scat['.$idx.']" value="'.htmlspecialchars($strSCat).'">';
$wgOut->addWikiText($out,TRUE); $out = '';
+
if ($canUpdSCat) {
 +
    if (empty($strSCatRec)) {
 +
$strAct = 'save this';
 +
    } else {
 +
$strAct = 'replace <b>'.$strSCatRec.'</b>';
 +
    }
 +
    $htSCat .= '<br><small><input type=checkbox name="do-upd-scat['.$idx.']">'.$strAct.'</small>';
 +
}
 +
$htName = $strInvTitle.'<input type=hidden name="name['.$idx.']" value="'.htmlspecialchars($strInvTitle).'">';
 +
if ($canUpdDescr) {
 +
    if (empty($strDescrRec)) {
 +
$strAct = 'save this';
 +
    } else {
 +
$strAct = 'replace <b>'.$strDescrRec.'</b>';
 +
    }
 +
    $htName .= '<br><small><input type=checkbox name="do-upd-desc['.$idx.']">'.$strAct.'</small>';
 +
}
  
// Open the VbzCart database
+
$htQty = $strQty.'<input type=hidden name="qty['.$idx.']" value='.$strQty.'>';
/* $dbVBZ = new clsVbzData(KS_DB_VBZCART);
+
$dbVBZ->Open();
+
$htPrBuy = $strPrBuy.'<input type=hidden name="$buy['.$idx.']" value="'.$strPrBuy.'">';
VbzClasses::DB($dbVBZ);
+
$htPrSell = $strPrSell.'<input type=hidden name="$sell['.$idx.']" value="'.$strPrSell.'">';
*/
 
$out = $this->Listing();
 
$wgOut->addWikiText($out,TRUE); $out = '';
 
    }
 
    public function Listing($iPlace=NULL) {
 
$dbVBZ = $this->objDB;
 
if (is_null($iPlace)) {
 
    $sqlFilt = '';
 
    $htPlaceHdr = ' where ||';
 
    $doPlace = TRUE;
 
} else {
 
    $sqlFilt = ' WHERE ID_Place='.$iPlace;
 
    $htPlaceHdr = '';
 
    $doPlace = FALSE;
 
}
 
  
$objRow = $dbVBZ->DataSet('SELECT * FROM '.ksQry_stock_bins_wInfo.$sqlFilt.' ORDER BY Code');
+
switch ($row['@state']) {
$out = "{| class=sortable \n|-\n! ID || A? ||code || qtys ||$htPlaceHdr description || when<br>created || when<br>voided";
+
  case 'use':
if ($objRow->hasRows()) {
+
    $htStatus = '<span style="color: #008800"><b>ready</b></span>';
    while ($objRow->NextRow()) {
+
    break;
      $row = $objRow->Row;
+
  case 'add':
 +
    $htStatus = '<span style="color: #000088" title="there is enough info to add this item">addable</span>';
 +
    break;
 +
  default:
 +
    $htStatus = '<span color=red title="need more information">?</span>';
 +
}
  
      $qtySale = $row['QtyForSale'];
+
$out .= "\n<tr$htAttr>"
      $qtyShip = $row['QtyForShip'];
+
  ."\n\t<td>$idx.</td>"
      $qtyRec = $row['QtyExisting'];
+
  ."\n\t<td>$htStatus</td>"
      $strQty = NULL;
+
  ."\n\t<td>$htItem</td>"
      if ($qtySale+$qtyShip+$qtyRec) {
+
  ."\n\t<td>$htOCat</td>"
  if ($qtySale) {
+
  ."\n\t<td>$htSCat</td>"
      $strQty .= "'''$qtySale'''";
+
  ."\n\t<td>$htName</td>"
  }
+
  ."\n\t<td align=center>$htQty</td>"
  if ($qtyShip <> $qtySale) {
+
  ."\n\t<td align=right>$htPrBuy</td>"
      $strQty .= '+'.$qtyShip-$qtySale;
+
  ."\n\t<td align=right>$htPrSell</td>"
  }
+
  ."\n\t</tr>";
  if ($qtyRec <> $qtyShip) {
 
      $strQty .= '{{faint|+'.($qtyRec-$qtyShip).'}}';
 
  }
 
      }
 
      if ($doPlace) {
 
  $htPlace =
 
    '[[{{FULLPAGENAME}}/page'.KS_CHAR_URL_ASSIGN.
 
    'place/place'.KS_CHAR_URL_ASSIGN.
 
    $row['ID_Place'].'|'.$row['PlaceName'].']] || ';
 
      } else {
 
  $htPlace = '';
 
      }
 
      $isActive = is_null($row['WhenVoided']);
 
      if ($isActive) {
 
  $htCellPfx = '';
 
  $htCellSfx = '';
 
  $htActive = '&radic;';
 
      } else {
 
  $htCellPfx = '<s>';
 
  $htCellSfx = '</s>';
 
  $htActive = '';
 
      }
 
      $id = $row['ID'];
 
      $htCode = '[[{{FULLPAGENAME}}/page'.KS_CHAR_URL_ASSIGN.'bin/id'.KS_CHAR_URL_ASSIGN.$id.'|'.$row['Code'].']]';
 
      $out .= "\n|-\n| "
 
.$htCellPfx.$id.$htCellSfx.' || '
 
.$htActive.' || '
 
.$htCellPfx.$htCode.$htCellSfx.' || '
 
.$htCellPfx.$strQty.$htCellSfx.' || '
 
.$htCellPfx.$htPlace.$htCellSfx
 
.$htCellPfx.'<small>'.$row['Descr'].'</small>'.$htCellSfx.' || '
 
.$htCellPfx.TimeStamp_HideTime($row['WhenCreated']).$htCellSfx.' || '
 
.TimeStamp_HideTime($row['WhenVoided']);
 
//       $out .= '<pre>'.var_export($row,TRUE).'</pre>';
 
 
    }
 
    }
 +
    $out .= '</table>';
 +
} else {
 +
    $out  = 'No titles entered.';
 
}
 
}
 
return $out;
 
return $out;
 
     }
 
     }
}
+
    /*----
class VbzStockBin extends clsDataSet {
+
      ACTION: Receives user data from form rendered by AdminItems_form_entry()
     public function PlaceObj() {
+
      INPUT: http POST data from Item reconciliation form
$objPlaces = new VbzStockPlaces($this->objDB);
+
id[line #] = array of Item IDs, where known
$obj = $objPlaces->GetItem($this->ID_Place);
+
name[line #] = array of item descriptions
return $obj;
+
qty[line #] = array of item quantities
 +
scat[line #] = array of supplier catalog numbers for each line, entered by user
 +
ocat[line #] = array of our catalog numbers for each line, entered by user
 +
$buy[line #] = array of price-to-us for each line, entered by user
 +
$sell[line #] = array of price-to-customer for each line, entered by user
 +
      NOTE: sell[] is not currently used in any known scenario. Possibly it should be removed.
 +
      RETURNS: array of all received data, but indexed by line number first
 +
includes the following fields:
 +
  ['qty'] = item quantity
 +
  ['ocat'] = catalog number entered by the user
 +
    to be used either for looking up the item or creating it
 +
      FUTURE: This should be generalized somehow
 +
  */
 +
     public function AdminItems_form_receive() {
 +
global $wgRequest;
 +
 
 +
$arCols = array('id','name','qty','ocat','scat','$buy','$sell','do-upd-scat','do-upd-desc');
 +
foreach ($arCols as $col) {
 +
    $arOut[$col] = $wgRequest->GetArray($col);
 +
}
 +
$arRtn = ArrayPivot($arOut);
 +
//echo '<pre>'.print_r($arRtn,TRUE).'</pre>';
 +
return $arRtn;
 
     }
 
     }
     public function SelfLink($iText) {
+
    /*----
return SelfLink('bin','id',$this->ID,$iText);
+
      ACTION: Check item data against database and return status information
    }
+
      INPUT:
    public function InfoPage() {
+
$iItems[line #]: array in format returned by AdminItems_form_receive()
global $wgOut;
+
      RETURNS:
 +
['#add'] = number of rows which need to be added to the catalog
 +
['#use'] = number of rows which are ready to be used (item exists in catalog)
 +
['rows'] = input data with additional fields:
 +
    ['@state']: status of line as indicated by one of the following strings:
 +
      'use' = item has been found, so this line is ready to use
 +
      'add' = item not found, but there is enough information to create it
 +
    ['@obj'] is the Item object (only included if @state = 'use')
 +
    */
 +
     public function AdminItems_data_check(array $iItems) {
 +
if (count($iItems) > 0) {
 +
    $cntUse = 0;
 +
    $cntAdd = 0;
 +
    $cntUpd = 0; // count of updatable fields
 +
    $arRows = array();
 +
    $strCatPfx = $this->Value('CatKey');
 +
    foreach ($iItems as $idx => $data) {
 +
$idItem = nz($data['id']);
 +
 
 +
$strOCatRaw = nz($data['ocat']);
 +
$strOCatFull = $strCatPfx.'-'.$strOCatRaw;
 +
$gotOCat = !empty($strOCatRaw);
 +
 
 +
$strSCat = nz($data['scat']);
 +
 
 +
$data['@state'] = NULL;
 +
$data['@obj'] = NULL;
 +
if (empty($idItem)) {
 +
    if ($gotOCat) {
 +
// look up item using our catalog #
 +
$objItem = $this->objDB->Items()->Get_byCatNum($strOCatFull);
 +
    } else {
 +
// look up item using supplier catalog #
 +
$objItem = $this->GetItem_bySCatNum($strSCat);
 +
    }
 +
    if (is_null($objItem)) {
 +
if ($gotOCat) {
 +
    $data['@state'] = 'add';
 +
    $cntAdd++;
 +
}
 +
    }
 +
} else {
 +
    $objItem = $this->objDB->Items($idItem);
 +
}
 +
if (is_object($objItem)) {
 +
    $data['@obj'] = $objItem;
 +
    $data['@state'] = 'use';
 +
    $cntUse++;
  
$out = '==Stock Bin '.$this->ID.'=='."\n";
+
    // compare entered values with recorded values
$out .= "\n* '''Code''': ".$this->Code;
+
    // -- supplier catalog #
$objPlace = $this->PlaceObj();
+
    $strSCatEnt = $strSCat; // entered
$out .= "\n* '''Where''': ".$objPlace->InfoLink();
+
    $strSCatRec = $objItem->Supp_CatNum; // recorded
if (!is_null($this->Descr)) {
+
    if ($strSCatEnt != $strSCatRec) {
    $out .= "\n* '''Description''': ".$this->Descr;
+
$cntUpd++;
}
+
$data['@can-upd-scat'] = TRUE;
if (!is_null($this->Notes)) {
+
    } else {
    $out .= "\n* '''Notes''': ".$this->Notes;
+
$data['@can-upd-scat'] = FALSE;
 +
    }
 +
    // -- title
 +
    $strDescrEnt = nz($data['name']); // entered
 +
    $strDescrRec = $objItem->Descr; // recorded
 +
    if ($strDescrEnt != $strDescrRec) {
 +
$cntUpd++;
 +
$data['@can-upd-desc'] = TRUE;
 +
    } else {
 +
$data['@can-upd-desc'] = FALSE;
 +
    }
 +
}
 +
$arRows[$idx] = $data;
 +
    } // foreach ($iItems...)
 +
} else {
 +
    $arRtn = NULL;
 
}
 
}
$wgOut->addWikiText($out,TRUE); $out = '';
+
$arRtn = array(
$out = "===Stock Lines===\n";
+
  'rows' => $arRows,
$out .= $this->StockList();
+
  '#use' => $cntUse,
$wgOut->addWikiText($out,TRUE); $out = '';
+
  '#upd' => $cntUpd,
 +
  '#add' => $cntAdd);
 +
return $arRtn;
 
     }
 
     }
     public function StockList() {
+
    /*----
$sqlSource = ksTbl_stock_items.' AS si LEFT JOIN qryCat_Items AS ci ON si.ID_Item=ci.ID';
+
      ACTION: Creates listed catalog items
$sqlCols = 'si.*, ci.CatNum AS ItCatNum, ci.ID_Title, ci.Title_Name AS TiName';
+
      INPUT: Array of items as returned by AdminItems_data_check()
$objRow = $this->objDB->DataSet(
+
      RETURNS: HTML to display (messages)
    'SELECT '.$sqlCols.
+
    */
    ' FROM '.$sqlSource.
+
     public function AdminItems_data_add(array $iItems) {
    ' WHERE ID_Bin='.$this->ID.
+
$out = '';
    ' ORDER BY WhenRemoved,ItCatNum',
+
 
  'VbzAdminItem');
+
$tblItems = $this->objDB->Items();
if ($objRow->hasRows()) {
 
    $out = "{| class=sortable \n|-".
 
"\n! ID || A? || CatNum || qty || title || when<br>added || when<br>changed || when<br>counted || when<br>removed || notes";
 
    $isOdd = TRUE;
 
    while ($objRow->NextRow()) {
 
$row = $objRow->Row;
 
  
$wtStyle = $isOdd?'background:#ffffff;':'background:#cccccc;';
+
$cntItems = count($iItems);
$isOdd = !$isOdd;
+
$txtOCats = '';
 +
foreach ($iItems as $idx => $row) {
 +
    $txtOCats .= ' '.$row['ocat'];
 +
}
 +
$strEv = 'Adding '.$cntItems.' item'.Pluralize($cntItems).':'.$txtOCats;
  
$isActive = is_null($row['WhenRemoved']) && ($row['Qty'] > 0);
+
$arEv = array(
if (!$isActive) {
+
  'descr' => SQLValue($strEv),
    $wtStyle .= ' color: #888888;';
+
  'where' => SQLValue(__METHOD__),
    $wtStyle .= ' text-decoration: line-through;';
+
  'code' => SQLValue('RI+') // Reconcile Items: add
}
+
  );
 +
$this->StartEvent($arEv);
  
$id = $row['ID'];
+
$strCatPfx = $this->Value('CatKey');
$htID = $objRow->AdminLink($id);
+
foreach ($iItems as $idx => $row) {
// $htID = $objRow->AdminLink('A').' '.$id;
+
    $strOCat = $strCatPfx.'-'.strtoupper($row['ocat']);
$idItem = $row['ID_Item'];
+
    $arAdd = array(
$wtCatNum = is_null($row['CatNum'])?"''".$row['ItCatNum']."''":$row['CatNum'];
+
      'CatNum' => SQLValue($strOCat),
$isActive = is_null($row['WhenRemoved']);
+
      'isCurrent' => 'FALSE', // we don't actually know anything about availability yet
$htActive = $isActive?'&radic;':'';
+
      'ID_Title' => 0, // needs to be assigned to a title
$txtQty = $row['Qty'];
+
      'Descr' => SQLValue($row['name']),
$txtTitle = $objRow->StoreLink($row['TiName']);
+
      'Supp_CatNum' => SQLValue($row['scat'])
$txtWhenAdded = TimeStamp_HideTime($row['WhenAdded']);
+
      );
$txtWhenChged = TimeStamp_HideTime($row['WhenChanged']);
+
    if (!empty($row['$buy'])) {
$txtWhenCnted = TimeStamp_HideTime($row['WhenCounted']);
+
$arAdd['PriceBuy'] = SQLValue($row['$buy']);
$txtWhenRmved = TimeStamp_HideTime($row['WhenRemoved']);
 
$txtNotes = $row['Notes'];
 
$out .= "\n|- style=\"$wtStyle\"\n| $htID || $htActive || $wtCatNum || $txtQty || $txtTitle || $txtWhenAdded || $txtWhenChged || $txtWhenCnted || $txtWhenRmved";
 
 
    }
 
    }
 +
    if (!empty($row['$sell'])) {
 +
$arAdd['PriceSell'] = SQLValue($row['$sell']);
 +
    }
 +
    //$out .= '<pre>'.print_r($arAdd,TRUE).'</pre>';
 +
    $tblItems->Insert($arAdd);
 
}
 
}
 +
$out = $strEv;
 +
$this->FinishEvent();
 
return $out;
 
return $out;
 
     }
 
     }
}
+
    /*----
 +
      ACTION: Renders drop-down box of all Suppliers, with the current one as default
 +
      USED BY: Restock edit screen
 +
      HISTORY:
 +
2011-03-02 What happened? Apparently this method used to exist, but got deleted without a trace.
 +
  Rewriting from scratch.
 +
    */
 +
    public function DropDown($iName=NULL,$iNone=NULL) {
 +
$strName = is_null($iName)?($this->Table->ActionKey()):$iName; // control name defaults to action key
  
class VbzAdminSuppliers extends clsSuppliers {
+
$rs = $this->Table->GetData();
    public function __construct($iDB) {
 
parent::__construct($iDB);
 
  $this->ClassSng('VbzAdminSupplier');
 
    }
 
    public function ListPage() {
 
global $wgOut;
 
  
$out = '==Suppliers==';
+
if ($rs->HasRows()) {
$wgOut->addWikiText($out,TRUE); $out = '';
+
    $out = "\n<SELECT NAME=$strName>";
$objRecs = $this->GetData();
+
    if (!is_null($iNone)) {
if ($objRecs->HasRows()) {
+
$out .= DropDown_row(NULL,$iNone,$iDefault);
    $out = "{| class=sortable\n|-\n! ID || A? || Code || Name";
+
    }
    $isOdd = TRUE;
+
    while ($rs->NextRow()) {
    while ($objRecs->NextRow()) {
+
$id = $rs->Value('ID');
$strCatKey = $objRecs->CatKey;
+
$txtAbbr = $rs->Value('CatKey');
$id = $objRecs->ID;
+
$htAbbr = is_null($txtAbbr)?'':($txtAbbr.' ');
$strCol2 =
+
$htShow = $htAbbr.$rs->Value('Name');
  "'''[[vbznet:cat/".strtolower($strCatKey)."|C]] [[{{FULLPAGENAME}}/page".
+
$out .= DropDown_row($id,$htShow,$this->Value('ID'));
  KS_CHAR_URL_ASSIGN."supp/id".
 
  KS_CHAR_URL_ASSIGN.$id."|A]]''' ";
 
$strCol2 .= $strCatKey;
 
$wtStyle = $isOdd?'background:#ffffff;':'background:#cccccc;';
 
$isActive = $objRecs->isActive;
 
if ($isActive) {
 
    $wtName = '[['.$objRecs->Name.']]';
 
} else {
 
    $wtName = $objRecs->Name;
 
    $wtStyle .= ' color: #888888;';
 
}
 
$out .= "\n|- style=\"$wtStyle\"\n| ".$id.' || '.($isActive?'&radic;':'').' || '.$strCol2.' || '.$wtName;
 
$isOdd = !$isOdd;
 
 
    }
 
    }
    $out .= "\n|}";
+
    $out .= "\n</select>";
 +
    return $out;
 
} else {
 
} else {
    $out = 'No suppliers have been created yet.';
+
    return NULL;
 
}
 
}
$wgOut->addWikiText($out,TRUE); $out = '';
 
 
     }
 
     }
}
+
    /*----
class VbzAdminSupplier extends clsSupplier {
+
      ACTION: Renders drop-down box of active departments for this supplier
     public function InfoPage() {
+
      RETURNS: HTML code
global $wgOut;
+
    */
 +
    public function Depts_DropDown($iName=NULL,$iDefault=NULL,$iNone=NULL) {
 +
$objRecs = $this->objDB->Depts()->Data_forSupp($this->ID,'isActive');
 +
$out = $objRecs->DropDown($iName,$iDefault,$iNone);
 +
return $out;
 +
    }
 +
    public function CatalogAdmin() {
 +
$objTbl = $this->objDB->Catalogs();
 +
$objRows = $objTbl->GetData('ID_Supplier='.$this->ID,NULL,'ID DESC');
 +
$out = $objRows->AdminList();
 +
return $out;
 +
    }
 +
     public function RstkReqAdmin() {
 +
$objTbl = $this->objDB->RstkReqs();
 +
$objRows = $objTbl->GetData('ID_Supplier='.$this->ID,NULL,'IFNULL(WhenOrdered,WhenCreated) DESC');
 +
$out = $objRows->AdminList();
 +
return $out;
 +
    }
 +
    public function CtgGrpAdmin($iEdit) {
 +
$objTbl = $this->objDB->CtgGrps();
 +
$id = $this->KeyValue();
 +
$objRows = $objTbl->GetData('ID_Supplier='.$id,NULL,'Sort');
 +
$out = $objRows->AdminList($iEdit,array('ID_Supplier'=>$id));
 +
return $out;
 +
    }
 +
    /*-----
 +
      ACTION: Finds the last restock request for the given supplier
 +
      RETURNS: the last request by date and the last request sorted by (our) PO #
 +
    */
 +
    public function LastReq() {
 +
//$sqlBase = 'SELECT * FROM `rstk_req` WHERE ID_Supplier='.$this->ID;
 +
$sqlBase = 'WHERE ID_Supplier='.$this->ID;
 +
$sql = $sqlBase.' ORDER BY PurchOrdNum DESC LIMIT 1;';
 +
//$objRow = $this->objDB->DataSet($sql);
 +
$objRow = $this->objDB->RstkReqs()->DataSet($sql);
 +
$objRow->NextRow();
 +
$arOut['by purch ord'] = $objRow->RowCopy();
 +
 
 +
$sql = $sqlBase.' ORDER BY WhenOrdered DESC LIMIT 1;';
 +
//$objRow = $this->objDB->DataSet($sql);
 +
$objRow = $this->objDB->RstkReqs()->DataSet($sql);
 +
$objRow->NextRow();
 +
$arOut['by ord date'] = $objRow->RowCopy();
  
$strCatKey = $this->CatKey;
+
return $arOut;
$out = '==Supplier=='."\n";
 
$out .= "\n* '''ID''': ".$this->ID;
 
$out .= "\n* '''CatKey''': [[vbznet:cat/".strtolower($strCatKey).'|'.$strCatKey.']]';
 
$out .= "\n* '''Name''': [[".$this->Name.']]';
 
$out .= "\n===Departments===";
 
$wgOut->addWikiText($out,TRUE); $out = '';
 
$out = $this->DeptsListing();
 
$wgOut->addWikiText($out,TRUE); $out = '';
 
 
     }
 
     }
     public function DeptsListing() {
+
    /*----
$out = $this->objDB->Depts()->Listing_forSupp($this->ID,$this);
+
      ACTION: Checks each item in the list to see if it corresponds to a given item for the current supplier
return $out;
+
      INPUT: Array of supplier catalog numbers
 +
      OUTPUT: Array in this format:
 +
array[cat#] = item object (if found) or NULL (if not found)
 +
    */
 +
/*
 +
     public function FindItems(array $iList) {
 +
$objTblItems = $this->objDB->Items();
 +
foreach ($iList as $catnum) {
 +
    $strCat = rtrim($catnum,';#!'); // remove comments
 +
    $strCat = trim($strCat); // remove leading & trailing whitespace
 +
    if (!empty($strCat)) {
 +
$sqlFind = 'Supp_CatNum="'.$strCat.'"';
 +
$objItem = $objTblItems->GetData($sqlFind);
 +
if (is_null($objItem)) {
 +
    $arOut[$strCat] = NULL;
 +
} else {
 +
    $arOut[$strCat] = $objItem->RowCopy();
 +
}
 +
    }
 +
}
 +
return $arOut;
 
     }
 
     }
 +
*/
 +
    // DEPRECATED - use GetItem_bySCatNum()
 +
    public function FindItem($iCatNum) { return $this->GetItem_bySCatNum($iCatNum); }
 
}
 
}
  
Line 888: Line 1,623:
 
  $this->ClassSng('VbzAdminDept');
 
  $this->ClassSng('VbzAdminDept');
 
     }
 
     }
     public function Listing_forSupp($iSuppID,$iSuppObj=NULL) {
+
    public function Data_forSupp($iSupp,$iFilt=NULL) {
 +
$sqlFilt = "ID_Supplier=$iSupp";
 +
if (!is_null($iFilt)) {
 +
    $sqlFilt = "($sqlFilt) AND ($iFilt)";
 +
}
 +
$objRecs = $this->GetData($sqlFilt,NULL,'isActive, Sort, CatKey, PageKey');
 +
return $objRecs;
 +
    }
 +
     public function Listing_forSupp($iSuppID,clsSupplier $iSuppObj=NULL) {
 
global $wgOut;
 
global $wgOut;
  
Line 898: Line 1,641:
 
$strSuppKey = strtolower($objSupp->CatKey);
 
$strSuppKey = strtolower($objSupp->CatKey);
  
$objRecs = $this->GetData('ID_Supplier='.$iSuppID,'VbzAdminDept','Sort');
+
$objRecs = $this->GetData('ID_Supplier='.$iSuppID,'VbzAdminDept','isActive, Sort, CatKey, PageKey');
 
if ($objRecs->HasRows()) {
 
if ($objRecs->HasRows()) {
 
    $out = "{| class=sortable\n|-\n! ID || A? || Cat || Page || Sort || Name || Description";
 
    $out = "{| class=sortable\n|-\n! ID || A? || Cat || Page || Sort || Name || Description";
Line 908: Line 1,651:
 
} else {
 
} else {
 
    $strPagePath = $strSuppKey.'/'.strtolower($strPageCode);
 
    $strPagePath = $strSuppKey.'/'.strtolower($strPageCode);
    $wtPageCode = '[[vbznet:cat/'.$strPagePath.'|'.$strPageCode.']]';
+
    $wtPageCode = '['.KWP_CAT.$strPagePath.' '.$strPageCode.']';
 
}
 
}
 
$id = $objRecs->ID;
 
$id = $objRecs->ID;
$wtID = SelfLink('dept','id',$id,$id);
+
$wtID = SelfLink_Page('dept','id',$id,$id);
 
$wtStyle = $isOdd?'background:#ffffff;':'background:#cccccc;';
 
$wtStyle = $isOdd?'background:#ffffff;':'background:#cccccc;';
 
$isActive = $objRecs->isActive;
 
$isActive = $objRecs->isActive;
Line 935: Line 1,678:
 
}
 
}
 
class VbzAdminDept extends clsDept {
 
class VbzAdminDept extends clsDept {
     public function InfoPage() {
+
    /*----
global $wgOut;
+
      HISTORY:
 +
2010-10-11 Replaced existing code with call to static function
 +
    */
 +
    public function AdminLink($iText=NULL,$iPopup=NULL,array $iarArgs=NULL) {
 +
return clsAdminData::_AdminLink($this,$iText,$iPopup,$iarArgs);
 +
    }
 +
    public function AdminLink_name() {
 +
$strPgKey = strtoupper($this->Value('PageKey'));
 +
$out = (is_null($strPgKey))?'':($strPgKey.' ');
 +
$out .= $this->Value('Name');
 +
return $this->AdminLink($out);
 +
    }
 +
    public function DropDown($iName=NULL,$iDefault=NULL,$iNone=NULL) {
 +
$strName = is_null($iName)?($this->Table->ActionKey()):$iName; // control name defaults to action key
 +
 
 +
if ($this->HasRows()) {
 +
    $out = "\n<SELECT NAME=$strName>";
 +
    if (!is_null($iNone)) {
 +
$out .= DropDown_row(NULL,$iNone,$iDefault);
 +
    }
 +
    while ($this->NextRow()) {
 +
$id = $this->ID;
 +
$htAbbr = (is_null($this->PageKey))?'':($this->PageKey.' ');
 +
$htShow = $htAbbr.$this->Name;
 +
$out .= DropDown_row($id,$htShow,$iDefault);
 +
    }
 +
    $out .= "\n</select>";
 +
    return $out;
 +
} else {
 +
    return NULL;
 +
}
 +
    }
 +
/* 2010-11-06 commenting out old event handling
 +
    public function StartEvent($iWhere,$iCode,$iDescr,$iNotes=NULL) {
 +
$arEvent = array(
 +
  'type' => clsEvents::kTypeDept,
 +
  'id' => $this->ID,
 +
  'where' => $iWhere,
 +
  'code' => $iCode,
 +
  'descr' => $iDescr
 +
  );
 +
if (!is_null($iNotes)) {
 +
    $arEvent['notes'] = $iNotes;
 +
}
 +
$this->idEvent = $this->objDB->Events()->StartEvent($arEvent);
 +
    }
 +
    public function FinishEvent() {
 +
$this->objDB->Events()->FinishEvent($this->idEvent);
 +
    }
 +
*/
 +
    /*----
 +
      HISTORY:
 +
2010-10-20 changing event logging to use helper class
 +
2010-11-07 added StartEvent(), FinishEvent()
 +
    */
 +
    protected function Log() {
 +
if (!is_object($this->logger)) {
 +
    $this->logger = new clsLogger_DataSet($this,$this->objDB->Events());
 +
}
 +
return $this->logger;
 +
    }
 +
     public function StartEvent(array $iArgs) {
 +
return $this->Log()->StartEvent($iArgs);
 +
    }
 +
    public function FinishEvent(array $iArgs=NULL) {
 +
return $this->Log()->FinishEvent($iArgs);
 +
    }
 +
    public function EventListing() {
 +
return $this->Log()->EventListing();
 +
/*
 +
$objTbl = $this->objDB->Events();
 +
$objRows = $objTbl->GetData('(ModType="'.clsEvents::kTypeDept.'") AND (ModIndex='.$this->ID.')');
 +
if ($objRows->HasRows()) {
 +
    $out = $objRows->AdminRows();
 +
} else {
 +
    $out = 'No events found for this department.';
 +
}
 +
return $out;
 +
*/
 +
    }
 +
    /*----
 +
      HISTORY:
 +
2011-09-25 renamed from InfoPage() to AdminPage()
 +
    */
 +
    public function AdminPage() {
 +
global $wgOut,$wgRequest;
 +
global $vgPage;
  
 
$strCatKey = $this->CatKey;
 
$strCatKey = $this->CatKey;
 
$strPageKey = $this->PageKey;
 
$strPageKey = $this->PageKey;
$out = '==Department=='."\n";
+
if (empty($strPageKey)) {
 +
    $strShopKey = strtolower($strCatKey);
 +
} else {
 +
    $strShopKey = strtolower($strPageKey);
 +
}
 +
$strAction = $vgPage->Arg('do');
 +
$doEdit = ($strAction == 'edit');
 +
$doEnter = ($strAction == 'enter');
 +
 
 +
$doTitleCheck = $wgRequest->GetBool('btnCheck');
 +
$doTitleAdd = $wgRequest->GetBool('btnAdd');
 +
$doEnterBox = $doEnter || $doTitleCheck || $doTitleAdd;
 +
 
 +
$strTitle = '&ldquo;'.$this->Name.'&rdquo; Department';
 +
 
 +
$vgPage->UseHTML();
 +
$objPage = new clsWikiFormatter($vgPage);
 +
//$objSection = new clsWikiAdminSection($strName);
 +
$objSection = new clsWikiSection($objPage,$strTitle);
 +
//$out = $objSection->HeaderHtml_Edit();
 +
$objSection->ActionAdd('edit');
 +
$objSection->ActionAdd('enter','enter titles for this department');
 +
$out = $objSection->Generate();
 +
 
 +
$wgOut->AddHTML($out); $out = '';
 +
 
 +
if ($doEnterBox) {
 +
    $out = '<table align=right><tr><td><h3>Enter Titles</h3>';
 +
    $doShowForm = $doEnter || $doTitleCheck;
 +
    if ($doShowForm) {
 +
$out .= $objSection->FormOpen();
 +
    }
 +
    $txtNotes = $wgRequest->GetText('notes');
 +
    $htNotes = 'Notes: <input type=text name=notes size=25 value="'.htmlspecialchars($txtNotes).'">';
 +
    if ($doEnter) {
 +
    // STAGE 1: display form for entering titles
 +
$out .= 'Enter titles to check:<br>';
 +
$out .= '<textarea name=titles cols=5 rows=30></textarea>';
 +
$out .= '<br>'.$htNotes;
 +
$out .= '<br><input type=submit name="btnCheck" value="Check">';
 +
    } elseif ($doTitleCheck) {
 +
    // STAGE 2: check entered titles, allow user to fix problems & confirm
 +
$strTitles = $wgRequest->getText('titles');
 +
//$arTitles = $this->ParseSubmittedTitles($strTitles);
 +
$arTitles = ParseTextLines($strTitles);
 +
if (is_array($arTitles)) {
 +
    $doDeptOnly = $this->AffectsCatNum();
 +
    $out .= '<table>';
 +
    foreach ($arTitles as $strCatKey=>$strName) {
 +
$sqlFilt = '';
 +
if ($doDeptOnly) {
 +
    $sqlFilt = '(ID_Dept='.$this->ID.') AND ';
 +
}
 +
$sqlFilt .= 'CatKey='.SQLValue($strCatKey);
 +
$objTitles = $this->objDB->Titles()->GetData($sqlFilt);
 +
if ($objTitles->HasRows()) {
 +
    $htStatus = '';
 +
    $htMatches = '';
 +
    while ($objTitles->NextRow()) {
 +
$htTitle = $objTitles->AdminLink($objTitles->CatNum()).': '.$objTitles->Name;
 +
$htMatches .= '<tr><td></td><td><small>'.$htTitle.'</td></tr>';
 +
    }
 +
} else {
 +
    $htStatus = '<td><font size=-2 color=green>new</font></td>';
 +
    $htMatches = '';
 +
}
 +
$out .= '<tr><td>'.$strCatKey.'</td><td>'.$strName.'</td>'.$htStatus.'</tr>';
 +
$out .= $htMatches;
 +
    }
 +
    $out .= '</table>';
 +
}
 +
$out .= $htNotes.'<br>';
 +
$out .= '<input type=hidden name="titles" value="'.htmlspecialchars($strTitles).'">';
 +
$out .= '<input type=submit name="btnAdd" value="Add Titles">';
 +
    } else {
 +
    // STAGE 3; process entered titles -- add them to the data:
 +
$strTitles = $wgRequest->getText('titles');
 +
$arTitles = $this->ParseSubmittedTitles($strTitles);
 +
$cntTitles = count($arTitles);
 +
$strAddText = 'Add '.$cntTitles.' title'.Pluralize($cntTitles);
 +
$this->StartEvent(__METHOD__,'ADD',$strAddText,$txtNotes);
 +
$out .= '<table>';
 +
$objTitles = $this->objDB->Titles();
 +
foreach ($arTitles as $strCatKey=>$strName) {
 +
    $idTitle = $objTitles->Add($strCatKey,$strName,$this->ID,$txtNotes);
 +
    $objTitle = $this->objDB->Titles()->GetItem($idTitle);
 +
    $out .= '<tr><td>'.$objTitle->AdminLink($objTitle->CatNum()).'</td><td>'.$objTitle->Name.'</td></tr>';
 +
}
 +
$out .= '</table>';
 +
$this->FinishEvent();
 +
    }
 +
    if ($doShowForm) {
 +
$out .= '<input type=submit name="btnCancel" value="Cancel">';
 +
$out .= '<input type=reset value="Reset">';
 +
$out .= '</form>';
 +
    }
 +
    $out .= '</td></tr></table>';
 +
    $wgOut->AddHTML($out); $out = '';
 +
}
 +
 
 +
if ($doEdit) {
 +
    $out .= $objSection->FormOpen();
 +
} else {
 +
}
 +
 
 +
$vgPage->UseWiki();
 
$out .= "\n* '''ID''': ".$this->ID;
 
$out .= "\n* '''ID''': ".$this->ID;
$out .= "\n* '''CatKey''': ".$strCatKey;
+
$out .= "\n* '''Supplier''': ".$this->SuppObj()->AdminLink_name();
$out .= "\n* '''PageKey''': [[vbznet:cat/".strtolower($strPageKey).'|'.$strPageKey.']]';
+
$out .= "\n* '''CatKey''': $strCatKey";
$out .= "\n* '''Name''': [[".$this->Name.']]';
+
$out .= "\n* '''PageKey''': $strPageKey";
 +
$out .= "\n* '''Shop''': [".$this->URL_Abs().' '.$this->URL_Rel().']';
 
$out .= "\n===Titles===";
 
$out .= "\n===Titles===";
 
$wgOut->addWikiText($out,TRUE); $out = '';
 
$wgOut->addWikiText($out,TRUE); $out = '';
 
$out = $this->TitleListing();
 
$out = $this->TitleListing();
 
$wgOut->addWikiText($out,TRUE); $out = '';
 
$wgOut->addWikiText($out,TRUE); $out = '';
 +
 +
if ($doEdit) {
 +
    $out .= '<input type=submit name="btnSave" value="Save">';
 +
    $out .= '<input type=submit name="btnCancel" value="Cancel">';
 +
    $out .= '<input type=reset value="Reset">';
 +
    $out .= '</form>';
 +
}
 +
$wgOut->AddHTML($out); $out = '';
 +
$wgOut->addWikiText('===Events===',TRUE);
 +
$out = $this->EventListing();
 +
$wgOut->addWikiText($out,TRUE);
 
     }
 
     }
 
     public function TitleListing() {
 
     public function TitleListing() {
$out = $this->objDB->Titles()->Listing_forDept($this);
+
$out = $this->objDB->Titles_Item()->Listing_forDept($this);
 
return $out;
 
return $out;
 +
    }
 +
    /*----
 +
      ACTION: Add a list of titles to this department
 +
      INPUT:
 +
iTitles: array
 +
  iTitles[catkey] = name
 +
iEvent: array to be passed to event log
 +
    */
 +
    public function AddTitles(array $iTitles,array $iEvent=NULL) {
 +
$cntTitles = count($iTitles);
 +
if ($cntTitles > 0) {
 +
    $strDescr = 'adding '.$cntTitles.' title'.Pluralize($cntTitles);
 +
    $iEvent['descr'] = StrCat($iEvent['descr'],$strDescr,' ');
 +
    $iEvent['where'] = nz($iEvent['where'],__METHOD__);
 +
    $iEvent['code'] = 'ADM'; // add multiple
 +
    $this->StartEvent($iEvent);
 +
    $cntAdded = 0;
 +
    $cntError = 0;
 +
    $txtAdded = '';
 +
    $txtError = '';
 +
    $tblTitles = $this->objDB->Titles();
 +
    foreach ($iTitles as $catnum => $name) {
 +
$arIns = array(
 +
  'Name' => SQLValue($name),
 +
  'CatKey' => SQLValue($catnum),
 +
  'ID_Dept' => $this->ID,
 +
  'DateAdded' => 'NOW()'  
 +
  );
 +
$ok = $tblTitles->Insert($arIns);
 +
if ($ok) {
 +
    $idNew = $tblTitles->LastID();
 +
    $cntAdded++;
 +
    $txtAdded .= '['.$catnum.' ID='.$idNew.']';
 +
} else {
 +
    $cntError++;
 +
    $txtError .= '['.$catnum.' Error: '.$this->objDB->getError().']';
 +
}
 +
    }
 +
    if ($cntError > 0) {
 +
$txtDescr = $cntError.' error'.Pluralize($cntError).': '.$txtError;
 +
$txtDescr .= ' and ';
 +
    } else {
 +
$txtDescr = 'Success:';
 +
    }
 +
    $txtDescr .= $cntAdded.' title'.Pluralize($cntAdded).' added '.$txtAdded;
 +
    $arEv = array(
 +
      'descrfin' => SQLValue($txtDescr),
 +
      'error' => SQLValue($cntError > 0)
 +
      );
 +
    $this->FinishEvent($arEv);
 +
}
 
     }
 
     }
 
}
 
}
class VbzAdminTitles extends clsTitles {
+
class VbzAdminTitles extends clsVbzTitles {
 
     public function __construct($iDB) {
 
     public function __construct($iDB) {
 
parent::__construct($iDB);
 
parent::__construct($iDB);
 
  $this->ClassSng('VbzAdminTitle');
 
  $this->ClassSng('VbzAdminTitle');
 +
  $this->ActionKey('title');
 +
    }
 +
    public function Add($iCatKey,$iName,$iDept,$iNotes) {
 +
      // log start of event
 +
$arEvent = array(
 +
  'type' => clsEvents::kTypeTitle,
 +
  'id' => NULL,
 +
  'where' => __METHOD__,
 +
  'code' => 'add',
 +
  'descr' => 'new title in dept. '.$iDept.': '.$iCatKey.': '.$iName
 +
  );
 +
if (!is_null($iNotes)) {
 +
    $arEvent['notes'] = $iNotes;
 +
}
 +
$idEvent = $this->objDB->Events()->StartEvent($arEvent);
 +
 +
      // add the title record
 +
$arIns = array(
 +
  'CatKey' => SQLValue($iCatKey),
 +
  'Name' => SQLValue($iName),
 +
  'ID_Dept' => $iDept,
 +
  'DateAdded' => 'NOW()'
 +
  );
 +
$this->Insert($arIns);
 +
$idTitle = $this->objDB->NewID(__METHOD__);
 +
 +
      // log the event's completion
 +
$arUpd = array('id' => $idTitle);
 +
$this->objDB->Events()->FinishEvent($idEvent,$arUpd);
 +
return $idTitle;
 +
    }
 +
    /*----
 +
      HISTORY:
 +
2010-11-15 Changed to use qryTitles_Item_info instead of qryCat_Titles_Item_stats
 +
    */
 +
    public function Data_Imageless() {
 +
//$sql = 'SELECT t.ID_Title AS ID, t.* FROM `qryCat_Titles_Item_stats` AS t LEFT JOIN `cat_images` AS i ON t.ID_Title=i.ID_Title'
 +
$sql = 'SELECT t.* FROM `qryTitles_Item_info` AS t LEFT JOIN `cat_images` AS i ON t.ID=i.ID_Title'
 +
  .' WHERE (i.ID IS NULL) AND (cntForSale > 0)';
 +
$this->ClassSng('VbzAdminTitle_info_Item');
 +
$objRows = $this->DataSQL($sql);
 +
return $objRows;
 +
    }
 +
}
 +
class VbzAdminTitle extends clsVbzTitle {
 +
    /*----
 +
      HISTORY:
 +
2010-10-20 changing event logging to use helper class
 +
2010-11-08 conversion complete: added StartEvent() and FinishEvent(), deleted commented code
 +
    */
 +
    //----
 +
    // BOILERPLATE: event logging
 +
    protected function Log() {
 +
if (!is_object($this->logger)) {
 +
    $this->logger = new clsLogger_DataSet($this,$this->objDB->Events());
 +
}
 +
return $this->logger;
 +
    }
 +
    public function EventListing() {
 +
return $this->Log()->EventListing();
 +
    }
 +
    public function StartEvent(array $iArgs) {
 +
return $this->Log()->StartEvent($iArgs);
 +
    }
 +
    public function FinishEvent(array $iArgs=NULL) {
 +
return $this->Log()->FinishEvent($iArgs);
 +
    }
 +
    // BOILERPLATE: admin HTML
 +
    /*----
 +
      HISTORY:
 +
2010-10-11 Replaced existing code with call to static function
 +
    */
 +
    public function AdminLink($iText=NULL,$iPopup=NULL,array $iarArgs=NULL) {
 +
return clsAdminData::_AdminLink($this,$iText,$iPopup,$iarArgs);
 +
    }
 +
    public function AdminLink_name() {
 +
return $this->AdminLink($this->Value('Name'));
 +
    }
 +
    public function AdminURL(array $iArgs=NULL) {
 +
return clsAdminData::_AdminURL($this,$iArgs);
 +
    }
 +
    // END BOILERPLATE
 +
    //----
 +
    /*----
 +
      ACTION:
 +
Return the current title name
 +
If a value is given, update it to the new value first (returns old value)
 +
If an event array is given, log the event
 +
      HISTORY:
 +
2010-11-07 adapted from clsItem::SCatNum()
 +
    */
 +
    public function Name($iVal=NULL,array $iEvent=NULL) {
 +
$strOld = $this->Name;
 +
if (!is_null($iVal)) {
 +
    if (is_array($iEvent)) {
 +
$iEvent['descr'] = StrCat($iEvent['descr'],'renaming title',': ');
 +
$iEvent['params'] = nz($iEvent['params']).':old=['.$strOld.']';
 +
$iEvent['code'] = 'NN'; // new name
 +
$this->StartEvent($iEvent);
 +
    }
 +
    $arUpd = array('Name'=>SQLValue($iVal));
 +
    $this->Update($arUpd);
 +
    if (is_array($iEvent)) {
 +
$this->FinishEvent();
 +
    }
 +
}
 +
return $strOld;
 +
    }
 +
    /*----
 +
      RETURNS: Text suitable for use as a title for this Title
 +
(Ok, can *you* think of a better method name?)
 +
      HISTORY:
 +
2010-11-19 Created for AdminPage()
 +
    */
 +
    public function Title() {
 +
return $this->CatNum().' '.$this->Name;
 +
    }
 +
    public function DeptObj() {
 +
$objDept = $this->objDB->Depts()->GetItem($this->ID_Dept);
 +
return $objDept;
 +
    }
 +
    public function ShopLink($iText) {
 +
return $this->LinkAbs().$iText.'</a>';
 +
    }
 +
    public function PageTitle() {
 +
return $this->CatNum('-');
 +
    }
 +
    /*----
 +
      RETURNS: List of titles as formatted text
 +
      HISTORY:
 +
2011-10-01 created for revised catalog entry -- no departments anymore, need more topic info
 +
    */
 +
    public function TopicList_ft($iNone='-') {
 +
$rcs = $this->Topics(); // recordset of Topics for this Title
 +
if ($rcs->HasRows()) {
 +
    $out = '';
 +
    while ($rcs->NextRow()) {
 +
$out .= ' '.$rcs->AdminLink();
 +
    }
 +
} else {
 +
    $out = $iNone;
 +
}
 +
return $out;
 +
    }
 +
    /*----
 +
      HISTORY:
 +
2011-02-23 Finally renamed from InfoPage() to AdminPage()
 +
    */
 +
    public function AdminPage() {
 +
global $wgOut,$wgRequest;
 +
global $vgPage,$vgOut;
 +
 +
$doEdit = $vgPage->Arg('edit');
 +
$doSave = $wgRequest->GetBool('btnSave');
 +
 +
$vgPage->UseHTML();
 +
 +
// save edits before showing events
 +
$ftSaveStatus = NULL;
 +
if ($doEdit || $doSave) {
 +
    $this->BuildEditForm();
 +
    if ($doSave) {
 +
$ftSaveStatus = $this->AdminSave();
 +
    }
 +
}
 +
 +
$isMissing = is_null($this->ID);
 +
if ($isMissing) {
 +
    $strTitle = 'Missing Record';
 +
    $this->ID = $vgPage->Arg('ID');
 +
} else {
 +
    // items
 +
    $ftItems = $this->ItemListing();
 +
    $htImages = $this->ImageListing(); // this may update the thumbnails, so do it before showing them
 +
    $htGroups = $this->CMGrpListing();
 +
    $wtEvents = $this->EventListing();
 +
 +
    $objTbl = $this->objDB->Images();
 +
    $htThumbs = $objTbl->Thumbnails($this->ID);
 +
    if (!is_null($htThumbs)) {
 +
$wgOut->AddHTML('<table align=right><tr><td>'.$htThumbs.'</td></tr></table>');
 +
    }
 +
 +
    //$strCatNum = $this->CatNum();
 +
    $strCatPage = $this->CatNum('/');
 +
 +
    $strTitle = 'Title: '.$this->Title();
 +
}
 +
 +
$objPage = new clsWikiFormatter($vgPage);
 +
$objSection = new clsWikiSection($objPage,$strTitle);
 +
$objSection->ToggleAdd('edit');
 +
$out = $objSection->Generate();
 +
$wgOut->AddHTML($out); $out = '';
 +
$vgOut->AddText($ftSaveStatus);
 +
 +
$objSupp = $this->SuppObj();
 +
assert(is_object($objSupp));
 +
 +
if ($doEdit) {
 +
    $out .= $objSection->FormOpen();
 +
 +
    $ftCatKey = $this->objForm->Ctrl('CatKey')->Render();
 +
    $ftSuppCN = $this->objForm->Ctrl('Supplier_CatNum')->Render();
 +
    $ftSupp = $objSupp->DropDown('ID_Supp');
 +
    $ftDept = $objSupp->Depts_DropDown('ID_Dept',$this->ID_Dept);
 +
    $ftName = $this->objForm->Ctrl('Name')->Render();
 +
    $ftSearch = $this->objForm->Ctrl('Search')->Render();
 +
    $ftDescr = $this->objForm->Ctrl('Desc')->Render();
 +
    $ftNotes = $this->objForm->Ctrl('Notes')->Render();
 +
    $ftWhAdded = $this->objForm->Ctrl('DateAdded')->Render();
 +
    $ftWhChckd = $this->objForm->Ctrl('DateChecked')->Render();
 +
    $ftWhUnavl = $this->objForm->Ctrl('DateUnavail')->Render();
 +
} else {
 +
    $ftCatKey = htmlspecialchars($this->CatKey);
 +
    $ftSuppCN = htmlspecialchars($this->Supplier_CatNum);
 +
    $ftSupp = $objSupp->AdminLink_name();
 +
    $objDept = $this->DeptObj();
 +
    if (is_object($objDept)) {
 +
$ftDept = $objDept->AdminLink($objDept->Name);
 +
    } else {
 +
$ftDept = 'not set';
 +
    }
 +
    $ftName = htmlspecialchars($this->Name);
 +
    $ftSearch = htmlspecialchars($this->Search);
 +
    $ftDescr = htmlspecialchars($this->Desc);
 +
    $ftNotes = htmlspecialchars($this->Notes);
 +
    $ftWhAdded = $this->DateAdded;
 +
    $ftWhChckd = $this->DateChecked;
 +
    $ftWhUnavl = $this->DateUnavail;
 +
}
 +
$out .= '<table>';
 +
$out .= '<tr><td align=right><b>ID</b>:</td><td>'.$this->ID.' ['.$this->ShopLink('shop').']';
 +
  $out .= '</td></tr>';
 +
$out .= '<tr><td align=right><b>Cat Key</b>:</td><td>'.$ftCatKey;
 +
  $out .= '</td></tr>';
 +
$out .= '<tr><td align=right title="supplier catalog #"><b>SC#</b>:</td><td>'.$ftSuppCN;
 +
  $out .= '</td></tr>';
 +
$out .= '<tr><td align=right><b>Supplier</b>:</td><td>'.$ftSupp;
 +
  $out .= '</td></tr>';
 +
$out .= '<tr><td align=right><b>Dept</b>:</td><td>'.$ftDept;
 +
  $out .= '</td></tr>';
 +
$out .= '<tr><td align=right><b>Name</b>:</td><td>'.$ftName;
 +
  $out .= '</td></tr>';
 +
$out .= '<tr><td align=right><b>Search</b>:</td><td>'.$ftSearch;
 +
  $out .= '</td></tr>';
 +
$out .= '<tr><td align=right><b>When Added</b>:</td><td>'.$ftWhAdded;
 +
  $out .= '</td></tr>';
 +
$out .= '<tr><td align=right><b>When Checked</b>:</td><td>'.$ftWhChckd;
 +
  $out .= '</td></tr>';
 +
$out .= '<tr><td align=right><b>When Unavailable</b>:</td><td>'.$ftWhUnavl;
 +
  $out .= '</td></tr>';
 +
$out .= '</table>';
 +
if ($doEdit) {
 +
    $out .= '<b>Edit notes</b>: <input type=text name="EvNotes" size=40><br>';
 +
    $out .= '<input type=submit name="btnSave" value="Save">';
 +
    $out .= '<input type=submit name="btnCancel" value="Cancel">';
 +
    $out .= '<input type=reset value="Reset">';
 +
    $out .= '</form>';
 +
}
 +
$wgOut->addHTML($out); $out = '';
 +
 +
if (!$isMissing) {
 +
    $wgOut->addWikiText('===Items===',TRUE);
 +
    $vgOut->addText($ftItems);
 +
    $wgOut->addHTML($htImages); // Images
 +
    $wgOut->addWikiText('===Topics===',TRUE);
 +
    $wgOut->addHTML($this->TopicListing());
 +
    $wgOut->addHTML($htGroups); // Catalog Groups
 +
    $wgOut->addWikiText('===Events===',TRUE);
 +
    $wgOut->addWikiText($wtEvents,TRUE);
 +
}
 +
    }
 +
    /*----
 +
      HISTORY:
 +
2010-11-06 adapted from VbzStockBin for VbzAdminTitle
 +
    */
 +
    private function BuildEditForm() {
 +
global $vgOut;
 +
 +
if (is_null($this->objForm)) {
 +
    // create fields & controls
 +
    $objForm = new clsForm_DataSet($this,$vgOut);
 +
    //$objCtrls = new clsCtrls($objForm->Fields());
 +
    //$objCtrls = $objForm;
 +
 +
    $objForm->AddField(new clsField('CatKey'), new clsCtrlHTML(array('size'=>8)));
 +
    $objForm->AddField(new clsField('Supplier_CatNum'), new clsCtrlHTML(array('size'=>25)));
 +
    $objForm->AddField(new clsFieldNum('ID_Supp'), new clsCtrlHTML());
 +
    $objForm->AddField(new clsFieldNum('ID_Dept'), new clsCtrlHTML());
 +
    $objForm->AddField(new clsField('Name'), new clsCtrlHTML(array('size'=>25)));
 +
    $objForm->AddField(new clsField('Search'), new clsCtrlHTML(array('size'=>25)));
 +
    $objForm->AddField(new clsField('Desc'), new clsCtrlHTML(array('size'=>25)));
 +
    $objForm->AddField(new clsField('Notes'), new clsCtrlHTML());
 +
    $objForm->AddField(new clsFieldTime('DateAdded'), new clsCtrlHTML());
 +
    $objForm->AddField(new clsFieldTime('DateChecked'), new clsCtrlHTML());
 +
    $objForm->AddField(new clsFieldTime('DateUnavail'), new clsCtrlHTML());
 +
 +
    $this->objForm = $objForm;
 +
    //$this->objCtrls = $objCtrls;
 +
}
 +
    }
 +
    public function AdminSave() {
 +
global $wgRequest;
 +
global $vgOut;
 +
 +
// check input for problems
 +
$strCatKeyNew = $wgRequest->GetText('CatKey');
 +
$strCatKeyOld = $this->CatKey;
 +
$ok = TRUE; // ok to save unless CatKey conflict
 +
$out = '';
 +
if ($strCatKeyNew != $strCatKeyOld) {
 +
    $ok = FALSE; // don't save unless CatKey passes tests
 +
    // if catkey is being changed, then check new number for duplicates
 +
    $objSupp = $this->SuppObj();
 +
    $objMatch = $objSupp->GetTitle_byCatKey($strCatKeyNew,'VbzAdminTitle');
 +
    if (is_null($objMatch)) {
 +
$ok = TRUE;
 +
    } else {
 +
/*
 +
  Requested catkey matches an existing title.
 +
  Look for other titles with the same base catkey (in same supplier),
 +
    on the theory that this will represent a list of previous renames
 +
    for this catkey.
 +
*/
 +
$objMatch->NextRow();
 +
$out = 'Your entered CatKey ['.$strCatKeyNew.'] has already been used for '.$objMatch->AdminLink($objMatch->Name);
 +
$objMatch = $objSupp->GetTitles_byCatKey($strCatKeyOld,'VbzAdminTitle');
 +
if (!is_null($objMatch)) {
 +
    // there are some similar entries -- show them:
 +
    $out .= ' Other similar CatKeys:';
 +
    while ($objMatch->NextRow()) {
 +
$out .= ' '.$objMatch->AdminLink($objMatch->CatKey);
 +
    }
 +
}
 +
    }
 +
}
 +
if ($ok) {
 +
    $out .= $this->objForm->Save($wgRequest->GetText('EvNotes'));
 +
}
 +
return $out;
 +
    }
 +
    public function ItemListing() {
 +
$out = $this->objDB->Items()->Listing_forTitle($this);
 +
return $out;
 +
    }
 +
    public function ImageListing() {
 +
$objTbl = $this->objDB->Images();
 +
$arArgs = array(
 +
  'filt' => 'ID_Title='.$this->ID,
 +
  'sort' => 'AttrSort,ID',
 +
  'event.obj' => $this,
 +
  'title.id' => $this->ID,
 +
  'new' => TRUE
 +
  );
 +
$out = $objTbl->AdminPage($arArgs);
 +
 +
// $objRows = $objTbl->GetData('ID_Title='.$this->ID,NULL,'AttrSort');
 +
// $out = $objRows->AdminList();
 +
return $out;
 +
    }
 +
    /*----
 +
      RETURNS: Editable listing of topics for this Title
 +
    */
 +
    protected function TopicListing() {
 +
global $wgRequest;
 +
global $vgPage;
 +
 +
$tblTitleTopics = $this->Engine()->TitleTopics();
 +
 +
$me = $this;
 +
$arOpts = $this->Engine()->Topics()->TopicListing_base_array();
 +
$arOpts['fHandleData_Change_Start'] = function($iText) use ($me) {
 +
      $arEv = array(
 +
'descr' => 'Adding '.$iText,
 +
'code' => 'topic++',
 +
'where' => __METHOD__
 +
);
 +
      $me->StartEvent($arEv);
 +
  };
 +
 +
$arOpts['fHandleData_Change_Finish'] = function($iText) use ($me) {
 +
      $arEv = array(
 +
'descrfin' => $iText
 +
);
 +
      $me->FinishEvent($arEv);
 +
  };
 +
$arOpts['fHandleData_Change_Item'] = function($iVal) use ($me,$tblTitleTopics) {
 +
      $sqlTopic = $iVal;
 +
      $arIns = array(
 +
'ID_Title' => SQLValue($me->KeyValue()),
 +
'ID_Topic' => $sqlTopic
 +
);
 +
      $db = $tblTitleTopics->Engine();
 +
      $db->ClearError();
 +
      $ok = $tblTitleTopics->Insert($arIns);
 +
      if (!$ok) {
 +
  $strErr = $db->getError();
 +
  $out = $sqlTopic.': '.$strErr.' (SQL:'.$tblTitleTopics->sqlExec.')';
 +
      } else {
 +
  $out = SQLValue($sqlTopic);
 +
      }
 +
      return $out;
 +
  };
 +
 +
$ctrlList = new clsWidget_ShortList();
 +
$ctrlList->Options($arOpts);
 +
$htStatus = $ctrlList->HandleInput();
 +
 +
$doRmvTopics = $wgRequest->GetBool('btnRmvTopics');
 +
 +
// begin output phase
 +
$out = '';
 +
 +
if ($doRmvTopics) {
 +
    $arTopics = $wgRequest->GetArray('rmvTitle');
 +
    $cnt = $tblTitleTopics->DelTopics($this->Value('ID'),$arTopics);
 +
    $out .= 'Removed '.$cnt.' topic'.Pluralize($cnt).':';
 +
    foreach ($arTopics as $id => $on) {
 +
$objTopic = $tblTopics->GetItem($id);
 +
$out .= ' '.$objTopic->AdminLink();
 +
    }
 +
}
 +
/*
 +
$htPath = $vgPage->SelfURL();
 +
$out = "\n<form method=post action=\"$htPath\">";
 +
*/
 +
$out .= "\n<form method=post>";
 +
 +
$rs = $this->Topics();
 +
if ($rs->HasRows()) {
 +
    while ($rs->NextRow()) {
 +
 +
$id = $rs->KeyString();
 +
$ftName = $rs->AdminLink_name();
 +
 +
$out .= "\n[<input type=checkbox name=\"rmvTitle[$id]\">$ftName ]";
 +
    }
 +
    $out .= '<br><input type=submit name="btnRmvTopics" value="Remove Checked">';
 +
} else {
 +
    $out .= '<i>None found.</i>';
 +
}
 +
/*
 +
$out .= '<input type=submit name="btnAddTopics" value="Add These:">';
 +
$out .= '<input size=40 name=txtNewTitles> (IDs separated by spaces)';
 +
*/
 +
$out .= '<br>'.$htStatus;
 +
$out .= $ctrlList->RenderForm_Entry();
 +
 +
$out .= '</form>';
 +
return $out;
 +
    }
 +
    /*----
 +
      RETURNS: Listing of CM (catalog management) groups for this title
 +
      HISTORY:
 +
2011-02-06 added controls to allow deactivating/activating selected rows
 +
    */
 +
    protected function CMGrpListing() {
 +
global $wgRequest;
 +
global $vgOut;
 +
 +
$out = $vgOut->Header('Catalog Groups',3);
 +
 +
$tblCMT = $this->objDB->CtgTitles(); // catalog management titles
 +
$tblCMS = $this->objDB->CtgSrcs(); // catalog management sources
 +
$tblCMG = $this->objDB->CtgGrps(); // catalog management groups
 +
 +
$doEnable = $wgRequest->GetBool('btnCtgEnable');
 +
$doDisable = $wgRequest->GetBool('btnCtgDisable');
 +
if ($doEnable || $doDisable) {
 +
    $arChg = $wgRequest->GetArray('ctg');
 +
    $out .= $doEnable?'Activating':'Deactivating';
 +
    foreach ($arChg as $id => $on) {
 +
$out .= ' '.$id;
 +
$arUpd = array(
 +
  'isActive' => SQLValue($doEnable)
 +
  );
 +
$tblCMT->Update($arUpd,'ID='.$id);
 +
    }
 +
}
 +
 +
$rsRows = $tblCMT->GetData('ID_Title='.$this->ID);
 +
if ($rsRows->HasRows()) {
 +
    $out .= '<form method=post>';
 +
    $out .= $vgOut->TableOpen();
 +
    $out .= $vgOut->TblRowOpen(NULL,TRUE);
 +
    $out .= $vgOut->TblCell('ID');
 +
    $out .= $vgOut->TblCell('A?');
 +
    $out .= $vgOut->TblCell('Catalog');
 +
    $out .= $vgOut->TblCell('Group');
 +
    $out .= $vgOut->TblCell('Discontinued');
 +
    $out .= $vgOut->TblCell('Grp Code');
 +
    $out .= $vgOut->TblCell('Grp Descr');
 +
    $out .= $vgOut->TblCell('Grp Sort');
 +
    $out .= $vgOut->TblCell('Supp Cat #');
 +
    $out .= $vgOut->TblCell('Notes');
 +
    $out .= $vgOut->TblRowShut();
 +
    while ($rsRows->NextRow()) {
 +
$isActive = $rsRows->isActive;
 +
$htActive = $isActive?'&radic;':'-';
 +
 +
$objCMSrce = $tblCMS->GetItem($rsRows->ID_Source);
 +
$objCMGrp = $tblCMG->GetItem($rsRows->ID_Group);
 +
if ($objCMSrce->HasRows()) {
 +
    $htCMSrce = $objCMSrce->AdminLink_name();
 +
} else {
 +
    $htCMSrce = '?'.$rsRows->ID_Source;
 +
}
 +
if ($objCMGrp->HasRows()) {
 +
    $htCMGrp = $objCMGrp->AdminLink_name();
 +
} else {
 +
    $htCMGrp = '?'.$rsRows->ID_Group;
 +
}
 +
 +
$out .= $vgOut->TblRowOpen();
 +
$htID = '<input type=checkbox name="ctg['.$rsRows->KeyValue().']">'.$rsRows->AdminLink();
 +
$out .= $vgOut->TblCell($htID);
 +
$out .= $vgOut->TblCell($htActive);
 +
$out .= $vgOut->TblCell($htCMSrce);
 +
$out .= $vgOut->TblCell($htCMGrp);
 +
// $out .= $vgOut->TblCell($rsRows->ID_Source);
 +
// $out .= $vgOut->TblCell($rsRows->ID_Group);
 +
 +
$out .= $vgOut->TblCell($rsRows->WhenDiscont);
 +
$out .= $vgOut->TblCell($rsRows->GroupCode);
 +
$out .= $vgOut->TblCell($rsRows->GroupDescr);
 +
$out .= $vgOut->TblCell($rsRows->GroupSort);
 +
$out .= $vgOut->TblCell($rsRows->Supp_CatNum);
 +
$out .= $vgOut->TblCell($rsRows->Notes);
 +
$out .= $vgOut->TblRowShut();
 +
    }
 +
    $out .= $vgOut->TableShut();
 +
    $out .= '<input type=submit name=btnCtgDisable value="Deactivate Selected">';
 +
    $out .= '<input type=submit name=btnCtgEnable value="Activate Selected">';
 +
    $out .= '</form>';
 +
} else {
 +
    $out .= 'None found.';
 +
}
 +
return $out;
 +
    }
 +
}
 +
/*====
 +
  PURPOSE: VbzAdminTitles with additional catalog information
 +
*/
 +
class VbzAdminTitles_info_Cat extends VbzAdminTitles {
 +
    public function __construct($iDB) {
 +
parent::__construct($iDB);
 +
  $this->Name('qryCat_Titles');
 +
    }
 +
    public function Search_forText_SQL($iFind) {
 +
$sqlFind = '"%'.$iFind.'%"';
 +
return "(Name LIKE $sqlFind) OR (Descr LIKE $sqlFind) OR (Search LIKE $sqlFind) OR (CatNum LIKE $sqlFind)";
 +
    }
 +
    public function SearchPage() {
 +
global $wgOut,$wgRequest;
 +
global $vgPage;
 +
 +
$strFind = $wgRequest->GetText('txtSearch');
 +
 +
$vgPage->UseHTML();
 +
$out = "\n<form method=post>";
 +
$htFind = htmlspecialchars($strFind);
 +
$out .= 'Search for:<input name=txtSearch size=40 value="'.$htFind.'"><input type=submit name=btnSearch value="Go">';
 +
$out .= '</form>';
 +
$wgOut->AddHTML($out); $out = '';
 +
 +
 +
//$tblTitles = $this->Engine()->Titles();
 +
$tblTitles = $this;
 +
$tblItems = $this->Engine()->Items();
 +
$tblImgs = $this->Engine()->Images();
 +
 +
$arTitles = NULL;
 +
 +
$rs = $tblTitles->Search_forText($strFind);
 +
if ($rs->HasRows()) {
 +
    while ($rs->NextRow()) {
 +
$id = $rs->ID;
 +
$arTitles[$id] = $rs->Values();
 +
    }
 +
}
 +
 +
if (!empty($strFind)) {
 +
    $out .= '<br><b>Searching for</b> "'.$htFind.'":<br>';
 +
    $wgOut->AddHTML($out); $out = '';
 +
 +
    $rs = $tblItems->Search_byCatNum($strFind);
 +
    if (is_object($rs)) {
 +
while ($rs->NextRow()) {
 +
    $id = $rs->Value('ID_Title');
 +
    if (!isset($arTitles[$id])) {
 +
$obj = $tblTitles->GetItem($id);
 +
$arTitles[$id] = $obj->Values();
 +
    }
 +
}
 +
    }
 +
 +
    if (!is_null($arTitles)) {
 +
if (empty($obj)) {
 +
    $obj = $tblTitles->SpawnItem();
 +
}
 +
$out .= '<table align=left style="border: solid black 1px;"><tr><td>';
 +
$ftImgs = '';
 +
$isFirst = TRUE;
 +
foreach ($arTitles as $id => $row) {
 +
    $obj->Values($row);
 +
    $txtCatNum = $obj->CatNum();
 +
    $txtName = $obj->Value('Name');
 +
    if ($isFirst) {
 +
$isFirst = FALSE;
 +
    } else {
 +
$out .= "\n<br>";
 +
    }
 +
    $out .= $obj->AdminLink($txtCatNum).' '.$txtName;
 +
 +
    $txtTitle = $txtCatNum.' &ldquo;'.htmlspecialchars($txtName).'&rdquo;';
 +
    $ftImg = $tblImgs->Thumbnails($id,array('title'=>$txtTitle));
 +
    $ftImgs .= '<a href="'.$obj->AdminURL().'">'.$ftImg.'</a>';
 +
}
 +
$out .= '</td></tr></table>'.$ftImgs;
 +
    }
 +
 +
    $wgOut->AddHTML($out); $out = '';
 +
}
 +
 +
return $out;
 +
    }
 +
}
 +
/*====
 +
  PURPOSE: VbzAdminTitles with additional item (and stock) information
 +
*/
 +
class VbzAdminTitles_info_Item extends VbzAdminTitles {
 +
    public function __construct($iDB) {
 +
parent::__construct($iDB);
 +
  $this->Name('qryTitles_Item_info');
 +
  $this->ClassSng('VbzAdminTitle_info_Item');
 
     }
 
     }
 
     public function Listing_forDept($iDeptObj) {
 
     public function Listing_forDept($iDeptObj) {
 
global $wgOut;
 
global $wgOut;
 +
global $vgPage;
 
global $sql;
 
global $sql;
 +
 +
$vgPage->UseHTML();
  
 
$objDept = $iDeptObj;
 
$objDept = $iDeptObj;
 
$idDept = $objDept->ID;
 
$idDept = $objDept->ID;
 
// $strSuppKey = strtolower($objSupp->CatKey);
 
// $strSuppKey = strtolower($objSupp->CatKey);
 +
// $objRecs = $this->GetData('ID_Dept='.$idDept,'VbzAdminTitle','CatKey');
 +
//$objRecs = $this->DataSQL('SELECT t.ID_Title AS ID, t.* FROM qryCat_Titles_Item_stats AS t WHERE t.ID_Dept='.$idDept);
 +
$objRecs = $this->GetData('ID_Dept='.$idDept,NULL,'CatKey');
 +
 +
$out = $objRecs->AdminList();
 +
$wgOut->addHTML($out);
 +
    }
 +
}
 +
class VbzAdminTitle_info_Item extends VbzAdminTitle {
 +
    /*----
 +
      RETURNS: listing of titles in the current dataset
 +
      HISTORY:
 +
2010-11-16 "in print" column now showing cntInPrint instead of cntForSale
 +
    */
 +
    public function AdminList(array $iarArgs=NULL) {
 +
$objRecs = $this;
  
$objRecs = $this->GetData('ID_Dept='.$idDept,'VbzAdminTitle','CatKey');
 
 
if ($objRecs->HasRows()) {
 
if ($objRecs->HasRows()) {
    $out = "{| class=sortable\n|-\n! ID || Cat # || Name || Discont.";
+
    $out = "\n<table class=sortable>"
 +
      ."\n<tr>"
 +
.'<th>ID</th>'
 +
.'<th>Name</th>'
 +
.'<th>Cat #</th>'
 +
.'<th><small>CatKey</small></th>'
 +
.'<th>SCat#</th>'
 +
.'<th>When Added</th>'
 +
.'<th title="number of item records"><small>item<br>recs</small></th>'
 +
.'<th title="number of items in print"><small>items<br>in print</small></th>'
 +
.'<th>stk<br>qty</th>'
 +
      .'</tr>';
 
    $isOdd = TRUE;
 
    $isOdd = TRUE;
 
    while ($objRecs->NextRow()) {
 
    while ($objRecs->NextRow()) {
//     $wtPageCode = '[[vbznet:cat/'.$strPagePath.'|'.$strPageCode.']]';
+
$ftID = $objRecs->AdminLink();
$id = $objRecs->ID;
+
$ftName = $objRecs->Name;
$wtID = SelfLink('title','id',$id,$id);
+
$ftCatNum = $objRecs->CatNum();
$wtStyle = $isOdd?'background:#ffffff;':'background:#cccccc;';
+
$ftCatKey = $objRecs->Row['CatKey'];
$isActive = $objRecs->IsActive();
+
$ftSCatNum = $objRecs->Row['Supplier_CatNum'];
if (!$isActive) {
+
$ftWhen = $objRecs->DateAdded;
 +
 
 +
// FUTURE: If we're using this on a dataset which does not have these fields,
 +
// test for them and then retrieve them the slow way if not found.
 +
$qtyStk = $objRecs->qtyForSale;
 +
//$cntAva = $objRecs->cntForSale;
 +
$cntPrn = $objRecs->cntInPrint;
 +
$cntItm = $objRecs->cntItems;
 +
 
 +
$isActive = (($qtyStk > 0) || ($cntPrn > 0));
 +
$isPassive = (nz($cntItm) == 0);
 +
 
 +
$isOdd = !$isOdd;
 +
$wtStyle = $isOdd?'background:#ffffff;':'background:#eeeeee;';
 +
 
 +
if ($isActive) {
 +
    $wtStyle .= ' font-weight: bold;';
 +
}
 +
if ($isPassive) {
 
    $wtStyle .= ' color: #888888;';
 
    $wtStyle .= ' color: #888888;';
}
 
$out .= "\n|- style=\"$wtStyle\"".
 
    "\n| ".$wtID.
 
    ' || '.$objRecs->CatKey.
 
    ' || '.$objRecs->Name.
 
    ' || '.DataDate($objRecs->DateUnavail);
 
if (!is_null($objRecs->Descr)) {
 
    $out .= "\n|- style=\"$wtStyle\"\n| colspan=4 | ".$objRecs->Descr;
 
 
}
 
}
  
$isOdd = !$isOdd;
+
$out .= "\n<tr style=\"$wtStyle\">".
 +
  "<td>$ftID</td>".
 +
  "<td>$ftName</td>".
 +
  "<td>$ftCatNum</td>".
 +
  "<td>$ftCatKey</td>".
 +
  "<td>$ftSCatNum</td>".
 +
  "<td>$ftWhen</td>".
 +
  "<td align=right>$cntItm</td>".
 +
  "<td align=right>$cntPrn</td>".
 +
  "<td align=right>$qtyStk</td>".
 +
  '</tr>';
 
    }
 
    }
    $out .= "\n|}";
+
    $out .= "\n</table>";
 
} else {
 
} else {
    $out = 'This department has no titles. (SQL='.$sql.')';
+
    if (isset($iarArgs['none'])) {
 +
$out .= $iarArgs['none'];
 +
    } else {
 +
$out .= 'No titles found.';
 +
    }
 
}
 
}
$wgOut->addWikiText($out,TRUE); $out = '';
+
return $out;
 
     }
 
     }
 
}
 
}
class VbzAdminTitle extends clsTitle {
+
/*****
     public function InfoPage() {
+
  GROUP: Item administration
global $wgOut;
+
*/
 +
class VbzAdminItems extends clsItems {
 +
// STATIC section //
 +
    /*----
 +
      HISTORY:
 +
2010-10-13 Re-enabled as a boilerplate call
 +
    */
 +
    public static function AdminLink($iID,$iShow=NULL,$iPopup=NULL) {
 +
return clsAdminTable::AdminLink($iID,$iShow,$iPopup);
 +
    }
 +
// DYNAMIC section //
 +
     public function __construct($iDB) {
 +
parent::__construct($iDB);
 +
  $this->ClassSng('VbzAdminItem');
 +
  $this->ActionKey('item');
 +
    }
 +
    public function Listing_forTitle(clsVbzTitle $iTitleObj) {
 +
$objTitle = $iTitleObj;
 +
$idTitle = $objTitle->ID;
 +
//$cntRow = 0;
  
$strCatNum = $this->CatNum();
+
$objRecs = $this->GetData('(IFNULL(isDumped,0)=0) AND (ID_Title='.$idTitle.')','VbzAdminItem','ItOpt_Sort');
$strCatPage = $this->CatNum('/');
+
return $objRecs->AdminList();
$out = '==Title=='."\n";
 
$out .= "\n* '''ID''': ".$this->ID;
 
$out .= "\n* '''Cat #''': [[vbznet:cat/".strtolower($strCatPage).'|'.$strCatNum.']]';
 
$out .= "\n* '''Name''': ".$this->Name;
 
$out .= "\n===Items===";
 
$wgOut->addWikiText($out,TRUE); $out = '';
 
$out = $this->ItemListing();
 
$wgOut->addWikiText($out,TRUE); $out = '';
 
 
     }
 
     }
     public function ItemListing() {
+
    /*----
$out = $this->objDB->Items()->Listing_forTitle($this);
+
      ACTION: Updates fields in given catalog items
 +
Does not log an event (maybe it should?)
 +
      INPUT: Array of items as returned by AdminItems_data_check()
 +
      RETURNS: HTML to display (messages)
 +
      FUTURE: This possibly should be in a helper class
 +
      HISTORY:
 +
2011-01-04 partially written
 +
    */
 +
     public function AdminItems_data_update(array $iItems) {
 +
$out = "\n<ul>";
 +
foreach ($iItems as $idx => $row) {
 +
    $obj = $row['@obj'];
 +
    $id = $obj->KeyValue();
 +
    $out .= "\n<li>Row $idx ID=$id:\n<ul>";
 +
    $arUpd = NULL;
 +
    if (!empty($row['do-upd-scat'])) {
 +
$arUpd['Supp_CatNum'] = SQLValue($row['scat']);
 +
$out .= "\n<li>scat# [".$obj->Supp_CatNum.']=>['.$row['scat'].']';
 +
    }
 +
    if (!empty($row['do-upd-desc'])) {
 +
$arUpd['Descr'] = SQLValue($row['name']);
 +
$out .= "\n<li>descr [".$obj->Descr.']=>['.$row['name'].']';
 +
    }
 +
    $out .= "\n</ul>";
 +
    $obj->Update($arUpd);
 +
}
 +
$out .= "\n</ul>";
 
return $out;
 
return $out;
 
     }
 
     }
 
}
 
}
class VbzAdminItems extends clsItems {
+
class VbzAdminItem extends clsItem {
     public function __construct($iDB) {
+
    private $idEvent;
parent::__construct($iDB);
+
 
  $this->ClassSng('VbzAdminItem');
+
    /*----
 +
      HISTORY:
 +
2010-10-11 Added iarArgs parameter
 +
    */
 +
     public function AdminLink($iText=NULL,$iPopup=NULL,array $iarArgs=NULL) {
 +
return clsAdminData::_AdminLink($this,$iText,$iPopup,$iarArgs);
 +
    }
 +
    public function AdminLink_name() {
 +
return $this->AdminLink($this->DescLong()); // can make this more elaborate later
 +
    }
 +
    /*----
 +
      PURPOSE: Like AdminLink_name(). but okay to take up more room to provide more info
 +
      HISTORY:
 +
2010-11-24 created
 +
    */
 +
    public function AdminLink_friendly() {
 +
$strItem = $this->AdminLink_CatNum();
 +
$strFull = $strItem.' '.$this->DescLong_ht();
 +
return $strFull;
 +
    }
 +
    /*----
 +
      HISTORY:
 +
2010-11-27 created
 +
    */
 +
    public function AdminLink_CatNum() {
 +
return $this->AdminLink($this->CatNum,$this->DescLong());
 +
    }
 +
    /*----
 +
      HISTORY:
 +
2010-11-06 replaced old event logging with boilerplate calls to helper class
 +
    */
 +
    protected function Log() {
 +
if (!is_object($this->logger)) {
 +
    $this->logger = new clsLogger_DataSet($this,$this->objDB->Events());
 +
}
 +
return $this->logger;
 +
    }
 +
    public function EventListing() {
 +
return $this->Log()->EventListing();
 +
    }
 +
    public function StartEvent(array $iArgs) {
 +
return $this->Log()->StartEvent($iArgs);
 +
    }
 +
    public function FinishEvent(array $iArgs=NULL) {
 +
return $this->Log()->FinishEvent($iArgs);
 +
    }
 +
    /*----
 +
      ACTION:
 +
Return the current supplier catalog number
 +
If a value is given, update it to the new value first (returns old value)
 +
If an event array is given, log the event
 +
    */
 +
    public function SCatNum($iVal=NULL,array $iEvent=NULL) {
 +
$strOld = $this->Supp_CatNum;
 +
if (!is_null($iVal)) {
 +
    if (is_array($iEvent)) {
 +
$iEvent['params'] = nz($iEvent['params']).':old=['.$strOld.']';
 +
$iEvent['code'] = 'SCN';
 +
$this->StartEvent($iEvent);
 +
    }
 +
    $arUpd = array('Supp_CatNum'=>SQLValue($iVal));
 +
    $this->Update($arUpd);
 +
    if (is_array($iEvent)) {
 +
$this->FinishEvent();
 +
    }
 +
}
 +
return $strOld;
 
     }
 
     }
     public function Listing_forTitle($iTitleObj) {
+
     public function AdminList() {
global $wgOut;
+
global $vgPage,$vgOut;
 
global $sql;
 
global $sql;
  
$objTitle = $iTitleObj;
 
$idTitle = $objTitle->ID;
 
 
$cntRow = 0;
 
$cntRow = 0;
  
$objRecs = $this->GetData('(NOT isDumped) AND (ID_Title='.$idTitle.')','VbzAdminItem','ItOpt_Sort');
+
if ($this->HasRows()) {
if ($objRecs->HasRows()) {
+
    $out = $vgOut->TableOpen('class=sortable');
    $out = "{| class=sortable\n|-\n! ID || Cat # || Description || $ buy || $ sell.";
+
    $out .= $vgOut->TblRowOpen(NULL,TRUE);
 +
      $out .= $vgOut->TblCell('ID');
 +
      $out .= $vgOut->TblCell('Cat #');
 +
      $out .= $vgOut->TblCell('Status');
 +
      $out .= $vgOut->TblCell('Description');
 +
      $out .= $vgOut->TblCell('$ buy');
 +
      $out .= $vgOut->TblCell('$ sell');
 +
    $out .= $vgOut->TblRowShut();
 
    $isOdd = TRUE;
 
    $isOdd = TRUE;
    while ($objRecs->NextRow()) {
+
    while ($this->NextRow()) {
//     $wtPageCode = '[[vbznet:cat/'.$strPagePath.'|'.$strPageCode.']]';
+
$id = $this->ID;
$id = $objRecs->ID;
+
//$wtID = SelfLink_Page('item','id',$id,$id);
$wtID = SelfLink('item','id',$id,$id);
+
$wtID = $this->AdminLink();
 
$wtStyle = $isOdd?'background:#ffffff;':'background:#cccccc;';
 
$wtStyle = $isOdd?'background:#ffffff;':'background:#cccccc;';
$isActive = $objRecs->isForSale;
+
$isActive = $this->isForSale;
$isInPrint = $objRecs->isInPrint;
+
$isCurrent = $this->isCurrent;
$isPulled = $objRecs->isPulled;
+
$isInPrint = $this->isInPrint;
 +
$isPulled = $this->isPulled;
 
if ($isActive) {
 
if ($isActive) {
 
    $cntRow++;
 
    $cntRow++;
Line 1,055: Line 2,850:
 
    $wtStyle .= ' text-decoration: line-through;';
 
    $wtStyle .= ' text-decoration: line-through;';
 
}
 
}
$out .= "\n|- style=\"$wtStyle\"".
+
$strStatus = '';
    "\n| ".$wtID.
+
if ($isActive) { $strStatus .= '<span title="A=active" style="color:green;">A</span>'; }
    ' || '.$objRecs->CatNum.
+
if ($isCurrent) { $strStatus .= '<span title="C=current" style="color: #006600;">C</span>'; }
    ' || '.$objRecs->ItOpt_Descr.
+
if ($isInPrint) { $strStatus .= '<span title="P=in print" style="color: blue;">P</span>'; }
    ' || '.DataCurr($objRecs->PriceBuy).
+
if ($isPulled) { $strStatus .= '<span title="U=pulled" style="color: red;">U</span>'; }
    ' || '.DataCurr($objRecs->PriceSell);
+
$out .= $vgOut->TblRowOpen('style="'.$wtStyle.'"');
if (!is_null($objRecs->Descr)) {
+
  $out .= $vgOut->TblCell($wtID);
    $out .= "\n|- style=\"$wtStyle\"\n| colspan=4 | ".$objRecs->Descr;
+
  $out .= $vgOut->TblCell($this->CatNum);
 +
  $out .= $vgOut->TblCell($strStatus,'align=center');
 +
  $out .= $vgOut->TblCell($this->ItOpt_Descr);
 +
  $out .= $vgOut->TblCell(DataCurr($this->PriceBuy));
 +
  $out .= $vgOut->TblCell(DataCurr($this->PriceSell));
 +
$out .= $vgOut->TblRowShut();
 +
if (!is_null($this->Descr)) {
 +
    $out .= $vgOut->TblRowOpen('style="'.$wtStyle.'"');
 +
      $out .= $vgOut->TblCell($this->Descr,'colspan=4');
 +
    $out .= $vgOut->TblRowShut();
 
}
 
}
  
 
$isOdd = !$isOdd;
 
$isOdd = !$isOdd;
 
//$objLine = $objRecs->CloneFields();
 
//$objLine = $objRecs->CloneFields();
$objLine = clone $objRecs;
+
$objLine = clone $this;
 
    }
 
    }
    $out .= "\n|}\n";
+
    $out .= $vgOut->TableShut();
/*
+
} else {
    $inf = get_included_files();
+
    $out = 'No items listed. (SQL='.$sql.')';
    foreach ($inf as $fn) {
+
}
echo $fn."<br>";
+
return $out;
 +
    }
 +
    public function Title() {
 +
return $this->objDB->Titles()->GetItem($this->ID_Title);
 +
    }
 +
    public function ItTyp() {
 +
return $this->objDB->ItTyps()->GetItem($this->ID_ItTyp);
 +
    }
 +
    public function FullDescr($iSep=' ') {
 +
$objTitle = $this->Title();
 +
return $objTitle->Name.$iSep.$this->ItOpt_Descr;
 +
    }
 +
    public function FullDescr_HTML($iSep=' ') {
 +
$objTitle = $this->Title();
 +
$objItTyp = $this->ItTyp();
 +
if ($objItTyp->IsNew()) {
 +
    $out = '(no item type)';
 +
} else {
 +
    $out =
 +
    //   $objTitle->SelfLink($objTitle->Name).$iSep.
 +
      $objTitle->AdminLink($objTitle->Name).$iSep.
 +
      $objItTyp->Row['NameSng'].$iSep.
 +
      $this->ItOpt_Descr;
 +
}
 +
return $out;
 +
    }
 +
/* 2010-11-11 This should be completely obsolete, right?
 +
    protected function ReceiveForm() {
 +
global $wgOut,$wgRequest;
 +
 
 +
if ($wgRequest->getCheck('btnSave')) {
 +
    $intQtyNew = $wgRequest->GetInt('StkMin');
 +
    $arUpd['QtyMin_Stk'] = $intQtyNew;
 +
    $intQtyOld = $this->QtyMin_Stk;
 +
    if ($intQtyOld == $intQtyNew) {
 +
$out = 'No change requested; min qty is already '.$intQtyOld.'.';
 +
    } else {
 +
$strDescr = 'Updating per-item stock minimum from '.$intQtyOld.' to '.$intQtyNew;
 +
$out = $strDescr;
 +
$this->StartEvent(__METHOD__,'UPD',$strDescr);
 +
$this->Update($arUpd);
 +
$this->Reload();
 +
$this->FinishEvent();
 
    }
 
    }
 +
    $wgOut->AddWikiText($out);
 +
}
 +
    }
 
*/
 
*/
    if ($cntRow == 1) {
+
    /*----
$out .= $objLine->InfoPage(TRUE);
+
      HISTORY:
 +
2011-02-24 Finally renamed from InfoPage() to AdminPage()
 +
    */
 +
    public function AdminPage() {
 +
global $wgOut,$wgRequest;
 +
global $vgPage;
 +
 
 +
$strCatNum = $this->CatNum;
 +
 
 +
//$this->ReceiveForm();
 +
 
 +
$vgPage->UseHTML();
 +
$objTitle = $this->Title();
 +
$strTitleName = $objTitle->Name;
 +
$ftTitleLink = (is_object($objTitle))?($objTitle->AdminLink($strTitleName)):'title N/A';
 +
$strTitle = 'Item: '.$strCatNum.' ('.$this->ID.') - '.$this->FullDescr();
 +
 
 +
$objPage = new clsWikiFormatter($vgPage);
 +
$objSection = new clsWikiSection($objPage,$strTitle);
 +
$objSection->ToggleAdd('edit');
 +
//$objSection->ActionAdd('view');
 +
$out = $objSection->Generate();
 +
 
 +
$strAction = $vgPage->Arg('do');
 +
$doAdd = ($strAction == 'add');
 +
$doEdit = $vgPage->Arg('edit');
 +
$doSave = $wgRequest->GetBool('btnSave');
 +
 
 +
if ($doEdit || $doSave) {
 +
    $this->BuildEditForm();
 +
    if ($doSave) {
 +
$this->AdminSave();
 
    }
 
    }
 +
}
  
 +
$ftPriceSell = $this->PriceSell; // this can be edited if item is not in print
 +
if ($doEdit) {
 +
    $out .= $objSection->FormOpen();
 +
    $objForm = $this->objForm;
  
 +
    $ftCatNum = $objForm->Render('CatNum');
 +
    $ftCatSfx = $objForm->Render('CatSfx');
 +
    $ftDescr = $objForm->Render('Descr');
 +
    if (!$this->isInPrint) {
 +
$ftPriceSell = $objForm->Render('PriceSell');
 +
    }
 +
    $ftPriceList = $objForm->Render('PriceList');
 +
    $ftSCatNum = $objForm->Render('Supp_CatNum');
 +
    $ftStkMin = $objForm->Render('QtyMin_Stk');
 
} else {
 
} else {
    $out = 'This title has no items. (SQL='.$sql.')';
+
    $ftCatNum = $this->CatNum;
 +
    $ftCatSfx = $this->CatSfx;
 +
    $ftDescr = $this->Descr;
 +
    $ftPriceList = $this->PriceList;
 +
    $ftSCatNum = $this->Supp_CatNum;
 +
    $ftStkMin = $this->QtyMin_Stk;
 
}
 
}
$wgOut->addWikiText($out,TRUE); $out = '';
+
// non-editable fields:
 +
$ftTitle = $ftTitleLink;
 +
$ftPriceBuy = $this->PriceBuy;
 +
$ftItOpt = $this->ID_ItOpt;
 +
$ftIODescr = $this->ItOpt_Descr;
 +
$ftIOSort = $this->ItOpt_Sort;
 +
$ftGrpCode = $this->GrpCode;
 +
$ftGrpDescr = $this->GrpDescr;
 +
$ftGrpSort = $this->GrpSort;
 +
 
 +
$out .= '<ul>';
 +
$out .= '<li> <b>ID</b>: '.$this->ID;
 +
$out .= '<li> <b>Cat #</b>: '.$ftCatNum.' <b>suffix</b>: '.$ftCatSfx;
 +
$out .= '<li> <b>Description</b>: '.$ftDescr;
 +
$out .= '<li> <b>Prices</b>: '.$ftItOpt;
 +
$out .= '<ul>';
 +
  $out .= '<li> <b>Buy</b>: '.$ftPriceBuy;
 +
  $out .= '<li> <b>Sell</b>: '.$ftPriceSell;
 +
  $out .= '<li> <i><b>List</b>: '.$ftPriceList.'</i>';
 +
$out .= '</ul>';
 +
$out .= '<li> <b>Item Option</b>: '.$ftItOpt;
 +
$out .= '<ul>';
 +
  $out .= '<li> <b>Descr</b>: '.$ftIODescr;
 +
  $out .= '<li> <b>Sort</b>: '.$ftIOSort;
 +
$out .= '</ul>';
 +
$out .= '<li> <b>Group</b> - <b>code</b>: '.$ftGrpCode.' <b>descr</b>: '.$ftGrpDescr.' <b>sort</b>: '.$ftGrpSort;
 +
$out .= '<li> <b>Title</b>: '.$ftTitle;
 +
$out .= '<li> <b>Stk Min</b>: '.$ftStkMin;
 +
$out .= '<li> <b>Status</b>:';
 +
if ($this->isMaster) { $out .= ' MASTER'; }
 +
if ($this->isForSale) { $out .= ' FOR-SALE'; }
 +
if ($this->isInPrint) { $out .= ' IN-PRINT'; }
 +
if ($this->isCloseOut) { $out .= ' CLOSEOUT'; }
 +
if ($this->isPulled) { $out .= ' PULLED'; }
 +
if ($this->isDumped) { $out .= ' DUMPED'; }
 +
$out .= '<li> <b>Supplier Cat #</b>:'.$ftSCatNum;
 +
$out .= '</ul>';
 +
 
 +
if ($doEdit) {
 +
    $out .= '<input type=submit name="btnSave" value="Save">';
 +
    $out .= '<input type=reset value="Reset">';
 +
    $out .= '</form>';
 +
}
 +
$wgOut->AddHTML($out);
 +
$wgOut->AddHTML("<h3>Stock</h3>");
 +
$wgOut->AddWikiText($this->StockListing(),TRUE);
 +
$wgOut->AddHTML("<h3>Orders</h3>");
 +
$wgOut->AddWikiText($this->OrderListing(),TRUE);
 +
$wgOut->AddHTML("<h3>Restocks</h3>");
 +
$wgOut->AddWikiText($this->RestockListing(),TRUE);
 +
$wgOut->AddHTML('<h3>Events</h3>');
 +
$wgOut->AddWikiText($this->EventListing(),TRUE);
 
     }
 
     }
}
+
    /*----
class VbzAdminItem extends clsItem {
+
      HISTORY:
     public function InfoPage($iAsSub=FALSE) {
+
2010-11-06 adapted from VbzStockBin
global $wgOut;
+
    */
 +
     private function BuildEditForm() {
 +
global $vgOut;
 +
 
 +
if (is_null($this->objForm)) {
 +
    // create fields & controls
 +
    $objForm = new clsForm_DataSet($this,$vgOut);
 +
    //$objCtrls = new clsCtrls($objForm->Fields());
 +
 
 +
    $objForm->AddField(new clsField('Descr'), new clsCtrlHTML(array('size'=>40)));
 +
    $objForm->AddField(new clsField('CatNum'), new clsCtrlHTML());
 +
    $objForm->AddField(new clsField('CatSfx'), new clsCtrlHTML(array('size'=>5)));
 +
    $objForm->AddField(new clsFieldNum('PriceSell'), new clsCtrlHTML());
 +
    $objForm->AddField(new clsFieldNum('PriceList'), new clsCtrlHTML());
 +
    $objForm->AddField(new clsField('Supp_CatNum'), new clsCtrlHTML());
 +
    $objForm->AddField(new clsFieldNum('QtyMin_Stk'), new clsCtrlHTML(array('size'=>3)));
  
$strCatNum = $this->CatNum;
+
    $this->objForm = $objForm;
if ($iAsSub) {
+
    //$this->objCtrls = $objCtrls;
    $out = "==Item: $strCatNum ({$this->ID}) - {$this->ItOpt_Descr}==\n";
 
} else {
 
    $out = '==Item=='."\n";
 
    $out .= "\n* '''ID''': ".$this->ID;
 
    $out .= "\n* '''Cat #''': $strCatNum";
 
    $out .= "\n* '''Descr''': ".$this->ItOpt_Descr;
 
 
}
 
}
$out .= "\n===Stock===\n";
+
    }
$out .= $this->StockListing();
+
    /*----
 +
      ACTION: Save user changes to the record
 +
      HISTORY:
 +
2010-11-06 copied from VbzStockBin to VbzAdminItem
 +
    */
 +
    public function AdminSave() {
 +
global $vgOut;
 +
 
 +
$out = $this->objForm->Save();
 +
$vgOut->AddText($out);
 +
    }
 +
    public function StockListing() {
 +
$out = $this->objDB->StkItems()->Listing_forItem($this);
 +
return $out;
 +
    }
 +
    public function OrderListing() {
 +
$objTbl = $this->objDB->OrdItems();
 +
$objRows = $objTbl->GetData('ID_Item='.$this->ID);
 +
$out = $objRows->AdminTable_forItem();
 
return $out;
 
return $out;
 
     }
 
     }
     public function StockListing() {
+
     public function RestockListing() {
$out = $this->objDB->StkLines()->Listing_forItem($this);
+
$objTbl = $this->objDB->RstkReqItems();
 +
$objRows = $objTbl->GetData('ID_Item='.$this->ID);
 +
$out = $objRows->AdminList('No restocks found for this item');
 
return $out;
 
return $out;
 
     }
 
     }
  public function StoreLink($iText) {
+
    /*----
/*
+
      RETURNS: wikitext which links to the catalog page for the item
RETURNS: wikitext which links to the catalog page for the item
+
      NOTE: Since the store doesn't yet have pages for each item,
NOTE: Since the store doesn't yet have pages for each item,
+
    this returns a link to the item's Title page
this returns a link to the item's Title page
+
      FUTURE: create StoreLink() function which uses RichText object
 +
    */
 +
    public function StoreLink_WT($iText) {
 +
return '[[vbznet:cat/'.$this->Title()->URL_part().'|'.$iText.']]';
 +
    }
 +
// FUNCTION DEPRECATED - remove eventually
 +
    public function AdminLink_WT($iText) {
 +
return '[[{{FULLPAGENAME}}/page'.KS_CHAR_URL_ASSIGN.'item/id'.KS_CHAR_URL_ASSIGN.$this->ID.'|'.$iText.']]';
 +
    }
 +
// FUNCTION DEPRECATED - remove eventually
 +
    public function StoreLink_HT($iText) {
 +
return '<a href="'.KWP_CAT.$this->Title()->URL_part().'" title="browse in store">'.$iText.'</a>';
 +
    }
 +
}
 +
class clsAdminItems_info_Cat extends clsItems_info_Cat {
 +
    public function __construct($iDB) {
 +
parent::__construct($iDB);
 +
  $this->ActionKey('item');
 +
    }
 +
}
 +
/*******
 +
  IMAGES
 
*/
 
*/
    return '[[vbznet:cat/'.$this->Title()->URL_part().'|'.$iText.']]';
+
class clsAdminImages extends clsImages {
  }
 
  public function AdminLink($iText) {
 
    return '[[{{FULLPAGENAME}}/page'.KS_CHAR_URL_ASSIGN.'item/id'.KS_CHAR_URL_ASSIGN.$this->ID.'|'.$iText.']]';
 
  }
 
}
 
 
 
class VbzAdminStkItems extends clsStkItems {
 
 
     public function __construct($iDB) {
 
     public function __construct($iDB) {
 
parent::__construct($iDB);
 
parent::__construct($iDB);
  $this->ClassSng('VbzAdminStkItem');
+
  $this->Name('cat_images');
 +
  $this->KeyName('ID');
 +
  $this->ClassSng('clsAdminImage');
 
     }
 
     }
     public function Listing_forItem($iObj) {
+
    /*-----
global $wgOut;
+
      ACTION: Processes form data, shows section header, loads image dataset, calls clsAdminImage::AdminList() to render
global $sql;
+
      INPUT:
 +
iarArgs: array of options
 +
  ['filt'] = SQL filter for dataset to show ("WHERE" clause)
 +
  ['sort'] = sorting order for dataset to show ("ORDER BY" clause)
 +
  ['event.obj'] = object used for event logging
 +
  ['title.id'] = ID_Title to use for new records
 +
  ['new']: if TRUE, allow user to create new records when editing
 +
    */
 +
     public function AdminPage(array $iarArgs) {
 +
global $wgRequest;
 +
global $vgPage,$vgOut;
 +
 
 +
$out = '';
 +
 
 +
// get URL input
 +
$doEdit = ($vgPage->Arg('edit.img'));
 +
$doAdd = ($vgPage->Arg('add.img'));
 +
$arArgs = $iarArgs;
 +
$arArgs['edit'] = $doEdit;
 +
$sqlFilt = $arArgs['filt'];
 +
$sqlSort = $arArgs['sort'];
 +
 
 +
// display section header
 +
// $strName = 'Images';
 +
 
 +
$vgPage->UseHTML();
 +
$objPage = new clsWikiFormatter($vgPage);
 +
$objSection = new clsWikiSection($objPage,'Images',NULL,3);
 +
$objSection->ToggleAdd('edit','edit image records','edit.img');
 +
$objSection->ToggleAdd('add','add multiple image records','add.img');
 +
$out .= $objSection->Generate();
 +
 
 +
    // handle possible form requests
 +
 
 +
// -- bulk-entry form stage 1: check input
 +
if ($wgRequest->getBool('btnCheckImgs')) {
 +
    $doCheck = TRUE;
 +
    $xts = new xtString($wgRequest->GetText('txtImgs'));
 +
    $arLines = $xts->ParseTextLines(array('line'=>'arr'));
 +
    $htForm = "\nImages submitted:\n<ul>";
 +
    foreach ($arLines as $idx => $arLine) {
 +
$txtURL = $arLine[0];
 +
$txtSize = isset($arLine[1])?$arLine[1]:NULL;
 +
 
 +
$rsFldr = $this->Engine()->Folders()->FindBest($txtURL);
 +
if (is_null($rsFldr)) {
 +
    $htForm .= "\n<li>No folder found for <b>$txtUrl</b></li>";
 +
} else {
 +
    $fsFldr = $rsFldr->Value('PathPart');
 +
    $fsImg = $rsFldr->Remainder($txtURL);
 +
    $idFldr = $rsFldr->KeyValue();
 +
 
 +
    $ftSize = empty($txtSize)?'':'<b>'.$txtSize.'</b> ';
 +
    $htForm .= "\n<li>$ftSize$fsFldr<a href=\"$fsFldr$fsImg\">$fsImg</a></li>";
 +
    $htForm .= '<input type=hidden name="img-fldr['.$idx.']" value='.$idFldr.'>';
 +
    $htForm .= '<input type=hidden name="img-spec['.$idx.']" value="'.$fsImg.'">';
 +
    if (!is_null($txtSize)) {
 +
$htForm .= '<input type=hidden name="img-size['.$idx.']" value="'.$txtSize.'">';
 +
    }
 +
}
 +
    }
 +
    $htForm .= '</ul>';
 +
} else { $doCheck = FALSE; }
 +
// -- bulk-entry form stage 2: create records
 +
if ($wgRequest->getBool('btnAddImgs')) {
 +
    $arFldrs = $wgRequest->GetArray('img-fldr');
 +
    $arSpecs = $wgRequest->GetArray('img-spec');
 +
    $arSizes = $wgRequest->GetArray('img-size');
 +
    $idTitle = $vgPage->Arg('id');
 +
    assert('!empty($idTitle);');
 +
 
 +
    // log event to the title
 +
    $objTitle = $this->Engine()->Titles($idTitle);
 +
    $cntImgs = count($arFldrs);
 +
    $arEv = array(
 +
      'descr' => 'Adding '.$cntImgs.' image'.Pluralize($cntImgs),
 +
      'where' => __METHOD__,
 +
      'code' => 'IMG++'
 +
      );
 +
    $objTitle->StartEvent($arEv);
 +
 
 +
    foreach ($arFldrs as $idx => $idFldr) {
 +
$fs = $arSpecs[$idx];
 +
$sz = $arSizes[$idx];
 +
$arIns = array(
 +
  'ID_Folder' => $idFldr,
 +
  'isActive' => 'TRUE',
 +
  'Spec' => SQLValue($fs),
 +
  'ID_Title' => $idTitle,
 +
  'WhenAdded' => 'NOW()'
 +
  );
 +
if (!empty($sz)) {
 +
  $arIns['Ab_Size'] = SQLValue($sz);
 +
}
 +
$this->Insert($arIns);
 +
$strNew = ' '.$this->LastID();
 +
    }
 +
    $arEv = array(
 +
      'descrfin' => 'New ID'.Pluralize($cntImgs).':'.$strNew
 +
      );
 +
    $objTitle->FinishEvent($arEv);
 +
}
 +
// -- existing item edit form
 +
if ($wgRequest->getBool('btnSaveImgs')) {
 +
 
 +
    $arUpdate = $wgRequest->getArray('update');
 +
    $arDelete = $wgRequest->getArray('del');
 +
    $arActive = $wgRequest->getArray('isActive');
 +
    $arFolder = $wgRequest->getArray('ID_Folder');
 +
    $arFileSpec = $wgRequest->getArray('txtFileSpec');
 +
    $arAttrSize = $wgRequest->getArray('txtAttrSize');
 +
    $arAttrFldr = $wgRequest->getArray('txtAttrFldr');
 +
    $arAttrDispl = $wgRequest->getArray('txtAttrDispl');
 +
    $arAttrSort = $wgRequest->getArray('txtAttrSort');
 +
 
 +
    if (count($arActive > 0)) {
 +
// add any reactivated rows to the update list
 +
foreach ($arActive as $id => $null) {
 +
    $arUpdate[$id] = TRUE;
 +
}
 +
    }
  
$obj = $iObj;
+
    $cntRows = count($arUpdate);
$id = $obj->ID;
+
    if ($cntRows > 0) {
 +
$out .= '<b>Updating</b>: ';
 +
$txtEvDescr = 'Checking '.$cntRows.' record'.Pluralize($cntRows);
 +
$txtRowEdits = '';
 +
$txtRowFlips = '';
  
$objRecs = $this->GetData('ID_Item='.$id,NULL,'WhenRemoved,WhenAdded,WhenChanged');
+
$doLog = isset($arArgs['event.obj']);
if ($objRecs->HasRows()) {
+
if ($doLog) {
    $out = "{| class=sortable\n|-\n! ID || Bin || Qty || Added || Changed || Counted || Removed";
+
    $objLog = $arArgs['event.obj'];
    $isOdd = TRUE;
+
    $arEv = array(
    while ($objRecs->NextRow()) {
+
      'descr' => $txtEvDescr,
$id = $objRecs->ID;
+
      'where' => __METHOD__,
 +
      'code' => 'IMG SVM' // image save multiple
 +
      );
 +
    $objLog->StartEvent($arEv);
 +
}
  
$objBin = $objRecs->Bin();
+
$cntUpd = 0;
$htBin = $objBin->SelfLink($objBin->Code);
+
foreach ($arUpdate as $id => $null) {
 +
    $isActive = isset($arActive[$id]);
 +
    $isNew = ($id == 'new');
 +
    if (empty($arFileSpec[$id])) {
 +
$isNew = FALSE; // nothing to save
 +
    }
 +
    $objImg = $this->GetItem($id);
  
$wtID = SelfLink('stk-line','id',$id,$id);
+
    if ($isNew) {
$wtStyle = $isOdd?'background:#ffffff;':'background:#cccccc;';
+
$isDiff = TRUE;
$isActive = is_null($objRecs->WhenRemoved) && ($objRecs->Qty > 0);
+
$doSaveActive = TRUE;
if (!$isActive) {
+
$doSaveValues = TRUE;
    $wtStyle .= ' color: #888888;';
+
    } else {
    $wtStyle .= ' text-decoration: line-through;';
+
$isDiff = ((int)$isActive != (int)$objImg->isActive);
 +
$isStateChg = $isDiff;
 +
$doSaveActive = $isDiff;
 +
$doSaveValues = !$isDiff;
 +
    }
 +
    if (!$isDiff) {
 +
$arUpd = array(
 +
  'ID_Folder' => $arFolder[$id],
 +
  'Spec' => $arFileSpec[$id],
 +
  'Ab_Size' => $arAttrSize[$id],
 +
  'AttrFldr' => nz($arAttrFldr[$id]),
 +
  'AttrDispl' => nz($arAttrDispl[$id]),
 +
  'AttrSort' => nz($arAttrSort[$id])
 +
  );
 +
$isDiff = !$objImg->SameAs($arUpd);
 +
    }
 +
    $arUpd = NULL;
 +
    if ($isDiff) {
 +
if ($doSaveValues) {
 +
    $arUpd = array(
 +
      'ID_Folder' => SQLValue($arFolder[$id]),
 +
      'Spec' => SQLValue($arFileSpec[$id]),
 +
      'Ab_Size' => SQLValue($arAttrSize[$id]),
 +
      'AttrFldr' => SQLValue(nz($arAttrFldr[$id])),
 +
      'AttrDispl' => SQLValue(nz($arAttrDispl[$id])),
 +
      'AttrSort' => SQLValue(nz($arAttrSort[$id]))
 +
      );
 +
    $txtRowEdits .= ' #'.$id;
 +
}
 +
if ($doSaveActive) {
 +
    $arUpd['isActive'] = SQLValue($isActive);
 +
    $txtRowFlips .= ' #'.$id.'('.NoYes($isActive,'off','ON').')';
 +
}
 +
if ($isNew) {
 +
    // create new record
 +
    $idTitle = (int)$arArgs['title.id'];
 +
    assert('is_int($idTitle)');
 +
    $arUpd['ID_Title'] = $idTitle;
 +
    $this->Insert($arUpd);
 +
} else {
 +
    // not new: just update
 +
    $objImg->Update($arUpd);
 +
//global $sql;
 +
//$out .= '<br>SQL: '.$objImg->sqlExec;
 +
}
 +
$cntUpd++;
 +
    }
 
}
 
}
$out .= "\n|- style=\"$wtStyle\"".
+
if ($doLog) {
    "\n| ".$wtID.
+
    $txtStat = $cntUpd.' image'.Pluralize($cntUpd).' updated -';
    ' || '.$htBin.
+
    if (!empty($txtRowFlips)) {
    ' || '.$objRecs->Qty.
+
$txtStat .= ' toggled:'.$txtRowEdits;
    ' || '.DataDate($objRecs->WhenAdded).
+
    }
    ' || '.DataDate($objRecs->WhenChanged).
+
    if (!empty($txtRowEdits)) {
    ' || '.DataDate($objRecs->WhenCounted).
+
$txtStat .= ' edits:'.$txtRowEdits;
    ' || '.DataDate($objRecs->WhenRemoved);
+
    }
if (!is_null($objRecs->Descr)) {
+
    $arEv = array(
    $out .= "\n|- style=\"$wtStyle\"\n| colspan=4 | ".$objRecs->Descr;
+
      'descrfin' => SQLValue($txtStat)
 +
      );
 +
    $objLog->FinishEvent($arEv);
 
}
 
}
 +
$out .= $txtStat;
 +
    } else {
 +
$out .= 'No image records selected for update.';
 +
    }
 +
}
 +
 +
// render edit form outer shell:
 +
if ($doEdit || $doAdd || $doCheck) {
 +
    $arLink = $vgPage->Args(array('page','id'));
 +
    $urlSelf = $vgPage->SelfURL($arLink,TRUE);
 +
    $arArgs['pfx'] = '<form method=post action="'.$urlSelf.'">';
  
 +
    if ($doEdit) {
 +
$sfx = '<input type=submit name=btnSaveImgs value="Save">';
 +
$sfx .= '<input type=reset value="Revert">';
 +
    }
 +
    if ($doAdd) {
 +
$sfx = 'Enter images, one complete URL per line:';
 +
$sfx .= '<textarea name=txtImgs rows=6></textarea>';
 +
$sfx .= '<input type=submit name=btnCheckImgs value="Check">';
 +
    }
 +
    if ($doCheck) {
 +
$sfx = $htForm; // calculated earlier
 +
$sfx .= '<input type=submit name=btnAddImgs value="Add These">';
 +
    }
 +
    $sfx .= '</form>';
 +
    $arArgs['sfx'] = $sfx;
 +
}
 +
 +
// load the latest data and show it in a table:
 +
$arArgs['none'] = 'No images found.';
 +
$objRows = $this->GetData($sqlFilt,NULL,$sqlSort);
 +
$out .= $objRows->AdminList($arArgs);
 +
 +
return $out;
 +
    }
 +
    /*----
 +
      HISTORY:
 +
2010-10-19 Adapted from AdminPage()
 +
2010-11-16 Commented out editing functions, per earlier thought, after partly updating them.
 +
  Note: they were written for AdminPage().
 +
    */
 +
    public function AdminPage_Unassigned() {
 +
global $wgRequest,$wgOut;
 +
global $vgPage,$vgOut;
 +
 +
$out = '';
 +
 +
// get URL input
 +
$doEdit = ($vgPage->Arg('edit.img'));
 +
$arArgs['edit'] = $doEdit;
 +
 +
// display section header
 +
// $strName = 'Images';
 +
 +
$vgPage->UseHTML();
 +
$objPage = new clsWikiFormatter($vgPage);
 +
$objSection = new clsWikiSection($objPage,'Unassigned Images',NULL,3);
 +
$objSection->ToggleAdd('edit','edit image records','edit.img');
 +
$out .= $objSection->Generate();
 +
 +
// load the latest data and show it in a table:
 +
$arArgs['none'] = 'No unassigned images found.';
 +
$sqlFilt = 'ID_Title IS NULL';
 +
$sqlSort = NULL; // maybe this could be useful later
 +
$objRows = $this->GetData($sqlFilt,NULL,$sqlSort);
 +
$out .= $objRows->AdminList($arArgs);
 +
 +
$objSection = new clsWikiSection($objPage,'Imageless Active Titles',NULL,3);
 +
$out .= $objSection->Generate();
 +
$objRows = $this->objDB->Titles()->Data_Imageless();
 +
$out .= $objRows->AdminList($arArgs);
 +
 +
$wgOut->AddHTML($out); $out = NULL;
 +
return $out;
 +
    }
 +
}
 +
class clsAdminImage extends clsImage {
 +
    /*-----
 +
      ACTION: Renders dataset as a table
 +
      INPUT: iarArgs
 +
none: text to insert as description if no records
 +
pfx: html to include before table rows, if there is data
 +
sfx: html to include after table rows, if there is data
 +
edit: render editable fields
 +
new: allow entering new records -- show edit even if no data
 +
    */
 +
    public function AdminList(array $iarArgs) {
 +
$out = '';
 +
$doNew = nz($iarArgs['new']);
 +
if ($doNew || $this->HasRows()) {
 +
    $doEdit = nz($iarArgs['edit']);
 +
    $out .= nz($iarArgs['pfx']);
 +
    $out .= "\n<table>";
 +
    $out .= '<tr><td colspan=4></td><th colspan=4 bgcolor="#cceeff">attributes</th></tr>';
 +
    $out .= '<tr>'
 +
      .'<th>ID</th>'
 +
      .'<th>A?</th>'
 +
      .'<th>folder</th>'
 +
      .'<th>filename</th>'
 +
      .'<th>size</th>'
 +
      .'<th bgcolor="#cceeff">folder</th>'
 +
      .'<th bgcolor="#cceeff">description</th>'
 +
      .'<th bgcolor="#cceeff">sorting</th>'
 +
      .'</tr>';
 +
    $isOdd = FALSE;
 +
    while ($this->NextRow()) {
 +
$out .= $this->AdminListRow($doEdit,$isOdd);
 
$isOdd = !$isOdd;
 
$isOdd = !$isOdd;
 
    }
 
    }
    $out .= "\n|}";
+
    if ($doEdit) {
 +
// when editing, we also allow for adding a new record
 +
$out .= $this->AdminListRow($doEdit,$isOdd,TRUE);
 +
    }
 +
    $out .= "\n</table>";
 +
    $out .= nz($iarArgs['sfx']);
 
} else {
 
} else {
    $out = 'This title has no items. (SQL='.$sql.')';
+
    if (isset($iarArgs['none'])) {
 +
$out .= $iarArgs['none'];
 +
    } else {
 +
$out .= 'No images found.';
 +
    }
 
}
 
}
 
return $out;
 
return $out;
 
     }
 
     }
}
+
    protected function AdminListRow($iEdit,$iOdd,$iNew=FALSE) {
class VbzAdminStkItem extends clsDataSet {
+
$isOdd = $iOdd;
    public function Bin() {
+
$doEdit = $iEdit;
$objBins = $this->objDB->Bins();
+
 
return $objBins->GetItem($this->ID_Bin);
+
if ($iNew) {
 +
    $doEdit = TRUE;
 +
    $isActive = TRUE;
 +
    $id = 'new';
 +
    $txtFileSpec = '';
 +
    $txtFolder = '';
 +
    $txtAttrSize = '';
 +
    $txtAttrFldr = '';
 +
    $txtAttrDispl = '';
 +
    $txtAttrSort = '';
 +
} else {
 +
    $id = $this->ID;
 +
    $wtID = $id;
 +
    $isActive = $this->isActive;
 +
    $txtFileSpec = $this->Spec;
 +
    $txtFolder = $this->FolderPath();
 +
    $txtAttrSize = $this->Ab_Size;
 +
    $txtAttrFldr = $this->AttrFldr;
 +
    $txtAttrDispl = $this->AttrDispl;
 +
    $txtAttrSort = $this->AttrSort;
 +
}
 +
 
 +
$wtStyle = $isOdd?'background:#ffffff;':'background:#eeeeee;';
 +
if ($isActive) {
 +
    $wtStyleCell = '';
 +
    $ftActive = '&radic;';
 +
} else {
 +
    $wtStyle .= ' color: #888888;';
 +
    $wtStyleCell = ' style="text-decoration: line-through;"';
 +
    $ftActive = '';
 +
}
 +
if ($doEdit) {
 +
    // replace field values with editable versions
 +
    if ($isActive) {
 +
$wtID = '<input type=hidden name=update['.$id.'] value=1>'.$id;
 +
    } else {
 +
$wtID = '<input type=checkbox name=del['.$id.'] title="check rows to delete">'.$id;
 +
    }
 +
    $htEnabled = $isActive?'':' disabled';
 +
    $ftActive = '<input type=checkbox name=isActive['.$id.'] title="check if this image should be used"'.($isActive?' checked':'').'>';
 +
    $htFolder = $this->objDB->Folders()->DropDown('ID_Folder['.$id.']',$this->ID_Folder);
 +
    $htFileSpec = '<input'.$htEnabled.' size=20 name=txtFileSpec['.$id.'] value="'.htmlspecialchars($txtFileSpec).'">';
 +
    $htAttrSize = '<input'.$htEnabled.' size=4 name=txtAttrSize['.$id.'] value="'.htmlspecialchars($txtAttrSize).'">';
 +
    $htAttrFldr = '<input'.$htEnabled.' size=4 name=txtAttrFldr['.$id.'] value="'.htmlspecialchars($txtAttrFldr).'">';
 +
    $htAttrDispl = '<input'.$htEnabled.' size=10 name=txtAttrDispl['.$id.'] value="'.htmlspecialchars($txtAttrDispl).'">';
 +
    $htAttrSort = '<input'.$htEnabled.' size=2 name=txtAttrSort['.$id.'] value="'.htmlspecialchars($txtAttrSort).'">';
 +
} else {
 +
    $htFolder = $txtFolder;
 +
    $htFileSpec = $txtFileSpec = '<a href="'.$this->WebSpec().'">'.$txtFileSpec.'</a>';
 +
 
 +
    $htAttrSize = $txtAttrSize;
 +
    $htAttrFldr = $txtAttrFldr;
 +
    $htAttrDispl = $txtAttrDispl;
 +
    $htAttrSort = $txtAttrSort;
 +
}
 +
 
 +
$out = "\n<tr style=\"$wtStyle\">".
 +
    "\n<td align=right$wtStyleCell>$wtID</td>".
 +
    "\n<td$wtStyleCell>$ftActive</td>".
 +
    "\n<td$wtStyleCell>$htFolder</td>".
 +
    "\n<td$wtStyleCell>$htFileSpec</td>".
 +
    "\n<td$wtStyleCell>$htAttrSize</td>".
 +
    "\n<td$wtStyleCell>$htAttrFldr</td>".
 +
    "\n<td$wtStyleCell>$htAttrDispl</td>".
 +
    "\n<td$wtStyleCell>$htAttrSort</td>".
 +
    "\n</tr>";
 +
 
 +
return $out;
 
     }
 
     }
 
}
 
}
  
 +
/******
 +
SHIPPING
 +
*/
 
class clsShipments extends clsVbzTable {
 
class clsShipments extends clsVbzTable {
 
     public function __construct($iDB) {
 
     public function __construct($iDB) {
Line 1,184: Line 3,547:
 
  $this->KeyName('ID');
 
  $this->KeyName('ID');
 
  $this->ClassSng('clsShipment');
 
  $this->ClassSng('clsShipment');
 +
  $this->ActionKey('shpmt');
 
     }
 
     }
 
     protected function _newItem() {
 
     protected function _newItem() {
 
       return new clsCatPage($this);
 
       return new clsCatPage($this);
 
     }
 
     }
     public function ListPage() {
+
     public function GetActive($iSort=NULL) {
 +
$objRows = $this->GetData('WhenClosed IS NULL',NULL,$iSort);
 +
return $objRows;
 +
    }
 +
    public function AdminPage() {
 
global $wgOut;
 
global $wgOut;
 +
global $vgPage;
  
 
$out = '==Shipments==';
 
$out = '==Shipments==';
 
$wgOut->addWikiText($out,TRUE); $out = '';
 
$wgOut->addWikiText($out,TRUE); $out = '';
 +
 +
$vgPage->UseWiki();
 +
 
$objRecs = $this->GetData(NULL,NULL,'ID DESC');
 
$objRecs = $this->GetData(NULL,NULL,'ID DESC');
 
if ($objRecs->HasRows()) {
 
if ($objRecs->HasRows()) {
Line 1,199: Line 3,571:
 
    while ($objRecs->NextRow()) {
 
    while ($objRecs->NextRow()) {
 
$id = $objRecs->ID;
 
$id = $objRecs->ID;
$wtID = SelfLink('shipmt','id',$id,$id);
+
//$wtID = SelfLink_Page('shipmt','id',$id,$id);
 +
$wtID = $objRecs->AdminLink();
 
$wtStyle = $isOdd?'background:#ffffff;':'background:#cccccc;';
 
$wtStyle = $isOdd?'background:#ffffff;':'background:#cccccc;';
 
$wtCode = $objRecs->Abbr;
 
$wtCode = $objRecs->Abbr;
Line 1,227: Line 3,600:
 
     }
 
     }
 
}
 
}
class clsShipment extends clsDataSet {
+
class clsShipment extends clsVbzRecs {
     public function InfoPage() {
+
    /*----
 +
      HISTORY:
 +
2010-10-11 Added iarArgs parameter
 +
    */
 +
     public function AdminLink($iText=NULL,$iPopup=NULL,array $iarArgs=NULL) {
 +
return clsAdminData::_AdminLink($this,$iText,$iPopup,$iarArgs);
 +
    }
 +
    public function AdminLink_name() {
 +
return $this->AdminLink($this->ShortName());
 +
    }
 +
    public function ShortName() {
 +
return $this->Value('Abbr');
 +
    }
 +
    /*----
 +
      ACTION: Redirect to the url of the admin page for this object
 +
      HISTORY:
 +
2010-11-26 copied from VbzAdminCatalog to clsRstkRcd
 +
2011-01-02 copied from clsRstkRcd to VbzAdminOrderTrxact
 +
2011-09-24 copied from VbzAdminOrderTrxact to clsShipment
 +
    */
 +
    public function AdminRedirect(array $iarArgs=NULL) {
 +
return clsAdminData::_AdminRedirect($this,$iarArgs);
 +
    }
 +
    /*-----
 +
      TO DO:
 +
* Convert old-style edit/header to new, wherever that is
 +
      HISTORY:
 +
2011-03-29 renamed from InfoPage() to AdminPage()
 +
    */
 +
    public function AdminPage() {
 +
global $wgOut,$wgRequest;
 +
global $vgPage;
 +
 
 +
$vgPage->UseHTML();
 +
 
 +
// check for form data
 +
$doNew = ($vgPage->Arg('id') == 'new');
 +
$didAdd = FALSE;
 +
 
 +
// 2011-09-02 This was the old code for saving a new record. Keeping it in case tweaks are needed to the new code.
 +
/*
 +
if ($wgRequest->getBool('btnCreate')) {
 +
    $wgOut->AddWikiText('==Creating Shipment==',TRUE);
 +
    // create new record from form data
 +
    $strAbbr = $wgRequest->getText('abbr');
 +
    $strDescr = $wgRequest->getText('descr');
 +
    $strNotes = $wgRequest->getText('notes');
 +
 
 +
    $arEv = array(
 +
      'descr' => 'new shipment',
 +
      'where' => __METHOD__,
 +
      'code' => 'new'
 +
      );
 +
    $this->StartEvent($arEv);
 +
    $arIns = array(
 +
      'id' => 0,
 +
      'WhenCreated' => 'NOW()',
 +
      'Abbr' => SQLValue($strAbbr),
 +
      'Descr' => SQLValue($strDescr),
 +
      'Notes' => SQLValue($strNotes)
 +
      );
 +
    $this->Table->Insert($arIns);
 +
    $this->ID = $this->Table->LastID();
 +
    $wgOut->AddWikiText('New ID='.$this->ID,TRUE);
 +
    $this->Reload(); // load the newly-created record
 +
    $didAdd = TRUE; // a new record has just been created
 +
    $this->FinishEvent(array('id'=>$this->ID));
 +
}
 +
*/
 +
 
 +
// check for more actions:
 +
$doEdit = ($doNew || $vgPage->Arg('edit'));
 +
$doClose = $vgPage->Arg('close');
 +
$doSave = $wgRequest->getBool('btnSave');
 +
 
 +
if ($doClose) {
 +
    // add up totals
 +
    $objRecs = $this->PkgsData();
 +
    if ($objRecs->HasRows()) {
 +
$wgOut->AddWikiText('==Closing Shipment==',TRUE);
 +
$ok = TRUE;
 +
$dlrShip = 0;
 +
$dlrPack = 0;
 +
$cntPkgErr = 0;
 +
$out = '';
 +
while ($objRecs->NextRow()) {
 +
    $out .= '<br>Pkg ID '.$objRecs->AdminLink();
 +
    if (is_null($objRecs->ShipCost)) {
 +
$out .= ': no shipping cost!';
 +
$ok = FALSE;
 +
$cntPkgErr++;
 +
    } elseif (is_null($objRecs->PkgCost)) {
 +
$out .= ': no materials cost!';
 +
$ok = FALSE;
 +
$cntPkgErr++;
 +
    } else {
 +
$dlrShip += $objRecs->ShipCost;
 +
$dlrPack += $objRecs->PkgCost;
 +
    }
 +
}
 +
if ($ok) {
 +
    $strUpd = '$'.$dlrShip.' shipping, $'.$dlrPack.' materials';
 +
    $out = '<br>Cost totals: '.$strUpd;
 +
} else {
 +
    $out .= '<br>'.$cntPkgErr.Pluralize($cntPkgErr,' package has','packages have').' missing information.';
 +
}
 +
    } else {
 +
$ok = FALSE;
 +
$out = 'No packages in shipment; nothing to close.';
 +
    }
 +
    $wgOut->AddHTML($out); $out=NULL;
 +
 
 +
    if ($ok) {
 +
// log the attempt
 +
$arEv = array(
 +
  'descr' => 'closing shipment: '.$strUpd,
 +
  'where' => __METHOD__,
 +
  'code' => 'CLO'
 +
  );
 +
$this->StartEvent($arEv);
 +
 
 +
// fill in stats
 +
$arUpd = array(
 +
  'WhenClosed' => 'NOW()',
 +
  'OrderCost' => $dlrShip,
 +
  'SupplCost' => $dlrPack
 +
  );
 +
$this->Update($arUpd);
 +
global $sql;
 +
$out = '<br>Shipment updated - SQL: '.$sql;
 +
$this->Reload();
 +
 
 +
// log the completion
 +
$this->FinishEvent();
 +
$wgOut->AddWikiText($out,TRUE); $out=NULL;
 +
    }
 +
}
 +
 
 +
if ($doEdit || $doSave) {
 +
    $this->BuildEditForm();
 +
    if ($doSave) {
 +
$this->AdminSave();
 +
    }
 +
}
 +
 
 +
$htAbbr = htmlspecialchars($this->Abbr);
 +
$htDescr = htmlspecialchars($this->Descr);
 +
$htNotes = htmlspecialchars($this->Notes);
 +
// values which are always static
 +
if ($doNew) {
 +
    $strID = 'NEW';
 +
    $strTitle = 'NEW Shipment';
 +
} else {
 +
    if ($didAdd) {
 +
$strID = $this->AdminLink();
 +
    } else {
 +
$strID = $this->ID;
 +
    }
 +
    $strTitle = 'Shipment '.$htAbbr;
 +
}
 +
$out = '';
 +
if ($doEdit) {
 +
    // open editing form
 +
    $sqlID = $doNew?'new':$this->ID;
 +
    $arLink = array(
 +
      'edit' => FALSE,
 +
      'id' => $sqlID
 +
      );
 +
    $htPath = $vgPage->SelfURL($arLink);
 +
    $out .= "\n<form method=post action=\"$htPath\">";
 +
    // code for editable values
 +
/*
 +
    $strAbbr = '<input name=abbr type=text size=16 value="'.$htAbbr.'">';
 +
    $strDescr = '<input name=descr type=text size=50 value="'.$htDescr.'">';
 +
    $strNotes = '<textarea name=notes width=50 height=3>'.$htNotes.'</textarea>';
 +
*/
 +
    $objForm = $this->objForm;
 +
    $ctrlAbbr = $objForm->Render('Abbr');
 +
    $ctrlDescr = $objForm->Render('Descr');
 +
    $ctrlNotes = $objForm->Render('Notes');
 +
 
 +
    $ctrlWhenCre = $objForm->Render('WhenCreated');
 +
    $ctrlWhenShp = $objForm->Render('WhenShipped');
 +
    $ctrlCostRcpt = '$'.$objForm->Render('ReceiptCost');
 +
    $ctrlCostOuts = '$'.$objForm->Render('OutsideCost');
 +
    $ctrlCostOrdr = '$'.$objForm->Render('OrderCost');
 +
    $ctrlCostSupp = '$'.$objForm->Render('SupplCost');
 +
    $ctrlCarrier = $objForm->Render('Carrier');
 +
 
 +
    $ctrlIsDedic = $objForm->Render('isDedicated');
 +
    $ctrlIsOnHold = $objForm->Render('isOnHold');
 +
    $ctrlStatus = $ctrlIsDedic.'dedicated '.$ctrlIsOnHold.'on hold';
 +
 
 +
    $htClose = '';
 +
} else {
 +
    // Only allow closing the shipment if we're not editing.
 +
    // Clicking a link from edit mode loses any edits.
 +
    if (is_null($this->WhenClosed)) {
 +
$arLink = array(
 +
  'close' => TRUE,
 +
  );
 +
$htClose = ' ['.$vgPage->SelfLink($arLink,'close the shipment','set closing timestamp and add up totals').']';
 +
    } else {
 +
$htClose = ''; // already closed
 +
    }
 +
 
 +
    // code for static values
 +
    $ctrlAbbr = $htAbbr;
 +
    $ctrlDescr = $htDescr;
 +
    $ctrlNotes = $htNotes;
 +
 
 +
    $ctrlWhenCre = $this->WhenCreated;
 +
    $ctrlWhenShp = $this->WhenShipped;
 +
    $ctrlCostRcpt = $this->ReceiptCost;
 +
    $ctrlCostOuts = $this->OutsideCost;
 +
    $ctrlCostOrdr = $this->OrderCost;
 +
    $ctrlCostSupp = $this->SupplCost;
 +
    $ctrlCarrier = $this->Carrier;
 +
 
 +
    $isDedicated = (ord($this->isDedicated));
 +
    $isOnHold = (ord($this->isOnHold));
 +
    if ($isDedicated || $isOnHold) {
 +
$ctrlStatus = ($isDedicated?'Dedicated':'') . ($isOnHold?' OnHold':'');
 +
    } else {
 +
$ctrlStatus = '<i>normal</i>';
 +
    }
 +
}
 +
// non-editable controls
 +
$ctrlWhenClo = $this->WhenClosed.$htClose;
 +
 
 +
$out .= WikiSectionHdr_Edit($strTitle,$doEdit); // old style
 +
// $out .= "\n<h2>$strTitle</h2>";
 +
 
 +
$out .= "\n<table>";
 +
$out .= "\n<tr><td align=right valign=top><b>ID</b>:</td><td>$strID</td></tr>";
 +
$out .= "\n<tr><td align=right valign=top><b>Name</b>:</td><td>$ctrlAbbr</td></tr>";
 +
$out .= "\n<tr><td align=right valign=top><b>Description</b>:</td><td>$ctrlDescr</td></tr>";
 +
$out .= "\n<tr><td align=right valign=top><b>Type</b>:</td><td>$ctrlStatus</td></tr>";
 +
if (!$doNew) {
 +
    $out .= "\n<tr><td align=right valign=top><b>When Created</b>:</td><td>$ctrlWhenCre</td></tr>";
 +
    $out .= "\n<tr><td align=right valign=top><b>When Shipped</b>:</td><td>$ctrlWhenShp</td></tr>";
 +
    $out .= "\n<tr><td align=right valign=top><b>When Closed</b>:</td><td>$ctrlWhenClo</td></tr>";
 +
    $out .= "\n<tr><td align=right valign=top><b>Receipt Cost</b>:</td><td>$ctrlCostRcpt</td></tr>";
 +
    $out .= "\n<tr><td align=right valign=top><b>Outside Cost</b>:</td><td>$ctrlCostOuts</td></tr>";
 +
    $out .= "\n<tr><td align=right valign=top><b>Order Cost</b>:</td><td>$ctrlCostOrdr</td></tr>";
 +
    $out .= "\n<tr><td align=right valign=top><b>Supplier Cost</b>:</td><td>$ctrlCostSupp</td></tr>";
 +
}
 +
$out .= "\n<tr><td align=right valign=top><b>Carrier</b>:</td><td>$ctrlCarrier</td></tr>";
 +
$out .= "\n<tr><td align=right valign=top><b>Notes</b>:</td><td>$ctrlNotes</td></tr>";
 +
$out .= "\n</table>";
 +
if ($doEdit) {
 +
// form buttons
 +
    if ($doNew) {
 +
// next line needed only if we have special code for Create vs. Save
 +
// $out .= '<input type=submit name="btnCreate" value="Create">';
 +
// 2011-09-02 testing this instead:
 +
$out .= '<input type=submit name="btnSave" value="Create">';
 +
    } else {
 +
$out .= '<input type=submit name="btnSave" value="Save">';
 +
$out .= '<input type=reset value="Revert">';
 +
    }
 +
// close editing form
 +
    $out .= "\n</form>";
 +
}
 +
$wgOut->addHTML($out); $out = '';
 +
 
 +
if (!$doNew) {
 +
    $wgOut->addWikiText('===Packages===',TRUE); $out = '';
 +
    $out .= $this->PkgTable();
 +
    $wgOut->addWikiText($out,TRUE); $out = '';
 +
 
 +
    $wgOut->addWikiText('===Events===',TRUE);
 +
    $out = $this->EventListing();
 +
    $wgOut->addWikiText($out,TRUE); $out = '';
 +
}
 +
    }
 +
    /*----
 +
      HISTORY:
 +
2011-02-17 Updated to use objForm instead of objFlds/objCtrls
 +
    */
 +
    private function BuildEditForm() {
 +
global $vgOut;
 +
 
 +
// create fields & controls
 +
 
 +
if (is_null($this->objForm)) {
 +
    $objForm = new clsForm_DataSet($this,$vgOut);
 +
 
 +
    $objForm->AddField(new clsFieldTime('WhenCreated'), new clsCtrlHTML());
 +
    $objForm->AddField(new clsFieldTime('WhenShipped'), new clsCtrlHTML());
 +
    //$objCtrls->AddField(new clsFieldTime('WhenClosed'), new clsCtrlHTML());
 +
    $objForm->AddField(new clsFieldNum('ReceiptCost'), new clsCtrlHTML(array('size'=>5)));
 +
    $objForm->AddField(new clsFieldNum('OutsideCost'), new clsCtrlHTML(array('size'=>5)));
 +
    $objForm->AddField(new clsFieldNum('OrderCost'), new clsCtrlHTML(array('size'=>5)));
 +
    $objForm->AddField(new clsFieldNum('SupplCost'), new clsCtrlHTML(array('size'=>5)));
 +
    $objForm->AddField(new clsField('Carrier'), new clsCtrlHTML());
 +
    $objForm->AddField(new clsField('Abbr'), new clsCtrlHTML(array('size'=>16)));
 +
    $objForm->AddField(new clsField('Descr'), new clsCtrlHTML(array('size'=>50)));
 +
    $objForm->AddField(new clsField('Notes'), new clsCtrlHTML_TextArea(array('height'=>3,'width'=>50)));
 +
    $objForm->AddField(new clsFieldBool('isDedicated'), new clsCtrlHTML_CheckBox());
 +
    $objForm->AddField(new clsFieldBool('isOnHold'), new clsCtrlHTML_CheckBox());
 +
 
 +
    $this->objForm = $objForm;
 +
}
 +
    }
 +
    /*-----
 +
      ACTION: Save the user's edits to the shipment
 +
      HISTORY:
 +
2011-02-17 Retired old custom code; now using objForm helper object
 +
    */
 +
    private function AdminSave() {
 +
global $vgOut;
 +
 
 +
$out = $this->objForm->Save();
 +
$vgOut->AddText($out);
 +
/* 2011-02-17 old code
 
global $wgOut;
 
global $wgOut;
  
$out = '==Shipment=='."\n";
+
// get the form data and note any changes
$out .= "\n* '''ID''': ".$this->ID;
+
$objFlds = $this->objCtrls->Fields();
$out .= "\n* '''Code''': ".$this->Code;
+
$objFlds->RecvVals();
$out .= "\n* '''Status''': ".(ord($objRecs->isDedicated)=='1'?'Dedicated':'') . (ord($objRecs->isOnHold)=='1'?' OnHold':'');
+
// get the list of field updates
$out .= "\n===Packages===";
+
$arUpd = $objFlds->DataUpdates();
$wgOut->addWikiText($out,TRUE); $out = '';
+
// log that we are about to update
$out = $this->PkgTable();
+
$strDescr = 'Edited: '.$objFlds->DescrUpdates();
$wgOut->addWikiText($out,TRUE); $out = '';
+
$wgOut->AddWikiText('==Saving Edit==',TRUE);
 +
$wgOut->AddWikiText($strDescr,TRUE);
 +
 
 +
$arEv = array(
 +
  'descr' => $strDescr,
 +
  'where' => __METHOD__,
 +
  'code' => 'ED'
 +
  );
 +
$this->StartEvent($arEv);
 +
// update the recordset
 +
$this->Update($arUpd);
 +
global $sql;
 +
$wgOut->AddWikiText('<br>SQL='.$sql,TRUE);
 +
$this->Reload();
 +
// log completion
 +
$this->FinishEvent();
 +
*/
 +
    }
 +
    public function PkgsData() {
 +
$objTbl = $this->objDB->Pkgs();
 +
$objRows = $objTbl->GetData('(ID_Shipment='.$this->KeyValue().') AND (WhenVoided IS NULL)');
 +
return $objRows;
 
     }
 
     }
 
     public function PkgTable() {
 
     public function PkgTable() {
$objPkgs = new clsPackages($this->objDB);
+
/*
$out = $objPkgs->WikiTable_forShipmtPkgs($this->ID);
+
//$objTbl = new clsPackages($this->objDB);
 +
$objTbl = $this->objDB->Pkgs();
 +
$objRows = $objTbl->GetData('ID_Shipment='.$this->ID);
 +
*/
 +
$objRows = $this->PkgsData();
 +
$arArgs = array(
 +
  'descr' => ' for this shipment',
 +
  'omit' => '',
 +
  'ord' => $this->ID_Order
 +
  );
 +
$out = $objRows->AdminTable($arArgs);
 +
return $out;
 +
    }
 +
    /*----
 +
      HISTORY:
 +
2010-10-23 added event logging using helper class
 +
    */
 +
    protected function Log() {
 +
if (!is_object($this->logger)) {
 +
    $this->logger = new clsLogger_DataSet($this,$this->objDB->Events());
 +
}
 +
return $this->logger;
 +
    }
 +
    public function EventListing() {
 +
return $this->Log()->EventListing();
 +
    }
 +
    public function DropDown($iName,$iDefault=NULL) {
 +
if ($this->HasRows()) {
 +
    $out = '<select name="'.$iName.'">'."\n";
 +
    while ($this->NextRow()) {
 +
$id = $this->Value('ID');
 +
if ($id == $iDefault) {
 +
    $htSelect = " selected";
 +
} else {
 +
    $htSelect = '';
 +
}
 +
$htDescr = $this->Descr();
 +
$out .= "<option$htSelect value=\"$id\">$htDescr</option>\n";
 +
    }
 +
    $out .= '</select>';
 +
} else {
 +
    $out = 'No shipments matching filter';
 +
}
 +
return $out;
 +
    }
 +
    public function Descr() {
 +
$out = $this->Abbr;
 
return $out;
 
return $out;
 
     }
 
     }
 
}
 
}
class clsPackages extends clsVbzTable {
+
/******
 +
  TOPIC MANAGEMENT
 +
*/
 +
class clsAdminTopics extends clsTopics {
 +
 
 
     public function __construct($iDB) {
 
     public function __construct($iDB) {
 
parent::__construct($iDB);
 
parent::__construct($iDB);
  $this->Name('ord_pkgs');
+
  $this->ClassSng('clsAdminTopic');
  $this->KeyName('ID');
+
  $this->ActionKey('topic');
  $this->ClassSng('clsPackage');
 
 
     }
 
     }
     public function WikiTable_forShipmtPkgs($iID) {
+
     protected function AdminRedirect() {
//$objRecs = $this->GetData('ID_Shipment='.$iID,'clsPackage');
+
global $vgPage;
$objRecs = $this->objDB->DataSet('SELECT * FROM qryPkgs_status WHERE ID_Shipment='.$iID);
+
global $wgOut;
  
$isOdd = FALSE;
+
$ar = array('page'=>$this->ActionKey());
if ($objRecs->HasRows()) {
+
$url = $vgPage->SelfURL($ar,TRUE);
    $out = "{| class=sortable\n|-\n! ID || ord/seq || Status || Created || Shipped || Closed || Descr/Notes";
+
$wgOut->redirect($url);
    while ($objRecs->NextRow()) {
+
    }
$wtID = SelfLink('shipmt','id',$id,$id);
+
    public function RootNode() {
$wtStyle = $isOdd?'background:#ffffff;':'background:#cccccc;';
+
$objRoot = $this->SpawnItem();
 +
$objRoot->ID = NULL;
 +
return $objRoot;
 +
    }
 +
    /*----
 +
      PURPOSE: renders tree with colors and links suitable for admin usage
 +
      LATER: The parent method should be generalized for color and link-function
 +
    */
 +
/*
 +
    public function RenderTree($iTwig=NULL) {
 +
if (is_null($iTwig)) {
 +
    $objRoot = $this->RootNode();
 +
} else {
 +
    $objRoot = $this->GetItem($iTwig);
 +
}
 +
$out = $objRoot->DrawTree();
 +
return $out;
 +
    }
 +
*/
 +
    public function ListTitles_unassigned() {
 +
global $vgPage;
  
$keyDept = $objDepts->PageKey();
+
$sql = 'SELECT tc.*, t.Name'
$out .= "\n|- style=\"$wtStyle\"\n| ".$wtID.' || '.$wtCode.' || '.$wtStatus.' || '.$wtWhenCre.' || '.$wtWhenShp.' || '.$wtWhenCls.' || '.$wtDescr;
+
  .' FROM (_titles AS tc LEFT JOIN cat_title_x_topic AS tt ON tc.ID=tt.ID_Title)'
$isOdd = !$isOdd;
+
  .' LEFT JOIN cat_titles AS t ON tc.ID=t.ID'
 +
  .' WHERE (tt.ID_Title IS NULL) AND (tc.cntForSale > 0)';
 +
$rs = $this->Engine()->DataSet($sql,$this->Engine()->Titles()->ClassSng());
 +
if ($rs->HasRows()) {
 +
    $vgPage->UseHTML();
 +
    $rs->Table = $this->Engine()->Titles();
 +
    $out = "\n<ul>";
 +
    while ($rs->NextRow()) {
 +
$out .= "\n<li>".$rs->AdminLink($rs->Value('CatNum')).' '.$rs->Value('Name').'</li>';
 
    }
 
    }
 +
    $out .= "\n</ul>";
 +
} else {
 +
    $out = 'All active titles have topics.';
 
}
 
}
$out .= "\n|}";
 
 
return $out;
 
return $out;
 
     }
 
     }
}
+
     public function Data_forTitle($iTitle) {
class clsPackage extends clsDataSet {
+
$sql = 'SELECT bt.* FROM cat_topic AS bt LEFT JOIN cat_title_x_topic AS bx ON bx.ID_Topic=bt.ID WHERE ID_Title='.$iTitle;
}
+
$objRows = $this->Engine()->DataSet($sql,$this->ClassSng());
/* ========================== *\
+
return $objRows;
- SHOPPING CART classes
 
\* ========================== */
 
class VbzAdminCarts extends clsShopCarts {
 
     public function __construct($iDB) {
 
parent::__construct($iDB);
 
  $this->ClassSng('VbzAdminCart');
 
 
     }
 
     }
     public function ListPage() {
+
     public function AdminPage() {
 
global $wgOut;
 
global $wgOut;
 +
global $vgPage,$vgOut;
  
$out = '==Carts==';
+
$out = "\n".'<table align=right style="border: solid black 1px;"><tr><td><h3>Unassigned Titles</h3>';
$wgOut->addWikiText($out,TRUE); $out = '';
+
$out .= $this->ListTitles_unassigned();
$this->Name('qryCarts_info');
+
$out .= "\n</td></tr></table>";
$objRecs = $this->GetData(NULL,NULL,'ID DESC');
+
 
if ($objRecs->HasRows()) {
+
$arLink = array('rebuild'=>TRUE);
    $out = "'''S'''=Session | '''O'''=Order | '''C'''=Customer | '''#D'''= # of Data lines | '''#I''' = # of Items in cart";
+
$htLink = $vgPage->SelfURL($arLink,TRUE);
    $out .= "\n{| class=sortable\n|-\n! ID || Created || Ordered || S || O || C || #D || #I";
+
 
    $isOdd = TRUE;
+
$doRebuild = $vgPage->Arg('rebuild');
    while ($objRecs->NextRow()) {
+
 
$wtStyle = $isOdd?'background:#ffffff;':'background:#eeeeee;';
+
if ($doRebuild) {
$isOdd = !$isOdd;
+
    // apparently there's no way to display a message without preventing the redirect
 +
    $this->RenderTree(TRUE);
 +
    $this->AdminRedirect();
 +
} else {
 +
    $out .= "\n".'[<a href="'.$htLink.'">rebuild tree</a>]';
 +
 
 +
    $this->TreeCtrl()->FileForCSS('dtree.css');
 +
    $out .= $this->RenderTree(FALSE);
 +
}
 +
$wgOut->AddHTML($out); $out = '';
 +
return $out;
 +
    }
 +
    /*----
 +
      RETURNS: options array for entering topics
 +
      USAGE:
 +
1. fill in fHandleData_Change_Start, fHandleData_Change_Finish, fHandleData_Change_Item
 +
2. Then, where $arOpts is the array returned:
 +
  $ctrlList = new clsWidget_ShortList();
 +
  $ctrlList->Options($arOpts);
 +
  $htOut = $ctrlList->HandleInput();
 +
      HISTORY:
 +
2011-09-29 adapted from VbzAdminTitle::TopicListing()
 +
    */
 +
    public function TopicListing_base_array() {
 +
$tblTopics = $this;
 +
$tblTopics->doBranch(TRUE);
 +
$arOpts = array(
 +
  'name' => 'title',
 +
  'btnChk_Text' => 'Enter topics:',
 +
  'btnChg_Text' => '<= Add',
 +
  'txtCargo_sng' => 'topic ID',
 +
  'txtCargo_plr' => 'topic IDs',
 +
  'txtProd_sng' => 'topic',
 +
  'txtProd_plr' => 'topics',
 +
  'txtConf_list' => 'Adding',
 +
  'fHandleData_Check' => function($iVal) use ($tblTopics) {
 +
      $obj = $tblTopics->GetItem($iVal); // for now, assume topic is ID
  
$id = $objRecs->ID;
+
      $arOut['html'] = $obj->AdminLink_name();
$wtID = SelfLink('cart','id',$id,$id);
+
      $arOut['text'] = $obj->KeyValue();
$wtWhenCre = $objRecs->WhenCreated;
+
      return $arOut;
$wtWhenShp = $objRecs->WhenOrdered;
+
  },
$wtSess = SelfLink('sess','id',$objRecs->ID_Sess);
+
  );
$wtOrd = SelfLink('ord','id',$objRecs->ID_Order);
+
return $arOpts;
$wtCust = SelfLink('cust','id',$objRecs->ID_Cust);
+
    }
$out .=  
+
}
  "\n|- style=\"$wtStyle\"\n"
+
class clsAdminTopic extends clsTopic {
  ."| $wtID || $wtWhenCre || $wtWhenShp || $wtSess || $wtOrd || $wtCust"
+
    /*----
  ."|| {$objRecs->DataCount} || {$objRecs->ItemCount}";
+
      HISTORY:
 +
2010-12-05 boilerplate event logging added
 +
    */
 +
    //----
 +
    // BOILERPLATE: event logging
 +
    protected function Log() {
 +
if (!is_object($this->logger)) {
 +
    $this->logger = new clsLogger_DataSet($this,$this->objDB->Events());
 +
}
 +
return $this->logger;
 +
    }
 +
    public function StartEvent(array $iArgs) {
 +
return $this->Log()->StartEvent($iArgs);
 +
    }
 +
    public function FinishEvent(array $iArgs=NULL) {
 +
return $this->Log()->FinishEvent($iArgs);
 +
    }
 +
    public function EventListing() {
 +
return $this->Log()->EventListing();
 +
    }
 +
    // BOILERPLATE: admin HTML
 +
    public function AdminURL() {
 +
return clsAdminData::_AdminURL($this);
 +
    }
 +
    public function AdminLink($iText=NULL,$iPopup=NULL,array $iarArgs=NULL) {
 +
$strPopup = $this->AdminLink_default_popup($iPopup);
 +
return clsAdminData::_AdminLink($this,$iText,$strPopup,$iarArgs);
 +
    }
 +
    // END BOILERPLATES
 +
    //----
 +
    //
 +
    // Boilerplate auxiliary functions
 +
    public function AdminLink_name() {
 +
if ($this->IsNew()) {
 +
    return 'root';
 +
} else {
 +
    $txtShow = $this->Value('Name');
 +
    if ($this->doBranch()) {
 +
$txtPopup = $this->RenderBranch_text('<');
 +
    } else {
 +
$txtPopup = $this->NameFull();
 
    }
 
    }
    $out .= "\n|}";
+
    return $this->AdminLink($txtShow,$txtPopup);
 +
}
 +
    }
 +
    protected function AdminLink_default_popup($iOverrideText) {
 +
if (is_null($iOverrideText)) {
 +
    $out = $this->Value('Name');
 
} else {
 
} else {
    $out = 'No carts have been created yet.';
+
    $out = $iOverrideText;
 
}
 
}
$wgOut->addWikiText($out,TRUE); $out = '';
+
return $out;
 +
    }
 +
    // END boilerplate auxiliary
 +
    //----
 +
    public function RenderBranch($iSep="&larr;") {
 +
$ftFullName = htmlspecialchars($this->Value('FullName'));
 +
$out = $this->AdminLink($this->Value('TreeName'),$ftFullName);
 +
if ($this->HasParent()) {
 +
    $out .= $iSep.$this->ParentObj()->RenderBranch($iSep);
 +
}
 +
return $out;
 +
    }
 +
    public function Tree_RenderTwig($iCntTitles) {
 +
$cntTitles = $iCntTitles;
 +
$txtNoun = ' title'.Pluralize($cntTitles).' available'; // for topic #'.$id;
 +
$out = ' [<b><span style="color: #00cc00;" title="'.$cntTitles.$txtNoun.'">'.$cntTitles.'</span></b>]';
 +
// $txt = $this->Value('CatNum').' '.$this->Value('Name');
 +
return $out;
 +
    }
 +
    public function Tree_AddTwig(clsTreeNode $iTwig,$iText) {
 +
$id = $this->Value('ID');
 +
// $objSub = $iTwig->Add($id,$iText,$this->ShopURL());
 +
$objSub = $iTwig->Add($id,$iText,$this->AdminURL());
 +
return $objSub;
 
     }
 
     }
}
+
     public function AdminPage() {
class VbzAdminCart extends clsShopCart {
+
global $wgOut,$wgRequest;
     public function InfoPage() {
+
global $vgPage,$vgOut;
global $wgOut;
+
 
 +
$doEdit = $vgPage->Arg('edit');
 +
$doSave = $wgRequest->GetBool('btnSave');
 +
$doRmvTitles = $wgRequest->GetBool('btnRmvTitles');
 +
 
 +
$vgPage->UseHTML();
 +
 
 +
$strTitle = 'Topic: '.$this->Value('Name');
 +
 
 +
$objPage = new clsWikiFormatter($vgPage);
 +
$objSection = new clsWikiSection($objPage,$strTitle);
 +
$objSection->ToggleAdd('edit');
 +
//$objSection->ActionAdd('view');
 +
$out = $objSection->Generate();
 +
 
 +
// save edits before re-displaying data
 +
 
 +
// edits to this record
 +
$ftSaveStatus = NULL;
 +
if ($doEdit || $doSave) {
 +
    $this->BuildEditForm();
 +
    if ($doSave) {
 +
$ftSaveStatus = $this->AdminSave();
 +
    }
 +
}
 +
 
 +
// topic deletion
 +
if ($doRmvTitles) {
 +
    // TO BE WRITTEN
 +
}
 +
 
 +
if ($doEdit) {
 +
    $out .= $objSection->FormOpen();
 +
    $objForm = $this->objForm;
 +
 
 +
    $ctParent = $objForm->Render('ID_Parent');
 +
    $ctName = $objForm->Render('Name');
 +
    $ctNameTree = $objForm->Render('NameTree');
 +
    $ctNameFull = $objForm->Render('NameFull');
 +
    $ctNameMeta = $objForm->Render('NameMeta');
 +
    $ctUsage = $objForm->Render('Usage');
 +
    $ctSort = $objForm->Render('Sort');
 +
    $ctVariants = $objForm->Render('Variants');
 +
    $ctMispeled = $objForm->Render('Mispeled');
 +
} else {
 +
    $ctParent = $this->ParentObj()->AdminLink_name();
 +
    $ctName = $this->Value('Name');
 +
    $ctNameTree = $this->Value('NameTree');
 +
    $ctNameFull = $this->Value('NameFull');
 +
    $ctNameMeta = $this->Value('NameMeta');
 +
    $ctUsage = $this->Value('Usage');
 +
    $ctSort = $this->Value('Sort');
 +
    $ctVariants = $this->Value('Variants');
 +
    $ctMispeled = $this->Value('Mispeled');
 +
}
  
$wtSess = SelfLink('sess','id',$this->ID_Sess);
+
$out .= '<ul>';
$wtOrd = SelfLink('ord','id',$this->ID_Order);
+
$out .= '<li> <b>ID</b>: '.$this->KeyValue().' ['.$this->ShopLink('shop').']';
$wtCust = SelfLink('cust','id',$this->ID_Cust);
+
$out .= '<li> <b>Parent</b>: '.$ctParent;
 +
$out .= '<li> <b>Name</b>: '.$ctName;
 +
  $out .= '<ul>';
 +
  $out .= '<li> <b>in tree</b>: '.$ctNameTree;
 +
  $out .= '<li> <b>complete</b>: '.$ctNameFull;
 +
  $out .= '<li> <b>meta</b>: '.$ctNameMeta;
 +
  $out .= '</ul>';
 +
$out .= '<li> <b>Usage</b>: '.$ctUsage;
 +
$out .= '<li> <b>Searching</b>: ';
 +
  $out .= '<ul>';
 +
  $out .= '<li> <b>variants</b>: '.$ctVariants;
 +
  $out .= '<li> <b>misspellings</b>: '.$ctMispeled;
 +
  $out .= '<li> <b>sort by</b>: '.$ctSort;
 +
  $out .= '</ul>';
 +
$out .= '</ul>';
  
$out = '==Cart=='."\n";
+
if ($doEdit) {
$out .= "\n* '''ID''': ".$this->ID;
+
    $out .= '<input type=submit name="btnSave" value="Save">';
$out .= "\n* '''When Created''': ".$this->WhenCreated;
+
    $out .= '<input type=reset value="Reset">';
$out .= "\n* '''When Ordered''': ".$this->WhenOrdered;
+
    $out .= '</form>';
$out .= "\n* '''Session''': ".$wtSess;
+
}
$out .= "\n* '''Order''': ".$wtOrd;
+
$wgOut->AddHTML($out);
$out .= "\n* '''Customer''': ".$wtCust;
+
$wgOut->AddHTML("<h3>Subtopics</h3>");
$wgOut->addWikiText($out,TRUE); $out = '';
+
$wgOut->AddHTML($this->SubtopicListing());
$out .= "\n===Items===";
+
$wgOut->AddHTML("<h3>Titles</h3>");
$out .= $this->ItemTable();
+
$wgOut->AddHTML($this->TitleListing());
$wgOut->addWikiText($out,TRUE); $out = '';
 
$out .= "\n===Data===";
 
$out .= $this->DataTable();
 
$wgOut->addWikiText($out,TRUE); $out = '';
 
 
     }
 
     }
/*
+
    /*----
PURPOSE: Display the cart's items as a table
+
      ACTION: Save user changes to the record
*/
+
      HISTORY:
     public function ItemTable() {
+
2010-11-06 copied from VbzStockBin to VbzAdminItem
$objItems = new VbzAdminCartLines($this->objDB);
+
2011-01-26 copied from VbzAdminItem to clsAdminTopic
return $objItems->Table_forCart($this->ID);
+
    */
 +
     public function AdminSave() {
 +
global $vgOut;
 +
 
 +
$out = $this->objForm->Save();
 +
$vgOut->AddText($out);
 
     }
 
     }
/*
+
    /*----
PURPOSE: Display the cart's data lines as a table
+
      HISTORY:
*/
+
2010-11-06 adapted from VbzStockBin for VbzAdminTitle
     public function DataTable() {
+
2011-01-26 adapted from VbzAdminTitle
$objItems = new VbzAdminCartData($this->objDB);
+
    */
return $objItems->Table_forCart($this->ID);
+
     private function BuildEditForm() {
 +
global $vgOut;
 +
 
 +
if (is_null($this->objForm)) {
 +
    // create fields & controls
 +
    $objForm = new clsForm_DataSet($this,$vgOut);
 +
    //$objCtrls = new clsCtrls($objForm->Fields());
 +
    //$objCtrls = $objForm;
 +
 
 +
    $objForm->AddField(new clsFieldNum('ID_Parent'), new clsCtrlHTML());
 +
    $objForm->AddField(new clsField('Name'), new clsCtrlHTML(array('size'=>20)));
 +
    $objForm->AddField(new clsField('NameTree'), new clsCtrlHTML(array('size'=>15)));
 +
    $objForm->AddField(new clsField('NameFull'), new clsCtrlHTML(array('size'=>25)));
 +
    $objForm->AddField(new clsField('NameMeta'), new clsCtrlHTML(array('size'=>25)));
 +
    $objForm->AddField(new clsField('Usage'), new clsCtrlHTML(array('size'=>25)));
 +
    $objForm->AddField(new clsField('Sort'), new clsCtrlHTML(array('size'=>5)));
 +
    $objForm->AddField(new clsField('Variants'), new clsCtrlHTML(array('size'=>40)));
 +
    $objForm->AddField(new clsField('Mispeled'), new clsCtrlHTML(array('size'=>40)));
 +
 
 +
    $this->objForm = $objForm;
 +
    //$this->objCtrls = $objCtrls;
 +
}
 
     }
 
     }
}
+
    protected function SubtopicListing() {
// SHOPPING CART ITEMS
+
global $wgRequest;
class VbzAdminCartLines extends clsShopCartLines {
+
 
    public function Table_forCart($iCart) {
+
$htStatus = NULL;
$objRecs = $this->GetData('ID_Cart='.$iCart,NULL,'Seq');
+
 
if ($objRecs->HasRows()) {
+
// set up the entry widget
    $out = "\n{| class=sortable\n|-\n! ID || # || Item || Qty || Added || Changed";
+
$ctrlList = new clsWidget_ShortList();
 +
$me = $this;
 +
$arOpts = array(
 +
  'name' => 'topic',
 +
  'btnChk_Text' => 'Enter subtopics:',
 +
  'btnChg_Text' => '<= Create',
 +
  'txtCargo_sng' => 'topic name',
 +
  'txtCargo_plr' => 'topic names',
 +
  'txtProd_sng' => 'subtopic',
 +
  'txtProd_plr' => 'subtopics',
 +
  'fHandleData_Check' => function($iVal) {
 +
      $arOut['html'] = $iVal;
 +
      $arOut['text'] = $iVal;
 +
      return $arOut;
 +
  },
 +
  'fHandleData_Change_Start' => function($iText) use ($me) {
 +
      $arEv = array(
 +
'descr' => 'Adding '.$iText,
 +
'code' => 'sub++',
 +
'where' => __METHOD__
 +
);
 +
      $me->StartEvent($arEv);
 +
  },
 +
  'fHandleData_Change_Finish' => function($iText) use ($me) {
 +
      $arEv = array(
 +
'descrfin' => $iText
 +
);
 +
      $me->FinishEvent($arEv);
 +
  },
 +
  'fHandleData_Change_Item' => function($iVal) use ($me) {
 +
      $txt = $iVal;
 +
      $arIns = array(
 +
'ID_Parent' => SQLValue($me->KeyValue()),
 +
'Name' => SQLValue($txt)
 +
);
 +
      $me->Table->Insert($arIns);
 +
      $out = $me->Table->LastID();
 +
      return $out;
 +
  },
 +
  );
 +
$ctrlList->Options($arOpts);
 +
$htStatus = $ctrlList->HandleInput();
 +
 
 +
$out = "\n<form method=post>";
 +
 
 +
 
 +
$rs = $this->Subtopics();
 +
if ($rs->HasRows()) {
 +
    $out .= "\n<table class=sortable>";
 +
    $out .= "\n<tr><th>ID</th><th>Name</th><th>in tree</th><th>full</th><th>sort</th><th>variants</th><th>mis-spellings</th></tr>";
 
    $isOdd = TRUE;
 
    $isOdd = TRUE;
    while ($objRecs->NextRow()) {
+
    while ($rs->NextRow()) {
$wtStyle = $isOdd?'background:#ffffff;':'background:#eeeeee;';
 
 
$isOdd = !$isOdd;
 
$isOdd = !$isOdd;
 +
$ftStyleShade = $isOdd?'ffffff':'#cccccc';
 +
$ftStyle = ' style="background: '.$ftStyleShade.';"';
  
$id = $objRecs->ID;
+
$id = $rs->KeyString();
$wtID = SelfLink('cart','id',$id,$id);
+
$ftID = $rs->AdminLink();
$wtItem = $objRecs->ItemDesc_wt();
+
$ftName = $rs->Value('Name');
/*
+
$ftNameTree = $rs->Value('NameTree');
$wtAdded = DataDateTime($objRecs->WhenAdded);
+
$ftNameFull = $rs->Value('NameFull');
$wtEdited = DataDateTime($objRecs->WhenEdited);
+
$ftSort = $rs->Value('Sort');
*/
+
$ftVari = $rs->Value('Variants');
$wtAdded = var_export($objRecs->WhenAdded, TRUE);
+
$ftMisp = $rs->Value('Mispeled');
$wtEdited = var_export($objRecs->WhenEdited, TRUE);
 
  
$out .=  
+
$out .= "\n<tr$ftStyle>"
  "\n|- style=\"$wtStyle\"\n"
+
  ."<td>$ftID</td>"
  ."| $wtID "
+
  ."<td>$ftName</td>"
  ."|| {$objRecs->Seq}"
+
  ."<td>$ftNameTree</td>"
  ."|| $wtItem"
+
  ."<td>$ftNameFull</td>"
  ."|| {$objRecs->Qty}"
+
  ."<td>$ftSort</td>"
  ."|| $wtAdded"
+
  ."<td>$ftVari</td>"
  ."|| $wtEdited"
+
  ."<td>$ftMisp</td>"
  ;
+
  ."</tr>";
 
    }
 
    }
 +
    $out .= "\n</table>";
 
} else {
 
} else {
    $out = "''No items in cart''";
+
    $out .= '<i>None found.</i>';
 
}
 
}
 +
$out .= '<br>'.$htStatus;
 +
$out .= $ctrlList->RenderForm_Entry();
 +
$out .= '</form>';
 
return $out;
 
return $out;
 
     }
 
     }
}
+
    protected function TitleListing() {
// SHOPPING CART DATA
+
global $wgRequest;
class VbzAdminCartData extends clsTable {
+
global $vgPage;
    public function __construct($iDB) {
+
 
      parent::__construct($iDB);
+
// check for any form actions
$this->Name('shop_cart_data');
+
$doChk = $wgRequest->GetBool('btnChkTitles');
$this->ClassSng('VbzAdminCartDatum');
+
$doAdd = $wgRequest->GetBool('btnAddTitles');
 +
$doRmv = $wgRequest->GetBool('btnRmvTitles');
 +
 
 +
$htStatus = NULL;
 +
 
 +
// pass-along vars for anon functions
 +
$tblTitles = $this->Engine()->Titles(); // for anon function to use
 +
$tblTitleTopics = $this->Engine()->TitleTopics();
 +
$me = $this;
 +
 
 +
$ctrlList = new clsWidget_ShortList();
 +
$arOpts = array(
 +
  'name' => 'title',
 +
  'btnChk_Text' => 'Enter titles:',
 +
  'btnChg_Text' => '<= Add',
 +
  'txtCargo_sng' => 'title ID',
 +
  'txtCargo_plr' => 'title IDs',
 +
  'txtProd_sng' => 'title',
 +
  'txtProd_plr' => 'titles',
 +
  'fHandleData_Check' => function($iVal) use ($tblTitles) {
 +
      $obj = $tblTitles->GetItem($iVal); // for now, assume title is ID
 +
 
 +
      $arOut['html'] = $obj->AdminLink($obj->CatNum(),$obj->Value('Name'));
 +
      //$arOut['text'] = $obj->KeyValue().'('.$obj->CatNum().')';
 +
      $arOut['text'] = $obj->KeyValue();
 +
      return $arOut;
 +
  },
 +
  'fHandleData_Change_Start' => function($iText) use ($me) {
 +
      $arEv = array(
 +
'descr' => 'Adding '.$iText,
 +
'code' => 'sub++',
 +
'where' => __METHOD__
 +
);
 +
      $me->StartEvent($arEv);
 +
  },
 +
  'fHandleData_Change_Finish' => function($iText) use ($me) {
 +
      $arEv = array(
 +
'descrfin' => $iText
 +
);
 +
      $me->FinishEvent($arEv);
 +
  },
 +
  'fHandleData_Change_Item' => function($iVal) use ($me,$tblTitleTopics) {
 +
      $txt = $iVal;
 +
      $arIns = array(
 +
'ID_Title' => SQLValue($txt),
 +
'ID_Topic' => SQLValue($me->KeyValue())
 +
);
 +
      //$this->Engine()->TitleTopics()->Insert($arIns);
 +
      $sql = $tblTitleTopics->Insert($arIns);
 +
      $out = SQLValue($txt);
 +
      return $out;
 +
  },
 +
  );
 +
$ctrlList->Options($arOpts);
 +
$htStatus = $ctrlList->HandleInput();
 +
if ($wgRequest->GetBool('btnRmvTitles')) {
 +
    $arRmv = $wgRequest->GetArray('rmvTitle');
 +
    $cntRmv = count($arRmv);
 +
    $arEv = array(
 +
      'descr' => 'Removing '.$cntRmv.' title'.Pluralize($cntRmv).' from this topic',
 +
      'code' => 'TTL--',
 +
      'where' => __METHOD__
 +
      );
 +
    $this->StartEvent($arEv);
 +
    $txtRmv = '';
 +
    foreach ($arRmv as $id => $on) {
 +
$sqlFilt = '(ID_Topic='.$this->ID.') AND (ID_Title='.$id.')';
 +
$this->Engine()->TitleTopics()->Delete($sqlFilt);
 +
$txtRmv .= ' '.$id;
 +
    }
 +
    $arEv = array(
 +
      'descrfin' => 'Titles removed:'.$txtRmv
 +
      );
 +
    $this->FinishEvent($arEv);
 +
    $htStatus .= 'Titles removed:'.$txtRmv;
 +
}
 +
 
 +
$out = "\n<form name=\"add-titles\" method=post>";
 +
 
 +
$rs = $this->Titles();
 +
if ($rs->HasRows()) {
 +
    $out .= "\n<table class=sortable>";
 +
    $out .= "\n<tr><th>ID</th><th>Cat #</th><th>Name</th><th>Dept</th><th>When Added</th><th>When Unavail</th></tr>";
 +
    $isOdd = TRUE;
 +
    while ($rs->NextRow()) {
 +
$isOdd = !$isOdd;
 +
$ftStyleShade = $isOdd?'ffffff':'#cccccc';
 +
$ftStyle = ' style="background: '.$ftStyleShade.';"';
 +
 
 +
$id = $rs->KeyString();
 +
$ftID = $rs->AdminLink();
 +
$ftCatNum = $rs->CatNum();
 +
$ftName = $rs->Value('Name');
 +
$rsDept = $rs->DeptObj();
 +
$ftDept = $rsDept->AdminLink_name();
 +
$ftAdded = $rs->Value('DateAdded');
 +
$ftUnavail = $rs->Value('DateUnavail');
 +
 
 +
$out .= "\n<tr$ftStyle>"
 +
  ."<td><input type=checkbox name=\"rmvTitle[$id]\">$ftID</td>"
 +
  ."<td>$ftCatNum</td>"
 +
  ."<td>$ftName</td>"
 +
  ."<td>$ftDept</td>"
 +
  ."<td>$ftAdded</td>"
 +
  ."<td>$ftUnavail</td>"
 +
  ."</tr>";
 +
    }
 +
    $out .= "\n</table>";
 +
    $out .= '<input type=submit name="btnRmvTitles" value="Remove Checked">';
 +
} else {
 +
    $out .= '<i>None found.</i>';
 +
}
 +
$out .= '<br>'.$htStatus;
 +
$out .= $ctrlList->RenderForm_Entry();
 +
/*
 +
$out .= '<input type=submit name="btnChkTitles" value="Add These:">';
 +
$out .= '<input size=40 name=txtNewTitles> (IDs separated by spaces)';
 +
*/
 +
$out .= '</form>';
 +
return $out;
 
     }
 
     }
 +
    /*----
 +
      What uses this?
 +
 +
    */
 +
    public function AdminList() {
 +
$objRecs = $this;
  
    public function Table_forCart($iCart) {
 
$objRecs = $this->GetData('ID_Cart='.$iCart);
 
 
if ($objRecs->HasRows()) {
 
if ($objRecs->HasRows()) {
    $out = "\n{| class=sortable\n|-\n! Type || Value";
+
    $out = "{| class=sortable\n|-\n! ID || Name || Abbr || When Avail || Superceded || Status";
 
    $isOdd = TRUE;
 
    $isOdd = TRUE;
 
    while ($objRecs->NextRow()) {
 
    while ($objRecs->NextRow()) {
$wtStyle = $isOdd?'background:#ffffff;':'background:#eeeeee;';
+
$objTopic = $this->objDB->Topics()->GetItem($this->ID_Topic);
 +
$id = $objTopic->ID;
 +
$ftID = $id;
 +
$out .= "\n|- style=\"$wtStyle\"".
 +
    "\n| ".$ftID.
 +
    ' || '.$objRecs->Name.
 +
    ' || '.$objRecs->Abbr.
 +
    ' || '.$strDate.
 +
    ' || '.$strSuper.
 +
    ' || '.$strStatus;
 
$isOdd = !$isOdd;
 
$isOdd = !$isOdd;
 
$wtType = $objRecs->ValueText();
 
$wtVal = $objRecs->Val;
 
 
$out .= "\n|- style=\"$wtStyle\"\n| $wtType || $wtVal";
 
 
    }
 
    }
 +
    $out .= "\n|}";
 
} else {
 
} else {
    $out = "\n''No data in cart''";
+
    $out = 'No topics found.';
 
}
 
}
 
return $out;
 
return $out;
 
     }
 
     }
}
+
    /*----
class VbzAdminCartDatum extends clsDataSet {
+
      HISTORY:
     public function ValueText() {
+
2010-10-11 Created -- then discovered that it probably doesn't need
global $vgaCartDataType;
+
  to be a separate function... but I think it makes things clearer.
 +
    */
 +
    public function Twigs() {
 +
if (is_null($this->ID)) {
 +
    $sql = 'ID_Parent IS NULL';
 +
} else {
 +
    $sql = 'ID_Parent='.$this->ID;
 +
}
 +
$objRows = $this->Table->GetData($sql,NULL,'Sort,NameTree,Name');
 +
return $objRows;
 +
    }
 +
     public function DrawTree($iLevel=0,$iRootName="Topics") {
 +
global $vgPage;
 +
 
 +
$out = '';
 +
$intLevel = $iLevel + 1;
 +
$strIndent = str_repeat('*',$intLevel);
  
$strType = $this->Type;
+
$objRows = $this->Twigs();
if (isset($vgaCartDataType[$strType])) {
+
if ($objRows->HasRows()) {
    $wtType = $vgaCartDataType[$strType];
+
    if (empty($iLevel)) {
 +
$strName = $this->Name;
 +
if (empty($strName)) {
 +
    $strName = $iRootName;
 +
}
 +
$out .= "\n{{#tree:id=root|root='''$strName'''|";
 +
$vgPage->UseWiki();
 +
    }
 +
    while ($objRows->NextRow()) {
 +
$strNameTree = $objRows->NameTree;
 +
$strTwig = ifEmpty($strNameTree,$objRows->Name);
 +
$out .= "\n$strIndent".$objRows->AdminLink($strTwig);
 +
$out .= $objRows->DrawTree($intLevel);
 +
    }
 +
    if ($iLevel == 0) {
 +
$out .= "\n}}";
 +
$vgPage->UseWiki();
 +
    }
 +
    return $out;
 
} else {
 
} else {
    $wtType = "'''?'''$strType";
+
    if (empty($iLevel)) {
 +
return 'NO TOPICS FOUND';
 +
    } else {
 +
return NULL;
 +
    }
 
}
 
}
return $wtType;
 
 
     }
 
     }
 
}
 
}
/* ========================== *\
+
class clsAdminTitleTopic_Titles extends clsTitleTopic_Titles {
- CUSTOMER ORDER classes
+
    public function __construct(clsDatabase $iDB) {
\* ========================== */
+
parent::__construct($iDB);
class VbzAdminOrders extends clsOrders {
+
  $this->ClassSng('VbzAdminTitle');
     public function __construct($iDB) {
+
  $this->ActionKey($this->Engine()->Titles()->ActionKey());
 +
    }
 +
}
 +
class clsAdminTitleTopic_Topics extends clsTitleTopic_Topics {
 +
     public function __construct(clsDatabase $iDB) {
 
parent::__construct($iDB);
 
parent::__construct($iDB);
  $this->ClassSng('VbzAdminOrder'); // override parent
+
  $this->ClassSng('clsAdminTopic');
 +
  $this->ActionKey($this->Engine()->Topics()->ActionKey());
 +
    }
 +
}
 +
/*==========
 +
| UTILITY FUNCTIONS
 +
| These should probably go into a separate file at some point
 +
*/
 +
/*----
 +
  PURPOSE: This is the newer version of WhoString_wt
 +
    which uses WhoAdmin, WhoSystem, and WhoNetwork
 +
    instead of VbzUser, SysUser, and Machine
 +
*/
 +
function WhoString2_wt($iRow) {
 +
    $htUnknown = '<span style="color: #888888;">?</span>';
 +
 
 +
    if (isset($iRow['WhoSystem'])) {
 +
$strSysUser = $iRow['WhoSystem'];
 +
$hasSysUser = TRUE;
 +
    } else {
 +
$strSysUser = NULL;
 +
$hasSysUser = FALSE;
 
     }
 
     }
     public function ListPage() {
+
     $strMachine = $iRow['WhoNetwork'];
global $wgOut;
+
    $strVbzUser = $iRow['WhoAdmin'];
  
$out = '==Orders=='."\n";
+
    $htSysUser = is_null($strSysUser)?$htUnknown:$strSysUser;
$wgOut->addWikiText($out,TRUE); $out = '';
+
    $htMachine = is_null($strMachine)?$htUnknown:$strMachine;
 +
    $htVbzUser = is_null($strVbzUser)?$htUnknown:$strVbzUser;
  
$out = $this->Listing();
+
    $htWho = $htVbzUser;
$wgOut->addWikiText($out,TRUE); $out = '';
+
    if ($hasSysUser) {
 +
$htWho .= '/'.$htSysUser;
 
     }
 
     }
     protected function Listing() {
+
     $htWho .= '@'.$htMachine;
$objRow = $this->GetData(NULL,NULL,'SortPfx, Number DESC');
+
 
if ($objRow->hasRows()) {
+
    return $htWho;
    $out = "{| class=sortable \n|-\n! ID || Number || Status || Total Amt || created || closed";
+
}
    $isOdd = TRUE;
+
/*
    while ($objRow->NextRow()) {
+
  STATUS: DEPRECATED
$wtStyle = $isOdd?'background:#ffffff;':'background:#eeeeee;';
+
    Where possible, convert table fieldnames to be compatible with WhoString2_wt
$isOdd = !$isOdd;
+
*/
 +
function WhoString_wt($iRow) {
 +
    $htUnknown = '<span style="color: #888888;">?</span>';
  
$row = $objRow->Row;
+
    if (isset($iRow['SysUser'])) {
 +
$strSysUser = $iRow['SysUser'];
 +
$hasSysUser = TRUE;
 +
    } else {
 +
$strSysUser = NULL;
 +
$hasSysUser = FALSE;
 +
    }
 +
    $strMachine = $iRow['Machine'];
 +
    $strVbzUser = $iRow['VbzUser'];
  
$id = $row['ID'];
+
    $htSysUser = is_null($strSysUser)?$htUnknown:$strSysUser;
$strNum = $row['Number'];
+
    $htMachine = is_null($strMachine)?$htUnknown:$strMachine;
$idPull = $row['ID_Pull'];
+
    $htVbzUser = is_null($strVbzUser)?$htUnknown:$strVbzUser;
$mnyTotal = $row['WebTotal_Final'];
 
$dtCreate = $row['WhenStarted'];
 
$dtClosed = $row['WhenClosed'];
 
  
$wtNum = SelfLink('order','id',$id,$strNum);
+
    $htWho = $htVbzUser;
$strTotal = DataCurr($mnyTotal);
+
    if ($hasSysUser) {
$strWhenCreated = DataDate($dtCreate);
+
$htWho .= '/'.$htSysUser;
$strWhenClosed = DataDate($dtClosed);
+
    }
 +
    $htWho .= '@'.$htMachine;
  
$out .= "\n|- style=\"$wtStyle\"";
+
    return $htWho;
$out .= "\n| $id || $wtNum || $idPull || align=right | $strTotal || $strWhenCreated || $strWhenClosed";
+
}
    }
+
function SelfLink_Page($iPage,$iKey,$iVal,$iText=NULL) {
    $out .= "\n|}\n";
+
    $strText = (is_null($iText))?$iVal:$iText;
} else {
+
    if (is_null($strText)) {
    $out = 'There do not seem to be any order records yet.';
+
return NULL;
}
+
    } else {
return $out;
+
return '[[{{FULLPAGENAME}}/page'.KS_CHAR_URL_ASSIGN.$iPage.'/'.$iKey.KS_CHAR_URL_ASSIGN.$iVal.'|'.$strText.']]';
 
     }
 
     }
 
}
 
}
class VbzAdminOrder extends clsOrder {
 
    public function InfoPage() {
 
global $wgOut;
 
  
$wtSess = SelfLink('sess','id',$this->ID_Sess);
+
function WikiSelfLink($iArgs,$iText) {
$wtOrd = SelfLink('ord','id',$this->ID_Order);
+
// this function is deprecated; gradually convert to SelfLink and then rename it
$wtCust = SelfLink('cust','id',$this->ID_Cust);
+
  return '[{{fullurl:{{FULLPAGENAME}}|'.$iArgs.'}} '.$iText.']';
 +
}
 +
function WikiSectionHdr($iTitle,$iMenuName,array $iMenu) {
 +
    global $vgPage;
  
$out = '==Order=='."\n";
+
    $out = '<h2>';
$out .= "\n* '''ID''': ".$this->ID.' - #'.$this->Number;
+
    foreach ($iMenu as $name=>$arLink) {
$out .= "\n* '''When Created''': ".$this->WhenStarted;
+
$htPath = $arLink['path'];
$out .= "\n* '''When Closed''': ".$this->WhenClosed;
+
$htPopup = $arLink['popup'];
$wgOut->addWikiText($out,TRUE); $out = '';
+
$htDispl = $arLink['displ'];
$out .= "\n===Items===";
+
$out .= '<span class="editsection">[<a href="'.$htPath.'" title="'.$htPopup.'">'.$htDispl.'</a>]</span> ';
$out .= $this->ItemTable();
 
$wgOut->addWikiText($out,TRUE); $out = '';
 
$out .= "\n===Transactions===";
 
$out .= "\n===Messages===";
 
$out .= "\n===Charges===";
 
 
     }
 
     }
     public function ItemTable() {
+
     $out .= '<span class="mw-headline">'.$iTitle.'</span></h2>';
$objItems = new VbzAdminOrderItems($this->objDB);
+
    return $out;
return $objItems->Table_forOrder($this->ID);
+
}
 +
function WikiSectionHdr_Edit($iTitle,$iEditTitle) {
 +
    global $vgPage;
 +
//    global $vgOut;
 +
 
 +
    $doEdit = $vgPage->Arg('edit');
 +
    $arLink = array(
 +
      'edit' => !$doEdit,
 +
      'page' => $vgPage->Arg('page'),
 +
      'id' => $vgPage->Arg('id')
 +
      );
 +
    $htPath = $vgPage->SelfURL($arLink,TRUE);
 +
 
 +
    $out = '<h2>';
 +
    if ($doEdit) {
 +
$out .= '<span class="editsection">[<a href="'.$htPath.'" title="View '.$iEditTitle.'">view</a>]</span> ';
 +
    } else {
 +
$out .= '<span class="editsection">[<a href="'.$htPath.'" title="Edit '.$iEditTitle.'">edit</a>]</span> ';
 
     }
 
     }
 +
    $out .= '<span class="mw-headline">'.$iTitle.'</span></h2>';
 +
    return $out;
 
}
 
}
class VbzAdminOrderItems extends clsOrderLines {
+
 
     public function __construct($iDB) {
+
if (!function_exists('TimeStamp_HideTime')) {
parent::__construct($iDB);
+
//--
  $this->ClassSng('VbzAdminOrderItem'); // override parent
+
function TimeStamp_HideTime($iStamp) {
 +
 
 +
     if (is_string($iStamp)) {
 +
$intStamp = strtotime($iStamp);
 +
    } else if (is_int($iStamp)) {
 +
$intStamp = $iStamp;
 +
    } else {
 +
$intStamp = NULL;
 
     }
 
     }
     public function Table_forOrder() {
+
     if (!is_null($intStamp)) {
 +
return date('Y-m-d',$intStamp);
 +
    } else {
 +
return NULL;
 
     }
 
     }
 
}
 
}
class VbzAdminOrderItem extends clsOrderLine {
+
//--
 
}
 
}
</php>
+
 
 +
function IsWebSecure() {
 +
    if (isset($_SERVER["HTTPS"])) {
 +
return $_SERVER["HTTPS"] == 'on';
 +
    } else {
 +
return FALSE;
 +
    }
 +
}</php>

Revision as of 03:59, 25 December 2011

<php><?php /*

 NAME: SpecialVbzAdmin
 PURPOSE: Special page for administering VbzCart
 AUTHOR: Woozle (Nick) Staddon
 REQUIRES:
   Tabber extension for tabs on Supplier admin page
   TreeAndMenu extension (tentatively) for category management
 VERSION:
   2009-03-10 0.0 (Wzl) Started writing
     had a few functions implemented by June or so, but not enough to process anything
   2009-07-09 (Wzl)
     rewrote menu functions as classes
     started on Shipments
   2009-10-04 (Wzl)
     menu classes now in separate file; removed from here
     added 'orders' and 'order' pages/classes
   2009-10-06 (Wzl) clsTitles -> clsVbzTitles, clsTitle -> clsVbzTitle
   2010-06-27 (Wzl) new functionality in Bins, Images; moved catalog rebuild out to standalone script
   2010-09-22 (Wzl) working on email confirmation of orders (finally)
   2011-02-06 (Wzl) extensive work since 9/22... most features usable
   2011-12-21 (Wzl) extracted clsVbzAdminData into base.admin.php so it could be used from command line
  • /

$wgSpecialPages['VbzAdmin'] = 'SpecialVbzAdmin'; # Let MediaWiki know about your new special page. $wgExtensionCredits['other'][] = array(

       'name' => 'Special:VbzAdmin',

'url' => 'http://htyp.org/VbzCart',

       'description' => 'special page for VbzCart administration',
       'author' => 'Woozle (Nick) Staddon',

'version' => '2011-12-21 unreleased' ); global $dbgShowLibs; $dbgShowLibs = TRUE;

if (!defined('LIBMGR')) {

   require('libmgr.php');

} //clsLibMgr::$doDebug = TRUE; clsLibMgr::Add('vbz.site', KFP_LIB_VBZ.'/site.php',__FILE__,__LINE__); clsLibMgr::Add('vbz.shop', KFP_LIB_VBZ.'/shop.php',__FILE__,__LINE__); clsLibMgr::Add('vbz.ckout', KFP_LIB_VBZ.'/ckout.php',__FILE__,__LINE__); clsLibMgr::Add('vbz.topic', KFP_LIB_VBZ.'/topic.php',__FILE__,__LINE__); clsLibMgr::Add('admin.events', KFP_MW_PLUGINS.'/lib/admin.events.php',__FILE__,__LINE__); clsLibMgr::Add('admin.forms', KFP_MW_PLUGINS.'/lib/admin.forms.php',__FILE__,__LINE__); clsLibMgr::Add('vbz.admin.base', KFP_LIB_VBZ.'/base.admin.php',__FILE__,__LINE__); clsLibMgr::Add('vbz.admin.cache', KFP_LIB_VBZ.'/admin.cache.php',__FILE__,__LINE__); clsLibMgr::Add('vbz.admin.cat', KFP_LIB_VBZ.'/admin.cat.php',__FILE__,__LINE__); clsLibMgr::Add('vbz.admin.sess',KFP_LIB_VBZ.'/admin.sess.php',__FILE__,__LINE__); clsLibMgr::Add('vbz.admin.cart',KFP_LIB_VBZ.'/admin.cart.php',__FILE__,__LINE__); clsLibMgr::Add('vbz.admin.ord', KFP_LIB_VBZ.'/admin.ord.php',__FILE__,__LINE__); clsLibMgr::Add('vbz.admin.pkg', KFP_LIB_VBZ.'/admin.pkg.php',__FILE__,__LINE__); clsLibMgr::Add('vbz.admin.cust',KFP_LIB_VBZ.'/admin.cust.php',__FILE__,__LINE__); clsLibMgr::Add('vbz.admin.rstk',KFP_LIB_VBZ.'/admin.rstk.php',__FILE__,__LINE__); clsLibMgr::Add('vbz.admin.stock',KFP_LIB_VBZ.'/admin.stock.php',__FILE__,__LINE__); clsLibMgr::Add('richtext', KFP_MW_PLUGINS.'/richtext.php',__FILE__,__LINE__); clsLibMgr::Add('menus', KFP_MW_PLUGINS.'/menu.php',__FILE__,__LINE__); clsLibMgr::Load('vbz.site' ,__FILE__,__LINE__); clsLibMgr::Load('vbz.shop' ,__FILE__,__LINE__); clsLibMgr::Load('vbz.ckout' ,__FILE__,__LINE__); clsLibMgr::Load('vbz.topic' ,__FILE__,__LINE__); clsLibMgr::Load('admin.events' ,__FILE__,__LINE__); clsLibMgr::Load('admin.forms' ,__FILE__,__LINE__); clsLibMgr::Load('vbz.admin.base' ,__FILE__,__LINE__); clsLibMgr::Load('vbz.admin.cache' ,__FILE__,__LINE__); clsLibMgr::Load('vbz.admin.cat' ,__FILE__,__LINE__); clsLibMgr::Load('vbz.admin.sess' ,__FILE__,__LINE__); clsLibMgr::Load('vbz.admin.ord' ,__FILE__,__LINE__); clsLibMgr::Load('vbz.admin.pkg' ,__FILE__,__LINE__); clsLibMgr::Load('vbz.admin.cart' ,__FILE__,__LINE__); clsLibMgr::Load('vbz.admin.cust' ,__FILE__,__LINE__); clsLibMgr::Load('vbz.admin.rstk' ,__FILE__,__LINE__); clsLibMgr::Load('vbz.admin.stock' ,__FILE__,__LINE__); clsLibMgr::Load('richtext' ,__FILE__,__LINE__); clsLibMgr::Load('menus' ,__FILE__,__LINE__);

define('kwp_DocPfx','htyp:VbzCart/'); define('kwp_DocTblPfx',kwp_DocPfx.'tables/'); define('kwp_DocPrcPfx',kwp_DocPfx.'procs/'); define('kwp_DocTermPfx',kwp_DocPfx.'ui/terms/'); //echo 'LIB LOG:'.clsLibMgr::$Log;

if (!defined('KS_CHAR_URL_ASSIGN')) {

   define('KS_CHAR_URL_ASSIGN',':');	// character used for encoding values in wiki-internal URLs

}

// data source names -- these are used only by admin functions; general tables are in store.php define('KSQL_DS_ITEMS_TO_SHIP','qryStock_forOpenOrders');

function Date_DefaultYear($iDate,$iYear,$iSmallerPfx='',$iSmallerSfx='') {

   if (empty($iDate)) {

return NULL;

   } else {

$dtIn = strtotime($iDate); $yrIn = date('Y',$dtIn); $doYr = ($yrIn != $iYear); $out = ; if ($doYr) { $out .= $iSmallerPfx; } $ftIn = date('m/d',$dtIn); $out .= $ftIn; if ($doYr) { $out .= '
'.$yrIn; $out .= $iSmallerSfx; } return $out;

   }

}

function wfSpecialVbzAdmin() { // This registers the page's class. I think. global $wgRequest;

$app = new SpecialVbzAdmin($wgRequest); } function NextSeq($iData) {

   if ($iData->HasRows()) {

$intMax = 0; while ($iData->NextRow()) { if ($iData->Seq > $intMax) { $intMax = $iData->Seq; } } return $intMax+1;

   } else {

return 1;

   }

}

/* DEACTIVATED 2010-11-08 function VbzDb() {

 static $objDb;
   if (!isset($objDb)) {

$objDb = new clsVbzAdminData(KS_DB_VBZCART); $objDb->Open();

   }
   return $objDb;

}

  • /

class SpecialVbzAdmin extends SpecialPageApp {

   protected $args;
   protected $objDB;
   public function __construct() {

global $wgMessageCache,$wgUser; global $vgUserName,$vgPage;

parent::__construct( 'VbzAdmin' ); $this->includable( TRUE );

       $this->SetTitle('VbzAdmin');

$vgUserName = 'wiki:'.$wgUser->getName(); $vgPage = $this;

   }
   /*----
     USAGE: Must be called before parent::SetHeaders()
   */
   public function SetTitle($iText) {

global $wgMessageCache;

       $wgMessageCache->addMessage('vbzadmin',$iText);
   }
   protected function DB() {

if (!isset($this->objDB)) { $this->objDB = new clsVbzAdminData(KS_DB_VBZCART); $this->objDB->Open(); } return $this->objDB;

   }
   function execute( $par ) {

global $wgUser;

$doAdmin = $wgUser->isAllowed('editinterface'); $this->GetArgs($par);

if ($doAdmin) { $this->RegObjs($this->ClassList()); $this->HandlePageArgs(); }

$this->setHeaders();

$this->doMenu($doAdmin);

if ($doAdmin) { $this->doAdmin(); } else { $this->doUser(); }

   }
   protected function doMenu($iAdmin) {

global $wgOut;

$wtSelf = 'Special:'.$this->name();

$objMenu = new clsMenu($wtSelf); if ($iAdmin) { $objMenu->Add($objRow = new clsMenuRow('Stock','menu.stock')); $objRow->Add(new clsMenuItem('stock places','place')); $objRow->Add(new clsMenuItem('stock bins','bin')); $objMenu->Add($objRow = new clsMenuRow('Catalog','menu.cat')); $objRow->Add(new clsMenuItem('suppliers','supp')); $objRow->Add(new clsMenuItem('images','cat.img')); $objRow->Add(new clsMenuItem('topics','topic')); $objRow->Add(new clsMenuItem('search','cat.search')); $objMenu->Add($objRow = new clsMenuRow('Restocks','menu.rstk')); $objRow->Add(new clsMenuItem('needed','rstk.need')); $objRow->Add(new clsMenuItem('expected','rstk.wait')); $objRow->Add(new clsMenuItem('past','rstk.past')); $objMenu->Add($objRow = new clsMenuRow('Orders','menu.orders')); $objRow->Add(new clsMenuItem('carts','cart')); $objRow->Add(new clsMenuItem('orders',KS_URL_PAGE_ORDER)); $objRow->Add(new clsMenuItem('charges','chg')); $objMenu->Add($objRow = new clsMenuRow('Ship','menu.ship')); $objRow->Add(new clsMenuItem('items to ship','toship')); $objRow->Add(new clsMenuItem('shipments','shpmt')); $objMenu->Add($objRow = new clsMenuRow('Utilities','menu.utils')); $objRow->Add(new clsMenuItem('cache tables','cache')); $objRow->Add(new clsMenuItem('ccard encryption','migr.encr')); $objRow->Add(new clsMenuItem('update stats','util.stats')); $objRow->Add(new clsMenuItem('price list','util.plist')); $objRow->Add(new clsMenuItem('inventory','util.inv')); $objMenu->Add($objRow = new clsMenuRow('Logs','menu.logs')); $objRow->Add(new clsMenuItem('general','log.misc')); $objRow->Add(new clsMenuItem('carts','log.cart')); }

$wgOut->addHTML('

');

$out = $objMenu->WikiText($this->page); $out .= $objMenu->Execute(); $wgOut->addWikiText($out,TRUE); $out = ;

$wgOut->addHTML('

');

// a little diagnostic info $isFnd = FALSE; $out .= ''; if (is_object($this->tbl)) { $out .= 'table class: '.get_class($this->tbl).''; $isFnd = TRUE; } if (is_object($this->obj)) { $out .'record class: '.get_class($this->obj).''; $isFnd = TRUE; } if (!$isFnd) { $out .= 'No classes found for page ['.$this->page.'].'; } $out .= ''; $wgOut->addHTML($out); $out = ;

   }
   protected function ClassList() {

$ar = array( //'clsAdminCacheFlows', //'clsAdminCacheProc', //'clsAdminCacheTables', //'VbzAdminCartLines', //'VbzAdminCartLog', 'VbzAdminCarts', 'VbzAdminCatalogs', 'clsAdminCustAddrs', 'VbzAdminCustCards', 'clsAdminCustEmails', 'clsAdminCustNames', 'clsAdminCustPhones', 'VbzAdminCusts', 'VbzAdminDepts', 'clsAdminEvents', 'clsAdminImages', 'VbzAdminItems', //'clsAdminItems_info_Cat', 'VbzAdminOrderChgs', 'VbzAdminOrderItems', //'VbzAdminOrderPulls', 'VbzAdminOrders', 'VbzAdminOrderTrxacts', //'VbzAdminOrderTrxTypes', 'VbzAdminOrderMsgs', //'clsAdminRstkReqItems', 'clsAdminRstkReqs', //'VbzAdminSessions', 'VbzAdminStkItems', 'VbzAdminSuppliers', 'VbzAdminTitles', //'VbzAdminTitles_info_Cat', //'VbzAdminTitles_info_Item', //'clsAdminTitleTopic_Titles', //'clsAdminTitleTopic_Topics', 'clsAdminTopics',

//'clsCMITems', 'clsCtgGroups', //'clsCtgTitles', //'clsOrderPullTypes', 'clsPackages', //'clsPkgLines', 'clsShipments', //'clsStkLog', //'clsTitleTopics_base', //'clsRstkRcdLines', 'clsRstkRcds', //'VbzStockBinLog', 'VbzStockBins', 'VbzStockPlaces', ); return $ar;

   }
   /*-----
     PURPOSE: do stuff that only admins are allowed to do
   */
   public function doAdmin() {

global $wgOut; $obj = $this->obj; $tbl = $this->tbl;

$out =NULL; $didPage = FALSE;

if (is_object($obj)) { $out = $obj->AdminPage(); $didPage = TRUE; } elseif (is_object($tbl)) { $out = $tbl->AdminPage(); $didPage = TRUE; }

if (!$didPage) { $page = $this->page; $idObj = $this->idObj; $doObj = $this->doObj;

if (!is_null($page)) { $dbVBZ = $this->DB();

$out = NULL; switch ($page) { case 'cache': case 'cache.tbl': case 'cache.proc': $this->DB()->CacheMgr()->MenuDispatch($page,$idObj); break; case 'cat.search': $tbl = $dbVBZ->Titles_Cat(); $out = $tbl->SearchPage(); break; case 'log.cart': $objTbl = new VbzAdminCartLog($dbVBZ); $out = $objTbl->AdminPage(); break; case 'log.misc': $objLog = new clsAdminEvents($dbVBZ); $objLog->ListPage(); break; case 'migr.encr': $objCards = $dbVBZ->CustCards(); $objCards->EncryptAdmin(); break; case 'rstk.need': $objTbl = $dbVBZ->RstkReqs(); $objTbl->AdminItemsNeeded(); break; case 'rstk.past': $objTbl = $dbVBZ->RstkReqs(); $objRows = $objTbl->RowsInactive(); $out = $objRows->AdminList(); break; case 'rstk-rcd': $objTbl = $dbVBZ->RstkRcds(); $objRow = $objTbl->GetItem($idObj); $out = $objRow->AdminPage(); break; case 'rstk-req': $objTbl = $dbVBZ->RstkReqs(); $objRow = $objTbl->GetItem($idObj); $out = $objRow->AdminPage(); break; case 'rstk.wait': $objTbl = $dbVBZ->RstkReqs(); $objRows = $objTbl->RowsActive(); $out = $objRows->AdminList(); break; case 'toship': $this->doStockToShip(); break; case 'util.stats': $this->DoUpdateStats(); break; case 'util.plist': $this->DoPriceList(); break; case 'util.inv': $this->DoInvCompare(); break; default: $out = 'Select from the menu above.'; } } } if (!is_null($out)) { $wgOut->AddWikiText($out,TRUE); }

   }
   public function doCharges() {

global $wgOut; global $vgPage;

$doAll = $vgPage->Arg('all'); $strMnuAll = $this->SelfLink_WT(array('all' => TRUE),'all'); $strMnuUnp = $this->SelfLink_WT(array('all' => FALSE),'to process');

$objTbl = new VbzAdminOrderChgs($this->DB()); if ($doAll) { $strMenu = "$strMnuUnp .. $strMnuAll"; $strDescr = ' in database'; $sqlFilt = NULL; } else { $strMenu = "$strMnuUnp .. $strMnuAll"; $strDescr = ' to be processed'; $sqlFilt = '(WhenDecided IS NULL) AND ((WhenXmitted IS NULL) OR isSuccess) AND (WhenVoided IS NULL) AND (WhenHeldUp IS NULL)'; } $objRows = $objTbl->GetData($sqlFilt,NULL,'ID DESC'); $wgOut->AddWikiText("Show Charges: $strMenu", TRUE); $arArgs['descr'] = $strDescr; $wgOut->AddWikiText($objRows->AdminTable($arArgs),TRUE);

   }
   public function doUser() {

global $wgOut; /* PURPOSE: do only stuff that regular users are allowed to do

  • /

$wgOut->AddWikiText('Hello regular user! I haven\'t written anything for you yet, but soon (Josh permitting).');

 }

// individual admin functions

   public function doStockToShip() {

global $wgOut;

$dbVBZ = $this->DB(); $out = '==Stock to Ship=='."\n"; $wgOut->addWikiText($out,TRUE); $out = ; $objRows = $dbVBZ->DataSet('SELECT * FROM '.KSQL_DS_ITEMS_TO_SHIP); if ($objRows->hasRows()) { $out = "{| class=sortable \n|-\n! item || order || # needed || # avail || bin"; while ($objRows->NextRow()) { $idItem = $objRows->ID_Item; $idOrd = $objRows->ID_Order; $idBin = $objRows->ID_Bin; $strOrd = $objRows->OrdText?$objRows->OrdText:'?ord#?'; $wtItem = ''.$idItem.' '.SelfLink_Page('item','id',$idItem,$objRows->ItemText); $wtOrder = ''.$idOrd.' '.SelfLink_Page(KS_URL_PAGE_ORDER,'id',$idOrd,$strOrd); $wtBin = ''.$idBin.' '.SelfLink_Page('bin','id',$idBin,$objRows->BinText); $wtQtyNeed = $objRows->QtyOpen; $intQtyForShip = $objRows->QtyForSale; $intQtyForSale = $objRows->QtyForSale; $wtQtyAvail = $intQtyForShip; if ($intQtyForShip != $intQtyForSale) { $wtQtyAvail .= ' ('.$intQtyForSale.')'; } $out .= "\n|-\n| $wtItem || $wtOrder || $wtQtyNeed || $wtQtyAvail || $wtBin"; } $out .= "\n|}\n(Retrieval complete.)"; } else { $out = 'No stock items available for open orders.'; } $wgOut->addWikiText($out,TRUE); $out = ;

   }

/*

   public function doCacheTables() {

$this->DB()->CacheMgr()->AdminPage();

   }
  • /
   public function doSuppliers() {

$objSupps = $this->DB()->Suppliers(); $objSupps->ListPage();

   }
   public function doSupplier($iID) {

$objSupps = $this->DB()->Suppliers(); $objSupp = $objSupps->GetItem($iID); return $objSupp->AdminPage();

   }
   public function doDept($iID) {

$objDepts = $this->DB()->Depts(); $objDept = $objDepts->GetItem($iID); return $objDept->InfoPage();

   }
   public function doTitle($iID) {

$objTitles = $this->DB()->Titles(); $objTitle = $objTitles->GetItem($iID); return $objTitle->InfoPage();

   }
   public function doItem($iID) {

$objTbl = $this->DB()->Items(); $objRow = $objTbl->GetItem($iID); return $objRow->InfoPage();

   }
   public function doImgAdmin() {

$objTbl = $this->DB()->Images(); return $objTbl->AdminPage_Unassigned();

   }
   /*----
     TO DO: This really should be rewritten as a method of clsContactNode
     USED BY: VbzAdminOrder::DoSetupCart() in admin.ord.php
     HISTORY:

2011-04-17 using AdminLink() on customer object instead of hand-building the links

   */
   function CheckPersonMatches(clsPerson $iPerson,VbzAdminCart $iCart) {

$objDB = $this->DB(); $objPage = $this; $objPerson = $iPerson; $objCart = $iCart; //$arLink = $iLinkArr;

$strName = $objPerson->FormName(); $strDescr = $objPerson->Descr();

$objName = $iPerson->Node('name'); if (!is_object($objName)) { echo $iPerson->DumpHTML(); throw new exception('Internal error: missing object in tree.'); } $strCustName = $objName->Value();

$out = "\n


Contact information for $strDescr:"; $out .= "\n

  • Customer: ".$strCustName; $out .= "\n
      "; if ($objCart->DataItem(KSI_SHIP_IS_CARD)) { $strAddrShip = 'Address'; } else { // $strCardAddr = $objPerson->Card->Addr->AsSingleLine(); $objPay = $objPerson->Payment(); if (is_null($objPay)) { /* 2011-10-04 this isn't a problem as long as _one_ of the calls has payment in iPerson echo 'Person object tree:'; echo $objPerson->DumpHTML(); throw new exception('Payment object is NULL'); */ $strCardAddr = NULL; // so later code knows not to try using it } else { $strCardAddr = $objPay->Addr()->AsSingleLine(); $out .= "\n
    • Card Address: ".$strCardAddr.'
    • '; $strAddrShip = 'Shipping Address'; } } if ($objPerson->HasContact()) { $objAddr = $objPerson->Contact()->Addr(); if ($objAddr) { $strShipAddr = $objAddr->AsSingleLine(); $out .= "\n
    • $strAddrShip: ".$strShipAddr.'
    • '; $out .= "\n
      • Searching as: ".clsCustAddrs::Searchable($strShipAddr).'
      ';

      } if ($objPerson->Contact()->HasEmail()) { $strEmail = $objPerson->Contact()->Email()->Value();

      $out .= "\n
    • Email: ".$strEmail.'
    • '; } if ($objPerson->Contact()->HasPhone()) { $strPhone = $objPerson->Contact()->Phone()->Value(); $out .= "\n
    • Phone: ".$strPhone.'
    • '; } } $out .= "\n
    ";

    // Look for matches to existing contacts $out .= "\nChecking $strDescr for matches to existing customers..."; // -- name // --- customer $objRows = $objDB->CustNames()->Find($strCustName); if ($objRows->HasRows()) { while ($objRows->NextRow()) { $idCont = $objRows->ID_Cust; $idName = $objRows->ID; $arSame[$idCont]['name'] = $objRows->RowCopy(); } } // --- destination (if different) if (isset($strDestName)) { $objRows = $objDB->CustNames()->Find($strDestName); if ($objRows->HasRows()) { while ($objRows->NextRow()) { $idCont = $objRows->ID_Cust; $idName = $objRows->ID; $arSame[$idCont]['name'] = $objRows->RowCopy(); } } }

    // -- address // --- card if ($objCart->DataItem(KSI_SHIP_IS_CARD)) { $strAddrShip = 'addr'; } else { $strAddrShip = 'addr-ship'; if (!is_null($strCardAddr)) { $objRows = $objDB->CustAddrs()->Find($strCardAddr); if ($objRows->HasRows()) { while ($objRows->NextRow()) { $idCont = $objRows->ID_Cust; $idName = $objRows->ID; $arSame[$idCont]['addr-card'] = $objRows->RowCopy(); } } } } // --- shipping if (isset($strCardAddr)) { $objRows = $objDB->CustAddrs()->Find($strCardAddr); if ($objRows->HasRows()) { while ($objRows->NextRow()) { $idCont = $objRows->ID_Cust; $idName = $objRows->ID; $arSame[$idCont][$strAddrShip] = $objRows->RowCopy(); } } } if (isset($objPerson->Contact)) { // -- phone if (isset($strPhone)) { $objRows = $objDB->CustPhones()->Find($strPhone); if ($objRows->HasRows()) { while ($objRows->NextRow()) { $idCont = $objRows->ID_Cust; $idName = $objRows->ID; $arSame[$idCont]['phone'] = $objRows->RowCopy(); } } }

    // -- email if (isset($strEmail)) { // sometimes this isn't set; this may be a bug. figure out why later. $objRows = $objDB->CustEmails()->Find($strEmail); if ($objRows->HasRows()) { while ($objRows->NextRow()) { $idCont = $objRows->ID_Cust; $idName = $objRows->ID; $arSame[$idCont]['email'] = $objRows->RowCopy(); } } } } // -- credit card $strCard = $objCart->DataItem(KSI_CUST_CARD_NUM); $objRows = $objDB->CustCards()->Find($strCard); if ($objRows->HasRows()) { while ($objRows->NextRow()) { $idCont = $objRows->ID_Cust; $idName = $objRows->ID; $arSame[$idCont]['card'] = $objRows->RowCopy(); } } // Report any matches found: if (isset($arSame)) { $out .= "\nChoose how to resolve the match:";

    $out .= "\n
      "; foreach ($arSame as $idCont=>$val) { $objCust = $objDB->Custs($idCont); $htLink = $objCust->AdminLink_status(); $out .= "\n
    • <input type=radio name=\"$strName\" value=\"$idCont\">Use contact #$htLink</a>:"; $out .= "\n
        "; foreach($val as $vkey=>$vval) { $strDescr = $vval->ShortDescr(); $out .= "\n
      • $vkey: $strDescr
      • "; } $out .= "\n
    • ";

      }

      $out .= "\n
    • <input type=radio name=\"$strName\" value=\"new\">Create new contact record
    • "; $out .= "\n
    ";

    } else { // 2011-07-28 removing "create new records" link; should be created on import if none found // $htURL = $objPage->SelfURL(array('allnew'=>TRUE)); // $htLink = '<a href="'.$htURL.'">create new records</a>'; $out .= "\n
    No matches found; new contact records will be created."; $out .= '<input type=hidden name="cust" value=new /><input type=hidden name="ship" value=new />'; } return $out;

       }
       protected function DoUpdateStats() {
    

    $objVars = $this->objDB->VarsGlobal();

    $sqlStkQty = 'SELECT SUM(QtyForSale) AS Qty FROM qryStkItms_for_sale'; $intStkQty = 0;

    $objVars->Val('stat.stock.qty',$intStkQty); // total stock quantity

       }
       protected function DoPriceList() {
    

    global $wgOut,$wgRequest; global $vgPage;

    $vgPage->UseHTML();

    $doCheck = $wgRequest->GetBool('btnCheck');

    $out = NULL; $out .= 'Enter catalog numbers or item IDs:';

    if ($doCheck) { $txt = $wgRequest->GetText('list'); $xts = new xtString($txt); $xts->ReplaceSequence("\n\t ", ' ',0); $ar = explode (' ',$xts->Value);

    $pos = strpos ($txt,':'); // colon means there are quantities $hasQtys = is_numeric($pos);

    $htTxt = htmlspecialchars($txt); $htTxtRows = 3; } else { $htTxt = ; $htTxtRows = 30; }

    if ($doCheck) {

    $out .= '';

    } else { $htQtyCol = ; }

    $objDB = $this->DB();

    $out .= '
    ';

    if ($hasQtys) {

    $htQtyCol = '
    Qty'; $out .= ''.$htQtyCol.'';

    $arItems = array(); $arQtys = array(); foreach ($ar as $word) { // if word contains a colon, ignore it and everything after (so we can use that format here even though qty is irrelevant): $pos = strpos ($word,':'); if ($pos) { $qty = substr($word,$pos+1); $word = substr($word,0,$pos); } else { $qty = NULL; } if (is_numeric($word)) { $id = $word; $objItem = $objDB->Items($id);

    if (is_object($objItem)) { $id = $objItem->Value('ID'); if (!array_key_exists($id,$arItems)) { $arItems[$id] = $objItem->Values(); $arCatNums[$objItem->Value('CatNum')] = $id; } $arQtys[$id] = NzArray($arQtys,$id)+$qty;

    } else {

    $out .= "\n" .'';

    } } else { // to be written } }

    ksort($arCatNums);

    foreach ($arCatNums as $catnum => $id) { //echo '
    CATNUM=['.$catnum.'] ID=['.$id.']'; $arVals = $arItems[$id]; $objItem->Values($arVals); // load the row into the object

    $mnSellExact = $objItem->Value('PriceSell'); $mnSellRound = round($mnSellExact) + 1.00;

    $out .= "\n" .'';

    if ($hasQtys) { $qty = $arQtys[$id]; if (is_null($qty)) {

    $out .= '';

    } else {

    $out .= "";

    } } $out .=

    '' .'' .'' .'' .''; } $out .= '
    IDCat #NameExactRounded
    '.$id.'not found
    '.$objItem->AdminLink().'$qty'.$objItem->Value('CatNum').''.$objItem->FullDescr_HTML().''.$mnSellExact.''.$mnSellRound.'
    '; // item listing table $out .= '
    '; // outer table

    }

    $out .= '<form method=post>'; $out .= '<textarea name=list rows='.$htTxtRows.'>'.$htTxt.'</textarea>'; $out .= '<input type=submit name=btnCheck value="Check" />'; $out .= '</form>';

    $wgOut->AddHTML($out); return NULL; // caller expects wikitext

       }
       private function DoInvCompare() {
    

    global $vgPage; global $wgOut,$wgRequest;

    $txtStart = $wgRequest->GetText('txtStart'); $txtFinish = $wgRequest->GetText('txtFinish');

    $vgPage->UseHTML();

    $htStart = htmlspecialchars($txtStart); $htFinish = htmlspecialchars($txtFinish);

    $fxParse = function($iText) { $ar = preg_split('/ /',$iText); foreach ($ar as $item) { list($id,$qty) = preg_split('/:/',$item); $arOut[$id] = $qty; } return $arOut; };

    $arStart = $fxParse($txtStart); $arFinish = $fxParse($txtFinish);

    $arDiff = array(); foreach ($arStart as $id => $qty) { $qtyFinish = nzArray($arFinish,$id); if ($qty != $qtyFinish) { $arDiff[$id] = 'old:'.$qty.' new:'.$qtyFinish; } } foreach ($arFinish as $id => $qty) { $qtyStart = nzArray($arStart,$id); if (!array_key_exists($id,$arStart)) { $arDiff[$id] = 'new:'.$qty; } }

    $out = '<form method=post action="'.$vgPage->SelfURL().'">'; $out .= 'Display difference between two inventory counts:';

    $out .= ''; $out .= ""; $out .= ""; $out .= ''; $out .= '
    Starting inventory:<textarea rows=10 name=txtStart>$txtStart</textarea>Ending inventory:<textarea rows=10 name=txtFinish>$txtFinish</textarea>
    <input type=submit name=btnCalc value="Compare">
    ';

    $out .= '</form>';

    if (count($arDiff) > 0) { $tbl = $this->DB()->Items();

    $out .= ''; foreach ($arDiff as $id => $txt) { $obj = $tbl->GetItem($id); $out .= '';

    }

    $out .= '
    '.$obj->AdminLink_friendly().''.$txt.'
    ';

    } else { $cnt = count($arStart); $out .= $cnt.' item'.Pluralize($cnt).' compared - inventories are identical.'; }

    $wgOut->AddHTML($out); return NULL; // caller expects wikitext

       }
    

    }

    /* *****

    • CATALOG DATA
    • /

    class VbzAdminSuppliers extends clsSuppliers {

       public function __construct($iDB) {
    

    parent::__construct($iDB); $this->ClassSng('VbzAdminSupplier');

       }
       public function AdminPage() {
    

    global $wgOut; global $vgPage;

    $vgPage->UseWiki();

    $out = '==Suppliers=='; $wgOut->addWikiText($out,TRUE); $out = ; $objRecs = $this->GetData(); if ($objRecs->HasRows()) { $out = "{| class=sortable\n|-\n! ID || A? || Code || Actions || Name"; $isOdd = TRUE; while ($objRecs->NextRow()) { $strCatKey = $objRecs->CatKey; $id = $objRecs->ID; $wtActions = '['.KWP_CAT.strtolower($strCatKey)." shop] " .$objRecs->AdminLink('manage'); $wtCatNum = $strCatKey; $wtStyle = $isOdd?'background:#ffffff;':'background:#cccccc;'; $isActive = $objRecs->isActive; if ($isActive) { $wtName = '[['.$objRecs->Name.']]'; } else { $wtName = $objRecs->Name; $wtStyle .= ' color: #888888;'; } $out .= "\n|- style=\"$wtStyle\"\n| ".$id .' || '.($isActive?'√':) .' || '.$wtCatNum .' || '.$wtActions .' || '.$wtName; $isOdd = !$isOdd; } $out .= "\n|}"; } else { $out = 'No suppliers have been created yet.'; } $wgOut->addWikiText($out,TRUE); $out = ;

       }
    

    } class VbzAdminSupplier extends clsSupplier {

       /*====
         HISTORY:
    

    2010-12-05 boilerplate event logging added to VbzAdminSupplier

       */
       protected function Log() {
    

    if (!is_object($this->logger)) { $this->logger = new clsLogger_DataSet($this,$this->objDB->Events()); } return $this->logger;

       }
       public function StartEvent(array $iArgs) {
    

    return $this->Log()->StartEvent($iArgs);

       }
       public function FinishEvent(array $iArgs=NULL) {
    

    return $this->Log()->FinishEvent($iArgs);

       }
       public function EventListing() {
    

    return $this->Log()->EventListing();

       }
       //====
       /*----
         HISTORY:
    

    2010-10-11 Replaced existing code with call to static function

       */
       public function AdminLink($iText=NULL,$iPopup=NULL,array $iarArgs=NULL) {
    

    return clsAdminData::_AdminLink($this,$iText,$iPopup,$iarArgs);

       }
       public function AdminLink_name() {
    

    return $this->AdminLink($this->Name);

       }
       /*----
         HISTORY:
    

    2010-11-04 Created so AdminPage() can use HTML 2011-02-16 Disabled until I figure out why it isn't redundant

       */
    

    /*

       public function ShopLink($iText=NULL) {
    

    return '<a href="'.KWP_CAT.strtolower($this->CatKey).'">'.$iText.'</a>';

       }
    
    • /
       public function PageTitle() {
    

    global $vgPage;

    $doShow = $vgPage->Arg('show'); return $this->Value('CatKey').':'.$doShow;

       }
       /*----
         RETURNS: object for Supplier's Topic
         HISTORY:
    

    2011-10-01 written -- replacing Departments with Topics

       */
       public function TopicObj() {
    

    $id = $this->Value('ID_Topic'); if (is_null($id)) { return NULL; } else { $row = $this->Engine()->Topics($id); return $row; }

       }
       /*----
         RETURNS: nicely-formatted link to Supplier's Topic
         HISTORY:
    

    2011-10-01 written -- replacing Departments with Topics

       */
       public function TopicLink($iNone='n/a') {
    

    $row = $this->TopicObj(); if (is_object($row)) { return $row->AdminLink_name(); } else { return $iNone; }

       }
       /*----
       */
       public function AdminPage() {
    

    global $wgOut,$wgRequest; global $vgPage,$vgOut;

    $vgPage->UseHTML(); $out = NULL;

    $doEdit = $vgPage->Arg('edit'); $doSave = $wgRequest->GetBool('btnSave');

    // save edits before showing events $ftSaveStatus = NULL; if ($doEdit || $doSave) { $this->BuildEditForm(); if ($doSave) { $ftSaveStatus = $this->AdminSave(); } }

    $strCatKey = $this->CatKey; $strName = $this->Name;

    $doDeptAdd = $vgPage->Arg('add.dept');

    $objPage = new clsWikiFormatter($vgPage); $objSection = new clsWikiSection($objPage,$strName.' ('.$strCatKey.')'); $out = $objSection->Generate(); $wgOut->AddHTML($out); $out = ;

    $objSection = new clsWikiSection($objPage,'Current Record (ID '.$this->ID.')',NULL,3); $objSection->ToggleAdd('edit'); $out = $objSection->Generate();

    if ($doEdit) { $out .= $objSection->FormOpen();

    $objForm = $this->objForm; $ftName = $objForm->Render('Name'); $ftCatKey = $objForm->Render('CatKey'); $ftTopic = $objForm->Render('ID_Topic'); $ftActive = $objForm->Render('isActive'); } else { $ftName = $vgOut->InternalLink($strName); $ftCatKey = $this->ShopLink($strCatKey); $ftTopic = $this->TopicLink(); $ftActive = NoYes($this->isActive); }

    $ftID = $this->AdminLink();

    $out .= $vgOut->TableOpen();

    $out .= $vgOut->TblRowOpen(); $out .= $vgOut->TblCell('ID:','align=right'); $out .= $vgOut->TblCell($ftID); $out .= $vgOut->TblRowShut();

    $out .= $vgOut->TblRowOpen(); $out .= $vgOut->TblCell('Name:','align=right'); $out .= $vgOut->TblCell($ftName); $out .= $vgOut->TblRowShut();

    $out .= $vgOut->TblRowOpen(); $out .= $vgOut->TblCell('CatKey:','align=right'); $out .= $vgOut->TblCell($ftCatKey); $out .= $vgOut->TblRowShut();

    $out .= $vgOut->TblRowOpen(); $out .= $vgOut->TblCell('Topic:','align=right'); $out .= $vgOut->TblCell($ftTopic); $out .= $vgOut->TblRowShut();

    $out .= $vgOut->TblRowOpen(); $out .= $vgOut->TblCell('Active:','align=right'); $out .= $vgOut->TblCell($ftActive); $out .= $vgOut->TblRowShut();

    $out .= $vgOut->TableShut();

    if ($doEdit) { $out .= 'Edit notes: <input type=text name="EvNotes" size=40>
    '; $out .= '<input type=submit name="btnSave" value="Save">'; $out .= '<input type=submit name="btnCancel" value="Cancel">'; $out .= '<input type=reset value="Reset">'; $out .= '</form>'; }

    $vgOut->addText($out,TRUE); $out = ;

    // show submenu $arMnu = array( 'dept' => '.departments.'.$strName.' departments', 'cat' => '.catalogs.'.$strName.' wholesale catalogs', 'rreq' => '.restocks.'.$strName.' restock requests', 'ctg' => '.catalog groups.groups for organizing '.$strName.' catalog items' ); $out = 'Manage: '.$vgPage->SelfLinkMenu('show',$arMnu); $vgOut->AddText($out); $out = ;

    $doShow = $vgPage->Arg('show');

    //$vgPage->UseWiki(); switch ($doShow) { /* Some remediation needed here. Some of these output in wikitext, others in HTML.

    All of them seem to output directly, rather than returning rendered text.
    
    • /

    case 'dept': $objSection = new clsWikiSection($objPage,'Departments',NULL,3); $objSection->ToggleAdd('add','add a department to '.$strName,'add.dept'); $out = $objSection->Generate(); $wgOut->addHTML($out,TRUE); $out = ; $out .= $this->DeptsListing(); break; case 'cat': $objSection = new clsWikiSection($objPage,'Catalogs',NULL,3); $arLink = array( 'page' => $this->objDB->CtgSrcs()->ActionKey(), 'id' => 'new', 'supp' => $this->ID ); $objSection->ActionAdd('add','add a catalog to '.$strName,FALSE,$arLink); $out = $objSection->Generate(); $wgOut->addHTML($out,TRUE); $out = ; $out .= $this->CatalogAdmin(); break; case 'rreq': $objSection = new clsWikiSection($objPage,'Restock Requests',NULL,3); $out = $objSection->Generate(); $wgOut->addHTML($out,TRUE); $out = ; $out .= $this->RstkReqAdmin(); break; case 'ctg': $objSection = new clsWikiSection($objPage,'Catalog Groups','catalog management groups',3); $objSection->ArgsToKeep(array('show','page','id')); $objSection->ToggleAdd('edit','edit the list of groups','edit.ctg'); $out = $objSection->Generate(); $wgOut->addHTML($out,TRUE); $out = ; $doEdit = $vgPage->Arg('edit.ctg'); $out .= $this->CtgGrpAdmin($doEdit); break; default: $out = ; } $vgOut->addText($out);

       }
       /*----
         ACTION: Save user changes to the record
         HISTORY:
    

    2010-11-06 copied from VbzStockBin to VbzAdminItem 2011-01-26 copied from VbzAdminItem to clsAdminTopic 2011-10-02 copied from clsAdminTopic to VbzAdminSupplier

       */
       public function AdminSave() {
    

    global $vgOut;

    $out = $this->objForm->Save(); $vgOut->AddText($out);

       }
       /*----
         HISTORY:
    

    2010-11-06 adapted from VbzStockBin for VbzAdminTitle 2011-10-01 adapted from VbzAdminTitle for VbzAdminSupplier

       */
       private function BuildEditForm() {
    

    global $vgOut;

    if (is_null($this->objForm)) { // create fields & controls $objForm = new clsForm_DataSet($this,$vgOut); //$objCtrls = new clsCtrls($objForm->Fields()); //$objCtrls = $objForm;

    $objForm->AddField(new clsField('Name'), new clsCtrlHTML(array('size'=>25))); $objForm->AddField(new clsFieldNum('ID_Topic'), new clsCtrlHTML()); $objForm->AddField(new clsField('CatKey'), new clsCtrlHTML(array('size'=>8))); $objForm->AddField(new clsFieldBool('isActive'), new clsCtrlHTML_CheckBox()); $objForm->AddField(new clsField('Notes'), new clsCtrlHTML_TextArea(array('height'=>3,'width'=>50)));

    $this->objForm = $objForm; //$this->objCtrls = $objCtrls; }

       }
       public function DeptsListing() {
    

    $out = $this->objDB->Depts()->Listing_forSupp($this->ID,$this); return $out;

       }
     /*%%%%
       SECTION: Data Entry Management
       PROCESS:
         * User enters a list of Titles or Items in a textarea box, one per line.
         * Each line is checked against Supplier catalog #s
         * if found, shows details for the title/item and provides option to approve it in the final resultset
         * if not found, gives user the option to give more information identifying the Title/Item, such as
    

    our catalog # (or what our catalog # would be if the Title/Item existed in the database)

     */
       /*----
         PURPOSE: renders form for reconciliation of a user-entered list of Titles from a Supplier source document
         INPUT:
    

    $iTitles[line #] = array of title information, format to be determined ['id'] = ID of Title record to be approved as matching the input ['scat'] = supplier's catalog number ['ocat'] = our catalog number (may be hypothetical) ['$buy'] = cost to us ['$sell'] = our selling price (to customer) ['name'] = descriptive name for the Title

         RETURNS: HTML code for reconciliation form. Does not include <form> tags or buttons.
       */
    

    /*

       public function AdminTitles_form_entry(array $iTitles) {
    

    die('This function is not ready yet!');

    if (count($iTitles) > 0) { $isOdd = TRUE; $isReady = TRUE; // ready to enter - all items have been identified

    $out .= '';

    foreach ($iTitles as $cnt => $data) { $ftStyle = $isOdd?'background:#ffffff;':'background:#eeeeee;'; $htAttr = ' style="'.$ftStyle.'"'; $isOdd = !$isOdd;

    $strScat = nz($data['scat']); $strInvTitle = nz($data['title']); $strPrBuy = nz($data['$buy']); $strPrSell = nz($data['$sell']); $strQty = nz($arOut['qty']);

    $out .= "<tr$htAttr>";

    } } else { $out = 'No titles entered.'; }

       }
    
    • /
       /*----
         PURPOSE: renders form for reconciliation of a user-entered list of Items from a Supplier source document
    

    (same as AdminTitles_form_entry() but for Items instead of Titles)

         ACTION: Renders an Item-reconciliation form
         INPUT: output from AdminItems_data_check()
         OUTPUT: returned data
         RETURNS: HTML of form containing data AdminItems_form_receive() is expecting to see
       */
       public function AdminItems_form_entry(array $iData) {
    

    $cntItems = count($iData);

    if ($cntItems > 0) { $strPfx = $this->Value('CatKey'); $isOdd = TRUE;

    $out = '
    IDCat#TitleQtyPrice
    $strScat$strInvTitle$strQty$strPrice
    ' .'' .'' .'' .'' .'' .'' .'' .'' .'' .''; foreach ($iData as $idx => $row) { $ftStyle = $isOdd?'background:#ffffff;':'background:#eeeeee;'; $htAttr = ' style="'.$ftStyle.'"'; $isOdd = !$isOdd; $idItem = nz($row['id']); $strOCat = nz($row['ocat']); $strSCat = nz($row['scat']); $strInvTitle = nz($row['name']); $strPrBuy = nz($row['$buy']); $strPrSell = nz($row['$sell']); $strQty = nz($row['qty']); $objItem = $row['@obj']; $htOCat = $strOCat; $htItem = NULL; $cnOCat = "ocat[$idx]"; $canUpdSCat = FALSE; $canUpdDescr = FALSE; if (is_null($objItem)) { //$cntNoItem++; if (!empty($strOCat)) { $arOkAdd[$idx] = $data; } // let user enter our catalog # $htOCat = $strPfx.'-<input name="'.$cnOCat.'" size=15 value="'.htmlspecialchars($strOCat).'">'; } else { $data['obj'] = $objItem; $arOkFnd[$idx] = $data; $strOCat = $objItem->Value('CatNum'); $idItem = $objItem->KeyValue(); $htOCat = $strOCat.'<input type=hidden name="'.$cnOCat.'" value="'.htmlspecialchars($strOCat).'">'; $htItem = $objItem->AdminLink().'<input type=hidden name="id['.$idx.']" value="'.$idItem.'">'; $htOCat = $strOCat; // compare entered values with recorded values // -- supplier catalog # $strSCatEnt = $strSCat; // entered $strSCatRec = $objItem->Supp_CatNum; // recorded if ($strSCatEnt != $strSCatRec) { $canUpdSCat = TRUE; } // -- title $strDescrEnt = $strInvTitle; // entered $strDescrRec = $objItem->Descr; // recorded if ($strDescrEnt != $strDescrRec) { $canUpdDescr = TRUE; } } $htSCat = $strSCat.'<input type=hidden name="scat['.$idx.']" value="'.htmlspecialchars($strSCat).'">'; if ($canUpdSCat) { if (empty($strSCatRec)) { $strAct = 'save this'; } else { $strAct = 'replace '.$strSCatRec.''; } $htSCat .= '
    <input type=checkbox name="do-upd-scat['.$idx.']">'.$strAct.''; } $htName = $strInvTitle.'<input type=hidden name="name['.$idx.']" value="'.htmlspecialchars($strInvTitle).'">'; if ($canUpdDescr) { if (empty($strDescrRec)) { $strAct = 'save this'; } else { $strAct = 'replace '.$strDescrRec.''; } $htName .= '
    <input type=checkbox name="do-upd-desc['.$idx.']">'.$strAct.''; } $htQty = $strQty.'<input type=hidden name="qty['.$idx.']" value='.$strQty.'>'; $htPrBuy = $strPrBuy.'<input type=hidden name="$buy['.$idx.']" value="'.$strPrBuy.'">'; $htPrSell = $strPrSell.'<input type=hidden name="$sell['.$idx.']" value="'.$strPrSell.'">'; switch ($row['@state']) { case 'use': $htStatus = 'ready'; break; case 'add': $htStatus = 'addable'; break; default: $htStatus = '?'; } $out .= "\n<tr$htAttr>" ."\n\t" ."\n\t" ."\n\t" ."\n\t" ."\n\t" ."\n\t" ."\n\t" ."\n\t" ."\n\t" ."\n\t"; } $out .= '
    statusIDOur Cat#SCat#WhatQty$buy$sell
    $idx.$htStatus$htItem$htOCat$htSCat$htName$htQty$htPrBuy$htPrSell
    ';

    } else { $out = 'No titles entered.'; } return $out;

       }
       /*----
         ACTION: Receives user data from form rendered by AdminItems_form_entry()
         INPUT: http POST data from Item reconciliation form
    

    id[line #] = array of Item IDs, where known name[line #] = array of item descriptions qty[line #] = array of item quantities scat[line #] = array of supplier catalog numbers for each line, entered by user ocat[line #] = array of our catalog numbers for each line, entered by user $buy[line #] = array of price-to-us for each line, entered by user $sell[line #] = array of price-to-customer for each line, entered by user

         NOTE: sell[] is not currently used in any known scenario. Possibly it should be removed.
         RETURNS: array of all received data, but indexed by line number first
    

    includes the following fields: ['qty'] = item quantity ['ocat'] = catalog number entered by the user to be used either for looking up the item or creating it

         FUTURE: This should be generalized somehow
      */
       public function AdminItems_form_receive() {
    

    global $wgRequest;

    $arCols = array('id','name','qty','ocat','scat','$buy','$sell','do-upd-scat','do-upd-desc'); foreach ($arCols as $col) { $arOut[$col] = $wgRequest->GetArray($col); } $arRtn = ArrayPivot($arOut);

    //echo '
    '.print_r($arRtn,TRUE).'
    ';

    return $arRtn;

       }
       /*----
         ACTION: Check item data against database and return status information
         INPUT:
    

    $iItems[line #]: array in format returned by AdminItems_form_receive()

         RETURNS:
    

    ['#add'] = number of rows which need to be added to the catalog ['#use'] = number of rows which are ready to be used (item exists in catalog) ['rows'] = input data with additional fields: ['@state']: status of line as indicated by one of the following strings: 'use' = item has been found, so this line is ready to use 'add' = item not found, but there is enough information to create it ['@obj'] is the Item object (only included if @state = 'use')

       */
       public function AdminItems_data_check(array $iItems) {
    

    if (count($iItems) > 0) { $cntUse = 0; $cntAdd = 0; $cntUpd = 0; // count of updatable fields $arRows = array(); $strCatPfx = $this->Value('CatKey'); foreach ($iItems as $idx => $data) { $idItem = nz($data['id']);

    $strOCatRaw = nz($data['ocat']); $strOCatFull = $strCatPfx.'-'.$strOCatRaw; $gotOCat = !empty($strOCatRaw);

    $strSCat = nz($data['scat']);

    $data['@state'] = NULL; $data['@obj'] = NULL; if (empty($idItem)) { if ($gotOCat) { // look up item using our catalog # $objItem = $this->objDB->Items()->Get_byCatNum($strOCatFull); } else { // look up item using supplier catalog # $objItem = $this->GetItem_bySCatNum($strSCat); } if (is_null($objItem)) { if ($gotOCat) { $data['@state'] = 'add'; $cntAdd++; } } } else { $objItem = $this->objDB->Items($idItem); } if (is_object($objItem)) { $data['@obj'] = $objItem; $data['@state'] = 'use'; $cntUse++;

    // compare entered values with recorded values // -- supplier catalog # $strSCatEnt = $strSCat; // entered $strSCatRec = $objItem->Supp_CatNum; // recorded if ($strSCatEnt != $strSCatRec) { $cntUpd++; $data['@can-upd-scat'] = TRUE; } else { $data['@can-upd-scat'] = FALSE; } // -- title $strDescrEnt = nz($data['name']); // entered $strDescrRec = $objItem->Descr; // recorded if ($strDescrEnt != $strDescrRec) { $cntUpd++; $data['@can-upd-desc'] = TRUE; } else { $data['@can-upd-desc'] = FALSE; } } $arRows[$idx] = $data; } // foreach ($iItems...) } else { $arRtn = NULL; } $arRtn = array( 'rows' => $arRows, '#use' => $cntUse, '#upd' => $cntUpd, '#add' => $cntAdd); return $arRtn;

       }
       /*----
         ACTION: Creates listed catalog items
         INPUT: Array of items as returned by AdminItems_data_check()
         RETURNS: HTML to display (messages)
       */
       public function AdminItems_data_add(array $iItems) {
    

    $out = ;

    $tblItems = $this->objDB->Items();

    $cntItems = count($iItems); $txtOCats = ; foreach ($iItems as $idx => $row) { $txtOCats .= ' '.$row['ocat']; } $strEv = 'Adding '.$cntItems.' item'.Pluralize($cntItems).':'.$txtOCats;

    $arEv = array( 'descr' => SQLValue($strEv), 'where' => SQLValue(__METHOD__), 'code' => SQLValue('RI+') // Reconcile Items: add ); $this->StartEvent($arEv);

    $strCatPfx = $this->Value('CatKey'); foreach ($iItems as $idx => $row) { $strOCat = $strCatPfx.'-'.strtoupper($row['ocat']); $arAdd = array( 'CatNum' => SQLValue($strOCat), 'isCurrent' => 'FALSE', // we don't actually know anything about availability yet 'ID_Title' => 0, // needs to be assigned to a title 'Descr' => SQLValue($row['name']), 'Supp_CatNum' => SQLValue($row['scat']) ); if (!empty($row['$buy'])) { $arAdd['PriceBuy'] = SQLValue($row['$buy']); } if (!empty($row['$sell'])) { $arAdd['PriceSell'] = SQLValue($row['$sell']); }

    //$out .= '
    '.print_r($arAdd,TRUE).'
    ';

    $tblItems->Insert($arAdd); } $out = $strEv; $this->FinishEvent(); return $out;

       }
       /*----
         ACTION: Renders drop-down box of all Suppliers, with the current one as default
         USED BY: Restock edit screen
         HISTORY:
    

    2011-03-02 What happened? Apparently this method used to exist, but got deleted without a trace. Rewriting from scratch.

       */
       public function DropDown($iName=NULL,$iNone=NULL) {
    

    $strName = is_null($iName)?($this->Table->ActionKey()):$iName; // control name defaults to action key

    $rs = $this->Table->GetData();

    if ($rs->HasRows()) { $out = "\n<SELECT NAME=$strName>"; if (!is_null($iNone)) { $out .= DropDown_row(NULL,$iNone,$iDefault); } while ($rs->NextRow()) { $id = $rs->Value('ID'); $txtAbbr = $rs->Value('CatKey'); $htAbbr = is_null($txtAbbr)?:($txtAbbr.' '); $htShow = $htAbbr.$rs->Value('Name'); $out .= DropDown_row($id,$htShow,$this->Value('ID')); } $out .= "\n</select>"; return $out; } else { return NULL; }

       }
       /*----
         ACTION: Renders drop-down box of active departments for this supplier
         RETURNS: HTML code
       */
       public function Depts_DropDown($iName=NULL,$iDefault=NULL,$iNone=NULL) {
    

    $objRecs = $this->objDB->Depts()->Data_forSupp($this->ID,'isActive'); $out = $objRecs->DropDown($iName,$iDefault,$iNone); return $out;

       }
       public function CatalogAdmin() {
    

    $objTbl = $this->objDB->Catalogs(); $objRows = $objTbl->GetData('ID_Supplier='.$this->ID,NULL,'ID DESC'); $out = $objRows->AdminList(); return $out;

       }
       public function RstkReqAdmin() {
    

    $objTbl = $this->objDB->RstkReqs(); $objRows = $objTbl->GetData('ID_Supplier='.$this->ID,NULL,'IFNULL(WhenOrdered,WhenCreated) DESC'); $out = $objRows->AdminList(); return $out;

       }
       public function CtgGrpAdmin($iEdit) {
    

    $objTbl = $this->objDB->CtgGrps(); $id = $this->KeyValue(); $objRows = $objTbl->GetData('ID_Supplier='.$id,NULL,'Sort'); $out = $objRows->AdminList($iEdit,array('ID_Supplier'=>$id)); return $out;

       }
       /*-----
         ACTION: Finds the last restock request for the given supplier
         RETURNS: the last request by date and the last request sorted by (our) PO #
       */
       public function LastReq() {
    

    //$sqlBase = 'SELECT * FROM `rstk_req` WHERE ID_Supplier='.$this->ID; $sqlBase = 'WHERE ID_Supplier='.$this->ID; $sql = $sqlBase.' ORDER BY PurchOrdNum DESC LIMIT 1;'; //$objRow = $this->objDB->DataSet($sql); $objRow = $this->objDB->RstkReqs()->DataSet($sql); $objRow->NextRow(); $arOut['by purch ord'] = $objRow->RowCopy();

    $sql = $sqlBase.' ORDER BY WhenOrdered DESC LIMIT 1;'; //$objRow = $this->objDB->DataSet($sql); $objRow = $this->objDB->RstkReqs()->DataSet($sql); $objRow->NextRow(); $arOut['by ord date'] = $objRow->RowCopy();

    return $arOut;

       }
       /*----
         ACTION: Checks each item in the list to see if it corresponds to a given item for the current supplier
         INPUT: Array of supplier catalog numbers
         OUTPUT: Array in this format:
    

    array[cat#] = item object (if found) or NULL (if not found)

       */
    

    /*

       public function FindItems(array $iList) {
    

    $objTblItems = $this->objDB->Items(); foreach ($iList as $catnum) { $strCat = rtrim($catnum,';#!'); // remove comments $strCat = trim($strCat); // remove leading & trailing whitespace if (!empty($strCat)) { $sqlFind = 'Supp_CatNum="'.$strCat.'"'; $objItem = $objTblItems->GetData($sqlFind); if (is_null($objItem)) { $arOut[$strCat] = NULL; } else { $arOut[$strCat] = $objItem->RowCopy(); } } } return $arOut;

       }
    
    • /
       // DEPRECATED - use GetItem_bySCatNum()
       public function FindItem($iCatNum) { return $this->GetItem_bySCatNum($iCatNum); }
    

    }

    class VbzAdminDepts extends clsDepts {

       public function __construct($iDB) {
    

    parent::__construct($iDB); $this->ClassSng('VbzAdminDept');

       }
       public function Data_forSupp($iSupp,$iFilt=NULL) {
    

    $sqlFilt = "ID_Supplier=$iSupp"; if (!is_null($iFilt)) { $sqlFilt = "($sqlFilt) AND ($iFilt)"; } $objRecs = $this->GetData($sqlFilt,NULL,'isActive, Sort, CatKey, PageKey'); return $objRecs;

       }
       public function Listing_forSupp($iSuppID,clsSupplier $iSuppObj=NULL) {
    

    global $wgOut;

    if (is_null($iSuppObj)) { $objSupp = $this->objDB->Suppliers()->GetItem($iSuppID); } else { $objSupp = $iSuppObj; } $strSuppKey = strtolower($objSupp->CatKey);

    $objRecs = $this->GetData('ID_Supplier='.$iSuppID,'VbzAdminDept','isActive, Sort, CatKey, PageKey'); if ($objRecs->HasRows()) { $out = "{| class=sortable\n|-\n! ID || A? || Cat || Page || Sort || Name || Description"; $isOdd = TRUE; while ($objRecs->NextRow()) { $strPageCode = $objRecs->PageKey; if (is_null($strPageCode)) { $wtPageCode = $strPageCode; } else { $strPagePath = $strSuppKey.'/'.strtolower($strPageCode); $wtPageCode = '['.KWP_CAT.$strPagePath.' '.$strPageCode.']'; } $id = $objRecs->ID; $wtID = SelfLink_Page('dept','id',$id,$id); $wtStyle = $isOdd?'background:#ffffff;':'background:#cccccc;'; $isActive = $objRecs->isActive; if (!$isActive) { $wtStyle .= ' color: #888888;'; } $out .= "\n|- style=\"$wtStyle\"". "\n| ".$wtID. ' || '.($isActive?'√':). ' || '.$objRecs->CatKey. ' || '.$wtPageCode. ' || '.$objRecs->Sort. ' || '.$objRecs->Name. ' || '.$objRecs->Descr; $isOdd = !$isOdd; } $out .= "\n|}"; } else { $out = 'This supplier has no departments.'; } $wgOut->addWikiText($out,TRUE); $out = ;

       }
    

    } class VbzAdminDept extends clsDept {

       /*----
         HISTORY:
    

    2010-10-11 Replaced existing code with call to static function

       */
       public function AdminLink($iText=NULL,$iPopup=NULL,array $iarArgs=NULL) {
    

    return clsAdminData::_AdminLink($this,$iText,$iPopup,$iarArgs);

       }
       public function AdminLink_name() {
    

    $strPgKey = strtoupper($this->Value('PageKey')); $out = (is_null($strPgKey))?:($strPgKey.' '); $out .= $this->Value('Name'); return $this->AdminLink($out);

       }
       public function DropDown($iName=NULL,$iDefault=NULL,$iNone=NULL) {
    

    $strName = is_null($iName)?($this->Table->ActionKey()):$iName; // control name defaults to action key

    if ($this->HasRows()) { $out = "\n<SELECT NAME=$strName>"; if (!is_null($iNone)) { $out .= DropDown_row(NULL,$iNone,$iDefault); } while ($this->NextRow()) { $id = $this->ID; $htAbbr = (is_null($this->PageKey))?:($this->PageKey.' '); $htShow = $htAbbr.$this->Name; $out .= DropDown_row($id,$htShow,$iDefault); } $out .= "\n</select>"; return $out; } else { return NULL; }

       }
    

    /* 2010-11-06 commenting out old event handling

       public function StartEvent($iWhere,$iCode,$iDescr,$iNotes=NULL) {
    

    $arEvent = array( 'type' => clsEvents::kTypeDept, 'id' => $this->ID, 'where' => $iWhere, 'code' => $iCode, 'descr' => $iDescr ); if (!is_null($iNotes)) { $arEvent['notes'] = $iNotes; } $this->idEvent = $this->objDB->Events()->StartEvent($arEvent);

       }
       public function FinishEvent() {
    

    $this->objDB->Events()->FinishEvent($this->idEvent);

       }
    
    • /
       /*----
         HISTORY:
    

    2010-10-20 changing event logging to use helper class 2010-11-07 added StartEvent(), FinishEvent()

       */
       protected function Log() {
    

    if (!is_object($this->logger)) { $this->logger = new clsLogger_DataSet($this,$this->objDB->Events()); } return $this->logger;

       }
       public function StartEvent(array $iArgs) {
    

    return $this->Log()->StartEvent($iArgs);

       }
       public function FinishEvent(array $iArgs=NULL) {
    

    return $this->Log()->FinishEvent($iArgs);

       }
       public function EventListing() {
    

    return $this->Log()->EventListing(); /* $objTbl = $this->objDB->Events(); $objRows = $objTbl->GetData('(ModType="'.clsEvents::kTypeDept.'") AND (ModIndex='.$this->ID.')'); if ($objRows->HasRows()) { $out = $objRows->AdminRows(); } else { $out = 'No events found for this department.'; } return $out;

    • /
       }
       /*----
         HISTORY:
    

    2011-09-25 renamed from InfoPage() to AdminPage()

       */
       public function AdminPage() {
    

    global $wgOut,$wgRequest; global $vgPage;

    $strCatKey = $this->CatKey; $strPageKey = $this->PageKey; if (empty($strPageKey)) { $strShopKey = strtolower($strCatKey); } else { $strShopKey = strtolower($strPageKey); } $strAction = $vgPage->Arg('do'); $doEdit = ($strAction == 'edit'); $doEnter = ($strAction == 'enter');

    $doTitleCheck = $wgRequest->GetBool('btnCheck'); $doTitleAdd = $wgRequest->GetBool('btnAdd'); $doEnterBox = $doEnter || $doTitleCheck || $doTitleAdd;

    $strTitle = '“'.$this->Name.'” Department';

    $vgPage->UseHTML(); $objPage = new clsWikiFormatter($vgPage); //$objSection = new clsWikiAdminSection($strName); $objSection = new clsWikiSection($objPage,$strTitle); //$out = $objSection->HeaderHtml_Edit(); $objSection->ActionAdd('edit'); $objSection->ActionAdd('enter','enter titles for this department'); $out = $objSection->Generate();

    $wgOut->AddHTML($out); $out = ;

    if ($doEnterBox) {

    $out = '

    Enter Titles

    ';

    $doShowForm = $doEnter || $doTitleCheck; if ($doShowForm) { $out .= $objSection->FormOpen(); } $txtNotes = $wgRequest->GetText('notes'); $htNotes = 'Notes: <input type=text name=notes size=25 value="'.htmlspecialchars($txtNotes).'">'; if ($doEnter) { // STAGE 1: display form for entering titles $out .= 'Enter titles to check:
    '; $out .= '<textarea name=titles cols=5 rows=30></textarea>'; $out .= '
    '.$htNotes; $out .= '
    <input type=submit name="btnCheck" value="Check">'; } elseif ($doTitleCheck) { // STAGE 2: check entered titles, allow user to fix problems & confirm $strTitles = $wgRequest->getText('titles'); //$arTitles = $this->ParseSubmittedTitles($strTitles); $arTitles = ParseTextLines($strTitles); if (is_array($arTitles)) { $doDeptOnly = $this->AffectsCatNum();

    $out .= ''; foreach ($arTitles as $strCatKey=>$strName) { $sqlFilt = ; if ($doDeptOnly) { $sqlFilt = '(ID_Dept='.$this->ID.') AND '; } $sqlFilt .= 'CatKey='.SQLValue($strCatKey); $objTitles = $this->objDB->Titles()->GetData($sqlFilt); if ($objTitles->HasRows()) { $htStatus = ; $htMatches = ; while ($objTitles->NextRow()) { $htTitle = $objTitles->AdminLink($objTitles->CatNum()).': '.$objTitles->Name; $htMatches .= '';

    } } else {

    $htStatus = '';

    $htMatches = ; }

    $out .= ''.$htStatus.'';

    $out .= $htMatches; }

    $out .= '
    '.$htTitle.'
    new
    '.$strCatKey.''.$strName.'
    ';

    } $out .= $htNotes.'
    '; $out .= '<input type=hidden name="titles" value="'.htmlspecialchars($strTitles).'">'; $out .= '<input type=submit name="btnAdd" value="Add Titles">'; } else { // STAGE 3; process entered titles -- add them to the data: $strTitles = $wgRequest->getText('titles'); $arTitles = $this->ParseSubmittedTitles($strTitles); $cntTitles = count($arTitles); $strAddText = 'Add '.$cntTitles.' title'.Pluralize($cntTitles); $this->StartEvent(__METHOD__,'ADD',$strAddText,$txtNotes);

    $out .= ''; $objTitles = $this->objDB->Titles(); foreach ($arTitles as $strCatKey=>$strName) { $idTitle = $objTitles->Add($strCatKey,$strName,$this->ID,$txtNotes); $objTitle = $this->objDB->Titles()->GetItem($idTitle); $out .= '';

    }

    $out .= '
    '.$objTitle->AdminLink($objTitle->CatNum()).''.$objTitle->Name.'
    ';

    $this->FinishEvent(); } if ($doShowForm) { $out .= '<input type=submit name="btnCancel" value="Cancel">'; $out .= '<input type=reset value="Reset">'; $out .= '</form>'; }

    $out .= '
    ';

    $wgOut->AddHTML($out); $out = ; }

    if ($doEdit) { $out .= $objSection->FormOpen(); } else { }

    $vgPage->UseWiki(); $out .= "\n* ID: ".$this->ID; $out .= "\n* Supplier: ".$this->SuppObj()->AdminLink_name(); $out .= "\n* CatKey: $strCatKey"; $out .= "\n* PageKey: $strPageKey"; $out .= "\n* Shop: [".$this->URL_Abs().' '.$this->URL_Rel().']'; $out .= "\n===Titles==="; $wgOut->addWikiText($out,TRUE); $out = ; $out = $this->TitleListing(); $wgOut->addWikiText($out,TRUE); $out = ;

    if ($doEdit) { $out .= '<input type=submit name="btnSave" value="Save">'; $out .= '<input type=submit name="btnCancel" value="Cancel">'; $out .= '<input type=reset value="Reset">'; $out .= '</form>'; } $wgOut->AddHTML($out); $out = ; $wgOut->addWikiText('===Events===',TRUE); $out = $this->EventListing(); $wgOut->addWikiText($out,TRUE);

       }
       public function TitleListing() {
    

    $out = $this->objDB->Titles_Item()->Listing_forDept($this); return $out;

       }
       /*----
         ACTION: Add a list of titles to this department
         INPUT:
    

    iTitles: array iTitles[catkey] = name iEvent: array to be passed to event log

       */
       public function AddTitles(array $iTitles,array $iEvent=NULL) {
    

    $cntTitles = count($iTitles); if ($cntTitles > 0) { $strDescr = 'adding '.$cntTitles.' title'.Pluralize($cntTitles); $iEvent['descr'] = StrCat($iEvent['descr'],$strDescr,' '); $iEvent['where'] = nz($iEvent['where'],__METHOD__); $iEvent['code'] = 'ADM'; // add multiple $this->StartEvent($iEvent); $cntAdded = 0; $cntError = 0; $txtAdded = ; $txtError = ; $tblTitles = $this->objDB->Titles(); foreach ($iTitles as $catnum => $name) { $arIns = array( 'Name' => SQLValue($name), 'CatKey' => SQLValue($catnum), 'ID_Dept' => $this->ID, 'DateAdded' => 'NOW()' ); $ok = $tblTitles->Insert($arIns); if ($ok) { $idNew = $tblTitles->LastID(); $cntAdded++; $txtAdded .= '['.$catnum.' ID='.$idNew.']'; } else { $cntError++; $txtError .= '['.$catnum.' Error: '.$this->objDB->getError().']'; } } if ($cntError > 0) { $txtDescr = $cntError.' error'.Pluralize($cntError).': '.$txtError; $txtDescr .= ' and '; } else { $txtDescr = 'Success:'; } $txtDescr .= $cntAdded.' title'.Pluralize($cntAdded).' added '.$txtAdded; $arEv = array( 'descrfin' => SQLValue($txtDescr), 'error' => SQLValue($cntError > 0) ); $this->FinishEvent($arEv); }

       }
    

    } class VbzAdminTitles extends clsVbzTitles {

       public function __construct($iDB) {
    

    parent::__construct($iDB); $this->ClassSng('VbzAdminTitle'); $this->ActionKey('title');

       }
       public function Add($iCatKey,$iName,$iDept,$iNotes) {
         // log start of event
    

    $arEvent = array( 'type' => clsEvents::kTypeTitle, 'id' => NULL, 'where' => __METHOD__, 'code' => 'add', 'descr' => 'new title in dept. '.$iDept.': '.$iCatKey.': '.$iName ); if (!is_null($iNotes)) { $arEvent['notes'] = $iNotes; } $idEvent = $this->objDB->Events()->StartEvent($arEvent);

         // add the title record
    

    $arIns = array( 'CatKey' => SQLValue($iCatKey), 'Name' => SQLValue($iName), 'ID_Dept' => $iDept, 'DateAdded' => 'NOW()' ); $this->Insert($arIns); $idTitle = $this->objDB->NewID(__METHOD__);

         // log the event's completion
    

    $arUpd = array('id' => $idTitle); $this->objDB->Events()->FinishEvent($idEvent,$arUpd); return $idTitle;

       }
       /*----
         HISTORY:
    

    2010-11-15 Changed to use qryTitles_Item_info instead of qryCat_Titles_Item_stats

       */
       public function Data_Imageless() {
    

    //$sql = 'SELECT t.ID_Title AS ID, t.* FROM `qryCat_Titles_Item_stats` AS t LEFT JOIN `cat_images` AS i ON t.ID_Title=i.ID_Title' $sql = 'SELECT t.* FROM `qryTitles_Item_info` AS t LEFT JOIN `cat_images` AS i ON t.ID=i.ID_Title' .' WHERE (i.ID IS NULL) AND (cntForSale > 0)'; $this->ClassSng('VbzAdminTitle_info_Item'); $objRows = $this->DataSQL($sql); return $objRows;

       }
    

    } class VbzAdminTitle extends clsVbzTitle {

       /*----
         HISTORY:
    

    2010-10-20 changing event logging to use helper class 2010-11-08 conversion complete: added StartEvent() and FinishEvent(), deleted commented code

       */
       //----
       // BOILERPLATE: event logging
       protected function Log() {
    

    if (!is_object($this->logger)) { $this->logger = new clsLogger_DataSet($this,$this->objDB->Events()); } return $this->logger;

       }
       public function EventListing() {
    

    return $this->Log()->EventListing();

       }
       public function StartEvent(array $iArgs) {
    

    return $this->Log()->StartEvent($iArgs);

       }
       public function FinishEvent(array $iArgs=NULL) {
    

    return $this->Log()->FinishEvent($iArgs);

       }
       // BOILERPLATE: admin HTML
       /*----
         HISTORY:
    

    2010-10-11 Replaced existing code with call to static function

       */
       public function AdminLink($iText=NULL,$iPopup=NULL,array $iarArgs=NULL) {
    

    return clsAdminData::_AdminLink($this,$iText,$iPopup,$iarArgs);

       }
       public function AdminLink_name() {
    

    return $this->AdminLink($this->Value('Name'));

       }
       public function AdminURL(array $iArgs=NULL) {
    

    return clsAdminData::_AdminURL($this,$iArgs);

       }
       // END BOILERPLATE
       //----
       /*----
         ACTION:
    

    Return the current title name If a value is given, update it to the new value first (returns old value) If an event array is given, log the event

         HISTORY:
    

    2010-11-07 adapted from clsItem::SCatNum()

       */
       public function Name($iVal=NULL,array $iEvent=NULL) {
    

    $strOld = $this->Name; if (!is_null($iVal)) { if (is_array($iEvent)) { $iEvent['descr'] = StrCat($iEvent['descr'],'renaming title',': '); $iEvent['params'] = nz($iEvent['params']).':old=['.$strOld.']'; $iEvent['code'] = 'NN'; // new name $this->StartEvent($iEvent); } $arUpd = array('Name'=>SQLValue($iVal)); $this->Update($arUpd); if (is_array($iEvent)) { $this->FinishEvent(); } } return $strOld;

       }
       /*----
         RETURNS: Text suitable for use as a title for this Title
    

    (Ok, can *you* think of a better method name?)

         HISTORY:
    

    2010-11-19 Created for AdminPage()

       */
       public function Title() {
    

    return $this->CatNum().' '.$this->Name;

       }
       public function DeptObj() {
    

    $objDept = $this->objDB->Depts()->GetItem($this->ID_Dept); return $objDept;

       }
       public function ShopLink($iText) {
    

    return $this->LinkAbs().$iText.'</a>';

       }
       public function PageTitle() {
    

    return $this->CatNum('-');

       }
       /*----
         RETURNS: List of titles as formatted text
         HISTORY:
    

    2011-10-01 created for revised catalog entry -- no departments anymore, need more topic info

       */
       public function TopicList_ft($iNone='-') {
    

    $rcs = $this->Topics(); // recordset of Topics for this Title if ($rcs->HasRows()) { $out = ; while ($rcs->NextRow()) { $out .= ' '.$rcs->AdminLink(); } } else { $out = $iNone; } return $out;

       }
       /*----
         HISTORY:
    

    2011-02-23 Finally renamed from InfoPage() to AdminPage()

       */
       public function AdminPage() {
    

    global $wgOut,$wgRequest; global $vgPage,$vgOut;

    $doEdit = $vgPage->Arg('edit'); $doSave = $wgRequest->GetBool('btnSave');

    $vgPage->UseHTML();

    // save edits before showing events $ftSaveStatus = NULL; if ($doEdit || $doSave) { $this->BuildEditForm(); if ($doSave) { $ftSaveStatus = $this->AdminSave(); } }

    $isMissing = is_null($this->ID); if ($isMissing) { $strTitle = 'Missing Record'; $this->ID = $vgPage->Arg('ID'); } else { // items $ftItems = $this->ItemListing(); $htImages = $this->ImageListing(); // this may update the thumbnails, so do it before showing them $htGroups = $this->CMGrpListing(); $wtEvents = $this->EventListing();

    $objTbl = $this->objDB->Images(); $htThumbs = $objTbl->Thumbnails($this->ID); if (!is_null($htThumbs)) {

    $wgOut->AddHTML('
    '.$htThumbs.'
    ');

    }

    //$strCatNum = $this->CatNum(); $strCatPage = $this->CatNum('/');

    $strTitle = 'Title: '.$this->Title(); }

    $objPage = new clsWikiFormatter($vgPage); $objSection = new clsWikiSection($objPage,$strTitle); $objSection->ToggleAdd('edit'); $out = $objSection->Generate(); $wgOut->AddHTML($out); $out = ; $vgOut->AddText($ftSaveStatus);

    $objSupp = $this->SuppObj(); assert(is_object($objSupp));

    if ($doEdit) { $out .= $objSection->FormOpen();

    $ftCatKey = $this->objForm->Ctrl('CatKey')->Render(); $ftSuppCN = $this->objForm->Ctrl('Supplier_CatNum')->Render(); $ftSupp = $objSupp->DropDown('ID_Supp'); $ftDept = $objSupp->Depts_DropDown('ID_Dept',$this->ID_Dept); $ftName = $this->objForm->Ctrl('Name')->Render(); $ftSearch = $this->objForm->Ctrl('Search')->Render(); $ftDescr = $this->objForm->Ctrl('Desc')->Render(); $ftNotes = $this->objForm->Ctrl('Notes')->Render(); $ftWhAdded = $this->objForm->Ctrl('DateAdded')->Render(); $ftWhChckd = $this->objForm->Ctrl('DateChecked')->Render(); $ftWhUnavl = $this->objForm->Ctrl('DateUnavail')->Render(); } else { $ftCatKey = htmlspecialchars($this->CatKey); $ftSuppCN = htmlspecialchars($this->Supplier_CatNum); $ftSupp = $objSupp->AdminLink_name(); $objDept = $this->DeptObj(); if (is_object($objDept)) { $ftDept = $objDept->AdminLink($objDept->Name); } else { $ftDept = 'not set'; } $ftName = htmlspecialchars($this->Name); $ftSearch = htmlspecialchars($this->Search); $ftDescr = htmlspecialchars($this->Desc); $ftNotes = htmlspecialchars($this->Notes); $ftWhAdded = $this->DateAdded; $ftWhChckd = $this->DateChecked; $ftWhUnavl = $this->DateUnavail; }

    $out .= ''; $out .= ''; $out .= ''; $out .= ''; $out .= ''; $out .= ''; $out .= ''; $out .= ''; $out .= ''; $out .= ''; $out .= ''; $out .= '
    ID:'.$this->ID.' ['.$this->ShopLink('shop').']'; $out .= '
    Cat Key:'.$ftCatKey; $out .= '
    SC#:'.$ftSuppCN; $out .= '
    Supplier:'.$ftSupp; $out .= '
    Dept:'.$ftDept; $out .= '
    Name:'.$ftName; $out .= '
    Search:'.$ftSearch; $out .= '
    When Added:'.$ftWhAdded; $out .= '
    When Checked:'.$ftWhChckd; $out .= '
    When Unavailable:'.$ftWhUnavl; $out .= '
    ';

    if ($doEdit) { $out .= 'Edit notes: <input type=text name="EvNotes" size=40>
    '; $out .= '<input type=submit name="btnSave" value="Save">'; $out .= '<input type=submit name="btnCancel" value="Cancel">'; $out .= '<input type=reset value="Reset">'; $out .= '</form>'; } $wgOut->addHTML($out); $out = ;

    if (!$isMissing) { $wgOut->addWikiText('===Items===',TRUE); $vgOut->addText($ftItems); $wgOut->addHTML($htImages); // Images $wgOut->addWikiText('===Topics===',TRUE); $wgOut->addHTML($this->TopicListing()); $wgOut->addHTML($htGroups); // Catalog Groups $wgOut->addWikiText('===Events===',TRUE); $wgOut->addWikiText($wtEvents,TRUE); }

       }
       /*----
         HISTORY:
    

    2010-11-06 adapted from VbzStockBin for VbzAdminTitle

       */
       private function BuildEditForm() {
    

    global $vgOut;

    if (is_null($this->objForm)) { // create fields & controls $objForm = new clsForm_DataSet($this,$vgOut); //$objCtrls = new clsCtrls($objForm->Fields()); //$objCtrls = $objForm;

    $objForm->AddField(new clsField('CatKey'), new clsCtrlHTML(array('size'=>8))); $objForm->AddField(new clsField('Supplier_CatNum'), new clsCtrlHTML(array('size'=>25))); $objForm->AddField(new clsFieldNum('ID_Supp'), new clsCtrlHTML()); $objForm->AddField(new clsFieldNum('ID_Dept'), new clsCtrlHTML()); $objForm->AddField(new clsField('Name'), new clsCtrlHTML(array('size'=>25))); $objForm->AddField(new clsField('Search'), new clsCtrlHTML(array('size'=>25))); $objForm->AddField(new clsField('Desc'), new clsCtrlHTML(array('size'=>25))); $objForm->AddField(new clsField('Notes'), new clsCtrlHTML()); $objForm->AddField(new clsFieldTime('DateAdded'), new clsCtrlHTML()); $objForm->AddField(new clsFieldTime('DateChecked'), new clsCtrlHTML()); $objForm->AddField(new clsFieldTime('DateUnavail'), new clsCtrlHTML());

    $this->objForm = $objForm; //$this->objCtrls = $objCtrls; }

       }
       public function AdminSave() {
    

    global $wgRequest; global $vgOut;

    // check input for problems $strCatKeyNew = $wgRequest->GetText('CatKey'); $strCatKeyOld = $this->CatKey; $ok = TRUE; // ok to save unless CatKey conflict $out = ; if ($strCatKeyNew != $strCatKeyOld) { $ok = FALSE; // don't save unless CatKey passes tests // if catkey is being changed, then check new number for duplicates $objSupp = $this->SuppObj(); $objMatch = $objSupp->GetTitle_byCatKey($strCatKeyNew,'VbzAdminTitle'); if (is_null($objMatch)) { $ok = TRUE; } else { /* Requested catkey matches an existing title. Look for other titles with the same base catkey (in same supplier), on the theory that this will represent a list of previous renames for this catkey. */ $objMatch->NextRow(); $out = 'Your entered CatKey ['.$strCatKeyNew.'] has already been used for '.$objMatch->AdminLink($objMatch->Name); $objMatch = $objSupp->GetTitles_byCatKey($strCatKeyOld,'VbzAdminTitle'); if (!is_null($objMatch)) { // there are some similar entries -- show them: $out .= ' Other similar CatKeys:'; while ($objMatch->NextRow()) { $out .= ' '.$objMatch->AdminLink($objMatch->CatKey); } } } } if ($ok) { $out .= $this->objForm->Save($wgRequest->GetText('EvNotes')); } return $out;

       }
       public function ItemListing() {
    

    $out = $this->objDB->Items()->Listing_forTitle($this); return $out;

       }
       public function ImageListing() {
    

    $objTbl = $this->objDB->Images(); $arArgs = array( 'filt' => 'ID_Title='.$this->ID, 'sort' => 'AttrSort,ID', 'event.obj' => $this, 'title.id' => $this->ID, 'new' => TRUE ); $out = $objTbl->AdminPage($arArgs);

    // $objRows = $objTbl->GetData('ID_Title='.$this->ID,NULL,'AttrSort'); // $out = $objRows->AdminList(); return $out;

       }
       /*----
         RETURNS: Editable listing of topics for this Title
       */
       protected function TopicListing() {
    

    global $wgRequest; global $vgPage;

    $tblTitleTopics = $this->Engine()->TitleTopics();

    $me = $this; $arOpts = $this->Engine()->Topics()->TopicListing_base_array(); $arOpts['fHandleData_Change_Start'] = function($iText) use ($me) { $arEv = array( 'descr' => 'Adding '.$iText, 'code' => 'topic++', 'where' => __METHOD__ ); $me->StartEvent($arEv); };

    $arOpts['fHandleData_Change_Finish'] = function($iText) use ($me) { $arEv = array( 'descrfin' => $iText ); $me->FinishEvent($arEv); }; $arOpts['fHandleData_Change_Item'] = function($iVal) use ($me,$tblTitleTopics) { $sqlTopic = $iVal; $arIns = array( 'ID_Title' => SQLValue($me->KeyValue()), 'ID_Topic' => $sqlTopic ); $db = $tblTitleTopics->Engine(); $db->ClearError(); $ok = $tblTitleTopics->Insert($arIns); if (!$ok) { $strErr = $db->getError(); $out = $sqlTopic.': '.$strErr.' (SQL:'.$tblTitleTopics->sqlExec.')'; } else { $out = SQLValue($sqlTopic); } return $out; };

    $ctrlList = new clsWidget_ShortList(); $ctrlList->Options($arOpts); $htStatus = $ctrlList->HandleInput();

    $doRmvTopics = $wgRequest->GetBool('btnRmvTopics');

    // begin output phase $out = ;

    if ($doRmvTopics) { $arTopics = $wgRequest->GetArray('rmvTitle'); $cnt = $tblTitleTopics->DelTopics($this->Value('ID'),$arTopics); $out .= 'Removed '.$cnt.' topic'.Pluralize($cnt).':'; foreach ($arTopics as $id => $on) { $objTopic = $tblTopics->GetItem($id); $out .= ' '.$objTopic->AdminLink(); } } /* $htPath = $vgPage->SelfURL(); $out = "\n<form method=post action=\"$htPath\">";

    • /

    $out .= "\n<form method=post>";

    $rs = $this->Topics(); if ($rs->HasRows()) { while ($rs->NextRow()) {

    $id = $rs->KeyString(); $ftName = $rs->AdminLink_name();

    $out .= "\n[<input type=checkbox name=\"rmvTitle[$id]\">$ftName ]"; } $out .= '
    <input type=submit name="btnRmvTopics" value="Remove Checked">'; } else { $out .= 'None found.'; } /* $out .= '<input type=submit name="btnAddTopics" value="Add These:">'; $out .= '<input size=40 name=txtNewTitles> (IDs separated by spaces)';

    • /

    $out .= '
    '.$htStatus; $out .= $ctrlList->RenderForm_Entry();

    $out .= '</form>'; return $out;

       }
       /*----
         RETURNS: Listing of CM (catalog management) groups for this title
         HISTORY:
    

    2011-02-06 added controls to allow deactivating/activating selected rows

       */
       protected function CMGrpListing() {
    

    global $wgRequest; global $vgOut;

    $out = $vgOut->Header('Catalog Groups',3);

    $tblCMT = $this->objDB->CtgTitles(); // catalog management titles $tblCMS = $this->objDB->CtgSrcs(); // catalog management sources $tblCMG = $this->objDB->CtgGrps(); // catalog management groups

    $doEnable = $wgRequest->GetBool('btnCtgEnable'); $doDisable = $wgRequest->GetBool('btnCtgDisable'); if ($doEnable || $doDisable) { $arChg = $wgRequest->GetArray('ctg'); $out .= $doEnable?'Activating':'Deactivating'; foreach ($arChg as $id => $on) { $out .= ' '.$id; $arUpd = array( 'isActive' => SQLValue($doEnable) ); $tblCMT->Update($arUpd,'ID='.$id); } }

    $rsRows = $tblCMT->GetData('ID_Title='.$this->ID); if ($rsRows->HasRows()) { $out .= '<form method=post>'; $out .= $vgOut->TableOpen(); $out .= $vgOut->TblRowOpen(NULL,TRUE); $out .= $vgOut->TblCell('ID'); $out .= $vgOut->TblCell('A?'); $out .= $vgOut->TblCell('Catalog'); $out .= $vgOut->TblCell('Group'); $out .= $vgOut->TblCell('Discontinued'); $out .= $vgOut->TblCell('Grp Code'); $out .= $vgOut->TblCell('Grp Descr'); $out .= $vgOut->TblCell('Grp Sort'); $out .= $vgOut->TblCell('Supp Cat #'); $out .= $vgOut->TblCell('Notes'); $out .= $vgOut->TblRowShut(); while ($rsRows->NextRow()) { $isActive = $rsRows->isActive; $htActive = $isActive?'√':'-';

    $objCMSrce = $tblCMS->GetItem($rsRows->ID_Source); $objCMGrp = $tblCMG->GetItem($rsRows->ID_Group); if ($objCMSrce->HasRows()) { $htCMSrce = $objCMSrce->AdminLink_name(); } else { $htCMSrce = '?'.$rsRows->ID_Source; } if ($objCMGrp->HasRows()) { $htCMGrp = $objCMGrp->AdminLink_name(); } else { $htCMGrp = '?'.$rsRows->ID_Group; }

    $out .= $vgOut->TblRowOpen(); $htID = '<input type=checkbox name="ctg['.$rsRows->KeyValue().']">'.$rsRows->AdminLink(); $out .= $vgOut->TblCell($htID); $out .= $vgOut->TblCell($htActive); $out .= $vgOut->TblCell($htCMSrce); $out .= $vgOut->TblCell($htCMGrp); // $out .= $vgOut->TblCell($rsRows->ID_Source); // $out .= $vgOut->TblCell($rsRows->ID_Group);

    $out .= $vgOut->TblCell($rsRows->WhenDiscont); $out .= $vgOut->TblCell($rsRows->GroupCode); $out .= $vgOut->TblCell($rsRows->GroupDescr); $out .= $vgOut->TblCell($rsRows->GroupSort); $out .= $vgOut->TblCell($rsRows->Supp_CatNum); $out .= $vgOut->TblCell($rsRows->Notes); $out .= $vgOut->TblRowShut(); } $out .= $vgOut->TableShut(); $out .= '<input type=submit name=btnCtgDisable value="Deactivate Selected">'; $out .= '<input type=submit name=btnCtgEnable value="Activate Selected">'; $out .= '</form>'; } else { $out .= 'None found.'; } return $out;

       }
    

    } /*====

     PURPOSE: VbzAdminTitles with additional catalog information
    
    • /

    class VbzAdminTitles_info_Cat extends VbzAdminTitles {

       public function __construct($iDB) {
    

    parent::__construct($iDB); $this->Name('qryCat_Titles');

       }
       public function Search_forText_SQL($iFind) {
    

    $sqlFind = '"%'.$iFind.'%"'; return "(Name LIKE $sqlFind) OR (Descr LIKE $sqlFind) OR (Search LIKE $sqlFind) OR (CatNum LIKE $sqlFind)";

       }
       public function SearchPage() {
    

    global $wgOut,$wgRequest; global $vgPage;

    $strFind = $wgRequest->GetText('txtSearch');

    $vgPage->UseHTML(); $out = "\n<form method=post>"; $htFind = htmlspecialchars($strFind); $out .= 'Search for:<input name=txtSearch size=40 value="'.$htFind.'"><input type=submit name=btnSearch value="Go">'; $out .= '</form>'; $wgOut->AddHTML($out); $out = ;


    //$tblTitles = $this->Engine()->Titles(); $tblTitles = $this; $tblItems = $this->Engine()->Items(); $tblImgs = $this->Engine()->Images();

    $arTitles = NULL;

    $rs = $tblTitles->Search_forText($strFind); if ($rs->HasRows()) { while ($rs->NextRow()) { $id = $rs->ID; $arTitles[$id] = $rs->Values(); } }

    if (!empty($strFind)) { $out .= '
    Searching for "'.$htFind.'":
    '; $wgOut->AddHTML($out); $out = ;

    $rs = $tblItems->Search_byCatNum($strFind); if (is_object($rs)) { while ($rs->NextRow()) { $id = $rs->Value('ID_Title'); if (!isset($arTitles[$id])) { $obj = $tblTitles->GetItem($id); $arTitles[$id] = $obj->Values(); } } }

    if (!is_null($arTitles)) { if (empty($obj)) { $obj = $tblTitles->SpawnItem(); }

    $out .= '
    ';

    $ftImgs = ; $isFirst = TRUE; foreach ($arTitles as $id => $row) { $obj->Values($row); $txtCatNum = $obj->CatNum(); $txtName = $obj->Value('Name'); if ($isFirst) { $isFirst = FALSE; } else { $out .= "\n
    "; } $out .= $obj->AdminLink($txtCatNum).' '.$txtName;

    $txtTitle = $txtCatNum.' “'.htmlspecialchars($txtName).'”'; $ftImg = $tblImgs->Thumbnails($id,array('title'=>$txtTitle)); $ftImgs .= '<a href="'.$obj->AdminURL().'">'.$ftImg.'</a>'; }

    $out .= '
    '.$ftImgs;

    }

    $wgOut->AddHTML($out); $out = ; }

    return $out;

       }
    

    } /*====

     PURPOSE: VbzAdminTitles with additional item (and stock) information
    
    • /

    class VbzAdminTitles_info_Item extends VbzAdminTitles {

       public function __construct($iDB) {
    

    parent::__construct($iDB); $this->Name('qryTitles_Item_info'); $this->ClassSng('VbzAdminTitle_info_Item');

       }
       public function Listing_forDept($iDeptObj) {
    

    global $wgOut; global $vgPage; global $sql;

    $vgPage->UseHTML();

    $objDept = $iDeptObj; $idDept = $objDept->ID; // $strSuppKey = strtolower($objSupp->CatKey); // $objRecs = $this->GetData('ID_Dept='.$idDept,'VbzAdminTitle','CatKey'); //$objRecs = $this->DataSQL('SELECT t.ID_Title AS ID, t.* FROM qryCat_Titles_Item_stats AS t WHERE t.ID_Dept='.$idDept); $objRecs = $this->GetData('ID_Dept='.$idDept,NULL,'CatKey');

    $out = $objRecs->AdminList(); $wgOut->addHTML($out);

       }
    

    } class VbzAdminTitle_info_Item extends VbzAdminTitle {

       /*----
         RETURNS: listing of titles in the current dataset
         HISTORY:
    

    2010-11-16 "in print" column now showing cntInPrint instead of cntForSale

       */
       public function AdminList(array $iarArgs=NULL) {
    

    $objRecs = $this;

    if ($objRecs->HasRows()) {

    $out = "\n" ."\n" .'' .'' .'' .'' .'' .'' .'' .'' .'' .''; $isOdd = TRUE; while ($objRecs->NextRow()) { $ftID = $objRecs->AdminLink(); $ftName = $objRecs->Name; $ftCatNum = $objRecs->CatNum(); $ftCatKey = $objRecs->Row['CatKey']; $ftSCatNum = $objRecs->Row['Supplier_CatNum']; $ftWhen = $objRecs->DateAdded; // FUTURE: If we're using this on a dataset which does not have these fields, // test for them and then retrieve them the slow way if not found. $qtyStk = $objRecs->qtyForSale; //$cntAva = $objRecs->cntForSale; $cntPrn = $objRecs->cntInPrint; $cntItm = $objRecs->cntItems; $isActive = (($qtyStk > 0) || ($cntPrn > 0)); $isPassive = (nz($cntItm) == 0); $isOdd = !$isOdd; $wtStyle = $isOdd?'background:#ffffff;':'background:#eeeeee;'; if ($isActive) { $wtStyle .= ' font-weight: bold;'; } if ($isPassive) { $wtStyle .= ' color: #888888;'; } $out .= "\n". "". "". "". "". "". "". "". "". "". ''; } $out .= "\n
    IDNameCat #CatKeySCat#When Addeditem
    recs
    items
    in print
    stk
    qty
    $ftID$ftName$ftCatNum$ftCatKey$ftSCatNum$ftWhen$cntItm$cntPrn$qtyStk
    ";

    } else { if (isset($iarArgs['none'])) { $out .= $iarArgs['none']; } else { $out .= 'No titles found.'; } } return $out;

       }
    

    } /*****

     GROUP: Item administration
    
    • /

    class VbzAdminItems extends clsItems { // STATIC section //

       /*----
         HISTORY:
    

    2010-10-13 Re-enabled as a boilerplate call

       */
       public static function AdminLink($iID,$iShow=NULL,$iPopup=NULL) {
    

    return clsAdminTable::AdminLink($iID,$iShow,$iPopup);

       }
    

    // DYNAMIC section //

       public function __construct($iDB) {
    

    parent::__construct($iDB); $this->ClassSng('VbzAdminItem'); $this->ActionKey('item');

       }
       public function Listing_forTitle(clsVbzTitle $iTitleObj) {
    

    $objTitle = $iTitleObj; $idTitle = $objTitle->ID; //$cntRow = 0;

    $objRecs = $this->GetData('(IFNULL(isDumped,0)=0) AND (ID_Title='.$idTitle.')','VbzAdminItem','ItOpt_Sort'); return $objRecs->AdminList();

       }
       /*----
         ACTION: Updates fields in given catalog items
    

    Does not log an event (maybe it should?)

         INPUT: Array of items as returned by AdminItems_data_check()
         RETURNS: HTML to display (messages)
         FUTURE: This possibly should be in a helper class
         HISTORY:
    

    2011-01-04 partially written

       */
       public function AdminItems_data_update(array $iItems) {
    
    $out = "\n
      "; foreach ($iItems as $idx => $row) { $obj = $row['@obj']; $id = $obj->KeyValue(); $out .= "\n
    • Row $idx ID=$id:\n
        "; $arUpd = NULL; if (!empty($row['do-upd-scat'])) { $arUpd['Supp_CatNum'] = SQLValue($row['scat']); $out .= "\n
      • scat# [".$obj->Supp_CatNum.']=>['.$row['scat'].']'; } if (!empty($row['do-upd-desc'])) { $arUpd['Descr'] = SQLValue($row['name']); $out .= "\n
      • descr [".$obj->Descr.']=>['.$row['name'].']'; } $out .= "\n
      ";

      $obj->Update($arUpd); }

      $out .= "\n
    ";

    return $out;

       }
    

    } class VbzAdminItem extends clsItem {

       private $idEvent;
    
       /*----
         HISTORY:
    

    2010-10-11 Added iarArgs parameter

       */
       public function AdminLink($iText=NULL,$iPopup=NULL,array $iarArgs=NULL) {
    

    return clsAdminData::_AdminLink($this,$iText,$iPopup,$iarArgs);

       }
       public function AdminLink_name() {
    

    return $this->AdminLink($this->DescLong()); // can make this more elaborate later

       }
       /*----
         PURPOSE: Like AdminLink_name(). but okay to take up more room to provide more info
         HISTORY:
    

    2010-11-24 created

       */
       public function AdminLink_friendly() {
    

    $strItem = $this->AdminLink_CatNum(); $strFull = $strItem.' '.$this->DescLong_ht(); return $strFull;

       }
       /*----
         HISTORY:
    

    2010-11-27 created

       */
       public function AdminLink_CatNum() {
    

    return $this->AdminLink($this->CatNum,$this->DescLong());

       }
       /*----
         HISTORY:
    

    2010-11-06 replaced old event logging with boilerplate calls to helper class

       */
       protected function Log() {
    

    if (!is_object($this->logger)) { $this->logger = new clsLogger_DataSet($this,$this->objDB->Events()); } return $this->logger;

       }
       public function EventListing() {
    

    return $this->Log()->EventListing();

       }
       public function StartEvent(array $iArgs) {
    

    return $this->Log()->StartEvent($iArgs);

       }
       public function FinishEvent(array $iArgs=NULL) {
    

    return $this->Log()->FinishEvent($iArgs);

       }
       /*----
         ACTION:
    

    Return the current supplier catalog number If a value is given, update it to the new value first (returns old value) If an event array is given, log the event

       */
       public function SCatNum($iVal=NULL,array $iEvent=NULL) {
    

    $strOld = $this->Supp_CatNum; if (!is_null($iVal)) { if (is_array($iEvent)) { $iEvent['params'] = nz($iEvent['params']).':old=['.$strOld.']'; $iEvent['code'] = 'SCN'; $this->StartEvent($iEvent); } $arUpd = array('Supp_CatNum'=>SQLValue($iVal)); $this->Update($arUpd); if (is_array($iEvent)) { $this->FinishEvent(); } } return $strOld;

       }
       public function AdminList() {
    

    global $vgPage,$vgOut; global $sql;

    $cntRow = 0;

    if ($this->HasRows()) { $out = $vgOut->TableOpen('class=sortable'); $out .= $vgOut->TblRowOpen(NULL,TRUE); $out .= $vgOut->TblCell('ID'); $out .= $vgOut->TblCell('Cat #'); $out .= $vgOut->TblCell('Status'); $out .= $vgOut->TblCell('Description'); $out .= $vgOut->TblCell('$ buy'); $out .= $vgOut->TblCell('$ sell'); $out .= $vgOut->TblRowShut(); $isOdd = TRUE; while ($this->NextRow()) { $id = $this->ID; //$wtID = SelfLink_Page('item','id',$id,$id); $wtID = $this->AdminLink(); $wtStyle = $isOdd?'background:#ffffff;':'background:#cccccc;'; $isActive = $this->isForSale; $isCurrent = $this->isCurrent; $isInPrint = $this->isInPrint; $isPulled = $this->isPulled; if ($isActive) { $cntRow++; } else { $wtStyle .= ' color: #888888;'; } if (!$isInPrint) { $wtStyle .= ' font-style: italic;'; } if ($isPulled) { $wtStyle .= ' text-decoration: line-through;'; } $strStatus = ; if ($isActive) { $strStatus .= 'A'; } if ($isCurrent) { $strStatus .= 'C'; } if ($isInPrint) { $strStatus .= 'P'; } if ($isPulled) { $strStatus .= 'U'; } $out .= $vgOut->TblRowOpen('style="'.$wtStyle.'"'); $out .= $vgOut->TblCell($wtID); $out .= $vgOut->TblCell($this->CatNum); $out .= $vgOut->TblCell($strStatus,'align=center'); $out .= $vgOut->TblCell($this->ItOpt_Descr); $out .= $vgOut->TblCell(DataCurr($this->PriceBuy)); $out .= $vgOut->TblCell(DataCurr($this->PriceSell)); $out .= $vgOut->TblRowShut(); if (!is_null($this->Descr)) { $out .= $vgOut->TblRowOpen('style="'.$wtStyle.'"'); $out .= $vgOut->TblCell($this->Descr,'colspan=4'); $out .= $vgOut->TblRowShut(); }

    $isOdd = !$isOdd; //$objLine = $objRecs->CloneFields(); $objLine = clone $this; } $out .= $vgOut->TableShut(); } else { $out = 'No items listed. (SQL='.$sql.')'; } return $out;

       }
       public function Title() {
    

    return $this->objDB->Titles()->GetItem($this->ID_Title);

       }
       public function ItTyp() {
    

    return $this->objDB->ItTyps()->GetItem($this->ID_ItTyp);

       }
       public function FullDescr($iSep=' ') {
    

    $objTitle = $this->Title(); return $objTitle->Name.$iSep.$this->ItOpt_Descr;

       }
       public function FullDescr_HTML($iSep=' ') {
    

    $objTitle = $this->Title(); $objItTyp = $this->ItTyp(); if ($objItTyp->IsNew()) { $out = '(no item type)'; } else { $out =

       //	  $objTitle->SelfLink($objTitle->Name).$iSep.
    

    $objTitle->AdminLink($objTitle->Name).$iSep. $objItTyp->Row['NameSng'].$iSep. $this->ItOpt_Descr; } return $out;

       }
    

    /* 2010-11-11 This should be completely obsolete, right?

       protected function ReceiveForm() {
    

    global $wgOut,$wgRequest;

    if ($wgRequest->getCheck('btnSave')) { $intQtyNew = $wgRequest->GetInt('StkMin'); $arUpd['QtyMin_Stk'] = $intQtyNew; $intQtyOld = $this->QtyMin_Stk; if ($intQtyOld == $intQtyNew) { $out = 'No change requested; min qty is already '.$intQtyOld.'.'; } else { $strDescr = 'Updating per-item stock minimum from '.$intQtyOld.' to '.$intQtyNew; $out = $strDescr; $this->StartEvent(__METHOD__,'UPD',$strDescr); $this->Update($arUpd); $this->Reload(); $this->FinishEvent(); } $wgOut->AddWikiText($out); }

       }
    
    • /
       /*----
         HISTORY:
    

    2011-02-24 Finally renamed from InfoPage() to AdminPage()

       */
       public function AdminPage() {
    

    global $wgOut,$wgRequest; global $vgPage;

    $strCatNum = $this->CatNum;

    //$this->ReceiveForm();

    $vgPage->UseHTML(); $objTitle = $this->Title(); $strTitleName = $objTitle->Name; $ftTitleLink = (is_object($objTitle))?($objTitle->AdminLink($strTitleName)):'title N/A'; $strTitle = 'Item: '.$strCatNum.' ('.$this->ID.') - '.$this->FullDescr();

    $objPage = new clsWikiFormatter($vgPage); $objSection = new clsWikiSection($objPage,$strTitle); $objSection->ToggleAdd('edit'); //$objSection->ActionAdd('view'); $out = $objSection->Generate();

    $strAction = $vgPage->Arg('do'); $doAdd = ($strAction == 'add'); $doEdit = $vgPage->Arg('edit'); $doSave = $wgRequest->GetBool('btnSave');

    if ($doEdit || $doSave) { $this->BuildEditForm(); if ($doSave) { $this->AdminSave(); } }

    $ftPriceSell = $this->PriceSell; // this can be edited if item is not in print if ($doEdit) { $out .= $objSection->FormOpen(); $objForm = $this->objForm;

    $ftCatNum = $objForm->Render('CatNum'); $ftCatSfx = $objForm->Render('CatSfx'); $ftDescr = $objForm->Render('Descr'); if (!$this->isInPrint) { $ftPriceSell = $objForm->Render('PriceSell'); } $ftPriceList = $objForm->Render('PriceList'); $ftSCatNum = $objForm->Render('Supp_CatNum'); $ftStkMin = $objForm->Render('QtyMin_Stk'); } else { $ftCatNum = $this->CatNum; $ftCatSfx = $this->CatSfx; $ftDescr = $this->Descr; $ftPriceList = $this->PriceList; $ftSCatNum = $this->Supp_CatNum; $ftStkMin = $this->QtyMin_Stk; } // non-editable fields: $ftTitle = $ftTitleLink; $ftPriceBuy = $this->PriceBuy; $ftItOpt = $this->ID_ItOpt; $ftIODescr = $this->ItOpt_Descr; $ftIOSort = $this->ItOpt_Sort; $ftGrpCode = $this->GrpCode; $ftGrpDescr = $this->GrpDescr; $ftGrpSort = $this->GrpSort;

    $out .= '
      '; $out .= '
    • ID: '.$this->ID; $out .= '
    • Cat #: '.$ftCatNum.' suffix: '.$ftCatSfx; $out .= '
    • Description: '.$ftDescr; $out .= '
    • Prices: '.$ftItOpt; $out .= '
        '; $out .= '
      • Buy: '.$ftPriceBuy; $out .= '
      • Sell: '.$ftPriceSell; $out .= '
      • List: '.$ftPriceList.''; $out .= '
      '; $out .= '
    • Item Option: '.$ftItOpt; $out .= '
        '; $out .= '
      • Descr: '.$ftIODescr; $out .= '
      • Sort: '.$ftIOSort; $out .= '
      '; $out .= '
    • Group - code: '.$ftGrpCode.' descr: '.$ftGrpDescr.' sort: '.$ftGrpSort; $out .= '
    • Title: '.$ftTitle; $out .= '
    • Stk Min: '.$ftStkMin; $out .= '
    • Status:'; if ($this->isMaster) { $out .= ' MASTER'; } if ($this->isForSale) { $out .= ' FOR-SALE'; } if ($this->isInPrint) { $out .= ' IN-PRINT'; } if ($this->isCloseOut) { $out .= ' CLOSEOUT'; } if ($this->isPulled) { $out .= ' PULLED'; } if ($this->isDumped) { $out .= ' DUMPED'; } $out .= '
    • Supplier Cat #:'.$ftSCatNum; $out .= '
    ';

    if ($doEdit) { $out .= '<input type=submit name="btnSave" value="Save">'; $out .= '<input type=reset value="Reset">'; $out .= '</form>'; } $wgOut->AddHTML($out);

    $wgOut->AddHTML("

    Stock

    ");

    $wgOut->AddWikiText($this->StockListing(),TRUE);

    $wgOut->AddHTML("

    Orders

    ");

    $wgOut->AddWikiText($this->OrderListing(),TRUE);

    $wgOut->AddHTML("

    Restocks

    ");

    $wgOut->AddWikiText($this->RestockListing(),TRUE);

    $wgOut->AddHTML('

    Events

    ');

    $wgOut->AddWikiText($this->EventListing(),TRUE);

       }
       /*----
         HISTORY:
    

    2010-11-06 adapted from VbzStockBin

       */
       private function BuildEditForm() {
    

    global $vgOut;

    if (is_null($this->objForm)) { // create fields & controls $objForm = new clsForm_DataSet($this,$vgOut); //$objCtrls = new clsCtrls($objForm->Fields());

    $objForm->AddField(new clsField('Descr'), new clsCtrlHTML(array('size'=>40))); $objForm->AddField(new clsField('CatNum'), new clsCtrlHTML()); $objForm->AddField(new clsField('CatSfx'), new clsCtrlHTML(array('size'=>5))); $objForm->AddField(new clsFieldNum('PriceSell'), new clsCtrlHTML()); $objForm->AddField(new clsFieldNum('PriceList'), new clsCtrlHTML()); $objForm->AddField(new clsField('Supp_CatNum'), new clsCtrlHTML()); $objForm->AddField(new clsFieldNum('QtyMin_Stk'), new clsCtrlHTML(array('size'=>3)));

    $this->objForm = $objForm; //$this->objCtrls = $objCtrls; }

       }
       /*----
         ACTION: Save user changes to the record
         HISTORY:
    

    2010-11-06 copied from VbzStockBin to VbzAdminItem

       */
       public function AdminSave() {
    

    global $vgOut;

    $out = $this->objForm->Save(); $vgOut->AddText($out);

       }
       public function StockListing() {
    

    $out = $this->objDB->StkItems()->Listing_forItem($this); return $out;

       }
       public function OrderListing() {
    

    $objTbl = $this->objDB->OrdItems(); $objRows = $objTbl->GetData('ID_Item='.$this->ID); $out = $objRows->AdminTable_forItem(); return $out;

       }
       public function RestockListing() {
    

    $objTbl = $this->objDB->RstkReqItems(); $objRows = $objTbl->GetData('ID_Item='.$this->ID); $out = $objRows->AdminList('No restocks found for this item'); return $out;

       }
       /*----
         RETURNS: wikitext which links to the catalog page for the item
         NOTE: Since the store doesn't yet have pages for each item,
    

    this returns a link to the item's Title page

         FUTURE: create StoreLink() function which uses RichText object
       */
       public function StoreLink_WT($iText) {
    

    return '[[vbznet:cat/'.$this->Title()->URL_part().'|'.$iText.']]';

       }
    

    // FUNCTION DEPRECATED - remove eventually

       public function AdminLink_WT($iText) {
    

    return '[[VbzCart/archive/code/SpecialVbzAdmin/page'.KS_CHAR_URL_ASSIGN.'item/id'.KS_CHAR_URL_ASSIGN.$this->ID.'|'.$iText.']]';

       }
    

    // FUNCTION DEPRECATED - remove eventually

       public function StoreLink_HT($iText) {
    

    return '<a href="'.KWP_CAT.$this->Title()->URL_part().'" title="browse in store">'.$iText.'</a>';

       }
    

    } class clsAdminItems_info_Cat extends clsItems_info_Cat {

       public function __construct($iDB) {
    

    parent::__construct($iDB); $this->ActionKey('item');

       }
    

    } /*******

     IMAGES
    
    • /

    class clsAdminImages extends clsImages {

       public function __construct($iDB) {
    

    parent::__construct($iDB); $this->Name('cat_images'); $this->KeyName('ID'); $this->ClassSng('clsAdminImage');

       }
       /*-----
         ACTION: Processes form data, shows section header, loads image dataset, calls clsAdminImage::AdminList() to render
         INPUT:
    

    iarArgs: array of options ['filt'] = SQL filter for dataset to show ("WHERE" clause) ['sort'] = sorting order for dataset to show ("ORDER BY" clause) ['event.obj'] = object used for event logging ['title.id'] = ID_Title to use for new records ['new']: if TRUE, allow user to create new records when editing

       */
       public function AdminPage(array $iarArgs) {
    

    global $wgRequest; global $vgPage,$vgOut;

    $out = ;

    // get URL input $doEdit = ($vgPage->Arg('edit.img')); $doAdd = ($vgPage->Arg('add.img')); $arArgs = $iarArgs; $arArgs['edit'] = $doEdit; $sqlFilt = $arArgs['filt']; $sqlSort = $arArgs['sort'];

    // display section header // $strName = 'Images';

    $vgPage->UseHTML(); $objPage = new clsWikiFormatter($vgPage); $objSection = new clsWikiSection($objPage,'Images',NULL,3); $objSection->ToggleAdd('edit','edit image records','edit.img'); $objSection->ToggleAdd('add','add multiple image records','add.img'); $out .= $objSection->Generate();

       // handle possible form requests
    

    // -- bulk-entry form stage 1: check input if ($wgRequest->getBool('btnCheckImgs')) { $doCheck = TRUE; $xts = new xtString($wgRequest->GetText('txtImgs')); $arLines = $xts->ParseTextLines(array('line'=>'arr'));

    $htForm = "\nImages submitted:\n
      "; foreach ($arLines as $idx => $arLine) { $txtURL = $arLine[0]; $txtSize = isset($arLine[1])?$arLine[1]:NULL; $rsFldr = $this->Engine()->Folders()->FindBest($txtURL); if (is_null($rsFldr)) { $htForm .= "\n
    • No folder found for $txtUrl
    • "; } else { $fsFldr = $rsFldr->Value('PathPart'); $fsImg = $rsFldr->Remainder($txtURL); $idFldr = $rsFldr->KeyValue(); $ftSize = empty($txtSize)?:''.$txtSize.' '; $htForm .= "\n
    • $ftSize$fsFldr<a href=\"$fsFldr$fsImg\">$fsImg</a>
    • "; $htForm .= '<input type=hidden name="img-fldr['.$idx.']" value='.$idFldr.'>'; $htForm .= '<input type=hidden name="img-spec['.$idx.']" value="'.$fsImg.'">'; if (!is_null($txtSize)) { $htForm .= '<input type=hidden name="img-size['.$idx.']" value="'.$txtSize.'">'; } } } $htForm .= '
    ';

    } else { $doCheck = FALSE; } // -- bulk-entry form stage 2: create records if ($wgRequest->getBool('btnAddImgs')) { $arFldrs = $wgRequest->GetArray('img-fldr'); $arSpecs = $wgRequest->GetArray('img-spec'); $arSizes = $wgRequest->GetArray('img-size'); $idTitle = $vgPage->Arg('id'); assert('!empty($idTitle);');

    // log event to the title $objTitle = $this->Engine()->Titles($idTitle); $cntImgs = count($arFldrs); $arEv = array( 'descr' => 'Adding '.$cntImgs.' image'.Pluralize($cntImgs), 'where' => __METHOD__, 'code' => 'IMG++' ); $objTitle->StartEvent($arEv);

    foreach ($arFldrs as $idx => $idFldr) { $fs = $arSpecs[$idx]; $sz = $arSizes[$idx]; $arIns = array( 'ID_Folder' => $idFldr, 'isActive' => 'TRUE', 'Spec' => SQLValue($fs), 'ID_Title' => $idTitle, 'WhenAdded' => 'NOW()' ); if (!empty($sz)) { $arIns['Ab_Size'] = SQLValue($sz); } $this->Insert($arIns); $strNew = ' '.$this->LastID(); } $arEv = array( 'descrfin' => 'New ID'.Pluralize($cntImgs).':'.$strNew ); $objTitle->FinishEvent($arEv); } // -- existing item edit form if ($wgRequest->getBool('btnSaveImgs')) {

    $arUpdate = $wgRequest->getArray('update'); $arDelete = $wgRequest->getArray('del'); $arActive = $wgRequest->getArray('isActive'); $arFolder = $wgRequest->getArray('ID_Folder'); $arFileSpec = $wgRequest->getArray('txtFileSpec'); $arAttrSize = $wgRequest->getArray('txtAttrSize'); $arAttrFldr = $wgRequest->getArray('txtAttrFldr'); $arAttrDispl = $wgRequest->getArray('txtAttrDispl'); $arAttrSort = $wgRequest->getArray('txtAttrSort');

    if (count($arActive > 0)) { // add any reactivated rows to the update list foreach ($arActive as $id => $null) { $arUpdate[$id] = TRUE; } }

    $cntRows = count($arUpdate); if ($cntRows > 0) { $out .= 'Updating: '; $txtEvDescr = 'Checking '.$cntRows.' record'.Pluralize($cntRows); $txtRowEdits = ; $txtRowFlips = ;

    $doLog = isset($arArgs['event.obj']); if ($doLog) { $objLog = $arArgs['event.obj']; $arEv = array( 'descr' => $txtEvDescr, 'where' => __METHOD__, 'code' => 'IMG SVM' // image save multiple ); $objLog->StartEvent($arEv); }

    $cntUpd = 0; foreach ($arUpdate as $id => $null) { $isActive = isset($arActive[$id]); $isNew = ($id == 'new'); if (empty($arFileSpec[$id])) { $isNew = FALSE; // nothing to save } $objImg = $this->GetItem($id);

    if ($isNew) { $isDiff = TRUE; $doSaveActive = TRUE; $doSaveValues = TRUE; } else { $isDiff = ((int)$isActive != (int)$objImg->isActive); $isStateChg = $isDiff; $doSaveActive = $isDiff; $doSaveValues = !$isDiff; } if (!$isDiff) { $arUpd = array( 'ID_Folder' => $arFolder[$id], 'Spec' => $arFileSpec[$id], 'Ab_Size' => $arAttrSize[$id], 'AttrFldr' => nz($arAttrFldr[$id]), 'AttrDispl' => nz($arAttrDispl[$id]), 'AttrSort' => nz($arAttrSort[$id]) ); $isDiff = !$objImg->SameAs($arUpd); } $arUpd = NULL; if ($isDiff) { if ($doSaveValues) { $arUpd = array( 'ID_Folder' => SQLValue($arFolder[$id]), 'Spec' => SQLValue($arFileSpec[$id]), 'Ab_Size' => SQLValue($arAttrSize[$id]), 'AttrFldr' => SQLValue(nz($arAttrFldr[$id])), 'AttrDispl' => SQLValue(nz($arAttrDispl[$id])), 'AttrSort' => SQLValue(nz($arAttrSort[$id])) ); $txtRowEdits .= ' #'.$id; } if ($doSaveActive) { $arUpd['isActive'] = SQLValue($isActive); $txtRowFlips .= ' #'.$id.'('.NoYes($isActive,'off','ON').')'; } if ($isNew) { // create new record $idTitle = (int)$arArgs['title.id']; assert('is_int($idTitle)'); $arUpd['ID_Title'] = $idTitle; $this->Insert($arUpd); } else { // not new: just update $objImg->Update($arUpd); //global $sql; //$out .= '
    SQL: '.$objImg->sqlExec; } $cntUpd++; } } if ($doLog) { $txtStat = $cntUpd.' image'.Pluralize($cntUpd).' updated -'; if (!empty($txtRowFlips)) { $txtStat .= ' toggled:'.$txtRowEdits; } if (!empty($txtRowEdits)) { $txtStat .= ' edits:'.$txtRowEdits; } $arEv = array( 'descrfin' => SQLValue($txtStat) ); $objLog->FinishEvent($arEv); } $out .= $txtStat; } else { $out .= 'No image records selected for update.'; } }

    // render edit form outer shell: if ($doEdit || $doAdd || $doCheck) { $arLink = $vgPage->Args(array('page','id')); $urlSelf = $vgPage->SelfURL($arLink,TRUE); $arArgs['pfx'] = '<form method=post action="'.$urlSelf.'">';

    if ($doEdit) { $sfx = '<input type=submit name=btnSaveImgs value="Save">'; $sfx .= '<input type=reset value="Revert">'; } if ($doAdd) { $sfx = 'Enter images, one complete URL per line:'; $sfx .= '<textarea name=txtImgs rows=6></textarea>'; $sfx .= '<input type=submit name=btnCheckImgs value="Check">'; } if ($doCheck) { $sfx = $htForm; // calculated earlier $sfx .= '<input type=submit name=btnAddImgs value="Add These">'; } $sfx .= '</form>'; $arArgs['sfx'] = $sfx; }

    // load the latest data and show it in a table: $arArgs['none'] = 'No images found.'; $objRows = $this->GetData($sqlFilt,NULL,$sqlSort); $out .= $objRows->AdminList($arArgs);

    return $out;

       }
       /*----
         HISTORY:
    

    2010-10-19 Adapted from AdminPage() 2010-11-16 Commented out editing functions, per earlier thought, after partly updating them. Note: they were written for AdminPage().

       */
       public function AdminPage_Unassigned() {
    

    global $wgRequest,$wgOut; global $vgPage,$vgOut;

    $out = ;

    // get URL input $doEdit = ($vgPage->Arg('edit.img')); $arArgs['edit'] = $doEdit;

    // display section header // $strName = 'Images';

    $vgPage->UseHTML(); $objPage = new clsWikiFormatter($vgPage); $objSection = new clsWikiSection($objPage,'Unassigned Images',NULL,3); $objSection->ToggleAdd('edit','edit image records','edit.img'); $out .= $objSection->Generate();

    // load the latest data and show it in a table: $arArgs['none'] = 'No unassigned images found.'; $sqlFilt = 'ID_Title IS NULL'; $sqlSort = NULL; // maybe this could be useful later $objRows = $this->GetData($sqlFilt,NULL,$sqlSort); $out .= $objRows->AdminList($arArgs);

    $objSection = new clsWikiSection($objPage,'Imageless Active Titles',NULL,3); $out .= $objSection->Generate(); $objRows = $this->objDB->Titles()->Data_Imageless(); $out .= $objRows->AdminList($arArgs);

    $wgOut->AddHTML($out); $out = NULL; return $out;

       }
    

    } class clsAdminImage extends clsImage {

       /*-----
         ACTION: Renders dataset as a table
         INPUT: iarArgs
    

    none: text to insert as description if no records pfx: html to include before table rows, if there is data sfx: html to include after table rows, if there is data edit: render editable fields new: allow entering new records -- show edit even if no data

       */
       public function AdminList(array $iarArgs) {
    

    $out = ; $doNew = nz($iarArgs['new']); if ($doNew || $this->HasRows()) { $doEdit = nz($iarArgs['edit']); $out .= nz($iarArgs['pfx']);

    $out .= "\n"; $out .= ''; $out .= '' .'' .'' .'' .'' .'' .'' .'' .'' .''; $isOdd = FALSE; while ($this->NextRow()) { $out .= $this->AdminListRow($doEdit,$isOdd); $isOdd = !$isOdd; } if ($doEdit) { // when editing, we also allow for adding a new record $out .= $this->AdminListRow($doEdit,$isOdd,TRUE); } $out .= "\n
    attributes
    IDA?folderfilenamesizefolderdescriptionsorting
    ";

    $out .= nz($iarArgs['sfx']); } else { if (isset($iarArgs['none'])) { $out .= $iarArgs['none']; } else { $out .= 'No images found.'; } } return $out;

       }
       protected function AdminListRow($iEdit,$iOdd,$iNew=FALSE) {
    

    $isOdd = $iOdd; $doEdit = $iEdit;

    if ($iNew) { $doEdit = TRUE; $isActive = TRUE; $id = 'new'; $txtFileSpec = ; $txtFolder = ; $txtAttrSize = ; $txtAttrFldr = ; $txtAttrDispl = ; $txtAttrSort = ; } else { $id = $this->ID; $wtID = $id; $isActive = $this->isActive; $txtFileSpec = $this->Spec; $txtFolder = $this->FolderPath(); $txtAttrSize = $this->Ab_Size; $txtAttrFldr = $this->AttrFldr; $txtAttrDispl = $this->AttrDispl; $txtAttrSort = $this->AttrSort; }

    $wtStyle = $isOdd?'background:#ffffff;':'background:#eeeeee;'; if ($isActive) { $wtStyleCell = ; $ftActive = '√'; } else { $wtStyle .= ' color: #888888;'; $wtStyleCell = ' style="text-decoration: line-through;"'; $ftActive = ; } if ($doEdit) { // replace field values with editable versions if ($isActive) { $wtID = '<input type=hidden name=update['.$id.'] value=1>'.$id; } else { $wtID = '<input type=checkbox name=del['.$id.'] title="check rows to delete">'.$id; } $htEnabled = $isActive?:' disabled'; $ftActive = '<input type=checkbox name=isActive['.$id.'] title="check if this image should be used"'.($isActive?' checked':).'>'; $htFolder = $this->objDB->Folders()->DropDown('ID_Folder['.$id.']',$this->ID_Folder); $htFileSpec = '<input'.$htEnabled.' size=20 name=txtFileSpec['.$id.'] value="'.htmlspecialchars($txtFileSpec).'">'; $htAttrSize = '<input'.$htEnabled.' size=4 name=txtAttrSize['.$id.'] value="'.htmlspecialchars($txtAttrSize).'">'; $htAttrFldr = '<input'.$htEnabled.' size=4 name=txtAttrFldr['.$id.'] value="'.htmlspecialchars($txtAttrFldr).'">'; $htAttrDispl = '<input'.$htEnabled.' size=10 name=txtAttrDispl['.$id.'] value="'.htmlspecialchars($txtAttrDispl).'">'; $htAttrSort = '<input'.$htEnabled.' size=2 name=txtAttrSort['.$id.'] value="'.htmlspecialchars($txtAttrSort).'">'; } else { $htFolder = $txtFolder; $htFileSpec = $txtFileSpec = '<a href="'.$this->WebSpec().'">'.$txtFileSpec.'</a>';

    $htAttrSize = $txtAttrSize; $htAttrFldr = $txtAttrFldr; $htAttrDispl = $txtAttrDispl; $htAttrSort = $txtAttrSort; }

    $out = "\n". "\n$wtID". "\n<td$wtStyleCell>$ftActive". "\n<td$wtStyleCell>$htFolder". "\n<td$wtStyleCell>$htFileSpec". "\n<td$wtStyleCell>$htAttrSize". "\n<td$wtStyleCell>$htAttrFldr". "\n<td$wtStyleCell>$htAttrDispl". "\n<td$wtStyleCell>$htAttrSort". "\n"; return $out; } } /****** SHIPPING
    • /
    class clsShipments extends clsVbzTable { public function __construct($iDB) { parent::__construct($iDB); $this->Name('ord_shipmt'); $this->KeyName('ID'); $this->ClassSng('clsShipment'); $this->ActionKey('shpmt'); } protected function _newItem() { return new clsCatPage($this); } public function GetActive($iSort=NULL) { $objRows = $this->GetData('WhenClosed IS NULL',NULL,$iSort); return $objRows; } public function AdminPage() { global $wgOut; global $vgPage; $out = '==Shipments=='; $wgOut->addWikiText($out,TRUE); $out = ; $vgPage->UseWiki(); $objRecs = $this->GetData(NULL,NULL,'ID DESC'); if ($objRecs->HasRows()) { $out = "{| class=sortable\n|-\n! ID || Code || Status || Created || Shipped || Closed || Descr/Notes"; $isOdd = TRUE; while ($objRecs->NextRow()) { $id = $objRecs->ID; //$wtID = SelfLink_Page('shipmt','id',$id,$id); $wtID = $objRecs->AdminLink(); $wtStyle = $isOdd?'background:#ffffff;':'background:#cccccc;'; $wtCode = $objRecs->Abbr; // $wtStatus = ($objRecs->isDedicated==TRUE?'D':) . ($objRecs->isOnHold==TRUE?'H':); $wtStatus = (ord($objRecs->isDedicated)=='1'?'D':) . (ord($objRecs->isOnHold)=='1'?'H':); $wtWhenCre = TimeStamp_HideTime($objRecs->WhenCreated); $wtWhenShp = TimeStamp_HideTime($objRecs->WhenShipped); $wtWhenCls = TimeStamp_HideTime($objRecs->WhenClosed); $wtDescr = $objRecs->Descr; if (!is_null($objRecs->Notes)) { $wtDescr .= " ".$objRecs->Notes.""; } $isActive = is_null($objRecs->WhenShipped); if ($isActive) { //later: show link to ship/close it $wtStyle .= ' color: #006600;'; } else { } $out .= "\n|- style=\"$wtStyle\"\n| ".$wtID.' || '.$wtCode.' || '.$wtStatus.' || '.$wtWhenCre.' || '.$wtWhenShp.' || '.$wtWhenCls.' || '.$wtDescr; $isOdd = !$isOdd; } $out .= "\n|}"; } else { $out = 'No shipments have been created yet.'; } $wgOut->addWikiText($out,TRUE); $out = ; } } class clsShipment extends clsVbzRecs { /*---- HISTORY: 2010-10-11 Added iarArgs parameter */ public function AdminLink($iText=NULL,$iPopup=NULL,array $iarArgs=NULL) { return clsAdminData::_AdminLink($this,$iText,$iPopup,$iarArgs); } public function AdminLink_name() { return $this->AdminLink($this->ShortName()); } public function ShortName() { return $this->Value('Abbr'); } /*---- ACTION: Redirect to the url of the admin page for this object HISTORY: 2010-11-26 copied from VbzAdminCatalog to clsRstkRcd 2011-01-02 copied from clsRstkRcd to VbzAdminOrderTrxact 2011-09-24 copied from VbzAdminOrderTrxact to clsShipment */ public function AdminRedirect(array $iarArgs=NULL) { return clsAdminData::_AdminRedirect($this,$iarArgs); } /*----- TO DO: * Convert old-style edit/header to new, wherever that is HISTORY: 2011-03-29 renamed from InfoPage() to AdminPage() */ public function AdminPage() { global $wgOut,$wgRequest; global $vgPage; $vgPage->UseHTML(); // check for form data $doNew = ($vgPage->Arg('id') == 'new'); $didAdd = FALSE; // 2011-09-02 This was the old code for saving a new record. Keeping it in case tweaks are needed to the new code. /* if ($wgRequest->getBool('btnCreate')) { $wgOut->AddWikiText('==Creating Shipment==',TRUE); // create new record from form data $strAbbr = $wgRequest->getText('abbr'); $strDescr = $wgRequest->getText('descr'); $strNotes = $wgRequest->getText('notes'); $arEv = array( 'descr' => 'new shipment', 'where' => __METHOD__, 'code' => 'new' ); $this->StartEvent($arEv); $arIns = array( 'id' => 0, 'WhenCreated' => 'NOW()', 'Abbr' => SQLValue($strAbbr), 'Descr' => SQLValue($strDescr), 'Notes' => SQLValue($strNotes) ); $this->Table->Insert($arIns); $this->ID = $this->Table->LastID(); $wgOut->AddWikiText('New ID='.$this->ID,TRUE); $this->Reload(); // load the newly-created record $didAdd = TRUE; // a new record has just been created $this->FinishEvent(array('id'=>$this->ID)); }
    • /
    // check for more actions: $doEdit = ($doNew || $vgPage->Arg('edit')); $doClose = $vgPage->Arg('close'); $doSave = $wgRequest->getBool('btnSave'); if ($doClose) { // add up totals $objRecs = $this->PkgsData(); if ($objRecs->HasRows()) { $wgOut->AddWikiText('==Closing Shipment==',TRUE); $ok = TRUE; $dlrShip = 0; $dlrPack = 0; $cntPkgErr = 0; $out = ; while ($objRecs->NextRow()) { $out .= '
    Pkg ID '.$objRecs->AdminLink(); if (is_null($objRecs->ShipCost)) { $out .= ': no shipping cost!'; $ok = FALSE; $cntPkgErr++; } elseif (is_null($objRecs->PkgCost)) { $out .= ': no materials cost!'; $ok = FALSE; $cntPkgErr++; } else { $dlrShip += $objRecs->ShipCost; $dlrPack += $objRecs->PkgCost; } } if ($ok) { $strUpd = '$'.$dlrShip.' shipping, $'.$dlrPack.' materials'; $out = '
    Cost totals: '.$strUpd; } else { $out .= '
    '.$cntPkgErr.Pluralize($cntPkgErr,' package has','packages have').' missing information.'; } } else { $ok = FALSE; $out = 'No packages in shipment; nothing to close.'; } $wgOut->AddHTML($out); $out=NULL; if ($ok) { // log the attempt $arEv = array( 'descr' => 'closing shipment: '.$strUpd, 'where' => __METHOD__, 'code' => 'CLO' ); $this->StartEvent($arEv); // fill in stats $arUpd = array( 'WhenClosed' => 'NOW()', 'OrderCost' => $dlrShip, 'SupplCost' => $dlrPack ); $this->Update($arUpd); global $sql; $out = '
    Shipment updated - SQL: '.$sql; $this->Reload(); // log the completion $this->FinishEvent(); $wgOut->AddWikiText($out,TRUE); $out=NULL; } } if ($doEdit || $doSave) { $this->BuildEditForm(); if ($doSave) { $this->AdminSave(); } } $htAbbr = htmlspecialchars($this->Abbr); $htDescr = htmlspecialchars($this->Descr); $htNotes = htmlspecialchars($this->Notes); // values which are always static if ($doNew) { $strID = 'NEW'; $strTitle = 'NEW Shipment'; } else { if ($didAdd) { $strID = $this->AdminLink(); } else { $strID = $this->ID; } $strTitle = 'Shipment '.$htAbbr; } $out = ; if ($doEdit) { // open editing form $sqlID = $doNew?'new':$this->ID; $arLink = array( 'edit' => FALSE, 'id' => $sqlID ); $htPath = $vgPage->SelfURL($arLink); $out .= "\n<form method=post action=\"$htPath\">"; // code for editable values /* $strAbbr = '<input name=abbr type=text size=16 value="'.$htAbbr.'">'; $strDescr = '<input name=descr type=text size=50 value="'.$htDescr.'">'; $strNotes = '<textarea name=notes width=50 height=3>'.$htNotes.'</textarea>';
    • /
    $objForm = $this->objForm; $ctrlAbbr = $objForm->Render('Abbr'); $ctrlDescr = $objForm->Render('Descr'); $ctrlNotes = $objForm->Render('Notes'); $ctrlWhenCre = $objForm->Render('WhenCreated'); $ctrlWhenShp = $objForm->Render('WhenShipped'); $ctrlCostRcpt = '$'.$objForm->Render('ReceiptCost'); $ctrlCostOuts = '$'.$objForm->Render('OutsideCost'); $ctrlCostOrdr = '$'.$objForm->Render('OrderCost'); $ctrlCostSupp = '$'.$objForm->Render('SupplCost'); $ctrlCarrier = $objForm->Render('Carrier'); $ctrlIsDedic = $objForm->Render('isDedicated'); $ctrlIsOnHold = $objForm->Render('isOnHold'); $ctrlStatus = $ctrlIsDedic.'dedicated '.$ctrlIsOnHold.'on hold'; $htClose = ; } else { // Only allow closing the shipment if we're not editing. // Clicking a link from edit mode loses any edits. if (is_null($this->WhenClosed)) { $arLink = array( 'close' => TRUE, ); $htClose = ' ['.$vgPage->SelfLink($arLink,'close the shipment','set closing timestamp and add up totals').']'; } else { $htClose = ; // already closed } // code for static values $ctrlAbbr = $htAbbr; $ctrlDescr = $htDescr; $ctrlNotes = $htNotes; $ctrlWhenCre = $this->WhenCreated; $ctrlWhenShp = $this->WhenShipped; $ctrlCostRcpt = $this->ReceiptCost; $ctrlCostOuts = $this->OutsideCost; $ctrlCostOrdr = $this->OrderCost; $ctrlCostSupp = $this->SupplCost; $ctrlCarrier = $this->Carrier; $isDedicated = (ord($this->isDedicated)); $isOnHold = (ord($this->isOnHold)); if ($isDedicated || $isOnHold) { $ctrlStatus = ($isDedicated?'Dedicated':) . ($isOnHold?' OnHold':); } else { $ctrlStatus = 'normal'; } } // non-editable controls $ctrlWhenClo = $this->WhenClosed.$htClose; $out .= WikiSectionHdr_Edit($strTitle,$doEdit); // old style // $out .= "\n

    $strTitle

    "; $out .= "\n"; $out .= "\n"; $out .= "\n"; $out .= "\n"; $out .= "\n";

    if (!$doNew) {

    $out .= "\n"; $out .= "\n"; $out .= "\n"; $out .= "\n"; $out .= "\n"; $out .= "\n"; $out .= "\n";

    }

    $out .= "\n"; $out .= "\n"; $out .= "\n
    ID:$strID
    Name:$ctrlAbbr
    Description:$ctrlDescr
    Type:$ctrlStatus
    When Created:$ctrlWhenCre
    When Shipped:$ctrlWhenShp
    When Closed:$ctrlWhenClo
    Receipt Cost:$ctrlCostRcpt
    Outside Cost:$ctrlCostOuts
    Order Cost:$ctrlCostOrdr
    Supplier Cost:$ctrlCostSupp
    Carrier:$ctrlCarrier
    Notes:$ctrlNotes
    ";

    if ($doEdit) { // form buttons if ($doNew) { // next line needed only if we have special code for Create vs. Save // $out .= '<input type=submit name="btnCreate" value="Create">'; // 2011-09-02 testing this instead: $out .= '<input type=submit name="btnSave" value="Create">'; } else { $out .= '<input type=submit name="btnSave" value="Save">'; $out .= '<input type=reset value="Revert">'; } // close editing form $out .= "\n</form>"; } $wgOut->addHTML($out); $out = ;

    if (!$doNew) { $wgOut->addWikiText('===Packages===',TRUE); $out = ; $out .= $this->PkgTable(); $wgOut->addWikiText($out,TRUE); $out = ;

    $wgOut->addWikiText('===Events===',TRUE); $out = $this->EventListing(); $wgOut->addWikiText($out,TRUE); $out = ; }

       }
       /*----
         HISTORY:
    

    2011-02-17 Updated to use objForm instead of objFlds/objCtrls

       */
       private function BuildEditForm() {
    

    global $vgOut;

    // create fields & controls

    if (is_null($this->objForm)) { $objForm = new clsForm_DataSet($this,$vgOut);

    $objForm->AddField(new clsFieldTime('WhenCreated'), new clsCtrlHTML()); $objForm->AddField(new clsFieldTime('WhenShipped'), new clsCtrlHTML()); //$objCtrls->AddField(new clsFieldTime('WhenClosed'), new clsCtrlHTML()); $objForm->AddField(new clsFieldNum('ReceiptCost'), new clsCtrlHTML(array('size'=>5))); $objForm->AddField(new clsFieldNum('OutsideCost'), new clsCtrlHTML(array('size'=>5))); $objForm->AddField(new clsFieldNum('OrderCost'), new clsCtrlHTML(array('size'=>5))); $objForm->AddField(new clsFieldNum('SupplCost'), new clsCtrlHTML(array('size'=>5))); $objForm->AddField(new clsField('Carrier'), new clsCtrlHTML()); $objForm->AddField(new clsField('Abbr'), new clsCtrlHTML(array('size'=>16))); $objForm->AddField(new clsField('Descr'), new clsCtrlHTML(array('size'=>50))); $objForm->AddField(new clsField('Notes'), new clsCtrlHTML_TextArea(array('height'=>3,'width'=>50))); $objForm->AddField(new clsFieldBool('isDedicated'), new clsCtrlHTML_CheckBox()); $objForm->AddField(new clsFieldBool('isOnHold'), new clsCtrlHTML_CheckBox());

    $this->objForm = $objForm; }

       }
       /*-----
         ACTION: Save the user's edits to the shipment
         HISTORY:
    

    2011-02-17 Retired old custom code; now using objForm helper object

       */
       private function AdminSave() {
    

    global $vgOut;

    $out = $this->objForm->Save(); $vgOut->AddText($out); /* 2011-02-17 old code global $wgOut;

    // get the form data and note any changes $objFlds = $this->objCtrls->Fields(); $objFlds->RecvVals(); // get the list of field updates $arUpd = $objFlds->DataUpdates(); // log that we are about to update $strDescr = 'Edited: '.$objFlds->DescrUpdates(); $wgOut->AddWikiText('==Saving Edit==',TRUE); $wgOut->AddWikiText($strDescr,TRUE);

    $arEv = array( 'descr' => $strDescr, 'where' => __METHOD__, 'code' => 'ED' ); $this->StartEvent($arEv); // update the recordset $this->Update($arUpd); global $sql; $wgOut->AddWikiText('
    SQL='.$sql,TRUE); $this->Reload(); // log completion $this->FinishEvent();

    • /
       }
       public function PkgsData() {
    

    $objTbl = $this->objDB->Pkgs(); $objRows = $objTbl->GetData('(ID_Shipment='.$this->KeyValue().') AND (WhenVoided IS NULL)'); return $objRows;

       }
       public function PkgTable() {
    

    /* //$objTbl = new clsPackages($this->objDB); $objTbl = $this->objDB->Pkgs(); $objRows = $objTbl->GetData('ID_Shipment='.$this->ID);

    • /

    $objRows = $this->PkgsData(); $arArgs = array( 'descr' => ' for this shipment', 'omit' => , 'ord' => $this->ID_Order ); $out = $objRows->AdminTable($arArgs); return $out;

       }
       /*----
         HISTORY:
    

    2010-10-23 added event logging using helper class

       */
       protected function Log() {
    

    if (!is_object($this->logger)) { $this->logger = new clsLogger_DataSet($this,$this->objDB->Events()); } return $this->logger;

       }
       public function EventListing() {
    

    return $this->Log()->EventListing();

       }
       public function DropDown($iName,$iDefault=NULL) {
    

    if ($this->HasRows()) { $out = '<select name="'.$iName.'">'."\n"; while ($this->NextRow()) { $id = $this->Value('ID'); if ($id == $iDefault) { $htSelect = " selected"; } else { $htSelect = ; } $htDescr = $this->Descr(); $out .= "<option$htSelect value=\"$id\">$htDescr</option>\n"; } $out .= '</select>'; } else { $out = 'No shipments matching filter'; } return $out;

       }
       public function Descr() {
    

    $out = $this->Abbr; return $out;

       }
    

    } /******

     TOPIC MANAGEMENT
    
    • /

    class clsAdminTopics extends clsTopics {

       public function __construct($iDB) {
    

    parent::__construct($iDB); $this->ClassSng('clsAdminTopic'); $this->ActionKey('topic');

       }
       protected function AdminRedirect() {
    

    global $vgPage; global $wgOut;

    $ar = array('page'=>$this->ActionKey()); $url = $vgPage->SelfURL($ar,TRUE); $wgOut->redirect($url);

       }
       public function RootNode() {
    

    $objRoot = $this->SpawnItem(); $objRoot->ID = NULL; return $objRoot;

       }
       /*----
         PURPOSE: renders tree with colors and links suitable for admin usage
         LATER: The parent method should be generalized for color and link-function
       */
    

    /*

       public function RenderTree($iTwig=NULL) {
    

    if (is_null($iTwig)) { $objRoot = $this->RootNode(); } else { $objRoot = $this->GetItem($iTwig); } $out = $objRoot->DrawTree(); return $out;

       }
    
    • /
       public function ListTitles_unassigned() {
    

    global $vgPage;

    $sql = 'SELECT tc.*, t.Name' .' FROM (_titles AS tc LEFT JOIN cat_title_x_topic AS tt ON tc.ID=tt.ID_Title)' .' LEFT JOIN cat_titles AS t ON tc.ID=t.ID' .' WHERE (tt.ID_Title IS NULL) AND (tc.cntForSale > 0)'; $rs = $this->Engine()->DataSet($sql,$this->Engine()->Titles()->ClassSng()); if ($rs->HasRows()) { $vgPage->UseHTML(); $rs->Table = $this->Engine()->Titles();

    $out = "\n
      "; while ($rs->NextRow()) { $out .= "\n
    • ".$rs->AdminLink($rs->Value('CatNum')).' '.$rs->Value('Name').'
    • '; } $out .= "\n
    ";

    } else { $out = 'All active titles have topics.'; } return $out;

       }
       public function Data_forTitle($iTitle) {
    

    $sql = 'SELECT bt.* FROM cat_topic AS bt LEFT JOIN cat_title_x_topic AS bx ON bx.ID_Topic=bt.ID WHERE ID_Title='.$iTitle; $objRows = $this->Engine()->DataSet($sql,$this->ClassSng()); return $objRows;

       }
       public function AdminPage() {
    

    global $wgOut; global $vgPage,$vgOut;

    $out = "\n".'

    Unassigned Titles

    ';

    $out .= $this->ListTitles_unassigned();

    $out .= "\n
    ";

    $arLink = array('rebuild'=>TRUE); $htLink = $vgPage->SelfURL($arLink,TRUE);

    $doRebuild = $vgPage->Arg('rebuild');

    if ($doRebuild) { // apparently there's no way to display a message without preventing the redirect $this->RenderTree(TRUE); $this->AdminRedirect(); } else { $out .= "\n".'[<a href="'.$htLink.'">rebuild tree</a>]';

    $this->TreeCtrl()->FileForCSS('dtree.css'); $out .= $this->RenderTree(FALSE); } $wgOut->AddHTML($out); $out = ; return $out;

       }
       /*----
         RETURNS: options array for entering topics
         USAGE:
    

    1. fill in fHandleData_Change_Start, fHandleData_Change_Finish, fHandleData_Change_Item 2. Then, where $arOpts is the array returned: $ctrlList = new clsWidget_ShortList(); $ctrlList->Options($arOpts); $htOut = $ctrlList->HandleInput();

         HISTORY:
    

    2011-09-29 adapted from VbzAdminTitle::TopicListing()

       */
       public function TopicListing_base_array() {
    

    $tblTopics = $this; $tblTopics->doBranch(TRUE); $arOpts = array( 'name' => 'title', 'btnChk_Text' => 'Enter topics:', 'btnChg_Text' => '<= Add', 'txtCargo_sng' => 'topic ID', 'txtCargo_plr' => 'topic IDs', 'txtProd_sng' => 'topic', 'txtProd_plr' => 'topics', 'txtConf_list' => 'Adding', 'fHandleData_Check' => function($iVal) use ($tblTopics) { $obj = $tblTopics->GetItem($iVal); // for now, assume topic is ID

    $arOut['html'] = $obj->AdminLink_name(); $arOut['text'] = $obj->KeyValue(); return $arOut; }, ); return $arOpts;

       }
    

    } class clsAdminTopic extends clsTopic {

       /*----
         HISTORY:
    

    2010-12-05 boilerplate event logging added

       */
       //----
       // BOILERPLATE: event logging
       protected function Log() {
    

    if (!is_object($this->logger)) { $this->logger = new clsLogger_DataSet($this,$this->objDB->Events()); } return $this->logger;

       }
       public function StartEvent(array $iArgs) {
    

    return $this->Log()->StartEvent($iArgs);

       }
       public function FinishEvent(array $iArgs=NULL) {
    

    return $this->Log()->FinishEvent($iArgs);

       }
       public function EventListing() {
    

    return $this->Log()->EventListing();

       }
       // BOILERPLATE: admin HTML
       public function AdminURL() {
    

    return clsAdminData::_AdminURL($this);

       }
       public function AdminLink($iText=NULL,$iPopup=NULL,array $iarArgs=NULL) {
    

    $strPopup = $this->AdminLink_default_popup($iPopup); return clsAdminData::_AdminLink($this,$iText,$strPopup,$iarArgs);

       }
       // END BOILERPLATES
       //----
       //
       // Boilerplate auxiliary functions
       public function AdminLink_name() {
    

    if ($this->IsNew()) { return 'root'; } else { $txtShow = $this->Value('Name'); if ($this->doBranch()) { $txtPopup = $this->RenderBranch_text('<'); } else { $txtPopup = $this->NameFull(); } return $this->AdminLink($txtShow,$txtPopup); }

       }
       protected function AdminLink_default_popup($iOverrideText) {
    

    if (is_null($iOverrideText)) { $out = $this->Value('Name'); } else { $out = $iOverrideText; } return $out;

       }
       // END boilerplate auxiliary
       //----
       public function RenderBranch($iSep="←") {
    

    $ftFullName = htmlspecialchars($this->Value('FullName')); $out = $this->AdminLink($this->Value('TreeName'),$ftFullName); if ($this->HasParent()) { $out .= $iSep.$this->ParentObj()->RenderBranch($iSep); } return $out;

       }
       public function Tree_RenderTwig($iCntTitles) {
    

    $cntTitles = $iCntTitles; $txtNoun = ' title'.Pluralize($cntTitles).' available'; // for topic #'.$id; $out = ' ['.$cntTitles.']'; // $txt = $this->Value('CatNum').' '.$this->Value('Name'); return $out;

       }
       public function Tree_AddTwig(clsTreeNode $iTwig,$iText) {
    

    $id = $this->Value('ID'); // $objSub = $iTwig->Add($id,$iText,$this->ShopURL()); $objSub = $iTwig->Add($id,$iText,$this->AdminURL()); return $objSub;

       }
       public function AdminPage() {
    

    global $wgOut,$wgRequest; global $vgPage,$vgOut;

    $doEdit = $vgPage->Arg('edit'); $doSave = $wgRequest->GetBool('btnSave'); $doRmvTitles = $wgRequest->GetBool('btnRmvTitles');

    $vgPage->UseHTML();

    $strTitle = 'Topic: '.$this->Value('Name');

    $objPage = new clsWikiFormatter($vgPage); $objSection = new clsWikiSection($objPage,$strTitle); $objSection->ToggleAdd('edit'); //$objSection->ActionAdd('view'); $out = $objSection->Generate();

    // save edits before re-displaying data

    // edits to this record $ftSaveStatus = NULL; if ($doEdit || $doSave) { $this->BuildEditForm(); if ($doSave) { $ftSaveStatus = $this->AdminSave(); } }

    // topic deletion if ($doRmvTitles) { // TO BE WRITTEN }

    if ($doEdit) { $out .= $objSection->FormOpen(); $objForm = $this->objForm;

    $ctParent = $objForm->Render('ID_Parent'); $ctName = $objForm->Render('Name'); $ctNameTree = $objForm->Render('NameTree'); $ctNameFull = $objForm->Render('NameFull'); $ctNameMeta = $objForm->Render('NameMeta'); $ctUsage = $objForm->Render('Usage'); $ctSort = $objForm->Render('Sort'); $ctVariants = $objForm->Render('Variants'); $ctMispeled = $objForm->Render('Mispeled'); } else { $ctParent = $this->ParentObj()->AdminLink_name(); $ctName = $this->Value('Name'); $ctNameTree = $this->Value('NameTree'); $ctNameFull = $this->Value('NameFull'); $ctNameMeta = $this->Value('NameMeta'); $ctUsage = $this->Value('Usage'); $ctSort = $this->Value('Sort'); $ctVariants = $this->Value('Variants'); $ctMispeled = $this->Value('Mispeled'); }

    $out .= '
      '; $out .= '
    • ID: '.$this->KeyValue().' ['.$this->ShopLink('shop').']'; $out .= '
    • Parent: '.$ctParent; $out .= '
    • Name: '.$ctName; $out .= '
        '; $out .= '
      • in tree: '.$ctNameTree; $out .= '
      • complete: '.$ctNameFull; $out .= '
      • meta: '.$ctNameMeta; $out .= '
      '; $out .= '
    • Usage: '.$ctUsage; $out .= '
    • Searching: '; $out .= '
        '; $out .= '
      • variants: '.$ctVariants; $out .= '
      • misspellings: '.$ctMispeled; $out .= '
      • sort by: '.$ctSort; $out .= '
      '; $out .= '
    ';

    if ($doEdit) { $out .= '<input type=submit name="btnSave" value="Save">'; $out .= '<input type=reset value="Reset">'; $out .= '</form>'; } $wgOut->AddHTML($out);

    $wgOut->AddHTML("

    Subtopics

    ");

    $wgOut->AddHTML($this->SubtopicListing());

    $wgOut->AddHTML("

    Titles

    ");

    $wgOut->AddHTML($this->TitleListing());

       }
       /*----
         ACTION: Save user changes to the record
         HISTORY:
    

    2010-11-06 copied from VbzStockBin to VbzAdminItem 2011-01-26 copied from VbzAdminItem to clsAdminTopic

       */
       public function AdminSave() {
    

    global $vgOut;

    $out = $this->objForm->Save(); $vgOut->AddText($out);

       }
       /*----
         HISTORY:
    

    2010-11-06 adapted from VbzStockBin for VbzAdminTitle 2011-01-26 adapted from VbzAdminTitle

       */
       private function BuildEditForm() {
    

    global $vgOut;

    if (is_null($this->objForm)) { // create fields & controls $objForm = new clsForm_DataSet($this,$vgOut); //$objCtrls = new clsCtrls($objForm->Fields()); //$objCtrls = $objForm;

    $objForm->AddField(new clsFieldNum('ID_Parent'), new clsCtrlHTML()); $objForm->AddField(new clsField('Name'), new clsCtrlHTML(array('size'=>20))); $objForm->AddField(new clsField('NameTree'), new clsCtrlHTML(array('size'=>15))); $objForm->AddField(new clsField('NameFull'), new clsCtrlHTML(array('size'=>25))); $objForm->AddField(new clsField('NameMeta'), new clsCtrlHTML(array('size'=>25))); $objForm->AddField(new clsField('Usage'), new clsCtrlHTML(array('size'=>25))); $objForm->AddField(new clsField('Sort'), new clsCtrlHTML(array('size'=>5))); $objForm->AddField(new clsField('Variants'), new clsCtrlHTML(array('size'=>40))); $objForm->AddField(new clsField('Mispeled'), new clsCtrlHTML(array('size'=>40)));

    $this->objForm = $objForm; //$this->objCtrls = $objCtrls; }

       }
       protected function SubtopicListing() {
    

    global $wgRequest;

    $htStatus = NULL;

    // set up the entry widget $ctrlList = new clsWidget_ShortList(); $me = $this; $arOpts = array( 'name' => 'topic', 'btnChk_Text' => 'Enter subtopics:', 'btnChg_Text' => '<= Create', 'txtCargo_sng' => 'topic name', 'txtCargo_plr' => 'topic names', 'txtProd_sng' => 'subtopic', 'txtProd_plr' => 'subtopics', 'fHandleData_Check' => function($iVal) { $arOut['html'] = $iVal; $arOut['text'] = $iVal; return $arOut; }, 'fHandleData_Change_Start' => function($iText) use ($me) { $arEv = array( 'descr' => 'Adding '.$iText, 'code' => 'sub++', 'where' => __METHOD__ ); $me->StartEvent($arEv); }, 'fHandleData_Change_Finish' => function($iText) use ($me) { $arEv = array( 'descrfin' => $iText ); $me->FinishEvent($arEv); }, 'fHandleData_Change_Item' => function($iVal) use ($me) { $txt = $iVal; $arIns = array( 'ID_Parent' => SQLValue($me->KeyValue()), 'Name' => SQLValue($txt) ); $me->Table->Insert($arIns); $out = $me->Table->LastID(); return $out; }, ); $ctrlList->Options($arOpts); $htStatus = $ctrlList->HandleInput();

    $out = "\n<form method=post>";


    $rs = $this->Subtopics(); if ($rs->HasRows()) {

    $out .= "\n"; $out .= "\n";

    $isOdd = TRUE; while ($rs->NextRow()) { $isOdd = !$isOdd; $ftStyleShade = $isOdd?'ffffff':'#cccccc'; $ftStyle = ' style="background: '.$ftStyleShade.';"';

    $id = $rs->KeyString(); $ftID = $rs->AdminLink(); $ftName = $rs->Value('Name'); $ftNameTree = $rs->Value('NameTree'); $ftNameFull = $rs->Value('NameFull'); $ftSort = $rs->Value('Sort'); $ftVari = $rs->Value('Variants'); $ftMisp = $rs->Value('Mispeled');

    $out .= "\n<tr$ftStyle>"

    ."" ."" ."" ."" ."" ."" ."" .""; } $out .= "\n
    IDNamein treefullsortvariantsmis-spellings
    $ftID$ftName$ftNameTree$ftNameFull$ftSort$ftVari$ftMisp
    ";

    } else { $out .= 'None found.'; } $out .= '
    '.$htStatus; $out .= $ctrlList->RenderForm_Entry(); $out .= '</form>'; return $out;

       }
       protected function TitleListing() {
    

    global $wgRequest; global $vgPage;

    // check for any form actions $doChk = $wgRequest->GetBool('btnChkTitles'); $doAdd = $wgRequest->GetBool('btnAddTitles'); $doRmv = $wgRequest->GetBool('btnRmvTitles');

    $htStatus = NULL;

    // pass-along vars for anon functions $tblTitles = $this->Engine()->Titles(); // for anon function to use $tblTitleTopics = $this->Engine()->TitleTopics(); $me = $this;

    $ctrlList = new clsWidget_ShortList(); $arOpts = array( 'name' => 'title', 'btnChk_Text' => 'Enter titles:', 'btnChg_Text' => '<= Add', 'txtCargo_sng' => 'title ID', 'txtCargo_plr' => 'title IDs', 'txtProd_sng' => 'title', 'txtProd_plr' => 'titles', 'fHandleData_Check' => function($iVal) use ($tblTitles) { $obj = $tblTitles->GetItem($iVal); // for now, assume title is ID

    $arOut['html'] = $obj->AdminLink($obj->CatNum(),$obj->Value('Name')); //$arOut['text'] = $obj->KeyValue().'('.$obj->CatNum().')'; $arOut['text'] = $obj->KeyValue(); return $arOut; }, 'fHandleData_Change_Start' => function($iText) use ($me) { $arEv = array( 'descr' => 'Adding '.$iText, 'code' => 'sub++', 'where' => __METHOD__ ); $me->StartEvent($arEv); }, 'fHandleData_Change_Finish' => function($iText) use ($me) { $arEv = array( 'descrfin' => $iText ); $me->FinishEvent($arEv); }, 'fHandleData_Change_Item' => function($iVal) use ($me,$tblTitleTopics) { $txt = $iVal; $arIns = array( 'ID_Title' => SQLValue($txt), 'ID_Topic' => SQLValue($me->KeyValue()) ); //$this->Engine()->TitleTopics()->Insert($arIns); $sql = $tblTitleTopics->Insert($arIns); $out = SQLValue($txt); return $out; }, ); $ctrlList->Options($arOpts); $htStatus = $ctrlList->HandleInput(); if ($wgRequest->GetBool('btnRmvTitles')) { $arRmv = $wgRequest->GetArray('rmvTitle'); $cntRmv = count($arRmv); $arEv = array( 'descr' => 'Removing '.$cntRmv.' title'.Pluralize($cntRmv).' from this topic', 'code' => 'TTL--', 'where' => __METHOD__ ); $this->StartEvent($arEv); $txtRmv = ; foreach ($arRmv as $id => $on) { $sqlFilt = '(ID_Topic='.$this->ID.') AND (ID_Title='.$id.')'; $this->Engine()->TitleTopics()->Delete($sqlFilt); $txtRmv .= ' '.$id; } $arEv = array( 'descrfin' => 'Titles removed:'.$txtRmv ); $this->FinishEvent($arEv); $htStatus .= 'Titles removed:'.$txtRmv; }

    $out = "\n<form name=\"add-titles\" method=post>";

    $rs = $this->Titles(); if ($rs->HasRows()) {

    $out .= "\n"; $out .= "\n";

    $isOdd = TRUE; while ($rs->NextRow()) { $isOdd = !$isOdd; $ftStyleShade = $isOdd?'ffffff':'#cccccc'; $ftStyle = ' style="background: '.$ftStyleShade.';"';

    $id = $rs->KeyString(); $ftID = $rs->AdminLink(); $ftCatNum = $rs->CatNum(); $ftName = $rs->Value('Name'); $rsDept = $rs->DeptObj(); $ftDept = $rsDept->AdminLink_name(); $ftAdded = $rs->Value('DateAdded'); $ftUnavail = $rs->Value('DateUnavail');

    $out .= "\n<tr$ftStyle>"

    ."" ."" ."" ."" ."" ."" .""; } $out .= "\n
    IDCat #NameDeptWhen AddedWhen Unavail
    <input type=checkbox name=\"rmvTitle[$id]\">$ftID$ftCatNum$ftName$ftDept$ftAdded$ftUnavail
    ";

    $out .= '<input type=submit name="btnRmvTitles" value="Remove Checked">'; } else { $out .= 'None found.'; } $out .= '
    '.$htStatus; $out .= $ctrlList->RenderForm_Entry(); /* $out .= '<input type=submit name="btnChkTitles" value="Add These:">'; $out .= '<input size=40 name=txtNewTitles> (IDs separated by spaces)';

    • /

    $out .= '</form>'; return $out;

       }
       /*----
         What uses this?
    
       */
       public function AdminList() {
    

    $objRecs = $this;

    if ($objRecs->HasRows()) { $out = "{| class=sortable\n|-\n! ID || Name || Abbr || When Avail || Superceded || Status"; $isOdd = TRUE; while ($objRecs->NextRow()) { $objTopic = $this->objDB->Topics()->GetItem($this->ID_Topic); $id = $objTopic->ID; $ftID = $id; $out .= "\n|- style=\"$wtStyle\"". "\n| ".$ftID. ' || '.$objRecs->Name. ' || '.$objRecs->Abbr. ' || '.$strDate. ' || '.$strSuper. ' || '.$strStatus; $isOdd = !$isOdd; } $out .= "\n|}"; } else { $out = 'No topics found.'; } return $out;

       }
       /*----
         HISTORY:
    

    2010-10-11 Created -- then discovered that it probably doesn't need to be a separate function... but I think it makes things clearer.

       */
       public function Twigs() {
    

    if (is_null($this->ID)) { $sql = 'ID_Parent IS NULL'; } else { $sql = 'ID_Parent='.$this->ID; } $objRows = $this->Table->GetData($sql,NULL,'Sort,NameTree,Name'); return $objRows;

       }
       public function DrawTree($iLevel=0,$iRootName="Topics") {
    

    global $vgPage;

    $out = ; $intLevel = $iLevel + 1; $strIndent = str_repeat('*',$intLevel);

    $objRows = $this->Twigs(); if ($objRows->HasRows()) { if (empty($iLevel)) { $strName = $this->Name; if (empty($strName)) { $strName = $iRootName; } $out .= "\n{{#tree:id=root|root=$strName|"; $vgPage->UseWiki(); } while ($objRows->NextRow()) { $strNameTree = $objRows->NameTree; $strTwig = ifEmpty($strNameTree,$objRows->Name); $out .= "\n$strIndent".$objRows->AdminLink($strTwig); $out .= $objRows->DrawTree($intLevel); } if ($iLevel == 0) { $out .= "\n}}"; $vgPage->UseWiki(); } return $out; } else { if (empty($iLevel)) { return 'NO TOPICS FOUND'; } else { return NULL; } }

       }
    

    } class clsAdminTitleTopic_Titles extends clsTitleTopic_Titles {

       public function __construct(clsDatabase $iDB) {
    

    parent::__construct($iDB);

    	  $this->ClassSng('VbzAdminTitle');
    

    $this->ActionKey($this->Engine()->Titles()->ActionKey());

       }
    

    } class clsAdminTitleTopic_Topics extends clsTitleTopic_Topics {

       public function __construct(clsDatabase $iDB) {
    

    parent::__construct($iDB); $this->ClassSng('clsAdminTopic'); $this->ActionKey($this->Engine()->Topics()->ActionKey());

       }
    

    } /*========== | UTILITY FUNCTIONS | These should probably go into a separate file at some point

    • /

    /*----

     PURPOSE: This is the newer version of WhoString_wt
       which uses WhoAdmin, WhoSystem, and WhoNetwork
       instead of VbzUser, SysUser, and Machine
    
    • /

    function WhoString2_wt($iRow) {

       $htUnknown = '?';
    
       if (isset($iRow['WhoSystem'])) {
    

    $strSysUser = $iRow['WhoSystem']; $hasSysUser = TRUE;

       } else {
    

    $strSysUser = NULL; $hasSysUser = FALSE;

       }
       $strMachine	= $iRow['WhoNetwork'];
       $strVbzUser	= $iRow['WhoAdmin'];
    
       $htSysUser	= is_null($strSysUser)?$htUnknown:$strSysUser;
       $htMachine	= is_null($strMachine)?$htUnknown:$strMachine;
       $htVbzUser	= is_null($strVbzUser)?$htUnknown:$strVbzUser;
    
       $htWho = $htVbzUser;
       if ($hasSysUser) {
    

    $htWho .= '/'.$htSysUser;

       }
       $htWho .= '@'.$htMachine;
    
       return $htWho;
    

    } /*

     STATUS: DEPRECATED
       Where possible, convert table fieldnames to be compatible with WhoString2_wt
    
    • /

    function WhoString_wt($iRow) {

       $htUnknown = '?';
    
       if (isset($iRow['SysUser'])) {
    

    $strSysUser = $iRow['SysUser']; $hasSysUser = TRUE;

       } else {
    

    $strSysUser = NULL; $hasSysUser = FALSE;

       }
       $strMachine	= $iRow['Machine'];
       $strVbzUser	= $iRow['VbzUser'];
    
       $htSysUser	= is_null($strSysUser)?$htUnknown:$strSysUser;
       $htMachine	= is_null($strMachine)?$htUnknown:$strMachine;
       $htVbzUser	= is_null($strVbzUser)?$htUnknown:$strVbzUser;
    
       $htWho = $htVbzUser;
       if ($hasSysUser) {
    

    $htWho .= '/'.$htSysUser;

       }
       $htWho .= '@'.$htMachine;
    
       return $htWho;
    

    } function SelfLink_Page($iPage,$iKey,$iVal,$iText=NULL) {

       $strText = (is_null($iText))?$iVal:$iText;
       if (is_null($strText)) {
    

    return NULL;

       } else {
    

    return ''.$strText.'';

       }
    

    }

    function WikiSelfLink($iArgs,$iText) { // this function is deprecated; gradually convert to SelfLink and then rename it

     return ''.$iText.'';
    

    } function WikiSectionHdr($iTitle,$iMenuName,array $iMenu) {

       global $vgPage;
    
    $out = '

    '; foreach ($iMenu as $name=>$arLink) { $htPath = $arLink['path']; $htPopup = $arLink['popup']; $htDispl = $arLink['displ']; $out .= '[<a href="'.$htPath.'" title="'.$htPopup.'">'.$htDispl.'</a>] '; } $out .= ''.$iTitle.'

    ';
       return $out;
    

    } function WikiSectionHdr_Edit($iTitle,$iEditTitle) {

       global $vgPage;
    

    // global $vgOut;

       $doEdit = $vgPage->Arg('edit');
       $arLink = array(
         'edit'	=> !$doEdit,
         'page'	=> $vgPage->Arg('page'),
         'id'	=> $vgPage->Arg('id')
         );
       $htPath = $vgPage->SelfURL($arLink,TRUE);
    
    $out = '

    '; if ($doEdit) { $out .= '[<a href="'.$htPath.'" title="View '.$iEditTitle.'">view</a>] '; } else { $out .= '[<a href="'.$htPath.'" title="Edit '.$iEditTitle.'">edit</a>] '; } $out .= ''.$iTitle.'

    ';
       return $out;
    

    }

    if (!function_exists('TimeStamp_HideTime')) { //-- function TimeStamp_HideTime($iStamp) {

       if (is_string($iStamp)) {
    

    $intStamp = strtotime($iStamp);

       } else if (is_int($iStamp)) {
    

    $intStamp = $iStamp;

       } else {
    

    $intStamp = NULL;

       }
       if (!is_null($intStamp)) {
    

    return date('Y-m-d',$intStamp);

       } else {
    

    return NULL;

       }
    

    } //-- }

    function IsWebSecure() {

       if (isset($_SERVER["HTTPS"])) {
    

    return $_SERVER["HTTPS"] == 'on';

       } else {
    

    return FALSE;

       }
    

    }</php>