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
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

<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>