VbzCart/docs/archive/code/admin.cache

From Woozle Writes Code
< VbzCart‎ | docs‎ | archive‎ | code
Revision as of 12:14, 13 May 2012 by imported>Woozle (current version (can't save it!))
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Code

<php><?php /*

 LIBRARY: admin.cache.php - administration of cache management tables using MW UI
 HISTORY:
   2010-11-08 extracting from SpecialVbzAdmin
   2010-11-09 renaming "data" to "cache"

Also renamed everything "Proc" to "Query", but then later decided this was not as great an idea as I originally thought because procs are really the way to do this.

   2010-11-11 renaming "query" back to "proc"
  • /

class clsAdminCacheMgr extends clsCacheMgr { // STATIC methods -- these should later be methods of descendent classes of the component tables

   /*----
     INPUT:

iName: what to display for a page (or interwiki) link iPfx: full name of page (or interwiki) link, but without the name (iPfx+iName = full page name)

   */
   static public function PageLink($iName,$iPfx) {

global $vgOut;

return $vgOut->InternalLink($iPfx.$iName,$iName);

   }
   static public function TableLinkDoc($iName) {

return self::PageLink($iName,kwp_DocTblPfx);

   }
   static public function ProcLinkDoc($iName) {

return self::PageLink($iName,kwp_DocPrcPfx);

   }

// OVERRIDE methods

   protected function NewTblTables($iName) {

return new clsAdminCacheTables($this, $iName);

   }
   protected function NewTblProcs($iName) {

return new clsAdminCacheProcs($this,$iName);

   }
   protected function NewTblFlows($iName) {

return new clsAdminCacheFlows($this,$iName);

   }
   protected function NewTblEvents($iName) {

return new clsAdminCacheEvents($this,$iName);

   }

// DYNAMIC methods

   public function MenuDispatch($iAction,$iID=NULL) {

switch ($iAction) { case 'cache': $this->AdminPage(); break; case 'cache.tbl': $obj = $this->Tables->GetItem($iID); $obj->AdminPage(); break; case 'cache.proc': $obj = $this->Procs->GetItem($iID); $obj->AdminPage(); break; }

   }
   public function AdminPage() {

global $wgRequest, $wgOut; global $vgPage, $vgOut; $vgPage->UseWiki();

$out = '==Cache Management=='."\n"; $wgOut->addWikiText($out,TRUE); $out = ;

$dbVBZ = $this->Engine();

// check for action requests $strDo = $vgPage->Arg('do'); //$strTbls = $vgPage->Arg('id.table'); if ($strDo != ) { $idTbl = $vgPage->Arg('id'); if (is_numeric($idTbl)) { $objTbl = $this->Tables->GetItem($idTbl); } switch ($strDo) { case 'update': $out .= $objTbl->UpdateData_Verbose(); $out .= '
Update of '.$objTbl->AdminLink_Name().' complete.'; break; case 'stamp': $arRes = $objTbl->UpdateTime(__METHOD__); $out .= 'Stamped '.$objTbl->AdminLink_Name(); $out .= "\n* Was: ".$arRes['was']; $out .= "\n* SQL: ".$arRes['sql']; break; case 'clear': $arRes = $objTbl->ClearTime(__METHOD__); $out .= 'Cleared '.$objTbl->AdminLink_Name(); $out .= "\n* Was: ".$arRes['was']; $out .= "\n* SQL: ".$arRes['sql']; break; /* case 'table-info': $out = $this->AdminTable($idTbl); break; case 'table-update': $out = $this->UpdateTable($idTbl,'Special:VbzAdmin'); break; case 'table-stamp'; $out = $dbVBZ->StampTable($idTbl); break;

  • /

} $wgOut->addWikiText($out,TRUE); $out = ; } else { // display the current status $out = '===Cache Tables==='."\n"; $wgOut->addWikiText($out,TRUE); $out = ; //$out = $this->ShowTables($strTbls); $out = $this->ShowTables(); $wgOut->addWikiText($out,TRUE); $out = ; $out = '===Cache Procedures==='."\n"; $wgOut->addWikiText($out,TRUE); $out = ; $this->ShowProcs(); } $dbVBZ->Shut();

   }
   public function ShowProcs() {

global $vgPage,$vgOut;

$vgPage->UseHTML();

$tblProcs = $this->Procs;

$objRows = $tblProcs->DataSet(); // get all rows

if ($objRows->hasRows()) { $out = $vgOut->TableOpen('class=sortable'); $out .= $vgOut->TblRowOpen(NULL,TRUE); $out .= $vgOut->TblCell('procedure name'); $out .= $vgOut->TblCell('A?'); $out .= $vgOut->TblCell('Clr?'); $out .= $vgOut->TblCell('notes'); $out .= $vgOut->TblRowShut(); while ($objRows->NextRow()) { $out .= $vgOut->TblRowOpen(); //$ftName = $this->ProcLinkDoc($objRows->Name); $ftName = $objRows->AdminLink_Name(); $isActive = $objRows->Value('isActive'); if (!$isActive) { $ftName = ''.$ftName.''; } $out .= $vgOut->TblCell($ftName); $out .= $vgOut->TblCell($isActive?'√':'-'); $out .= $vgOut->TblCell(($objRows->Value('doesClear'))?'√':'-'); $out .= $vgOut->TblCell($objRows->Value('Notes')); $out .= $vgOut->TblRowShut(); } $out .= $vgOut->TableShut(); } else { $out .= 'No procedures found!'; } $vgOut->AddText($out);

   }
   /*----
     FUTURE:

Rename ShowTables() -> AdminTables() Move most of the code into clsAdminTables

   */
   public function ShowTables() {

global $vgPage,$vgOut;

$objPage = $vgPage; $vgPage->UseWiki();

//$objTbls = $this->objDB->DataSet('SELECT * FROM '.$this->Tables->Name().' WHERE Name != "" ORDER BY Name'); $objTbls = $this->Tables->GetData('Name != ""',NULL,'Name');

if ($objTbls->hasRows()) { $out = "{| class=sortable \n|-\n! table name || last update || sources || targets || notes"; while ($objTbls->NextRow()) { if ($objTbls->Value('isActive')) { //$strTbl = $objTbls->Name; $idTbl = $objTbls->KeyValue();

$objSrces = $this->Sources($idTbl); $objTargs = $this->Targets($idTbl); $cntSrces = $objSrces->RowCount(); $cntTargs = $objTargs->RowCount();

// table info open/shut calculations // $doInfo = isset($lstTbls[$idTbl]);

$htTblName = $objTbls->AdminLink_Name();

// common elements in action links $arLink = $vgPage->Args(array('page')); $arLink['id'] = $idTbl;

// source table list: if ($cntSrces) { /* $arLink = array( 'id' => $idTbl, 'do' => 'table-update' ); $txtSrces .= $objPage->SelfLink($arLink,'update').' ('.$cntSrces.')';

  • /

$arLink['do'] = 'update'; $ftLink = $vgOut->SelfLink($arLink,'update','update this table from its sources'); $txtSrces = $cntSrces.'→'.$ftLink; } else { $txtSrces = ; } // target table list:

if ($cntTargs) { $arLink['do'] = 'clear'; $ftLink1 = $vgOut->SelfLink($arLink,'un','clear the time-updated stamp for this table');

$arLink['do'] = 'stamp'; $ftLink2 = $vgOut->SelfLink($arLink,'stamp','update the time-updated stamp for this table');

$txtTargs = '('.$ftLink1.')'.$ftLink2.'→'.$cntTargs; } else { $txtTargs = ; }

$out .= "\n|-\n| ".$htTblName. ' || ' . $objTbls->Value('WhenUpdated') . ' || '.$txtSrces. ' || '.$txtTargs. ' || '.$objTbls->Value('Notes');

// if table is selected to show info, add a row for that: /* if ($doInfo) { $out .= "\n|-\n| colspan=5 |"; if ($objSrces->hasRows()) { $out .= "\n* Sources:"; while ($objSrces->NextRow()) { $objSrce = $objDataMgr->Tables->GetItem($objSrces->ID_Srce); if ($objSrce->isActive) { $strName = $objSrce->Name; $out .= ' '.$strName.''; } else { $out .= " N/A id=".$objSrces->ID_Srce.""; } } } if ($objTargs->hasRows()) { $out .= "\n* Targets:"; while ($objTargs->NextRow()) { $objTarg = $objDataMgr->Tables->GetItem($objTargs->ID_Dest); if ($objTarg->isActive) { $strName = $objTarg->Name; $out .= ' '.$strName.''; } else { $out .= " N/A id=".$objTargs->ID_Dest.""; } } } }

  • /

} } $out .= "\n|}"; } else { $out .= 'ERROR: Mysterious lack of data'; } return $out;

   }

} class clsAdminCacheTables extends clsCacheTables {

   protected $arMap,$arCkd;
   public function __construct(clsCacheMgr $iMgr,$iName) {

parent::__construct($iMgr,$iName); $this->ClassSng('clsAdminCacheTable'); $this->ActionKey('cache.tbl');

   }

// INFORMATION methods

   /*----
     RETURNS: recordset of targets with more recently-updated sources
     HISTORY:

2011-12-21 created for update-cat maintenance script

   */
   public function UpdatedTargets() {

// map out the cache and find out what needs to be run initially Write('Mapping the cache...'); $rcFlows = $this->Mgr()->Flow->GetData(); // get table of all flows $this->arMap = $rcFlows->FullMap(); $this->arCkd = array();

WriteLn(' ok'); $arRun = $this->arMap['run']; $cntRun = count($arRun); if ($cntRun > 0) { WriteLn('Starting with '.$cntRun.' update'.Pluralize($cntRun).':'); $this->RunUpdates($arRun); }

   }
   /*----
     INPUT:

$arRun: array of procs that need to be run

     NOTE: This does not take a rigorous approach to preventing loops.

It just cuts off execution after the same Proc has been executed more than a preset number of times. There's probably a very tidy algorithmic way to figure out what order everything should be executed in while rigorously preventing recursion, but I don't have time to figure it out right now.

     HISTORY:

2011-12-22 created for command line utility 2011-12-24 allowing limited number of duplicate Procs

   */
   public function RunUpdates(array $arRun) {

$tblT = $this->Mgr()->Tables; $rcT = $tblT->SpawnItem(); $arDone = array(); do { $isMore = FALSE; $arRunNext = array();

// display run list WriteLn("----------\nTO RUN:"); foreach ($arRun as $idP => $objP) { $txt = ' '.$objP->NameFull(); $msg = NULL; if (array_key_exists($idP,$arDone)) { $cnt = $arDone[$idP]; if ($cnt > 2) { $msg = ' - LOOP DETECTED; quitting.'; die($txt.$msg."\n"); } $msg = ' - repeat #'.$cnt; $arDone[$idP]++; } else { $arDone[$idP] = 1; } WriteLn($txt.$msg); }

foreach ($arRun as $idP => $objP) { Write('PROC: '.$objP->NameFull()); $arEx = $objP->Execute(TRUE); // FALSE = debug mode -- don't actually write data WriteLn(' - '.$arEx['text']);

if (array_key_exists('targ',$arEx)) { $arT = $arEx['targ']; // target tables updated if (count($arT) > 0) {

   //		    WriteLn(' - updated:');

// get list of procs that supply those tables foreach ($arT as $idT => $rowT) { WriteLn(' - updated TABLE: ['.$idT.'] '.$rowT['Name']); $rcT->Values($rowT); $arP = $rcT->TargProcs(); if (is_array($arP)) { foreach ($arP as $dummy => $rowP) { WriteLn(' -- used by PROC: '.$rowP->NameFull()); } $arRunNext = ArrayJoin($arRunNext,$arP,TRUE,TRUE); // replace = yes (probably n/a), append = yes

   //			    $isMore = TRUE;

} } } }

if (array_key_exists($idP,$arRunNext)) { WriteLn(' - removing '.$objP->NameFull().' from next run list'); unset($arRunNext[$idP]); $txt = ; foreach ($arRunNext as $idP => $objP) { $txt .= ' '.$idP; } WriteLn(' - list is now:'.$txt); }

} // ultimately, this list may need to be sorted too: $arRun = $arRunNext; $isMore = Count($arRun) > 0; /* Write('TO RUN NEXT:'); foreach ($arRun as $id => $objP) { Write(' '.$objP->Name()); } WriteLn();

  • /

} while ($isMore);

   }

