Search:

# CWIS Developers Documentation

- Main Page
- Classes
- Files

- File List
- File Members

# ApplicationFramework.php

Go to the documentation of this file.

    00001 <?PHP
    00002
    00003 #
    00004 #   FILE:  ApplicationFramework.php
    00005 #
    00006 #   Part of the ScoutLib application support library
    00007 #   Copyright 2009-2011 Edward Almasy and Internet Scout
    00008 #   http://scout.wisc.edu
    00009 #
    00010
    00015 class ApplicationFramework {
    00016
    00017     # ---- PUBLIC INTERFACE --------------------------------------------------
    00018  /*@(*/
    00020
    00028     function __construct($ObjectDirectories = NULL)
    00029     {
    00030         # save execution start time
    00031         $this->ExecutionStartTime = microtime(TRUE);
    00032
    00033         # save object directory search list
    00034         if ($ObjectDirectories) {  $this->AddObjectDirectories($ObjectDirectories);  }
    00035
    00036         # set up object file autoloader
    00037         $this->SetUpObjectAutoloading();
    00038
    00039         # set up function to output any buffered text in case of crash
    00040         register_shutdown_function(array($this, "OnCrash"));
    00041
    00042         # set up our internal environment
    00043         $this->DB = new Database();
    00044
    00045         # load our settings from database
    00046         $this->DB->Query("SELECT * FROM ApplicationFrameworkSettings");
    00047         $this->Settings = $this->DB->FetchRow();
    00048         if (!$this->Settings)
    00049         {
    00050             $this->DB->Query("INSERT INTO ApplicationFrameworkSettings"
    00051                     ." (LastTaskRunAt) VALUES ('2000-01-02 03:04:05')");
    00052             $this->DB->Query("SELECT * FROM ApplicationFrameworkSettings");
    00053             $this->Settings = $this->DB->FetchRow();
    00054         }
    00055
    00056         # set PHP maximum execution time
    00057         $this->MaxExecutionTime($this->Settings["MaxExecTime"]);
    00058
    00059         # register events we handle internally
    00060         $this->RegisterEvent($this->PeriodicEvents);
    00061         $this->RegisterEvent($this->UIEvents);
    00062     }
    00070     function AddObjectDirectories($Dirs)
    00071     {
    00072         foreach ($Dirs as $Location => $Prefix)
    00073         {
    00074             $Location = $Location
    00075                     .((substr($Location, -1) != "/") ? "/" : "");
    00076             self::$ObjectDirectories = array_merge(
    00077                     array($Location => $Prefix),
    00078                     self::$ObjectDirectories);
    00079         }
    00080     }
    00081
    00087     function SetBrowserDetectionFunc($DetectionFunc)
    00088     {
    00089         $this->BrowserDetectFunc = $DetectionFunc;
    00090     }
    00091
    00096     function LoadPage($PageName)
    00097     {
    00098         # buffer any output from includes or PHP file
    00099         ob_start();
    00100
    00101         # include any files needed to set up execution environment
    00102         foreach ($this->EnvIncludes as $IncludeFile)
    00103         {
    00104             include($IncludeFile);
    00105         }
    00106
    00107         # sanitize incoming page name
    00108         $PageName = preg_replace("/[^a-zA-Z0-9_.-]/", "", $PageName);
    00109
    00110         # signal page load
    00111         $this->SignalEvent("EVENT_PAGE_LOAD", array("PageName" => $PageName));
    00112
    00113         # signal PHP file load
    00114         $SignalResult = $this->SignalEvent("EVENT_PHP_FILE_LOAD", array(
    00115                 "PageName" => $PageName));
    00116
    00117         # if signal handler returned new page name value
    00118         $NewPageName = $PageName;
    00119         if (($SignalResult["PageName"] != $PageName)
    00120                 && strlen($SignalResult["PageName"]))
    00121         {
    00122             # if new page name value is page file
    00123             if (file_exists($SignalResult["PageName"]))
    00124             {
    00125                 # use new value for PHP file name
    00126                 $PageFile = $SignalResult["PageName"];
    00127             }
    00128             else
    00129             {
    00130                 # use new value for page name
    00131                 $NewPageName = $SignalResult["PageName"];
    00132             }
    00133         }
    00134
    00135         # if we do not already have a PHP file
    00136         if (!isset($PageFile))
    00137         {
    00138             # look for PHP file for page
    00139             $OurPageFile = "pages/".$NewPageName.".php";
    00140             $LocalPageFile = "local/pages/".$NewPageName.".php";
    00141             $PageFile = file_exists($LocalPageFile) ? $LocalPageFile
    00142                     : (file_exists($OurPageFile) ? $OurPageFile
    00143                     : "pages/".$this->DefaultPage.".php");
    00144         }
    00145
    00146         # load PHP file
    00147         include($PageFile);
    00148
    00149         # save buffered output to be displayed later after HTML file loads
    00150         $PageOutput = ob_get_contents();
    00151         ob_end_clean();
    00152
    00153         # set up for possible TSR (Terminate and Stay Resident :))
    00154         $ShouldTSR = $this->PrepForTSR();
    00155
    00156         # if PHP file indicated we should autorefresh to somewhere else
    00157         if ($this->JumpToPage)
    00158         {
    00159             if (!strlen(trim($PageOutput)))
    00160             {
    00161                 ?><html>
    00162                 <head>
    00163                     <meta http-equiv="refresh" content="0; URL=<?PHP
    00164                             print($this->JumpToPage);  ?>">
    00165                 </head>
    00166                 <body bgcolor="white">
    00167                 </body>
    00168                 </html><?PHP
    00169             }
    00170         }
    00171         # else if HTML loading is not suppressed
    00172         elseif (!$this->SuppressHTML)
    00173         {
    00174             # set content-type to get rid of diacritic errors
    00175             header("Content-Type: text/html; charset="
    00176                 .$this->HtmlCharset, TRUE);
    00177
    00178             # load common HTML file (defines common functions) if available
    00179             $CommonHtmlFile = $this->FindCommonTemplate("Common");
    00180             if ($CommonHtmlFile) {  include($CommonHtmlFile);  }
    00181
    00182             # load UI functions
    00183             $this->LoadUIFunctions();
    00184
    00185             # begin buffering content
    00186             ob_start();
    00187
    00188             # signal HTML file load
    00189             $SignalResult = $this->SignalEvent("EVENT_HTML_FILE_LOAD", array(
    00190                     "PageName" => $PageName));
    00191
    00192             # if signal handler returned new page name value
    00193             $NewPageName = $PageName;
    00194             $PageContentFile = NULL;
    00195             if (($SignalResult["PageName"] != $PageName)
    00196                     && strlen($SignalResult["PageName"]))
    00197             {
    00198                 # if new page name value is HTML file
    00199                 if (file_exists($SignalResult["PageName"]))
    00200                 {
    00201                     # use new value for HTML file name
    00202                     $PageContentFile = $SignalResult["PageName"];
    00203                 }
    00204                 else
    00205                 {
    00206                     # use new value for page name
    00207                     $NewPageName = $SignalResult["PageName"];
    00208                 }
    00209             }
    00210
    00211             # load page content HTML file if available
    00212             if ($PageContentFile === NULL)
    00213             {
    00214                 $PageContentFile = $this->FindTemplate(
    00215                         $this->ContentTemplateList, $NewPageName);
    00216             }
    00217             if ($PageContentFile)
    00218             {
    00219                 include($PageContentFile);
    00220             }
    00221             else
    00222             {
    00223                 print "<h2>ERROR:  No HTML/TPL template found"
    00224                         ." for this page.</h2>";
    00225             }
    00226
    00227             # signal HTML file load complete
    00228             $SignalResult = $this->SignalEvent("EVENT_HTML_FILE_LOAD_COMPLETE");
    00229
    00230             # stop buffering and save output
    00231             $PageContentOutput = ob_get_contents();
    00232             ob_end_clean();
    00233
    00234             # load page start HTML file if available
    00235             ob_start();
    00236             $PageStartFile = $this->FindCommonTemplate("Start");
    00237             if ($PageStartFile) {  include($PageStartFile);  }
    00238             $PageStartOutput = ob_get_contents();
    00239             ob_end_clean();
    00240
    00241             # load page end HTML file if available
    00242             ob_start();
    00243             $PageEndFile = $this->FindCommonTemplate("End");
    00244             if ($PageEndFile) {  include($PageEndFile);  }
    00245             $PageEndOutput = ob_get_contents();
    00246             ob_end_clean();
    00247
    00248             # get list of any required files not loaded
    00249             $RequiredFiles = $this->GetRequiredFilesNotYetLoaded($PageContentFile);
    00250
    00251             # if a browser detection function has been made available
    00252             if (is_callable($this->BrowserDetectFunc))
    00253             {
    00254                 # call function to get browser list
    00255                 $Browsers = call_user_func($this->BrowserDetectFunc);
    00256
    00257                 # for each required file
    00258                 $NewRequiredFiles = array();
    00259                 foreach ($RequiredFiles as $File)
    00260                 {
    00261                     # if file name includes browser keyword
    00262                     if (preg_match("/%BROWSER%/", $File))
    00263                     {
    00264                         # for each browser
    00265                         foreach ($Browsers as $Browser)
    00266                         {
    00267                             # substitute in browser name and add to new file list
    00268                             $NewRequiredFiles[] = preg_replace(
    00269                                     "/%BROWSER%/", $Browser, $File);
    00270                         }
    00271                     }
    00272                     else
    00273                     {
    00274                         # add to new file list
    00275                         $NewRequiredFiles[] = $File;
    00276                     }
    00277                 }
    00278                 $RequiredFiles = $NewRequiredFiles;
    00279             }
    00280
    00281             # for each required file
    00282             foreach ($RequiredFiles as $File)
    00283             {
    00284                 # locate specific file to use
    00285                 $FilePath = $this->GUIFile($File);
    00286
    00287                 # if file was found
    00288                 if ($FilePath)
    00289                 {
    00290                     # determine file type
    00291                     $NamePieces = explode(".", $File);
    00292                     $FileSuffix = strtolower(array_pop($NamePieces));
    00293
    00294                     # add file to HTML output based on file type
    00295                     $FilePath = htmlspecialchars($FilePath);
    00296                     switch ($FileSuffix)
    00297                     {
    00298                         case "js":
    00299                             $Tag = '<script type="text/javascript" src="'
    00300                                     .$FilePath.'"></script>';
    00301                             $PageEndOutput = preg_replace(
    00302                                     "#</body>#i", $Tag."\n</body>", $PageEndOutput, 1);
    00303                             break;
    00304
    00305                         case "css":
    00306                             $Tag = '<link rel="stylesheet" type="text/css"'
    00307                                     .' media="all" href="'.$FilePath.'">';
    00308                             $PageStartOutput = preg_replace(
    00309                                     "#</head>#i", $Tag."\n</head>", $PageStartOutput, 1);
    00310                             break;
    00311                     }
    00312                 }
    00313             }
    00314
    00315             # write out page
    00316             print $PageStartOutput.$PageContentOutput.$PageEndOutput;
    00317         }
    00318
    00319         # run any post-processing routines
    00320         foreach ($this->PostProcessingFuncs as $Func)
    00321         {
    00322             call_user_func_array($Func["FunctionName"], $Func["Arguments"]);
    00323         }
    00324
    00325         # write out any output buffered from page code execution
    00326         if (strlen($PageOutput))
    00327         {
    00328             if (!$this->SuppressHTML)
    00329             {
    00330                 ?><table width="100%" cellpadding="5"
    00331                         style="border: 2px solid #666666;  background: #CCCCCC;
    00332                         font-family: Courier New, Courier, monospace;
    00333                         margin-top: 10px;"><tr><td><?PHP
    00334             }
    00335             if ($this->JumpToPage)
    00336             {
    00337                 ?><div style="color: #666666;"><span style="font-size: 150%;">
    00338                 <b>Page Jump Aborted</b></span>
    00339                 (because of error or other unexpected output)<br />
    00340                 <b>Jump Target:</b>
    00341                 <i><?PHP  print($this->JumpToPage);  ?></i></div><?PHP
    00342             }
    00343             print($PageOutput);
    00344             if (!$this->SuppressHTML)
    00345             {
    00346                 ?></td></tr></table><?PHP
    00347             }
    00348         }
    00349
    00350         # terminate and stay resident (TSR!) if indicated and HTML has been output
    00351         # (only TSR if HTML has been output because otherwise browsers will misbehave)
    00352         if ($ShouldTSR) {  $this->LaunchTSR();  }
    00353     }
    00354
    00361     function SetJumpToPage($Page)
    00362     {
    00363         if ((strpos($Page, "?") === FALSE)
    00364                 && ((strpos($Page, "=") !== FALSE)
    00365                     || ((strpos($Page, ".php") === FALSE)
    00366                         && (strpos($Page, ".htm") === FALSE)
    00367                         && (strpos($Page, "/") === FALSE))))
    00368         {
    00369             $this->JumpToPage = "index.php?P=".$Page;
    00370         }
    00371         else
    00372         {
    00373             $this->JumpToPage = $Page;
    00374         }
    00375     }
    00376
    00381     function JumpToPageIsSet()
    00382     {
    00383         return ($this->JumpToPage === NULL) ? FALSE : TRUE;
    00384     }
    00385
    00395     function HtmlCharset($NewSetting = NULL)
    00396     {
    00397         if ($NewSetting !== NULL) {  $this->HtmlCharset = $NewSetting;  }
    00398         return $this->HtmlCharset;
    00399     }
    00400
    00407     function SuppressHTMLOutput($NewSetting = TRUE)
    00408     {
    00409         $this->SuppressHTML = $NewSetting;
    00410     }
    00411
    00418     function ActiveUserInterface($UIName = NULL)
    00419     {
    00420         if ($UIName !== NULL)
    00421         {
    00422             $this->ActiveUI = preg_replace("/^SPTUI--/", "", $UIName);
    00423         }
    00424         return $this->ActiveUI;
    00425     }
    00426
    00442     function AddPostProcessingCall($FunctionName,
    00443             &$Arg1 = self::NOVALUE, &$Arg2 = self::NOVALUE, &$Arg3 = self::NOVALUE,
    00444             &$Arg4 = self::NOVALUE, &$Arg5 = self::NOVALUE, &$Arg6 = self::NOVALUE,
    00445             &$Arg7 = self::NOVALUE, &$Arg8 = self::NOVALUE, &$Arg9 = self::NOVALUE)
    00446     {
    00447         $FuncIndex = count($this->PostProcessingFuncs);
    00448         $this->PostProcessingFuncs[$FuncIndex]["FunctionName"] = $FunctionName;
    00449         $this->PostProcessingFuncs[$FuncIndex]["Arguments"] = array();
    00450         $Index = 1;
    00451         while (isset(${"Arg".$Index}) && (${"Arg".$Index} !== self::NOVALUE))
    00452         {
    00453             $this->PostProcessingFuncs[$FuncIndex]["Arguments"][$Index]
    00454                     =& ${"Arg".$Index};
    00455             $Index++;
    00456         }
    00457     }
    00458
    00464     function AddEnvInclude($FileName)
    00465     {
    00466         $this->EnvIncludes[] = $FileName;
    00467     }
    00468
    00475     function GUIFile($FileName)
    00476     {
    00477         # pull off file name suffix
    00478         $NamePieces = explode(".", $FileName);
    00479         $Suffix = strtolower(array_pop($NamePieces));
    00480
    00481         # determine which location to search based on file suffix
    00482         $ImageSuffixes = array("gif", "jpg", "png");
    00483         $FileList = in_array($Suffix, $ImageSuffixes)
    00484                 ? $this->ImageFileList : $this->CommonTemplateList;
    00485
    00486         # search for file
    00487         $FoundFileName = $this->FindTemplate($FileList, $FileName);
    00488
    00489         # add non-image files to list of found files
    00490         if (!in_array($Suffix, $ImageSuffixes))
    00491                 {  $this->FoundUIFiles[] = basename($FoundFileName);  }
    00492
    00493         # return file name to caller
    00494         return $FoundFileName;
    00495     }
    00496
    00506     function PUIFile($FileName)
    00507     {
    00508         $FullFileName = $this->GUIFile($FileName);
    00509         if ($FullFileName) {  print($FullFileName);  }
    00510     }
    00511
    00516     function FindCommonTemplate($PageName)
    00517     {
    00518         return $this->FindTemplate(
    00519                 array_merge($this->CommonTemplateList, $this->ContentTemplateList),
    00520                 $PageName);
    00521     }
    00522
    00531     function LoadFunction($Callback)
    00532     {
    00533         if (!is_callable($Callback) && is_string($Callback))
    00534         {
    00535             $Locations = $this->FunctionFileList;
    00536             foreach (self::$ObjectDirectories as $Location => $Prefix)
    00537             {
    00538                 $Locations[] = $Location."%PAGENAME%.php";
    00539                 $Locations[] = $Location."%PAGENAME%.html";
    00540             }
    00541             $FunctionFileName = $this->FindTemplate($Locations, "F-".$Callback);
    00542             if ($FunctionFileName)
    00543             {
    00544                 include_once($FunctionFileName);
    00545             }
    00546         }
    00547         return is_callable($Callback);
    00548     }
    00549
    00554     function GetElapsedExecutionTime()
    00555     {
    00556         return microtime(TRUE) - $this->ExecutionStartTime;
    00557     }
    00558
    00563     function GetSecondsBeforeTimeout()
    00564     {
    00565         return ini_get("max_execution_time") - $this->GetElapsedExecutionTime();
    00566     }
    00567
    00568     /*@)*/ /* Application Framework */
    00569
    00570     # ---- Event Handling ----------------------------------------------------
    00571  /*@(*/
    00573
    00577     const EVENTTYPE_DEFAULT = 1;
    00583     const EVENTTYPE_CHAIN = 2;
    00589     const EVENTTYPE_FIRST = 3;
    00597     const EVENTTYPE_NAMED = 4;
    00598
    00600     const ORDER_FIRST = 1;
    00602     const ORDER_MIDDLE = 2;
    00604     const ORDER_LAST = 3;
    00605
    00614     function RegisterEvent($EventsOrEventName, $EventType = NULL)
    00615     {
    00616         # convert parameters to array if not already in that form
    00617         $Events = is_array($EventsOrEventName) ? $EventsOrEventName
    00618                 : array($EventsOrEventName => $Type);
    00619
    00620         # for each event
    00621         foreach ($Events as $Name => $Type)
    00622         {
    00623             # store event information
    00624             $this->RegisteredEvents[$Name]["Type"] = $Type;
    00625             $this->RegisteredEvents[$Name]["Hooks"] = array();
    00626         }
    00627     }
    00628
    00642     function HookEvent($EventsOrEventName, $Callback = NULL, $Order = self::ORDER_MIDDLE)
    00643     {
    00644         # convert parameters to array if not already in that form
    00645         $Events = is_array($EventsOrEventName) ? $EventsOrEventName
    00646                 : array($EventsOrEventName => $Callback);
    00647
    00648         # for each event
    00649         $Success = TRUE;
    00650         foreach ($Events as $EventName => $EventCallback)
    00651         {
    00652             # if callback is valid
    00653             if (is_callable($EventCallback))
    00654             {
    00655                 # if this is a periodic event we process internally
    00656                 if (isset($this->PeriodicEvents[$EventName]))
    00657                 {
    00658                     # process event now
    00659                     $this->ProcessPeriodicEvent($EventName, $EventCallback);
    00660                 }
    00661                 # if specified event has been registered
    00662                 elseif (isset($this->RegisteredEvents[$EventName]))
    00663                 {
    00664                     # add callback for event
    00665                     $this->RegisteredEvents[$EventName]["Hooks"][]
    00666                             = array("Callback" => $EventCallback, "Order" => $Order);
    00667
    00668                     # sort callbacks by order
    00669                     if (count($this->RegisteredEvents[$EventName]["Hooks"]) > 1)
    00670                     {
    00671                         usort($this->RegisteredEvents[$EventName]["Hooks"],
    00672                                 array("ApplicationFramework", "HookEvent_OrderCompare"));
    00673                     }
    00674                 }
    00675                 else
    00676                 {
    00677                     $Success = FALSE;
    00678                 }
    00679             }
    00680             else
    00681             {
    00682                 $Success = FALSE;
    00683             }
    00684         }
    00685
    00686         # report to caller whether all callbacks were hooked
    00687         return $Success;
    00688     }
    00689     private static function HookEvent_OrderCompare($A, $B)
    00690     {
    00691         if ($A["Order"] == $B["Order"]) {  return 0;  }
    00692         return ($A["Order"] < $B["Order"]) ? -1 : 1;
    00693     }
    00694
    00703     function SignalEvent($EventName, $Parameters = NULL)
    00704     {
    00705         $ReturnValue = NULL;
    00706
    00707         # if event has been registered
    00708         if (isset($this->RegisteredEvents[$EventName]))
    00709         {
    00710             # set up default return value (if not NULL)
    00711             switch ($this->RegisteredEvents[$EventName]["Type"])
    00712             {
    00713                 case self::EVENTTYPE_CHAIN:
    00714                     $ReturnValue = $Parameters;
    00715                     break;
    00716
    00717                 case self::EVENTTYPE_NAMED:
    00718                     $ReturnValue = array();
    00719                     break;
    00720             }
    00721
    00722             # for each callback for this event
    00723             foreach ($this->RegisteredEvents[$EventName]["Hooks"] as $Hook)
    00724             {
    00725                 # invoke callback
    00726                 $Callback = $Hook["Callback"];
    00727                 $Result = ($Parameters !== NULL)
    00728                         ? call_user_func_array($Callback, $Parameters)
    00729                         : call_user_func($Callback);
    00730
    00731                 # process return value based on event type
    00732                 switch ($this->RegisteredEvents[$EventName]["Type"])
    00733                 {
    00734                     case self::EVENTTYPE_CHAIN:
    00735                         $ReturnValue = $Result;
    00736                         $Parameters = $Result;
    00737                         break;
    00738
    00739                     case self::EVENTTYPE_FIRST:
    00740                         if ($Result !== NULL)
    00741                         {
    00742                             $ReturnValue = $Result;
    00743                             break 2;
    00744                         }
    00745                         break;
    00746
    00747                     case self::EVENTTYPE_NAMED:
    00748                         $CallbackName = is_array($Callback)
    00749                                 ? (is_object($Callback[0])
    00750                                         ? get_class($Callback[0])
    00751                                         : $Callback[0])."::".$Callback[1]
    00752                                 : $Callback;
    00753                         $ReturnValue[$CallbackName] = $Result;
    00754                         break;
    00755
    00756                     default:
    00757                         break;
    00758                 }
    00759             }
    00760         }
    00761
    00762         # return value if any to caller
    00763         return $ReturnValue;
    00764     }
    00765
    00771     function IsStaticOnlyEvent($EventName)
    00772     {
    00773         return isset($this->PeriodicEvents[$EventName]) ? TRUE : FALSE;
    00774     }
    00775
    00776     /*@)*/ /* Event Handling */
    00777
    00778     # ---- Task Management ---------------------------------------------------
    00779  /*@(*/
    00781
    00783     const PRIORITY_HIGH = 1;
    00785     const PRIORITY_MEDIUM = 2;
    00787     const PRIORITY_LOW = 3;
    00789     const PRIORITY_BACKGROUND = 4;
    00790
    00803     function QueueTask($Callback, $Parameters = NULL,
    00804             $Priority = self::PRIORITY_MEDIUM, $Description = "")
    00805     {
    00806         # pack task info and write to database
    00807         if ($Parameters === NULL) {  $Parameters = array();  }
    00808         $this->DB->Query("INSERT INTO TaskQueue"
    00809                 ." (Callback, Parameters, Priority, Description)"
    00810                 ." VALUES ('".addslashes(serialize($Callback))."', '"
    00811                 .addslashes(serialize($Parameters))."', ".intval($Priority).", '"
    00812                 .addslashes($Description)."')");
    00813     }
    00814
    00832     function QueueUniqueTask($Callback, $Parameters = NULL,
    00833             $Priority = self::PRIORITY_MEDIUM, $Description = "")
    00834     {
    00835         if ($this->TaskIsInQueue($Callback, $Parameters))
    00836         {
    00837             $QueryResult = $this->DB->Query("SELECT TaskId,Priority FROM TaskQueue"
    00838                     ." WHERE Callback = '".addslashes(serialize($Callback))."'"
    00839                     .($Parameters ? " AND Parameters = '"
    00840                             .addslashes(serialize($Parameters))."'" : ""));
    00841             if ($QueryResult !== FALSE)
    00842             {
    00843                 $Record = $this->DB->FetchRow();
    00844                 if ($Record["Priority"] > $Priority)
    00845                 {
    00846                     $this->DB->Query("UPDATE TaskQueue"
    00847                             ." SET Priority = ".intval($Priority)
    00848                             ." WHERE TaskId = ".intval($Record["TaskId"]));
    00849                 }
    00850             }
    00851             return FALSE;
    00852         }
    00853         else
    00854         {
    00855             $this->QueueTask($Callback, $Parameters, $Priority, $Description);
    00856             return TRUE;
    00857         }
    00858     }
    00859
    00869     function TaskIsInQueue($Callback, $Parameters = NULL)
    00870     {
    00871         $FoundCount = $this->DB->Query("SELECT COUNT(*) AS FoundCount FROM TaskQueue"
    00872                 ." WHERE Callback = '".addslashes(serialize($Callback))."'"
    00873                 .($Parameters ? " AND Parameters = '"
    00874                         .addslashes(serialize($Parameters))."'" : ""),
    00875                 "FoundCount")
    00876                 + $this->DB->Query("SELECT COUNT(*) AS FoundCount FROM RunningTasks"
    00877                 ." WHERE Callback = '".addslashes(serialize($Callback))."'"
    00878                 .($Parameters ? " AND Parameters = '"
    00879                         .addslashes(serialize($Parameters))."'" : ""),
    00880                 "FoundCount");
    00881         return ($FoundCount ? TRUE : FALSE);
    00882     }
    00883
    00889     function GetTaskQueueSize($Priority = NULL)
    00890     {
    00891         return $this->DB->Query("SELECT COUNT(*) AS QueueSize FROM TaskQueue"
    00892                 .($Priority ? " WHERE Priority = ".intval($Priority) : ""),
    00893                 "QueueSize");
    00894     }
    00895
    00903     function GetQueuedTaskList($Count = 100, $Offset = 0)
    00904     {
    00905         return $this->GetTaskList("SELECT * FROM TaskQueue"
    00906                 ." ORDER BY Priority, TaskId ", $Count, $Offset);
    00907     }
    00908
    00916     function GetRunningTaskList($Count = 100, $Offset = 0)
    00917     {
    00918         return $this->GetTaskList("SELECT * FROM RunningTasks"
    00919                 ." WHERE StartedAt >= '".date("Y-m-d H:i:s",
    00920                         (time() - ini_get("max_execution_time")))."'"
    00921                 ." ORDER BY StartedAt", $Count, $Offset);
    00922     }
    00923
    00931     function GetOrphanedTaskList($Count = 100, $Offset = 0)
    00932     {
    00933         return $this->GetTaskList("SELECT * FROM RunningTasks"
    00934                 ." WHERE StartedAt < '".date("Y-m-d H:i:s",
    00935                         (time() - ini_get("max_execution_time")))."'"
    00936                 ." ORDER BY StartedAt", $Count, $Offset);
    00937     }
    00938
    00943     function ReQueueOrphanedTask($TaskId)
    00944     {
    00945         $this->DB->Query("LOCK TABLES TaskQueue WRITE, RunningTasks WRITE");
    00946         $this->DB->Query("INSERT INTO TaskQueue"
    00947                          ." (Callback,Parameters,Priority,Description) "
    00948                          ."SELECT Callback, Parameters, Priority, Description"
    00949                          ." FROM RunningTasks WHERE TaskId = ".intval($TaskId));
    00950         $this->DB->Query("DELETE FROM RunningTasks WHERE TaskId = ".intval($TaskId));
    00951         $this->DB->Query("UNLOCK TABLES");
    00952     }
    00953
    00958     function DeleteTask($TaskId)
    00959     {
    00960         $this->DB->Query("DELETE FROM TaskQueue WHERE TaskId = ".intval($TaskId));
    00961         $this->DB->Query("DELETE FROM RunningTasks WHERE TaskId = ".intval($TaskId));
    00962     }
    00963
    00971     function GetTask($TaskId)
    00972     {
    00973         # assume task will not be found
    00974         $Task = NULL;
    00975
    00976         # look for task in task queue
    00977         $this->DB->Query("SELECT * FROM TaskQueue WHERE TaskId = ".intval($TaskId));
    00978
    00979         # if task was not found in queue
    00980         if (!$this->DB->NumRowsSelected())
    00981         {
    00982             # look for task in running task list
    00983             $this->DB->Query("SELECT * FROM RunningTasks WHERE TaskId = "
    00984                     .intval($TaskId));
    00985         }
    00986
    00987         # if task was found
    00988         if ($this->DB->NumRowsSelected())
    00989         {
    00990             # if task was periodic
    00991             $Row = $this->DB->FetchRow();
    00992             if ($Row["Callback"] ==
    00993                     serialize(array("ApplicationFramework", "PeriodicEventWrapper")))
    00994             {
    00995                 # unpack periodic task callback
    00996                 $WrappedCallback = unserialize($Row["Parameters"]);
    00997                 $Task["Callback"] = $WrappedCallback[1];
    00998                 $Task["Parameters"] = NULL;
    00999             }
    01000             else
    01001             {
    01002                 # unpack task callback and parameters
    01003                 $Task["Callback"] = unserialize($Row["Callback"]);
    01004                 $Task["Parameters"] = unserialize($Row["Parameters"]);
    01005             }
    01006         }
    01007
    01008         # return task to caller
    01009         return $Task;
    01010     }
    01011
    01017     function MaxTasks($NewValue = NULL)
    01018     {
    01019         if (func_num_args() && ($NewValue >= 1))
    01020         {
    01021             $this->DB->Query("UPDATE ApplicationFrameworkSettings"
    01022                     ." SET MaxTasksRunning = '".intval($NewValue)."'");
    01023             $this->Settings["MaxTasksRunning"] = intval($NewValue);
    01024         }
    01025         return $this->Settings["MaxTasksRunning"];
    01026     }
    01027
    01035     function MaxExecutionTime($NewValue = NULL)
    01036     {
    01037         if (func_num_args() && !ini_get("safe_mode"))
    01038         {
    01039             if ($NewValue != $this->Settings["MaxExecTime"])
    01040             {
    01041                 $this->Settings["MaxExecTime"] = max($NewValue, 5);
    01042                 $this->DB->Query("UPDATE ApplicationFrameworkSettings"
    01043                         ." SET MaxExecTime = '"
    01044                                 .intval($this->Settings["MaxExecTime"])."'");
    01045             }
    01046             ini_set("max_execution_time", $this->Settings["MaxExecTime"]);
    01047             set_time_limit($this->Settings["MaxExecTime"]);
    01048         }
    01049         return ini_get("max_execution_time");
    01050     }
    01051
    01052     /*@)*/ /* Task Management */
    01053
    01054     # ---- PRIVATE INTERFACE -------------------------------------------------
    01055
    01056     private $ActiveUI = "default";
    01057     private $BrowserDetectFunc;
    01058     private $DB;
    01059     private $DefaultPage = "Home";
    01060     private $EnvIncludes = array();
    01061     private $ExecutionStartTime;
    01062     private $FoundUIFiles = array();
    01063     private $HtmlCharset = "UTF-8";
    01064     private $JumpToPage = NULL;
    01065     private $MaxRunningTasksToTrack = 250;
    01066     private static $ObjectDirectories = array();
    01067     private $PostProcessingFuncs = array();
    01068     private $RunningTask;
    01069     private $Settings;
    01070     private $SuppressHTML = FALSE;
    01071
    01072     private $PeriodicEvents = array(
    01073                 "EVENT_HOURLY" => self::EVENTTYPE_DEFAULT,
    01074                 "EVENT_DAILY" => self::EVENTTYPE_DEFAULT,
    01075                 "EVENT_WEEKLY" => self::EVENTTYPE_DEFAULT,
    01076                 "EVENT_MONTHLY" => self::EVENTTYPE_DEFAULT,
    01077                 "EVENT_PERIODIC" => self::EVENTTYPE_NAMED,
    01078                 );
    01079     private $UIEvents = array(
    01080                 "EVENT_PAGE_LOAD" => self::EVENTTYPE_DEFAULT,
    01081                 "EVENT_PHP_FILE_LOAD" => self::EVENTTYPE_CHAIN,
    01082                 "EVENT_HTML_FILE_LOAD" => self::EVENTTYPE_CHAIN,
    01083                 "EVENT_HTML_FILE_LOAD_COMPLETE" => self::EVENTTYPE_DEFAULT,
    01084                 );
    01085
    01086     private function FindTemplate($FileList, $PageName)
    01087     {
    01088         $FileNameFound = NULL;
    01089         foreach ($FileList as $FileName)
    01090         {
    01091             $FileName = str_replace("%ACTIVEUI%", $this->ActiveUI, $FileName);
    01092             $FileName = str_replace("%PAGENAME%", $PageName, $FileName);
    01093             if (file_exists($FileName))
    01094             {
    01095                 $FileNameFound = $FileName;
    01096                 break;
    01097             }
    01098         }
    01099         return $FileNameFound;
    01100     }
    01101
    01108     private function GetRequiredFilesNotYetLoaded($PageContentFile)
    01109     {
    01110         # start out assuming no files required
    01111         $RequiredFiles = array();
    01112
    01113         # if page content file supplied
    01114         if ($PageContentFile)
    01115         {
    01116             # if file containing list of required files is available
    01117             $Path = dirname($PageContentFile);
    01118             $RequireListFile = $Path."/REQUIRES";
    01119             if (file_exists($RequireListFile))
    01120             {
    01121                 # read in list of required files
    01122                 $RequestedFiles = file($RequireListFile);
    01123
    01124                 # for each line in required file list
    01125                 foreach ($RequestedFiles as $Line)
    01126                 {
    01127                     # if line is not a comment
    01128                     $Line = trim($Line);
    01129                     if (!preg_match("/^#/", $Line))
    01130                     {
    01131                         # if file has not already been loaded
    01132                         if (!in_array($Line, $this->FoundUIFiles))
    01133                         {
    01134                             # add to list of required files
    01135                             $RequiredFiles[] = $Line;
    01136                         }
    01137                     }
    01138                 }
    01139             }
    01140         }
    01141
    01142         # return list of required files to caller
    01143         return $RequiredFiles;
    01144     }
    01145
    01146     private function SetUpObjectAutoloading()
    01147     {
    01148         function __autoload($ClassName)
    01149         {
    01150             ApplicationFramework::AutoloadObjects($ClassName);
    01151         }
    01152     }
    01153
    01155     static function AutoloadObjects($ClassName)
    01156     {
    01157         foreach (self::$ObjectDirectories as $Location => $Prefix)
    01158         {
    01159             $FileName = $Location.$Prefix.$ClassName.".php";
    01160             if (file_exists($FileName))
    01161             {
    01162                 require_once($FileName);
    01163                 break;
    01164             }
    01165         }
    01166     }
    01169     private function LoadUIFunctions()
    01170     {
    01171         $Dirs = array(
    01172                 "local/interface/%ACTIVEUI%/include",
    01173                 "interface/%ACTIVEUI%/include",
    01174                 "local/interface/default/include",
    01175                 "interface/default/include",
    01176                 );
    01177         foreach ($Dirs as $Dir)
    01178         {
    01179             $Dir = str_replace("%ACTIVEUI%", $this->ActiveUI, $Dir);
    01180             if (is_dir($Dir))
    01181             {
    01182                 $FileNames = scandir($Dir);
    01183                 foreach ($FileNames as $FileName)
    01184                 {
    01185                     if (preg_match("/^F-([A-Za-z_]+)\.php/", $FileName, $Matches)
    01186                             || preg_match("/^F-([A-Za-z_]+)\.html/", $FileName, $Matches))
    01187                     {
    01188                         if (!function_exists($Matches[1]))
    01189                         {
    01190                             include_once($Dir."/".$FileName);
    01191                         }
    01192                     }
    01193                 }
    01194             }
    01195         }
    01196     }
    01197
    01198     private function ProcessPeriodicEvent($EventName, $Callback)
    01199     {
    01200         # retrieve last execution time for event if available
    01201         $Signature = self::GetCallbackSignature($Callback);
    01202         $LastRun = $this->DB->Query("SELECT LastRunAt FROM PeriodicEvents"
    01203                 ." WHERE Signature = '".addslashes($Signature)."'", "LastRunAt");
    01204
    01205         # determine whether enough time has passed for event to execute
    01206         $EventPeriods = array(
    01207                 "EVENT_HOURLY" => 60*60,
    01208                 "EVENT_DAILY" => 60*60*24,
    01209                 "EVENT_WEEKLY" => 60*60*24*7,
    01210                 "EVENT_MONTHLY" => 60*60*24*30,
    01211                 "EVENT_PERIODIC" => 0,
    01212                 );
    01213         $ShouldExecute = (($LastRun === NULL)
    01214                 || (time() > (strtotime($LastRun) + $EventPeriods[$EventName])))
    01215                 ? TRUE : FALSE;
    01216
    01217         # if event should run
    01218         if ($ShouldExecute)
    01219         {
    01220             # add event to task queue
    01221             $WrapperCallback = array("ApplicationFramework", "PeriodicEventWrapper");
    01222             $WrapperParameters = array(
    01223                     $EventName, $Callback, array("LastRunAt" => $LastRun));
    01224             $this->QueueUniqueTask($WrapperCallback, $WrapperParameters);
    01225         }
    01226     }
    01227
    01228     private static function PeriodicEventWrapper($EventName, $Callback, $Parameters)
    01229     {
    01230         static $DB;
    01231         if (!isset($DB)) {  $DB = new Database();  }
    01232
    01233         # run event
    01234         $ReturnVal = call_user_func_array($Callback, $Parameters);
    01235
    01236         # if event is already in database
    01237         $Signature = self::GetCallbackSignature($Callback);
    01238         if ($DB->Query("SELECT COUNT(*) AS EventCount FROM PeriodicEvents"
    01239                 ." WHERE Signature = '".addslashes($Signature)."'", "EventCount"))
    01240         {
    01241             # update last run time for event
    01242             $DB->Query("UPDATE PeriodicEvents SET LastRunAt = "
    01243                     .(($EventName == "EVENT_PERIODIC")
    01244                             ? "'".date("Y-m-d H:i:s", time() + ($ReturnVal * 60))."'"
    01245                             : "NOW()")
    01246                     ." WHERE Signature = '".addslashes($Signature)."'");
    01247         }
    01248         else
    01249         {
    01250             # add last run time for event to database
    01251             $DB->Query("INSERT INTO PeriodicEvents (Signature, LastRunAt) VALUES "
    01252                     ."('".addslashes($Signature)."', "
    01253                     .(($EventName == "EVENT_PERIODIC")
    01254                             ? "'".date("Y-m-d H:i:s", time() + ($ReturnVal * 60))."'"
    01255                             : "NOW()").")");
    01256         }
    01257     }
    01258
    01259     private static function GetCallbackSignature($Callback)
    01260     {
    01261         return !is_array($Callback) ? $Callback
    01262                 : (is_object($Callback[0]) ? md5(serialize($Callback[0])) : $Callback[0])
    01263                         ."::".$Callback[1];
    01264     }
    01265
    01266     private function PrepForTSR()
    01267     {
    01268         # if HTML has been output and it's time to launch another task
    01269         # (only TSR if HTML has been output because otherwise browsers
    01270         #       may misbehave after connection is closed)
    01271         if (($this->JumpToPage || !$this->SuppressHTML)
    01272                 && (time() > (strtotime($this->Settings["LastTaskRunAt"])
    01273                         + (ini_get("max_execution_time")
    01274                                 / $this->Settings["MaxTasksRunning"]) + 5))
    01275                 && $this->GetTaskQueueSize())
    01276         {
    01277             # begin buffering output for TSR
    01278             ob_start();
    01279
    01280             # let caller know it is time to launch another task
    01281             return TRUE;
    01282         }
    01283         else
    01284         {
    01285             # let caller know it is not time to launch another task
    01286             return FALSE;
    01287         }
    01288     }
    01289
    01290     private function LaunchTSR()
    01291     {
    01292         # set needed headers and
    01293         ignore_user_abort(TRUE);
    01294         header("Connection: close");
    01295         header("Content-Length: ".ob_get_length());
    01296
    01297         # output buffered content
    01298         ob_end_flush();
    01299         flush();
    01300
    01301         # write out any outstanding data and end HTTP session
    01302         session_write_close();
    01303
    01304         # if there is still a task in the queue
    01305         if ($this->GetTaskQueueSize())
    01306         {
    01307             # turn on output buffering to (hopefully) record any crash output
    01308             ob_start();
    01309
    01310             # lock tables and grab last task run time to double check
    01311             $this->DB->Query("LOCK TABLES ApplicationFrameworkSettings WRITE");
    01312             $this->DB->Query("SELECT * FROM ApplicationFrameworkSettings");
    01313             $this->Settings = $this->DB->FetchRow();
    01314
    01315             # if still time to launch another task
    01316             if (time() > (strtotime($this->Settings["LastTaskRunAt"])
    01317                         + (ini_get("max_execution_time")
    01318                                 / $this->Settings["MaxTasksRunning"]) + 5))
    01319             {
    01320                 # update the "last run" time and release tables
    01321                 $this->DB->Query("UPDATE ApplicationFrameworkSettings"
    01322                         ." SET LastTaskRunAt = '".date("Y-m-d H:i:s")."'");
    01323                 $this->DB->Query("UNLOCK TABLES");
    01324
    01325                 # run tasks while there is a task in the queue and enough time left
    01326                 do
    01327                 {
    01328                     # run the next task
    01329                     $this->RunNextTask();
    01330                 }
    01331                 while ($this->GetTaskQueueSize()
    01332                         && ($this->GetSecondsBeforeTimeout() > 65));
    01333             }
    01334             else
    01335             {
    01336                 # release tables
    01337                 $this->DB->Query("UNLOCK TABLES");
    01338             }
    01339         }
    01340     }
    01341
    01349     private function GetTaskList($DBQuery, $Count, $Offset)
    01350     {
    01351         $this->DB->Query($DBQuery." LIMIT ".intval($Offset).",".intval($Count));
    01352         $Tasks = array();
    01353         while ($Row = $this->DB->FetchRow())
    01354         {
    01355             $Tasks[$Row["TaskId"]] = $Row;
    01356             if ($Row["Callback"] ==
    01357                     serialize(array("ApplicationFramework", "PeriodicEventWrapper")))
    01358             {
    01359                 $WrappedCallback = unserialize($Row["Parameters"]);
    01360                 $Tasks[$Row["TaskId"]]["Callback"] = $WrappedCallback[1];
    01361                 $Tasks[$Row["TaskId"]]["Parameters"] = NULL;
    01362             }
    01363             else
    01364             {
    01365                 $Tasks[$Row["TaskId"]]["Callback"] = unserialize($Row["Callback"]);
    01366                 $Tasks[$Row["TaskId"]]["Parameters"] = unserialize($Row["Parameters"]);
    01367             }
    01368         }
    01369         return $Tasks;
    01370     }
    01371
    01375     private function RunNextTask()
    01376     {
    01377         # look for task at head of queue
    01378         $this->DB->Query("SELECT * FROM TaskQueue ORDER BY Priority, TaskId LIMIT 1");
    01379         $Task = $this->DB->FetchRow();
    01380
    01381         # if there was a task available
    01382         if ($Task)
    01383         {
    01384             # move task from queue to running tasks list
    01385             $this->DB->Query("INSERT INTO RunningTasks "
    01386                              ."(TaskId,Callback,Parameters,Priority,Description) "
    01387                              ."SELECT * FROM TaskQueue WHERE TaskId = "
    01388                                     .intval($Task["TaskId"]));
    01389             $this->DB->Query("DELETE FROM TaskQueue WHERE TaskId = "
    01390                     .intval($Task["TaskId"]));
    01391
    01392             # unpack stored task info
    01393             $Callback = unserialize($Task["Callback"]);
    01394             $Parameters = unserialize($Task["Parameters"]);
    01395
    01396             # attempt to load task callback if not already available
    01397             $this->LoadFunction($Callback);
    01398
    01399             # run task
    01400             $this->RunningTask = $Task;
    01401             if ($Parameters)
    01402             {
    01403                 call_user_func_array($Callback, $Parameters);
    01404             }
    01405             else
    01406             {
    01407                 call_user_func($Callback);
    01408             }
    01409             unset($this->RunningTask);
    01410
    01411             # remove task from running tasks list
    01412             $this->DB->Query("DELETE FROM RunningTasks"
    01413                     ." WHERE TaskId = ".intval($Task["TaskId"]));
    01414
    01415             # prune running tasks list if necessary
    01416             $RunningTasksCount = $this->DB->Query(
    01417                     "SELECT COUNT(*) AS TaskCount FROM RunningTasks", "TaskCount");
    01418             if ($RunningTasksCount > $this->MaxRunningTasksToTrack)
    01419             {
    01420                 $this->DB->Query("DELETE FROM RunningTasks ORDER BY StartedAt"
    01421                         ." LIMIT ".($RunningTasksCount - $this->MaxRunningTasksToTrack));
    01422             }
    01423         }
    01424     }
    01425
    01431     function OnCrash()
    01432     {
    01433         if (isset($this->RunningTask))
    01434         {
    01435             if (function_exists("error_get_last"))
    01436             {
    01437                 $CrashInfo["LastError"] = error_get_last();
    01438             }
    01439             if (ob_get_length() !== FALSE)
    01440             {
    01441                 $CrashInfo["OutputBuffer"] = ob_get_contents();
    01442             }
    01443             if (isset($CrashInfo))
    01444             {
    01445                 $DB = new Database();
    01446                 $DB->Query("UPDATE RunningTasks SET CrashInfo = '"
    01447                         .addslashes(serialize($CrashInfo))
    01448                         ."' WHERE TaskId = ".intval($this->RunningTask["TaskId"]));
    01449             }
    01450         }
    01451
    01452         print("\n");
    01453         return;
    01454
    01455         if (ob_get_length() !== FALSE)
    01456         {
    01457             ?>
    01458             <table width="100%" cellpadding="5" style="border: 2px solid #666666;  background: #FFCCCC;  font-family: Courier New, Courier, monospace;  margin-top: 10px;  font-weight: bold;"><tr><td>
    01459             <div style="font-size: 200%;">CRASH OUTPUT</div><?PHP
    01460             ob_end_flush();
    01461             ?></td></tr></table><?PHP
    01462         }
    01463     }
    01464
    01465     private $CommonTemplateList = array(
    01466             "local/interface/%ACTIVEUI%/include/StdPage%PAGENAME%.tpl",
    01467             "local/interface/%ACTIVEUI%/include/StdPage%PAGENAME%.html",
    01468             "local/interface/%ACTIVEUI%/include/%PAGENAME%.tpl",
    01469             "local/interface/%ACTIVEUI%/include/%PAGENAME%.html",
    01470             "local/interface/%ACTIVEUI%/include/SPT--StandardPage%PAGENAME%.tpl",
    01471             "local/interface/%ACTIVEUI%/include/SPT--StandardPage%PAGENAME%.html",
    01472             "local/interface/%ACTIVEUI%/include/SPT--%PAGENAME%.tpl",
    01473             "local/interface/%ACTIVEUI%/include/SPT--%PAGENAME%.html",
    01474             "local/interface/%ACTIVEUI%/include/%PAGENAME%",
    01475             "interface/%ACTIVEUI%/include/StdPage%PAGENAME%.tpl",
    01476             "interface/%ACTIVEUI%/include/StdPage%PAGENAME%.html",
    01477             "interface/%ACTIVEUI%/include/%PAGENAME%.tpl",
    01478             "interface/%ACTIVEUI%/include/%PAGENAME%.html",
    01479             "interface/%ACTIVEUI%/include/SPT--StandardPage%PAGENAME%.tpl",
    01480             "interface/%ACTIVEUI%/include/SPT--StandardPage%PAGENAME%.html",
    01481             "interface/%ACTIVEUI%/include/SPT--%PAGENAME%.tpl",
    01482             "interface/%ACTIVEUI%/include/SPT--%PAGENAME%.html",
    01483             "interface/%ACTIVEUI%/include/%PAGENAME%",
    01484             "SPTUI--%ACTIVEUI%/include/StdPage%PAGENAME%.tpl",
    01485             "SPTUI--%ACTIVEUI%/include/StdPage%PAGENAME%.html",
    01486             "SPTUI--%ACTIVEUI%/include/%PAGENAME%.tpl",
    01487             "SPTUI--%ACTIVEUI%/include/%PAGENAME%.html",
    01488             "SPTUI--%ACTIVEUI%/include/SPT--StandardPage%PAGENAME%.tpl",
    01489             "SPTUI--%ACTIVEUI%/include/SPT--StandardPage%PAGENAME%.html",
    01490             "SPTUI--%ACTIVEUI%/include/SPT--%PAGENAME%.tpl",
    01491             "SPTUI--%ACTIVEUI%/include/SPT--%PAGENAME%.html",
    01492             "SPTUI--%ACTIVEUI%/include/%PAGENAME%",
    01493             "%ACTIVEUI%/include/StdPage%PAGENAME%.tpl",
    01494             "%ACTIVEUI%/include/StdPage%PAGENAME%.html",
    01495             "%ACTIVEUI%/include/%PAGENAME%.tpl",
    01496             "%ACTIVEUI%/include/%PAGENAME%.html",
    01497             "%ACTIVEUI%/include/SPT--StandardPage%PAGENAME%.tpl",
    01498             "%ACTIVEUI%/include/SPT--StandardPage%PAGENAME%.html",
    01499             "%ACTIVEUI%/include/SPT--%PAGENAME%.tpl",
    01500             "%ACTIVEUI%/include/SPT--%PAGENAME%.html",
    01501             "%ACTIVEUI%/include/%PAGENAME%",
    01502             "local/interface/default/include/StdPage%PAGENAME%.tpl",
    01503             "local/interface/default/include/StdPage%PAGENAME%.html",
    01504             "local/interface/default/include/%PAGENAME%.tpl",
    01505             "local/interface/default/include/%PAGENAME%.html",
    01506             "local/interface/default/include/SPT--StandardPage%PAGENAME%.tpl",
    01507             "local/interface/default/include/SPT--StandardPage%PAGENAME%.html",
    01508             "local/interface/default/include/SPT--%PAGENAME%.tpl",
    01509             "local/interface/default/include/SPT--%PAGENAME%.html",
    01510             "local/interface/default/include/%PAGENAME%",
    01511             "interface/default/include/StdPage%PAGENAME%.tpl",
    01512             "interface/default/include/StdPage%PAGENAME%.html",
    01513             "interface/default/include/%PAGENAME%.tpl",
    01514             "interface/default/include/%PAGENAME%.html",
    01515             "interface/default/include/SPT--StandardPage%PAGENAME%.tpl",
    01516             "interface/default/include/SPT--StandardPage%PAGENAME%.html",
    01517             "interface/default/include/SPT--%PAGENAME%.tpl",
    01518             "interface/default/include/SPT--%PAGENAME%.html",
    01519             "interface/default/include/%PAGENAME%",
    01520             );
    01521     private $ContentTemplateList = array(
    01522             "local/interface/%ACTIVEUI%/%PAGENAME%.tpl",
    01523             "local/interface/%ACTIVEUI%/%PAGENAME%.html",
    01524             "local/interface/%ACTIVEUI%/SPT--%PAGENAME%.tpl",
    01525             "local/interface/%ACTIVEUI%/SPT--%PAGENAME%.html",
    01526             "interface/%ACTIVEUI%/%PAGENAME%.tpl",
    01527             "interface/%ACTIVEUI%/%PAGENAME%.html",
    01528             "interface/%ACTIVEUI%/SPT--%PAGENAME%.tpl",
    01529             "interface/%ACTIVEUI%/SPT--%PAGENAME%.html",
    01530             "SPTUI--%ACTIVEUI%/%PAGENAME%.tpl",
    01531             "SPTUI--%ACTIVEUI%/%PAGENAME%.html",
    01532             "SPTUI--%ACTIVEUI%/SPT--%PAGENAME%.tpl",
    01533             "SPTUI--%ACTIVEUI%/SPT--%PAGENAME%.html",
    01534             "%ACTIVEUI%/%PAGENAME%.tpl",
    01535             "%ACTIVEUI%/%PAGENAME%.html",
    01536             "%ACTIVEUI%/SPT--%PAGENAME%.tpl",
    01537             "%ACTIVEUI%/SPT--%PAGENAME%.html",
    01538             "local/interface/default/%PAGENAME%.tpl",
    01539             "local/interface/default/%PAGENAME%.html",
    01540             "local/interface/default/SPT--%PAGENAME%.tpl",
    01541             "local/interface/default/SPT--%PAGENAME%.html",
    01542             "interface/default/%PAGENAME%.tpl",
    01543             "interface/default/%PAGENAME%.html",
    01544             "interface/default/SPT--%PAGENAME%.tpl",
    01545             "interface/default/SPT--%PAGENAME%.html",
    01546             );
    01547     private $ImageFileList = array(
    01548             "local/interface/%ACTIVEUI%/images/%PAGENAME%",
    01549             "interface/%ACTIVEUI%/images/%PAGENAME%",
    01550             "SPTUI--%ACTIVEUI%/images/%PAGENAME%",
    01551             "%ACTIVEUI%/images/%PAGENAME%",
    01552             "local/interface/default/images/%PAGENAME%",
    01553             "interface/default/images/%PAGENAME%",
    01554             );
    01555     private $FunctionFileList = array(
    01556             "local/interface/%ACTIVEUI%/include/%PAGENAME%.php",
    01557             "local/interface/%ACTIVEUI%/include/%PAGENAME%.html",
    01558             "interface/%ACTIVEUI%/include/%PAGENAME%.php",
    01559             "interface/%ACTIVEUI%/include/%PAGENAME%.html",
    01560             "SPTUI--%ACTIVEUI%/include/%PAGENAME%.php",
    01561             "SPTUI--%ACTIVEUI%/include/%PAGENAME%.html",
    01562             "%ACTIVEUI%/include/%PAGENAME%.php",
    01563             "%ACTIVEUI%/include/%PAGENAME%.html",
    01564             "local/interface/default/include/%PAGENAME%.php",
    01565             "local/interface/default/include/%PAGENAME%.html",
    01566             "local/include/%PAGENAME%.php",
    01567             "local/include/%PAGENAME%.html",
    01568             "interface/default/include/%PAGENAME%.php",
    01569             "interface/default/include/%PAGENAME%.html",
    01570             "include/%PAGENAME%.php",
    01571             "include/%PAGENAME%.html",
    01572             );
    01573
    01574     const NOVALUE = ".-+-.NO VALUE PASSED IN FOR ARGUMENT.-+-.";
    01575 };
    01576
    01577
    01578 ?>