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

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