/*

   protected function FindFlowSources(array $iSrce) {

$arOut = array(); foreach ($iSrce as $id => $obj) { // Write(' -- source ID='.$id.' - '.$obj->Value('Name')); if ($obj->IsActive()) { // WriteLn(); $ar = $this->FindRoots($obj); foreach ($ar as $id => $row) { if (!array_key_exists($id,$arOut)) { $arOut[$id] = $row; } } } else { // WriteLn(' - INACTIVE'); } } return $arOut;

   }
  • /

} class clsAdminCacheTable extends clsCacheTable {

// BOILERPLATE methods

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

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

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

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

   }
   public function DocLink() {

return $this->Mgr()->TableLinkDoc($this->Value('Name'));

   }

// ACTION methods

   /*----
     ACTION: Run $this->UpdateData() and display results
   */
   public function UpdateData_Verbose() {

global $vgPage, $vgUserName;

$out = ; //$arRes = $this->Update_byID($iID,$vgUserName.': '.__METHOD__); $arRes = $this->UpdateData($vgUserName.': '.__METHOD__); $out .= $arRes['msgs']; if (is_array($arRes['proc'])) { $arDone = $arRes['proc']; $out .= "\n===Update Procedures Run===\n"; foreach($arDone AS $obj) { $out .= "\n* ".$obj->Value('Name'); } } else { $out .= '
No procedures were executed.'; } if (is_array($arRes['targ'])) { $arDone = $arRes['targ']; $out .= "\n===Tables Updated===\n"; foreach($arDone AS $id=>$row) { $out .= "\n* ".$row['Name']; } } else { $out .= '
No tables were updated.'; } return $out;

   }

// ADMIN DISPLAY methods

   public function AdminPage() {

global $wgRequest; global $vgPage,$vgOut;

$vgPage->UseWiki();

$out = '==Table: '.$this->Value('Name')."==\n";

$out .= "Note: ADD and DELETE have not yet been tested, and they do not yet log changes.\n";

$idTbl = $this->Value('ID'); $out .= '===Table Record==='; $out .= "\n* ID: $idTbl"; $out .= "\n* Name: ".$this->DocLink(); $out .= "\n* Updated: ".$this->Value('WhenUpdated'); $out .= "\n* Notes: ".$this->Value('Notes');

$vgOut->AddText($out); $out=;

// check for any form input (adding flows/procs) $doAddSrce = $wgRequest->getBool('btnAddSrce'); $doAddTarg = $wgRequest->getBool('btnAddTarg'); if ($doAddSrce || $doAddTarg) { $idProc = $wgRequest->getBool('ID_Proc'); $doWrite = $doAddSrce; // if proc is a source, then it writes to this table $txtNotes = $wgRequest->getText('Notes'); $this->Mgr()->Flows->Add($iProc,$this->ID,$doWrite,$txtNotes); }

$vgPage->UseHTML();

// SOURCES cell (left): $out .= $vgOut->Header('Table Sources',3); $out .= $this->AdminSources();

// TARGETS cell (right): $out .= $vgOut->Header('Table Targets',3); $out .= $this->AdminTargets();

$vgOut->AddText($out);

   }
   public function AdminSources() {

$objRows = $this->Mgr()->Sources($this->KeyValue()); return $objRows->AdminList('btnAddSrce');

   }
   public function AdminTargets() {

$objRows = $this->Mgr()->Targets($this->KeyValue()); return $objRows->AdminList('btnAddTarg');

   }

} class clsAdminCacheProcs extends clsCacheProcs {

   public function __construct(clsCacheMgr $iMgr,$iName) {

parent::__construct($iMgr,$iName); $this->ClassSng('clsAdminCacheProc'); $this->ActionKey('cache.proc');

   }

} class clsAdminCacheProc extends clsCacheProc {

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

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

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

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

   }
   public function DocLink() {

return $this->Mgr()->ProcLinkDoc($this->Value('Name'));

   }
   public function AdminPage() {

global $vgPage,$vgOut;

$vgPage->UseHTML();

$out = $vgOut->Header('Procedure: '.$this->Value('Name'));

$out .= '

    '; $out .= '
  • ID: '.$this->KeyValue(); $out .= '
  • Name: '.$this->DocLink(); $out .= '
  • Active: '.NoYes($this->Value('isActive')); $out .= '
  • Clears: '.NoYes($this->Value('doesClear')); $out .= '

';

$vgOut->AddText($out); $out=;

$rcFlows = $this->Mgr()->Flow->Data_forProc($this->KeyValue()); if ($rcFlows->HasRows()) { $ar = $rcFlows->PoolMap(); /* while ($rcFlows->NextRow()) { $idTbl = $rcFlows->Value('ID_Table'); $objTbl = $this->Mgr()->Tables->GetItem($idTbl); if ($rcFlows->Value('doWrite')) { // the proc writes to these tables $arTarg[$idTbl] = $objTbl; } else { // the proc reads from these tables $arSrce[$idTbl] = $objTbl; } }

  • /

$arTarg = $ar['targ']; $arSrce = $ar['srce']; $dtNewest = NULL; $dtOldest = NULL;

$out .= $vgOut->Header('Source Tables',3); if (isset($arSrce)) {

$out .= '

    '; foreach ($arSrce as $id => $objTbl) { $dtThis = $objTbl->Value('WhenUpdated'); if ($dtThis > $dtNewest) { $dtNewest = $dtThis; } $strTime = (is_null($dtThis)?'never updated':('updated '.$dtThis)); $out .= '
  • '.$objTbl->AdminLink_Name().' - '.$strTime; } $out .= '

';

} else { $out .= 'No sources found.'; }

$out .= $vgOut->Header('Target Tables',3); if (isset($arTarg)) {

$out .= '

    '; foreach ($arTarg as $id => $objTbl) { $dtThis = $objTbl->Value('WhenUpdated'); if (($dtThis < $dtOldest) || (is_null($dtOldest))) { $dtOldest = $dtThis; } $strTime = (is_null($dtThis)?'never updated':('updated '.$dtThis)); $out .= '
  • '.$objTbl->AdminLink_Name().' - '.$strTime; } $out .= '

';

} else { $out .= 'No targets found.'; } $out .= $vgOut->Header('Status',3); if ($dtOldest < $dtNewest) { $out .= 'Update needed.'; } else { $out .= 'This table is up-to-date.'; } } else { $out .= 'This procedure is not used.'; }

$vgOut->AddText($out);

   }

} class clsAdminCacheFlows extends clsCacheFlows {

   public function __construct(clsCacheMgr $iMgr,$iName) {

parent::__construct($iMgr,$iName); $this->ClassSng('clsAdminCacheFlow'); $this->ActionKey('cache.flow');

   }

} class clsAdminCacheFlow extends clsCacheFlow {

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

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

   }
   /*----
     ACTION: Render administrative controls for the current dataset of flows
     INPUT: name of button for adding another row.

If no name given, does not display button.

     RETURNS: formatted text using $vgOut
   */
   public function AdminList($iAddBtn=NULL) {

global $vgOut;

$out = NULL; if ($this->hasRows()) { $out .= $vgOut->TableOpen('class=sortable'); $out .= $vgOut->TblRowOpen(NULL,TRUE); $out .= $vgOut->TblCell('Procedure'); $out .= $vgOut->TblCell('Action'); $out .= $vgOut->TblCell('notes'); $out .= $vgOut->TblRowShut();

$doBtn = !is_null($iAddBtn);

$objMgr = $this->Mgr(); assert('is_object($this->objMgr)'); $objProcs = $objMgr->Procs; $arProcs = NULL;

$isOdd = TRUE; while ($this->NextRow()) { $row = $this->Row;

$ftStyle = $isOdd?'background:#ffffff;':'background:#eeeeee;'; $htStyle = 'style="'.$ftStyle.'"'; $isOdd = !$isOdd;

$idProc = $this->Value('ID_Proc'); $objProc = $objProcs->GetItem($idProc); $ftProc = $objProc->AdminLink_Name();

// exclusion array for drop-down: $arProcs[$idProc] = TRUE;

$ftAct = $this->AdminLink('del');

$ftNotes = $this->Value('Notes');

$out .= $vgOut->TblRowOpen($htStyle); $out .= $vgOut->TblCell($ftProc); $out .= $vgOut->TblCell($ftAct); $out .= $vgOut->TblCell($ftNotes); $out .= $vgOut->TblRowShut(); }

// display a row for adding a proc if ($doBtn) { $out .= '<form method=POST>'; $out .= $vgOut->TblRowOpen(); $out .= $vgOut->TblCell($objProcs->DropDown('ID_Proc',NULL,$arProcs)); $out .= $vgOut->TblCell('<input type=submit name="'.$iAddBtn.'" value="Add">'); $out .= $vgOut->TblCell('<input name="notes">'); $out .= $vgOut->TblRowShut(); $out .= '</form>'; } $out .= $vgOut->TableShut(); } else { $out .= 'none'; } return $out;

   }

}

class clsAdminCacheEvents extends clsCacheEvents {

   public function __construct(clsCacheMgr $iMgr,$iName) {

parent::__construct($iMgr,$iName); $this->ClassSng('clsAdminCacheEvent'); $this->ActionKey('cache.event');

   }

} class clsAdminCacheEvent extends clsCacheEvent {

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

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

   }

}</php>