3 # FILE: ApplicationFramework.php
5 # Part of the ScoutLib application support library
6 # Copyright 2009-2013 Edward Almasy and Internet Scout Research Group
7 # http://scout.wisc.edu
16 # ---- PUBLIC INTERFACE --------------------------------------------------
24 function __construct()
26 # save execution start time
27 $this->ExecutionStartTime = microtime(TRUE);
29 # begin/restore PHP session
30 $SessionDomain = isset($_SERVER[
"SERVER_NAME"]) ? $_SERVER[
"SERVER_NAME"]
31 : isset($_SERVER[
"HTTP_HOST"]) ? $_SERVER[
"HTTP_HOST"]
33 if (is_writable(session_save_path()))
35 $SessionStorage = session_save_path()
36 .
"/".self::$AppName.
"_".md5($SessionDomain.dirname(__FILE__));
37 if (!is_dir($SessionStorage)) { mkdir($SessionStorage, 0700 ); }
38 if (is_writable($SessionStorage)) { session_save_path($SessionStorage); }
40 ini_set(
"session.gc_maxlifetime", self::$SessionLifetime);
41 session_set_cookie_params(
42 self::$SessionLifetime,
"/", $SessionDomain);
45 # set up object file autoloader
46 $this->SetUpObjectAutoloading();
48 # set up function to output any buffered text in case of crash
49 register_shutdown_function(array($this,
"OnCrash"));
51 # set up our internal environment
54 # set up our exception handler
55 set_exception_handler(array($this,
"GlobalExceptionHandler"));
57 # perform any work needed to undo PHP magic quotes
58 $this->UndoMagicQuotes();
60 # load our settings from database
61 $this->LoadSettings();
63 # set PHP maximum execution time
66 # register events we handle internally
78 # if template location cache is flagged to be saved
79 if ($this->SaveTemplateLocationCache)
81 # write template location cache out and update cache expiration
82 $this->DB->Query(
"UPDATE ApplicationFrameworkSettings"
83 .
" SET TemplateLocationCache = '"
84 .addslashes(serialize(
85 $this->Settings[
"TemplateLocationCache"])).
"',"
86 .
" TemplateLocationCacheExpiration = "
88 .$this->Settings[
"TemplateLocationCacheInterval"]
92 # if object location cache is flagged to be saved
93 if (self::$SaveObjectLocationCache)
95 # write object location cache out and update cache expiration
96 $this->DB->Query(
"UPDATE ApplicationFrameworkSettings"
97 .
" SET ObjectLocationCache = '"
98 .addslashes(serialize(
99 self::$ObjectLocationCache)).
"',"
100 .
" ObjectLocationCacheExpiration = "
101 .
" NOW() + INTERVAL "
102 .self::$ObjectLocationCacheInterval
112 function GlobalExceptionHandler($Exception)
114 # display exception info
115 $Location = $Exception->getFile().
"[".$Exception->getLine().
"]";
116 ?><table width=
"100%" cellpadding=
"5"
117 style=
"border: 2px solid #666666; background: #CCCCCC;
118 font-family: Courier New, Courier, monospace;
119 margin-top: 10px;"><tr><td>
120 <div style=
"color: #666666;">
121 <span style=
"font-size: 150%;">
122 <b>Uncaught Exception</b></span><br />
123 <b>
Message:</b> <i><?
PHP print $Exception->getMessage(); ?></i><br />
124 <b>Location:</b> <i><?
PHP print $Location; ?></i><br />
126 <blockquote><pre><?
PHP print $Exception->getTraceAsString();
127 ?></pre></blockquote>
129 </td></tr></table><?
PHP
131 # log exception if possible
132 $LogMsg =
"Uncaught exception (".$Exception->getMessage().
").";
133 $this->
LogError(self::LOGLVL_ERROR, $LogMsg);
149 $Dir, $Prefix =
"", $ClassPattern = NULL, $ClassReplacement = NULL)
151 # make sure directory has trailing slash
152 $Dir = $Dir.((substr($Dir, -1) !=
"/") ?
"/" :
"");
154 # add directory to directory list
155 self::$ObjectDirectories = array_merge(
158 "ClassPattern" => $ClassPattern,
159 "ClassReplacement" => $ClassReplacement,
161 self::$ObjectDirectories);
185 # add directories to existing image directory list
186 $this->ImageDirList = $this->AddToDirList(
187 $this->ImageDirList, $Dir, $SearchLast, $SkipSlashCheck);
212 # add directories to existing image directory list
213 $this->IncludeDirList = $this->AddToDirList(
214 $this->IncludeDirList, $Dir, $SearchLast, $SkipSlashCheck);
238 # add directories to existing image directory list
239 $this->InterfaceDirList = $this->AddToDirList(
240 $this->InterfaceDirList, $Dir, $SearchLast, $SkipSlashCheck);
264 # add directories to existing image directory list
265 $this->FunctionDirList = $this->AddToDirList(
266 $this->FunctionDirList, $Dir, $SearchLast, $SkipSlashCheck);
276 $this->BrowserDetectFunc = $DetectionFunc;
287 if (is_callable($Callback))
289 $this->UnbufferedCallbacks[] = array($Callback, $Parameters);
301 return $this->
UpdateSetting(
"TemplateLocationCacheInterval", $NewInterval);
312 return $this->
UpdateSetting(
"ObjectLocationCacheInterval", $NewInterval);
322 if ($NewValue !== NULL)
324 self::$SessionLifetime = $NewValue;
326 return self::$SessionLifetime;
355 function AddCleanUrl($Pattern, $Page, $GetVars = NULL, $Template = NULL)
357 # save clean URL mapping parameters
358 $this->CleanUrlMappings[] = array(
359 "Pattern" => $Pattern,
361 "GetVars" => $GetVars,
364 # if replacement template specified
365 if ($Template !== NULL)
367 # if GET parameters specified
370 # retrieve all possible permutations of GET parameters
371 $GetPerms = $this->ArrayPermutations(array_keys($GetVars));
373 # for each permutation of GET parameters
374 foreach ($GetPerms as $VarPermutation)
376 # construct search pattern for permutation
377 $SearchPattern =
"/href=([\"'])index\\.php\\?P=".$Page;
379 foreach ($VarPermutation as $GetVar)
381 if (preg_match(
"%\\\$[0-9]+%", $GetVars[$GetVar]))
383 $GetVarSegment .=
"&".$GetVar.
"=((?:(?!\\1)[^&])+)";
387 $GetVarSegment .=
"&".$GetVar.
"=".$GetVars[$GetVar];
390 $SearchPattern .= $GetVarSegment.
"\\1/i";
392 # if template is actually a callback
393 if (is_callable($Template))
395 # add pattern to HTML output mod callbacks list
396 $this->OutputModificationCallbacks[] = array(
397 "Pattern" => $Pattern,
399 "SearchPattern" => $SearchPattern,
400 "Callback" => $Template,
405 # construct replacement string for permutation
406 $Replacement = $Template;
408 foreach ($VarPermutation as $GetVar)
410 $Replacement = str_replace(
411 "\$".$GetVar,
"\$".$Index, $Replacement);
414 $Replacement =
"href=\"".$Replacement.
"\"";
416 # add pattern to HTML output modifications list
417 $this->OutputModificationPatterns[] = $SearchPattern;
418 $this->OutputModificationReplacements[] = $Replacement;
424 # construct search pattern
425 $SearchPattern =
"/href=\"index\\.php\\?P=".$Page.
"\"/i";
427 # if template is actually a callback
428 if (is_callable($Template))
430 # add pattern to HTML output mod callbacks list
431 $this->OutputModificationCallbacks[] = array(
432 "Pattern" => $Pattern,
434 "SearchPattern" => $SearchPattern,
435 "Callback" => $Template,
440 # add simple pattern to HTML output modifications list
441 $this->OutputModificationPatterns[] = $SearchPattern;
442 $this->OutputModificationReplacements[] =
"href=\"".$Template.
"\"";
455 foreach ($this->CleanUrlMappings as $Info)
457 if (preg_match($Info[
"Pattern"], $Path))
473 # the search patterns and callbacks require a specific format
474 $Format =
"href=\"".str_replace(
"&",
"&", $Path).
"\"";
477 # perform any regular expression replacements on the search string
478 $Search = preg_replace(
479 $this->OutputModificationPatterns,
480 $this->OutputModificationReplacements,
483 # only run the callbacks if a replacement hasn't already been performed
484 if ($Search == $Format)
486 # perform any callback replacements on the search string
487 foreach ($this->OutputModificationCallbacks as $Info)
489 # make the information available to the callback
490 $this->OutputModificationCallbackInfo = $Info;
492 # execute the callback
493 $Search = preg_replace_callback(
494 $Info[
"SearchPattern"],
495 array($this,
"OutputModificationCallbackShell"),
500 # return the path untouched if no replacements were performed
501 if ($Search == $Format)
506 # remove the bits added to the search string to get it recognized by
507 # the replacement expressions and callbacks
508 $Result = substr($Search, 6, -1);
521 # for each clean URL mapping
522 foreach ($this->CleanUrlMappings as $Info)
524 # if current path matches the clean URL pattern
525 if (preg_match($Info[
"Pattern"], $Path, $Matches))
527 # the GET parameters for the URL, starting with the page name
528 $GetVars = array(
"P" => $Info[
"Page"]);
530 # if additional $_GET variables specified for clean URL
531 if ($Info[
"GetVars"] !== NULL)
533 # for each $_GET variable specified for clean URL
534 foreach ($Info[
"GetVars"] as $VarName => $VarTemplate)
536 # start with template for variable value
537 $Value = $VarTemplate;
539 # for each subpattern matched in current URL
540 foreach ($Matches as $Index => $Match)
542 # if not first (whole) match
545 # make any substitutions in template
546 $Value = str_replace(
"$".$Index, $Match, $Value);
550 # add the GET variable
551 $GetVars[$VarName] = $Value;
555 # return the unclean URL
556 return "index.php?" . http_build_query($GetVars);
560 # return the path unchanged
580 $GetVars = array(
"P" => $this->
GetPageName()) + $_GET;
581 return "index.php?" . http_build_query($GetVars);
590 # perform any clean URL rewriting
591 $PageName = $this->RewriteCleanUrls($PageName);
593 # sanitize incoming page name and save local copy
594 $PageName = preg_replace(
"/[^a-zA-Z0-9_.-]/",
"", $PageName);
595 $this->PageName = $PageName;
597 # buffer any output from includes or PHP file
600 # include any files needed to set up execution environment
601 foreach ($this->EnvIncludes as $IncludeFile)
603 include($IncludeFile);
607 $this->
SignalEvent(
"EVENT_PAGE_LOAD", array(
"PageName" => $PageName));
609 # signal PHP file load
610 $SignalResult = $this->
SignalEvent(
"EVENT_PHP_FILE_LOAD", array(
611 "PageName" => $PageName));
613 # if signal handler returned new page name value
614 $NewPageName = $PageName;
615 if (($SignalResult[
"PageName"] != $PageName)
616 && strlen($SignalResult[
"PageName"]))
618 # if new page name value is page file
619 if (file_exists($SignalResult[
"PageName"]))
621 # use new value for PHP file name
622 $PageFile = $SignalResult[
"PageName"];
626 # use new value for page name
627 $NewPageName = $SignalResult[
"PageName"];
630 # update local copy of page name
631 $this->PageName = $NewPageName;
634 # if we do not already have a PHP file
635 if (!isset($PageFile))
637 # look for PHP file for page
638 $OurPageFile =
"pages/".$NewPageName.
".php";
639 $LocalPageFile =
"local/pages/".$NewPageName.
".php";
640 $PageFile = file_exists($LocalPageFile) ? $LocalPageFile
641 : (file_exists($OurPageFile) ? $OurPageFile
642 :
"pages/".$this->DefaultPage.
".php");
648 # save buffered output to be displayed later after HTML file loads
649 $PageOutput = ob_get_contents();
652 # signal PHP file load is complete
654 $Context[
"Variables"] = get_defined_vars();
656 array(
"PageName" => $PageName,
"Context" => $Context));
657 $PageCompleteOutput = ob_get_contents();
660 # set up for possible TSR (Terminate and Stay Resident :))
661 $ShouldTSR = $this->PrepForTSR();
663 # if PHP file indicated we should autorefresh to somewhere else
664 if ($this->JumpToPage)
666 if (!strlen(trim($PageOutput)))
670 <meta http-equiv=
"refresh" content=
"0; URL=<?PHP
671 print($this->JumpToPage); ?>">
673 <body bgcolor=
"white">
678 # else if HTML loading is not suppressed
679 elseif (!$this->SuppressHTML)
681 # set content-type to get rid of diacritic errors
682 header(
"Content-Type: text/html; charset="
685 # load common HTML file (defines common functions) if available
686 $CommonHtmlFile = $this->FindFile($this->IncludeDirList,
687 "Common", array(
"tpl",
"html"));
688 if ($CommonHtmlFile) { include($CommonHtmlFile); }
691 $this->LoadUIFunctions();
693 # begin buffering content
696 # signal HTML file load
697 $SignalResult = $this->
SignalEvent(
"EVENT_HTML_FILE_LOAD", array(
698 "PageName" => $PageName));
700 # if signal handler returned new page name value
701 $NewPageName = $PageName;
702 $PageContentFile = NULL;
703 if (($SignalResult[
"PageName"] != $PageName)
704 && strlen($SignalResult[
"PageName"]))
706 # if new page name value is HTML file
707 if (file_exists($SignalResult[
"PageName"]))
709 # use new value for HTML file name
710 $PageContentFile = $SignalResult[
"PageName"];
714 # use new value for page name
715 $NewPageName = $SignalResult[
"PageName"];
719 # load page content HTML file if available
720 if ($PageContentFile === NULL)
722 $PageContentFile = $this->FindFile(
723 $this->InterfaceDirList, $NewPageName,
724 array(
"tpl",
"html"));
726 if ($PageContentFile)
728 include($PageContentFile);
732 print
"<h2>ERROR: No HTML/TPL template found"
733 .
" for this page.</h2>";
736 # signal HTML file load complete
737 $SignalResult = $this->
SignalEvent(
"EVENT_HTML_FILE_LOAD_COMPLETE");
739 # stop buffering and save output
740 $PageContentOutput = ob_get_contents();
743 # load page start HTML file if available
745 $PageStartFile = $this->FindFile($this->IncludeDirList,
"Start",
746 array(
"tpl",
"html"), array(
"StdPage",
"StandardPage"));
747 if ($PageStartFile) { include($PageStartFile); }
748 $PageStartOutput = ob_get_contents();
751 # load page end HTML file if available
753 $PageEndFile = $this->FindFile($this->IncludeDirList,
"End",
754 array(
"tpl",
"html"), array(
"StdPage",
"StandardPage"));
755 if ($PageEndFile) { include($PageEndFile); }
756 $PageEndOutput = ob_get_contents();
759 # get list of any required files not loaded
760 $RequiredFiles = $this->GetRequiredFilesNotYetLoaded($PageContentFile);
762 # if a browser detection function has been made available
763 if (is_callable($this->BrowserDetectFunc))
765 # call function to get browser list
766 $Browsers = call_user_func($this->BrowserDetectFunc);
768 # for each required file
769 $NewRequiredFiles = array();
770 foreach ($RequiredFiles as $File)
772 # if file name includes browser keyword
773 if (preg_match(
"/%BROWSER%/", $File))
776 foreach ($Browsers as $Browser)
778 # substitute in browser name and add to new file list
779 $NewRequiredFiles[] = preg_replace(
780 "/%BROWSER%/", $Browser, $File);
785 # add to new file list
786 $NewRequiredFiles[] = $File;
789 $RequiredFiles = $NewRequiredFiles;
792 # for each required file
793 foreach ($RequiredFiles as $File)
795 # locate specific file to use
796 $FilePath = $this->
GUIFile($File);
801 # determine file type
802 $NamePieces = explode(
".", $File);
803 $FileSuffix = strtolower(array_pop($NamePieces));
805 # add file to HTML output based on file type
806 $FilePath = htmlspecialchars($FilePath);
810 $Tag =
'<script type="text/javascript" src="'
811 .$FilePath.
'"></script>';
812 $PageEndOutput = preg_replace(
813 "#</body>#i", $Tag.
"\n</body>", $PageEndOutput, 1);
817 $Tag =
'<link rel="stylesheet" type="text/css"'
818 .
' media="all" href="'.$FilePath.
'">';
819 $PageStartOutput = preg_replace(
820 "#</head>#i", $Tag.
"\n</head>", $PageStartOutput, 1);
827 $FullPageOutput = $PageStartOutput.$PageContentOutput.$PageEndOutput;
829 # perform any regular expression replacements in output
830 $FullPageOutput = preg_replace($this->OutputModificationPatterns,
831 $this->OutputModificationReplacements, $FullPageOutput);
833 # perform any callback replacements in output
834 foreach ($this->OutputModificationCallbacks as $Info)
836 $this->OutputModificationCallbackInfo = $Info;
837 $FullPageOutput = preg_replace_callback($Info[
"SearchPattern"],
838 array($this,
"OutputModificationCallbackShell"),
842 # if relative paths may not work because we were invoked via clean URL
843 if ($this->CleanUrlRewritePerformed || self::WasUrlRewritten())
845 # if using the <base> tag is okay
849 # add <base> tag to header
850 $PageStartOutput = preg_replace(
"%<head>%",
851 "<head><base href=\"".$BaseUrl.
"\" />",
854 # re-assemble full page with new header
855 $FullPageOutput = $PageStartOutput.$PageContentOutput.$PageEndOutput;
857 # the absolute URL to the current page
860 # make HREF attribute values with just a fragment ID
861 # absolute since they don't work with the <base> tag because
862 # they are relative to the current page/URL, not the site
864 $FullPageOutput = preg_replace(
865 array(
"%href=\"(#[^:\" ]+)\"%i",
"%href='(#[^:' ]+)'%i"),
866 array(
"href=\"".$FullUrl.
"$1\"",
"href='".$FullUrl.
"$1'"),
871 # try to fix any relative paths throughout code
872 $FullPageOutput = preg_replace(array(
873 "%src=\"([^?*:;{}\\\\\" ]+)\.(js|css|gif|png|jpg)\"%i",
874 "%src='([^?*:;{}\\\\' ]+)\.(js|css|gif|png|jpg)'%i",
875 # don
't rewrite HREF attributes that are just
876 # fragment IDs because they are relative to the
877 # current page/URL, not the site root
878 "%href=\"([^#][^:\" ]*)\"%i",
879 "%href='([^#][^:
' ]*)'%i
",
880 "%action=\
"([^#][^:\" ]*)\"%i",
881 "%action='([^#][^:' ]*)'%i",
882 "%@import\s+url\(\"([^:\" ]+)\"\s*\)%i",
883 "%@import\s+url\('([^:\" ]+)'\s*\)%i",
884 "%@import\s+\"([^:\" ]+)\"\s*%i",
885 "%@import\s+'([^:\" ]+)'\s*%i",
888 "src=\"".$BaseUrl.
"$1.$2\"",
889 "src=\"".$BaseUrl.
"$1.$2\"",
890 "href=\"".$BaseUrl.
"$1\"",
891 "href=\"".$BaseUrl.
"$1\"",
892 "action=\"".$BaseUrl.
"$1\"",
893 "action=\"".$BaseUrl.
"$1\"",
894 "@import url(\"".$BaseUrl.
"$1\")",
895 "@import url('".$BaseUrl.
"$1')",
896 "@import \"".$BaseUrl.
"$1\"",
897 "@import '".$BaseUrl.
"$1'",
903 # provide the opportunity to modify full page output
904 $SignalResult = $this->
SignalEvent(
"EVENT_PAGE_OUTPUT_FILTER", array(
905 "PageOutput" => $FullPageOutput));
906 if (isset($SignalResult[
"PageOutput"])
907 && strlen($SignalResult[
"PageOutput"]))
909 $FullPageOutput = $SignalResult[
"PageOutput"];
912 # write out full page
913 print $FullPageOutput;
916 # run any post-processing routines
917 foreach ($this->PostProcessingFuncs as $Func)
919 call_user_func_array($Func[
"FunctionName"], $Func[
"Arguments"]);
922 # write out any output buffered from page code execution
923 if (strlen($PageOutput))
925 if (!$this->SuppressHTML)
927 ?><table width=
"100%" cellpadding=
"5"
928 style=
"border: 2px solid #666666; background: #CCCCCC;
929 font-family: Courier New, Courier, monospace;
930 margin-top: 10px;"><tr><td><?
PHP
932 if ($this->JumpToPage)
934 ?><div style=
"color: #666666;"><span style=
"font-size: 150%;">
935 <b>Page Jump Aborted</b></span>
936 (because of error or other unexpected output)<br />
938 <i><?
PHP print($this->JumpToPage); ?></i></div><?
PHP
941 if (!$this->SuppressHTML)
943 ?></td></tr></table><?
PHP
947 # write out any output buffered from the page code execution complete signal
948 if (!$this->JumpToPage && !$this->SuppressHTML && strlen($PageCompleteOutput))
950 print $PageCompleteOutput;
953 # execute callbacks that should not have their output buffered
954 foreach ($this->UnbufferedCallbacks as $Callback)
956 call_user_func_array($Callback[0], $Callback[1]);
959 # log slow page loads
963 $SlowPageLoadMsg =
"Slow page load ("
965 .$this->FullUrl().
" from "
966 .$_SERVER[
"REMOTE_ADDR"];
967 $this->
LogMessage(self::LOGLVL_INFO, $SlowPageLoadMsg);
970 # terminate and stay resident (TSR!) if indicated and HTML has been output
971 # (only TSR if HTML has been output because otherwise browsers will misbehave)
972 if ($ShouldTSR) { $this->LaunchTSR(); }
982 return $this->PageName;
992 # retrieve current URL
995 # remove the base path if present
996 $BasePath = $this->Settings[
"BasePath"];
997 if (stripos($Url, $BasePath) === 0)
999 $Url = substr($Url, strlen($BasePath));
1026 && (strpos($Page,
"?") === FALSE)
1027 && ((strpos($Page,
"=") !== FALSE)
1028 || ((stripos($Page,
".php") === FALSE)
1029 && (stripos($Page,
".htm") === FALSE)
1030 && (strpos($Page,
"/") === FALSE)))
1031 && (stripos($Page,
"http://") !== 0)
1032 && (stripos($Page,
"https://") !== 0))
1034 $this->JumpToPage = self::BaseUrl() .
"index.php?P=".$Page;
1038 $this->JumpToPage = $Page;
1048 return ($this->JumpToPage === NULL) ? FALSE : TRUE;
1062 if ($NewSetting !== NULL) { $this->
HtmlCharset = $NewSetting; }
1063 return $this->HtmlCharset;
1075 return $this->UseMinimizedJavascript;
1090 if ($NewValue !== NULL) { $this->
UseBaseTag = $NewValue ? TRUE : FALSE; }
1091 return $this->UseBaseTag;
1102 $this->SuppressHTML = $NewSetting;
1113 if ($UIName !== NULL)
1115 $this->ActiveUI = preg_replace(
"/^SPTUI--/",
"", $UIName);
1117 return $this->ActiveUI;
1127 # possible UI directories
1128 $InterfaceDirs = array(
1132 # start out with an empty list
1133 $Interfaces = array();
1135 # for each possible UI directory
1136 foreach ($InterfaceDirs as $InterfaceDir)
1138 $Dir = dir($InterfaceDir);
1140 # for each file in current directory
1141 while (($DirEntry = $Dir->read()) !== FALSE)
1143 $InterfacePath = $InterfaceDir.
"/".$DirEntry;
1145 # skip anything that doesn't have a name in the required format
1146 if (!preg_match(
'/^[a-zA-Z0-9]+$/', $DirEntry))
1151 # skip anything that isn't a directory
1152 if (!is_dir($InterfacePath))
1157 # read the UI name (if available)
1158 $UIName = @file_get_contents($InterfacePath.
"/NAME");
1160 # use the directory name if the UI name isn't available
1161 if ($UIName === FALSE || !strlen($UIName))
1163 $UIName = $DirEntry;
1166 $Interfaces[$InterfacePath] = $UIName;
1172 # return list to caller
1192 &$Arg1 = self::NOVALUE, &$Arg2 = self::NOVALUE, &$Arg3 = self::NOVALUE,
1193 &$Arg4 = self::NOVALUE, &$Arg5 = self::NOVALUE, &$Arg6 = self::NOVALUE,
1194 &$Arg7 = self::NOVALUE, &$Arg8 = self::NOVALUE, &$Arg9 = self::NOVALUE)
1196 $FuncIndex = count($this->PostProcessingFuncs);
1197 $this->PostProcessingFuncs[$FuncIndex][
"FunctionName"] = $FunctionName;
1198 $this->PostProcessingFuncs[$FuncIndex][
"Arguments"] = array();
1200 while (isset(${
"Arg".$Index}) && (${
"Arg".$Index} !== self::NOVALUE))
1202 $this->PostProcessingFuncs[$FuncIndex][
"Arguments"][$Index]
1215 $this->EnvIncludes[] = $FileName;
1226 # determine if the file is an image or JavaScript file
1227 $FileIsImage = preg_match(
"/\.(gif|jpg|png)$/", $FileName);
1228 $FileIsJavascript = preg_match(
"/\.js$/", $FileName);
1230 # determine which location to search based on file suffix
1231 $DirList = $FileIsImage ? $this->ImageDirList : $this->IncludeDirList;
1233 # if directed to get a minimized JavaScript file
1236 # first try to find the minimized JavaScript file
1237 $MinimizedFileName = substr_replace($FileName,
".min", -3, 0);
1238 $FoundFileName = $this->FindFile($DirList, $MinimizedFileName);
1240 # search for the regular file if a minimized file wasn't found
1241 if (is_null($FoundFileName))
1243 $FoundFileName = $this->FindFile($DirList, $FileName);
1247 # otherwise just search for the file
1250 $FoundFileName = $this->FindFile($DirList, $FileName);
1253 # add non-image files to list of found files (used for required files loading)
1254 if (!$FileIsImage) { $this->FoundUIFiles[] = basename($FoundFileName); }
1256 # return file name to caller
1257 return $FoundFileName;
1271 $FullFileName = $this->
GUIFile($FileName);
1272 if ($FullFileName) { print($FullFileName); }
1284 $this->AdditionalRequiredUIFiles[] = $FileName;
1297 # if specified function is not currently available
1298 if (!is_callable($Callback))
1300 # if function info looks legal
1301 if (is_string($Callback) && strlen($Callback))
1303 # start with function directory list
1304 $Locations = $this->FunctionDirList;
1306 # add object directories to list
1307 $Locations = array_merge(
1308 $Locations, array_keys(self::$ObjectDirectories));
1310 # look for function file
1311 $FunctionFileName = $this->FindFile($Locations,
"F-".$Callback,
1312 array(
"php",
"html"));
1314 # if function file was found
1315 if ($FunctionFileName)
1317 # load function file
1318 include_once($FunctionFileName);
1322 # log error indicating function load failed
1323 $this->
LogError(self::LOGLVL_ERROR,
"Unable to load function"
1324 .
" for callback \"".$Callback.
"\".");
1329 # log error indicating specified function info was bad
1330 $this->
LogError(self::LOGLVL_ERROR,
"Unloadable callback value"
1332 .
" passed to AF::LoadFunction().");
1336 # report to caller whether function load succeeded
1337 return is_callable($Callback);
1346 return microtime(TRUE) - $this->ExecutionStartTime;
1365 $Str = strtoupper(ini_get(
"memory_limit"));
1366 if (substr($Str, -1) ==
"B") { $Str = substr($Str, 0, strlen($Str) - 1); }
1367 switch (substr($Str, -1))
1369 case "K": $MemoryLimit = (int)$Str * 1024;
break;
1370 case "M": $MemoryLimit = (int)$Str * 1048576;
break;
1371 case "G": $MemoryLimit = (int)$Str * 1073741824;
break;
1372 default: $MemoryLimit = (int)$Str;
break;
1375 return $MemoryLimit - memory_get_usage();
1402 return $this->
UpdateSetting(
"SlowPageLoadThreshold", $NewValue);
1411 # HTACCESS_SUPPORT is set in the .htaccess file
1412 return isset($_SERVER[
"HTACCESS_SUPPORT"]);
1421 $Protocol = (isset($_SERVER[
"HTTPS"]) ?
"https" :
"http");
1422 $BaseUrl = $Protocol.
"://"
1423 .(($_SERVER[
"SERVER_NAME"] !=
"127.0.0.1")
1424 ? $_SERVER[
"SERVER_NAME"]
1425 : $_SERVER[
"HTTP_HOST"])
1426 .dirname($_SERVER[
"SCRIPT_NAME"]);
1427 if (substr($BaseUrl, -1) !=
"/") { $BaseUrl .=
"/"; }
1437 $Protocol = (isset($_SERVER[
"HTTPS"]) ?
"https" :
"http");
1438 $FullUrl = $Protocol.
"://"
1439 .(($_SERVER[
"SERVER_NAME"] !=
"127.0.0.1")
1440 ? $_SERVER[
"SERVER_NAME"]
1441 : $_SERVER[
"HTTP_HOST"])
1442 .$_SERVER[
"REQUEST_URI"];
1452 $BasePath = dirname($_SERVER[
"SCRIPT_NAME"]);
1454 if (substr($BasePath, -1) !=
"/")
1469 if (array_key_exists(
"SCRIPT_URL", $_SERVER))
1471 return $_SERVER[
"SCRIPT_URL"];
1473 elseif (array_key_exists(
"REDIRECT_URL", $_SERVER))
1475 return $_SERVER[
"REDIRECT_URL"];
1477 elseif (array_key_exists(
"REQUEST_URI", $_SERVER))
1479 $Pieces = parse_url($_SERVER[
"REQUEST_URI"]);
1480 return $Pieces[
"path"];
1498 # needed to get the path of the URL minus the query and fragment pieces
1499 $Components = parse_url(self::GetScriptUrl());
1501 # if parsing was successful and a path is set
1502 if (is_array($Components) && isset($Components[
"path"]))
1504 $BasePath = self::BasePath();
1505 $Path = $Components[
"path"];
1507 # the URL was rewritten if the path isn't the base path, i.e., the
1508 # home page, and the file in the URL isn't the script generating the
1510 if ($BasePath != $Path && basename($Path) != $ScriptName)
1516 # the URL wasn't rewritten
1535 # if error level is at or below current logging level
1536 if ($this->Settings[
"LoggingLevel"] >= $Level)
1538 # attempt to log error message
1541 # if logging attempt failed and level indicated significant error
1542 if (($Result === FALSE) && ($Level <= self::LOGLVL_ERROR))
1544 # throw exception about inability to log error
1545 static $AlreadyThrewException = FALSE;
1546 if (!$AlreadyThrewException)
1548 $AlreadyThrewException = TRUE;
1549 throw new Exception(
"Unable to log error (".$Level.
": ".$Msg.
").");
1553 # report to caller whether message was logged
1558 # report to caller that message was not logged
1576 # if message level is at or below current logging level
1577 if ($this->Settings[
"LoggingLevel"] >= $Level)
1579 # attempt to open log file
1580 $FHndl = @fopen($this->LogFileName,
"a");
1582 # if log file could not be open
1583 if ($FHndl === FALSE)
1585 # report to caller that message was not logged
1591 $ErrorAbbrevs = array(
1592 self::LOGLVL_FATAL =>
"FTL",
1593 self::LOGLVL_ERROR =>
"ERR",
1594 self::LOGLVL_WARNING =>
"WRN",
1595 self::LOGLVL_INFO =>
"INF",
1596 self::LOGLVL_DEBUG =>
"DBG",
1597 self::LOGLVL_TRACE =>
"TRC",
1599 $LogEntry = date(
"Y-m-d H:i:s")
1600 .
" ".($this->RunningInBackground ?
"B" :
"F")
1601 .
" ".$ErrorAbbrevs[$Level]
1604 # write entry to log
1605 $Success = fwrite($FHndl, $LogEntry.
"\n");
1610 # report to caller whether message was logged
1611 return ($Success === FALSE) ? FALSE : TRUE;
1616 # report to caller that message was not logged
1644 # constrain new level (if supplied) to within legal bounds
1647 $NewValue = max(min($NewValue, 6), 1);
1650 # set new logging level (if supplied) and return current level to caller
1662 if ($NewValue !== NULL) { $this->LogFileName = $NewValue; }
1663 return $this->LogFileName;
1701 # ---- Event Handling ----------------------------------------------------
1747 # convert parameters to array if not already in that form
1748 $Events = is_array($EventsOrEventName) ? $EventsOrEventName
1749 : array($EventsOrEventName => $Type);
1752 foreach ($Events as $Name => $Type)
1754 # store event information
1755 $this->RegisteredEvents[$Name][
"Type"] = $Type;
1756 $this->RegisteredEvents[$Name][
"Hooks"] = array();
1768 return array_key_exists($EventName, $this->RegisteredEvents)
1780 # the event isn't hooked to if it isn't even registered
1786 # return TRUE if there is at least one callback hooked to the event
1787 return count($this->RegisteredEvents[$EventName][
"Hooks"]) > 0;
1803 function HookEvent($EventsOrEventName, $Callback = NULL, $Order = self::ORDER_MIDDLE)
1805 # convert parameters to array if not already in that form
1806 $Events = is_array($EventsOrEventName) ? $EventsOrEventName
1807 : array($EventsOrEventName => $Callback);
1811 foreach ($Events as $EventName => $EventCallback)
1813 # if callback is valid
1814 if (is_callable($EventCallback))
1816 # if this is a periodic event we process internally
1817 if (isset($this->PeriodicEvents[$EventName]))
1820 $this->ProcessPeriodicEvent($EventName, $EventCallback);
1822 # if specified event has been registered
1823 elseif (isset($this->RegisteredEvents[$EventName]))
1825 # add callback for event
1826 $this->RegisteredEvents[$EventName][
"Hooks"][]
1827 = array(
"Callback" => $EventCallback,
"Order" => $Order);
1829 # sort callbacks by order
1830 if (count($this->RegisteredEvents[$EventName][
"Hooks"]) > 1)
1832 usort($this->RegisteredEvents[$EventName][
"Hooks"],
1833 array(
"ApplicationFramework",
"HookEvent_OrderCompare"));
1847 # report to caller whether all callbacks were hooked
1851 private static function HookEvent_OrderCompare($A, $B)
1853 if ($A[
"Order"] == $B[
"Order"]) {
return 0; }
1854 return ($A[
"Order"] < $B[
"Order"]) ? -1 : 1;
1867 $ReturnValue = NULL;
1869 # if event has been registered
1870 if (isset($this->RegisteredEvents[$EventName]))
1872 # set up default return value (if not NULL)
1873 switch ($this->RegisteredEvents[$EventName][
"Type"])
1875 case self::EVENTTYPE_CHAIN:
1876 $ReturnValue = $Parameters;
1879 case self::EVENTTYPE_NAMED:
1880 $ReturnValue = array();
1884 # for each callback for this event
1885 foreach ($this->RegisteredEvents[$EventName][
"Hooks"] as $Hook)
1888 $Callback = $Hook[
"Callback"];
1889 $Result = ($Parameters !== NULL)
1890 ? call_user_func_array($Callback, $Parameters)
1891 : call_user_func($Callback);
1893 # process return value based on event type
1894 switch ($this->RegisteredEvents[$EventName][
"Type"])
1896 case self::EVENTTYPE_CHAIN:
1897 if ($Result !== NULL)
1899 foreach ($Parameters as $Index => $Value)
1901 if (array_key_exists($Index, $Result))
1903 $Parameters[$Index] = $Result[$Index];
1906 $ReturnValue = $Parameters;
1910 case self::EVENTTYPE_FIRST:
1911 if ($Result !== NULL)
1913 $ReturnValue = $Result;
1918 case self::EVENTTYPE_NAMED:
1919 $CallbackName = is_array($Callback)
1920 ? (is_object($Callback[0])
1921 ? get_class($Callback[0])
1922 : $Callback[0]).
"::".$Callback[1]
1924 $ReturnValue[$CallbackName] = $Result;
1934 $this->
LogError(self::LOGLVL_WARNING,
1935 "Unregistered event signaled (".$EventName.
").");
1938 # return value if any to caller
1939 return $ReturnValue;
1949 return isset($this->PeriodicEvents[$EventName]) ? TRUE : FALSE;
1964 # if event is not a periodic event report failure to caller
1965 if (!array_key_exists($EventName, $this->EventPeriods)) {
return FALSE; }
1967 # retrieve last execution time for event if available
1968 $Signature = self::GetCallbackSignature($Callback);
1969 $LastRunTime = $this->DB->Query(
"SELECT LastRunAt FROM PeriodicEvents"
1970 .
" WHERE Signature = '".addslashes($Signature).
"'",
"LastRunAt");
1972 # if event was not found report failure to caller
1973 if ($LastRunTime === NULL) {
return FALSE; }
1975 # calculate next run time based on event period
1976 $NextRunTime = strtotime($LastRunTime) + $this->EventPeriods[$EventName];
1978 # report next run time to caller
1979 return $NextRunTime;
1999 # retrieve last execution times
2000 $this->DB->Query(
"SELECT * FROM PeriodicEvents");
2001 $LastRunTimes = $this->DB->FetchColumn(
"LastRunAt",
"Signature");
2003 # for each known event
2005 foreach ($this->KnownPeriodicEvents as $Signature => $Info)
2007 # if last run time for event is available
2008 if (array_key_exists($Signature, $LastRunTimes))
2010 # calculate next run time for event
2011 $LastRun = strtotime($LastRunTimes[$Signature]);
2012 $NextRun = $LastRun + $this->EventPeriods[$Info[
"Period"]];
2013 if ($Info[
"Period"] ==
"EVENT_PERIODIC") { $LastRun = FALSE; }
2017 # set info to indicate run times are not known
2022 # add event info to list
2023 $Events[$Signature] = $Info;
2024 $Events[$Signature][
"LastRun"] = $LastRun;
2025 $Events[$Signature][
"NextRun"] = $NextRun;
2026 $Events[$Signature][
"Parameters"] = NULL;
2029 # return list of known events to caller
2035 # ---- Task Management ---------------------------------------------------
2061 $Priority = self::PRIORITY_LOW, $Description =
"")
2063 # pack task info and write to database
2064 if ($Parameters === NULL) { $Parameters = array(); }
2065 $this->DB->Query(
"INSERT INTO TaskQueue"
2066 .
" (Callback, Parameters, Priority, Description)"
2067 .
" VALUES ('".addslashes(serialize($Callback)).
"', '"
2068 .addslashes(serialize($Parameters)).
"', ".intval($Priority).
", '"
2069 .addslashes($Description).
"')");
2090 $Priority = self::PRIORITY_LOW, $Description =
"")
2094 $QueryResult = $this->DB->Query(
"SELECT TaskId,Priority FROM TaskQueue"
2095 .
" WHERE Callback = '".addslashes(serialize($Callback)).
"'"
2096 .($Parameters ?
" AND Parameters = '"
2097 .addslashes(serialize($Parameters)).
"'" :
""));
2098 if ($QueryResult !== FALSE)
2100 $Record = $this->DB->FetchRow();
2101 if ($Record[
"Priority"] > $Priority)
2103 $this->DB->Query(
"UPDATE TaskQueue"
2104 .
" SET Priority = ".intval($Priority)
2105 .
" WHERE TaskId = ".intval($Record[
"TaskId"]));
2112 $this->
QueueTask($Callback, $Parameters, $Priority, $Description);
2128 $QueuedCount = $this->DB->Query(
2129 "SELECT COUNT(*) AS FoundCount FROM TaskQueue"
2130 .
" WHERE Callback = '".addslashes(serialize($Callback)).
"'"
2131 .($Parameters ?
" AND Parameters = '"
2132 .addslashes(serialize($Parameters)).
"'" :
""),
2134 $RunningCount = $this->DB->Query(
2135 "SELECT COUNT(*) AS FoundCount FROM RunningTasks"
2136 .
" WHERE Callback = '".addslashes(serialize($Callback)).
"'"
2137 .($Parameters ?
" AND Parameters = '"
2138 .addslashes(serialize($Parameters)).
"'" :
""),
2140 $FoundCount = $QueuedCount + $RunningCount;
2141 return ($FoundCount ? TRUE : FALSE);
2163 return $this->GetTaskList(
"SELECT * FROM TaskQueue"
2164 .
" ORDER BY Priority, TaskId ", $Count, $Offset);
2181 $Parameters = NULL, $Priority = NULL, $Description = NULL)
2183 $Query =
"SELECT COUNT(*) AS TaskCount FROM TaskQueue";
2185 if ($Callback !== NULL)
2187 $Query .= $Sep.
" Callback = '".addslashes(serialize($Callback)).
"'";
2190 if ($Parameters !== NULL)
2192 $Query .= $Sep.
" Parameters = '".addslashes(serialize($Parameters)).
"'";
2195 if ($Priority !== NULL)
2197 $Query .= $Sep.
" Priority = ".intval($Priority);
2200 if ($Description !== NULL)
2202 $Query .= $Sep.
" Description = '".addslashes($Description).
"'";
2204 return $this->DB->Query($Query,
"TaskCount");
2216 return $this->GetTaskList(
"SELECT * FROM RunningTasks"
2217 .
" WHERE StartedAt >= '".date(
"Y-m-d H:i:s",
2218 (time() - ini_get(
"max_execution_time"))).
"'"
2219 .
" ORDER BY StartedAt", $Count, $Offset);
2231 return $this->GetTaskList(
"SELECT * FROM RunningTasks"
2232 .
" WHERE StartedAt < '".date(
"Y-m-d H:i:s",
2233 (time() - ini_get(
"max_execution_time"))).
"'"
2234 .
" ORDER BY StartedAt", $Count, $Offset);
2243 return $this->DB->Query(
"SELECT COUNT(*) AS Count FROM RunningTasks"
2244 .
" WHERE StartedAt < '".date(
"Y-m-d H:i:s",
2245 (time() - ini_get(
"max_execution_time"))).
"'",
2256 $this->DB->Query(
"LOCK TABLES TaskQueue WRITE, RunningTasks WRITE");
2257 $this->DB->Query(
"INSERT INTO TaskQueue"
2258 .
" (Callback,Parameters,Priority,Description) "
2259 .
"SELECT Callback, Parameters, Priority, Description"
2260 .
" FROM RunningTasks WHERE TaskId = ".intval($TaskId));
2261 if ($NewPriority !== NULL)
2263 $NewTaskId = $this->DB->LastInsertId();
2264 $this->DB->Query(
"UPDATE TaskQueue SET Priority = "
2265 .intval($NewPriority)
2266 .
" WHERE TaskId = ".intval($NewTaskId));
2268 $this->DB->Query(
"DELETE FROM RunningTasks WHERE TaskId = ".intval($TaskId));
2269 $this->DB->Query(
"UNLOCK TABLES");
2278 $this->DB->Query(
"DELETE FROM TaskQueue WHERE TaskId = ".intval($TaskId));
2279 $this->DB->Query(
"DELETE FROM RunningTasks WHERE TaskId = ".intval($TaskId));
2291 # assume task will not be found
2294 # look for task in task queue
2295 $this->DB->Query(
"SELECT * FROM TaskQueue WHERE TaskId = ".intval($TaskId));
2297 # if task was not found in queue
2298 if (!$this->DB->NumRowsSelected())
2300 # look for task in running task list
2301 $this->DB->Query(
"SELECT * FROM RunningTasks WHERE TaskId = "
2306 if ($this->DB->NumRowsSelected())
2308 # if task was periodic
2309 $Row = $this->DB->FetchRow();
2310 if ($Row[
"Callback"] ==
2311 serialize(array(
"ApplicationFramework",
"PeriodicEventWrapper")))
2313 # unpack periodic task callback
2314 $WrappedCallback = unserialize($Row[
"Parameters"]);
2315 $Task[
"Callback"] = $WrappedCallback[1];
2316 $Task[
"Parameters"] = $WrappedCallback[2];
2320 # unpack task callback and parameters
2321 $Task[
"Callback"] = unserialize($Row[
"Callback"]);
2322 $Task[
"Parameters"] = unserialize($Row[
"Parameters"]);
2326 # return task to caller
2339 return $this->
UpdateSetting(
"TaskExecutionEnabled", $NewValue);
2361 if (func_num_args() && !ini_get(
"safe_mode"))
2363 if ($NewValue != $this->Settings[
"MaxExecTime"])
2365 $this->Settings[
"MaxExecTime"] = max($NewValue, 5);
2366 $this->DB->Query(
"UPDATE ApplicationFrameworkSettings"
2367 .
" SET MaxExecTime = '"
2368 .intval($this->Settings[
"MaxExecTime"]).
"'");
2370 ini_set(
"max_execution_time", $this->Settings[
"MaxExecTime"]);
2371 set_time_limit($this->Settings[
"MaxExecTime"]);
2373 return ini_get(
"max_execution_time");
2378 # ---- Backward Compatibility --------------------------------------------
2388 return $this->FindFile(
2389 $this->IncludeDirList, $BaseName, array(
"tpl",
"html"));
2395 # ---- PRIVATE INTERFACE -------------------------------------------------
2397 private $ActiveUI =
"default";
2398 private $BrowserDetectFunc;
2399 private $CleanUrlMappings = array();
2400 private $CleanUrlRewritePerformed = FALSE;
2402 private $DefaultPage =
"Home";
2403 private $EnvIncludes = array();
2404 private $ExecutionStartTime;
2405 private $FoundUIFiles = array();
2406 private $AdditionalRequiredUIFiles = array();
2407 private $HtmlCharset =
"UTF-8";
2408 private $JumpToPage = NULL;
2409 private $LogFileName =
"local/logs/site.log";
2410 private $MaxRunningTasksToTrack = 250;
2411 private $OutputModificationPatterns = array();
2412 private $OutputModificationReplacements = array();
2413 private $OutputModificationCallbacks = array();
2414 private $OutputModificationCallbackInfo;
2416 private $PostProcessingFuncs = array();
2417 private $RunningInBackground = FALSE;
2418 private $RunningTask;
2420 private $SuppressHTML = FALSE;
2421 private $SaveTemplateLocationCache = FALSE;
2422 private $UnbufferedCallbacks = array();
2423 private $UseBaseTag = FALSE;
2424 private $UseMinimizedJavascript = FALSE;
2426 private static $AppName =
"ScoutAF";
2427 private static $ObjectDirectories = array();
2428 private static $ObjectLocationCache;
2429 private static $ObjectLocationCacheInterval = 60;
2430 private static $ObjectLocationCacheExpiration;
2431 private static $SaveObjectLocationCache = FALSE;
2432 private static $SessionLifetime = 1440;
2438 private $NoTSR = FALSE;
2440 private $KnownPeriodicEvents = array();
2441 private $PeriodicEvents = array(
2442 "EVENT_HOURLY" => self::EVENTTYPE_DEFAULT,
2443 "EVENT_DAILY" => self::EVENTTYPE_DEFAULT,
2444 "EVENT_WEEKLY" => self::EVENTTYPE_DEFAULT,
2445 "EVENT_MONTHLY" => self::EVENTTYPE_DEFAULT,
2446 "EVENT_PERIODIC" => self::EVENTTYPE_NAMED,
2448 private $EventPeriods = array(
2449 "EVENT_HOURLY" => 3600,
2450 "EVENT_DAILY" => 86400,
2451 "EVENT_WEEKLY" => 604800,
2452 "EVENT_MONTHLY" => 2592000,
2453 "EVENT_PERIODIC" => 0,
2455 private $UIEvents = array(
2456 "EVENT_PAGE_LOAD" => self::EVENTTYPE_DEFAULT,
2457 "EVENT_PHP_FILE_LOAD" => self::EVENTTYPE_CHAIN,
2458 "EVENT_PHP_FILE_LOAD_COMPLETE" => self::EVENTTYPE_DEFAULT,
2459 "EVENT_HTML_FILE_LOAD" => self::EVENTTYPE_CHAIN,
2460 "EVENT_HTML_FILE_LOAD_COMPLETE" => self::EVENTTYPE_DEFAULT,
2461 "EVENT_PAGE_OUTPUT_FILTER" => self::EVENTTYPE_CHAIN,
2467 private function LoadSettings()
2469 # read settings in from database
2470 $this->DB->Query(
"SELECT * FROM ApplicationFrameworkSettings");
2471 $this->Settings = $this->DB->FetchRow();
2473 # if settings were not previously initialized
2474 if (!$this->Settings)
2476 # initialize settings in database
2477 $this->DB->Query(
"INSERT INTO ApplicationFrameworkSettings"
2478 .
" (LastTaskRunAt) VALUES ('2000-01-02 03:04:05')");
2480 # read new settings in from database
2481 $this->DB->Query(
"SELECT * FROM ApplicationFrameworkSettings");
2482 $this->Settings = $this->DB->FetchRow();
2485 # if base path was not previously set or we appear to have moved
2486 if (!array_key_exists(
"BasePath", $this->Settings)
2487 || (!strlen($this->Settings[
"BasePath"]))
2488 || (!array_key_exists(
"BasePathCheck", $this->Settings))
2489 || (__FILE__ != $this->Settings[
"BasePathCheck"]))
2491 # attempt to extract base path from Apache .htaccess file
2492 if (is_readable(
".htaccess"))
2494 $Lines = file(
".htaccess");
2495 foreach ($Lines as $Line)
2497 if (preg_match(
"/\\s*RewriteBase\\s+/", $Line))
2499 $Pieces = preg_split(
2500 "/\\s+/", $Line, NULL, PREG_SPLIT_NO_EMPTY);
2501 $BasePath = $Pieces[1];
2506 # if base path was found
2507 if (isset($BasePath))
2509 # save base path locally
2510 $this->Settings[
"BasePath"] = $BasePath;
2512 # save base path to database
2513 $this->DB->Query(
"UPDATE ApplicationFrameworkSettings"
2514 .
" SET BasePath = '".addslashes($BasePath).
"'"
2515 .
", BasePathCheck = '".addslashes(__FILE__).
"'");
2519 # if template location cache has been saved to database
2520 if (isset($this->Settings[
"TemplateLocationCache"]))
2522 # unserialize cache values into array and use if valid
2523 $Cache = unserialize($this->Settings[
"TemplateLocationCache"]);
2524 $this->Settings[
"TemplateLocationCache"] =
2525 count($Cache) ? $Cache : array();
2529 # start with empty cache
2530 $this->Settings[
"TemplateLocationCache"] = array();
2533 # if object location cache has been saved to database
2534 if (isset($this->Settings[
"ObjectLocationCache"]))
2536 # unserialize cache values into array and use if valid
2537 $Cache = unserialize($this->Settings[
"ObjectLocationCache"]);
2538 $this->Settings[
"ObjectLocationCache"] =
2539 count($Cache) ? $Cache : array();
2541 # store static versions for use when autoloading objects
2542 self::$ObjectLocationCache =
2543 $this->Settings[
"ObjectLocationCache"];
2544 self::$ObjectLocationCacheInterval =
2545 $this->Settings[
"ObjectLocationCacheInterval"];
2546 self::$ObjectLocationCacheExpiration =
2547 $this->Settings[
"ObjectLocationCacheExpiration"];
2551 # start with empty cache
2552 $this->Settings[
"ObjectLocationCache"] = array();
2562 private function RewriteCleanUrls($PageName)
2564 # if URL rewriting is supported by the server
2567 # retrieve current URL and remove base path if present
2570 # for each clean URL mapping
2571 foreach ($this->CleanUrlMappings as $Info)
2573 # if current URL matches clean URL pattern
2574 if (preg_match($Info[
"Pattern"], $Url, $Matches))
2577 $PageName = $Info[
"Page"];
2579 # if $_GET variables specified for clean URL
2580 if ($Info[
"GetVars"] !== NULL)
2582 # for each $_GET variable specified for clean URL
2583 foreach ($Info[
"GetVars"] as $VarName => $VarTemplate)
2585 # start with template for variable value
2586 $Value = $VarTemplate;
2588 # for each subpattern matched in current URL
2589 foreach ($Matches as $Index => $Match)
2591 # if not first (whole) match
2594 # make any substitutions in template
2595 $Value = str_replace(
"$".$Index, $Match, $Value);
2599 # set $_GET variable
2600 $_GET[$VarName] = $Value;
2604 # set flag indicating clean URL mapped
2605 $this->CleanUrlRewritePerformed = TRUE;
2607 # stop looking for a mapping
2613 # return (possibly) updated page name to caller
2633 private function FindFile($DirectoryList, $BaseName,
2634 $PossibleSuffixes = NULL, $PossiblePrefixes = NULL)
2636 # generate template cache index for this page
2637 $CacheIndex = md5(serialize($DirectoryList))
2638 .
":".$this->ActiveUI.
":".$BaseName;
2640 # if we have cached location and cache expiration time has not elapsed
2641 if (($this->Settings[
"TemplateLocationCacheInterval"] > 0)
2642 && count($this->Settings[
"TemplateLocationCache"])
2643 && array_key_exists($CacheIndex,
2644 $this->Settings[
"TemplateLocationCache"])
2645 && (time() < strtotime(
2646 $this->Settings[
"TemplateLocationCacheExpiration"])))
2648 # use template location from cache
2649 $FoundFileName = $this->Settings[
2650 "TemplateLocationCache"][$CacheIndex];
2654 # if suffixes specified and base name does not include suffix
2655 if (count($PossibleSuffixes)
2656 && !preg_match(
"/\.[a-zA-Z0-9]+$/", $BaseName))
2658 # add versions of file names with suffixes to file name list
2659 $FileNames = array();
2660 foreach ($PossibleSuffixes as $Suffix)
2662 $FileNames[] = $BaseName.
".".$Suffix;
2667 # use base name as file name
2668 $FileNames = array($BaseName);
2671 # if prefixes specified
2672 if (count($PossiblePrefixes))
2674 # add versions of file names with prefixes to file name list
2675 $NewFileNames = array();
2676 foreach ($FileNames as $FileName)
2678 foreach ($PossiblePrefixes as $Prefix)
2680 $NewFileNames[] = $Prefix.$FileName;
2683 $FileNames = $NewFileNames;
2686 # for each possible location
2687 $FoundFileName = NULL;
2688 foreach ($DirectoryList as $Dir)
2690 # substitute active UI name into path
2691 $Dir = str_replace(
"%ACTIVEUI%", $this->ActiveUI, $Dir);
2693 # for each possible file name
2694 foreach ($FileNames as $File)
2696 # if template is found at location
2697 if (file_exists($Dir.$File))
2699 # save full template file name and stop looking
2700 $FoundFileName = $Dir.$File;
2706 # save location in cache
2707 $this->Settings[
"TemplateLocationCache"][$CacheIndex]
2710 # set flag indicating that cache should be saved
2711 $this->SaveTemplateLocationCache = TRUE;
2714 # return full template file name to caller
2715 return $FoundFileName;
2724 private function GetRequiredFilesNotYetLoaded($PageContentFile)
2726 # start out assuming no files required
2727 $RequiredFiles = array();
2729 # if page content file supplied
2730 if ($PageContentFile)
2732 # if file containing list of required files is available
2733 $Path = dirname($PageContentFile);
2734 $RequireListFile = $Path.
"/REQUIRES";
2735 if (file_exists($RequireListFile))
2737 # read in list of required files
2738 $RequestedFiles = file($RequireListFile);
2740 # for each line in required file list
2741 foreach ($RequestedFiles as $Line)
2743 # if line is not a comment
2744 $Line = trim($Line);
2745 if (!preg_match(
"/^#/", $Line))
2747 # if file has not already been loaded
2748 if (!in_array($Line, $this->FoundUIFiles))
2750 # add to list of required files
2751 $RequiredFiles[] = $Line;
2758 # add in additional required files if any
2759 if (count($this->AdditionalRequiredUIFiles))
2761 # make sure there are no duplicates
2762 $AdditionalRequiredUIFiles = array_unique(
2763 $this->AdditionalRequiredUIFiles);
2765 $RequiredFiles = array_merge(
2766 $RequiredFiles, $AdditionalRequiredUIFiles);
2769 # return list of required files to caller
2770 return $RequiredFiles;
2776 private function SetUpObjectAutoloading()
2779 function __autoload($ClassName)
2781 ApplicationFramework::AutoloadObjects($ClassName);
2790 static function AutoloadObjects($ClassName)
2792 # if caching is not turned off
2793 # and we have a cached location for class
2794 # and cache expiration has not elapsed
2795 # and file at cached location is readable
2796 if ((self::$ObjectLocationCacheInterval > 0)
2797 && count(self::$ObjectLocationCache)
2798 && array_key_exists($ClassName,
2799 self::$ObjectLocationCache)
2800 && (time() < strtotime(
2801 self::$ObjectLocationCacheExpiration))
2802 && is_readable(self::$ObjectLocationCache[$ClassName]))
2804 # use object location from cache
2805 require_once(self::$ObjectLocationCache[$ClassName]);
2809 # for each possible object file directory
2811 foreach (self::$ObjectDirectories as $Location => $Info)
2813 # if directory looks valid
2814 if (is_dir($Location))
2816 # build class file name
2817 $NewClassName = ($Info[
"ClassPattern"] && $Info[
"ClassReplacement"])
2818 ? preg_replace($Info[
"ClassPattern"],
2819 $Info[
"ClassReplacement"], $ClassName)
2822 # read in directory contents if not already retrieved
2823 if (!isset($FileLists[$Location]))
2825 $FileLists[$Location] = self::ReadDirectoryTree(
2826 $Location,
'/^.+\.php$/i');
2829 # for each file in target directory
2830 $FileNames = $FileLists[$Location];
2831 $TargetName = strtolower($Info[
"Prefix"].$NewClassName.
".php");
2832 foreach ($FileNames as $FileName)
2834 # if file matches our target object file name
2835 if (strtolower($FileName) == $TargetName)
2837 # include object file
2838 require_once($Location.$FileName);
2840 # save location to cache
2841 self::$ObjectLocationCache[$ClassName]
2842 = $Location.$FileName;
2844 # set flag indicating that cache should be saved
2845 self::$SaveObjectLocationCache = TRUE;
2863 private static function ReadDirectoryTree($Directory, $Pattern)
2865 $CurrentDir = getcwd();
2867 $DirIter =
new RecursiveDirectoryIterator(
".");
2868 $IterIter =
new RecursiveIteratorIterator($DirIter);
2869 $RegexResults =
new RegexIterator($IterIter, $Pattern,
2870 RecursiveRegexIterator::GET_MATCH);
2871 $FileList = array();
2872 foreach ($RegexResults as $Result)
2874 $FileList[] = substr($Result[0], 2);
2884 private function UndoMagicQuotes()
2886 # if this PHP version has magic quotes support
2887 if (version_compare(PHP_VERSION,
"5.4.0",
"<"))
2889 # turn off runtime magic quotes if on
2890 if (get_magic_quotes_runtime())
2892 set_magic_quotes_runtime(FALSE);
2895 # if magic quotes GPC is on
2896 if (get_magic_quotes_gpc())
2898 # strip added slashes from incoming variables
2899 $GPC = array(&$_GET, &$_POST, &$_COOKIE, &$_REQUEST);
2900 array_walk_recursive($GPC,
2901 array($this,
"UndoMagicQuotes_StripCallback"));
2905 private function UndoMagicQuotes_StripCallback(&$Value, $Key)
2907 $Value = stripslashes($Value);
2914 private function LoadUIFunctions()
2917 "local/interface/%ACTIVEUI%/include",
2918 "interface/%ACTIVEUI%/include",
2919 "local/interface/default/include",
2920 "interface/default/include",
2922 foreach ($Dirs as $Dir)
2924 $Dir = str_replace(
"%ACTIVEUI%", $this->ActiveUI, $Dir);
2927 $FileNames = scandir($Dir);
2928 foreach ($FileNames as $FileName)
2930 if (preg_match(
"/^F-([A-Za-z0-9_]+)\.php/", $FileName, $Matches)
2931 || preg_match(
"/^F-([A-Za-z0-9_]+)\.html/", $FileName, $Matches))
2933 if (!function_exists($Matches[1]))
2935 include_once($Dir.
"/".$FileName);
2948 private function ProcessPeriodicEvent($EventName, $Callback)
2950 # retrieve last execution time for event if available
2951 $Signature = self::GetCallbackSignature($Callback);
2952 $LastRun = $this->DB->Query(
"SELECT LastRunAt FROM PeriodicEvents"
2953 .
" WHERE Signature = '".addslashes($Signature).
"'",
"LastRunAt");
2955 # determine whether enough time has passed for event to execute
2956 $ShouldExecute = (($LastRun === NULL)
2957 || (time() > (strtotime($LastRun) + $this->EventPeriods[$EventName])))
2960 # if event should run
2963 # add event to task queue
2964 $WrapperCallback = array(
"ApplicationFramework",
"PeriodicEventWrapper");
2965 $WrapperParameters = array(
2966 $EventName, $Callback, array(
"LastRunAt" => $LastRun));
2970 # add event to list of periodic events
2971 $this->KnownPeriodicEvents[$Signature] = array(
2972 "Period" => $EventName,
2973 "Callback" => $Callback,
2974 "Queued" => $ShouldExecute);
2984 private static function PeriodicEventWrapper($EventName, $Callback, $Parameters)
2987 if (!isset($DB)) { $DB =
new Database(); }
2990 $ReturnVal = call_user_func_array($Callback, $Parameters);
2992 # if event is already in database
2993 $Signature = self::GetCallbackSignature($Callback);
2994 if ($DB->Query(
"SELECT COUNT(*) AS EventCount FROM PeriodicEvents"
2995 .
" WHERE Signature = '".addslashes($Signature).
"'",
"EventCount"))
2997 # update last run time for event
2998 $DB->Query(
"UPDATE PeriodicEvents SET LastRunAt = "
2999 .(($EventName ==
"EVENT_PERIODIC")
3000 ?
"'".date(
"Y-m-d H:i:s", time() + ($ReturnVal * 60)).
"'"
3002 .
" WHERE Signature = '".addslashes($Signature).
"'");
3006 # add last run time for event to database
3007 $DB->Query(
"INSERT INTO PeriodicEvents (Signature, LastRunAt) VALUES "
3008 .
"('".addslashes($Signature).
"', "
3009 .(($EventName ==
"EVENT_PERIODIC")
3010 ?
"'".date(
"Y-m-d H:i:s", time() + ($ReturnVal * 60)).
"'"
3020 private static function GetCallbackSignature($Callback)
3022 return !is_array($Callback) ? $Callback
3023 : (is_object($Callback[0]) ? md5(serialize($Callback[0])) : $Callback[0])
3031 private function PrepForTSR()
3033 # if HTML has been output and it's time to launch another task
3034 # (only TSR if HTML has been output because otherwise browsers
3035 # may misbehave after connection is closed)
3036 if (($this->JumpToPage || !$this->SuppressHTML)
3037 && (time() > (strtotime($this->Settings[
"LastTaskRunAt"])
3038 + (ini_get(
"max_execution_time")
3039 / $this->Settings[
"MaxTasksRunning"]) + 5))
3041 && $this->Settings[
"TaskExecutionEnabled"])
3043 # begin buffering output for TSR
3046 # let caller know it is time to launch another task
3051 # let caller know it is not time to launch another task
3060 private function LaunchTSR()
3062 # set headers to close out connection to browser
3065 ignore_user_abort(TRUE);
3066 header(
"Connection: close");
3067 header(
"Content-Length: ".ob_get_length());
3070 # output buffered content
3071 while (ob_get_level()) { ob_end_flush(); }
3074 # write out any outstanding data and end HTTP session
3075 session_write_close();
3077 # set flag indicating that we are now running in background
3078 $this->RunningInBackground = TRUE;
3080 # if there is still a task in the queue
3083 # turn on output buffering to (hopefully) record any crash output
3086 # lock tables and grab last task run time to double check
3087 $this->DB->Query(
"LOCK TABLES ApplicationFrameworkSettings WRITE");
3088 $this->LoadSettings();
3090 # if still time to launch another task
3091 if (time() > (strtotime($this->Settings[
"LastTaskRunAt"])
3092 + (ini_get(
"max_execution_time")
3093 / $this->Settings[
"MaxTasksRunning"]) + 5))
3095 # update the "last run" time and release tables
3096 $this->DB->Query(
"UPDATE ApplicationFrameworkSettings"
3097 .
" SET LastTaskRunAt = '".date(
"Y-m-d H:i:s").
"'");
3098 $this->DB->Query(
"UNLOCK TABLES");
3100 # run tasks while there is a task in the queue and enough time left
3104 $this->RunNextTask();
3112 $this->DB->Query(
"UNLOCK TABLES");
3124 private function GetTaskList($DBQuery, $Count, $Offset)
3126 $this->DB->Query($DBQuery.
" LIMIT ".intval($Offset).
",".intval($Count));
3128 while ($Row = $this->DB->FetchRow())
3130 $Tasks[$Row[
"TaskId"]] = $Row;
3131 if ($Row[
"Callback"] ==
3132 serialize(array(
"ApplicationFramework",
"PeriodicEventWrapper")))
3134 $WrappedCallback = unserialize($Row[
"Parameters"]);
3135 $Tasks[$Row[
"TaskId"]][
"Callback"] = $WrappedCallback[1];
3136 $Tasks[$Row[
"TaskId"]][
"Parameters"] = NULL;
3140 $Tasks[$Row[
"TaskId"]][
"Callback"] = unserialize($Row[
"Callback"]);
3141 $Tasks[$Row[
"TaskId"]][
"Parameters"] = unserialize($Row[
"Parameters"]);
3150 private function RunNextTask()
3152 # lock tables to prevent same task from being run by multiple sessions
3153 $this->DB->Query(
"LOCK TABLES TaskQueue WRITE, RunningTasks WRITE");
3155 # look for task at head of queue
3156 $this->DB->Query(
"SELECT * FROM TaskQueue ORDER BY Priority, TaskId LIMIT 1");
3157 $Task = $this->DB->FetchRow();
3159 # if there was a task available
3162 # move task from queue to running tasks list
3163 $this->DB->Query(
"INSERT INTO RunningTasks "
3164 .
"(TaskId,Callback,Parameters,Priority,Description) "
3165 .
"SELECT * FROM TaskQueue WHERE TaskId = "
3166 .intval($Task[
"TaskId"]));
3167 $this->DB->Query(
"DELETE FROM TaskQueue WHERE TaskId = "
3168 .intval($Task[
"TaskId"]));
3170 # release table locks to again allow other sessions to run tasks
3171 $this->DB->Query(
"UNLOCK TABLES");
3173 # unpack stored task info
3174 $Callback = unserialize($Task[
"Callback"]);
3175 $Parameters = unserialize($Task[
"Parameters"]);
3177 # attempt to load task callback if not already available
3181 $this->RunningTask = $Task;
3184 call_user_func_array($Callback, $Parameters);
3188 call_user_func($Callback);
3190 unset($this->RunningTask);
3192 # remove task from running tasks list
3193 $this->DB->Query(
"DELETE FROM RunningTasks"
3194 .
" WHERE TaskId = ".intval($Task[
"TaskId"]));
3196 # prune running tasks list if necessary
3197 $RunningTasksCount = $this->DB->Query(
3198 "SELECT COUNT(*) AS TaskCount FROM RunningTasks",
"TaskCount");
3199 if ($RunningTasksCount > $this->MaxRunningTasksToTrack)
3201 $this->DB->Query(
"DELETE FROM RunningTasks ORDER BY StartedAt"
3202 .
" LIMIT ".($RunningTasksCount - $this->MaxRunningTasksToTrack));
3207 # release table locks to again allow other sessions to run tasks
3208 $this->DB->Query(
"UNLOCK TABLES");
3219 if (isset($this->RunningTask))
3221 if (function_exists(
"error_get_last"))
3223 $CrashInfo[
"LastError"] = error_get_last();
3225 if (ob_get_length() !== FALSE)
3227 $CrashInfo[
"OutputBuffer"] = ob_get_contents();
3229 if (isset($CrashInfo))
3232 $DB->Query(
"UPDATE RunningTasks SET CrashInfo = '"
3233 .addslashes(serialize($CrashInfo))
3234 .
"' WHERE TaskId = ".intval($this->RunningTask[
"TaskId"]));
3258 private function AddToDirList($DirList, $Dir, $SearchLast, $SkipSlashCheck)
3260 # convert incoming directory to array of directories (if needed)
3261 $Dirs = is_array($Dir) ? $Dir : array($Dir);
3263 # reverse array so directories are searched in specified order
3264 $Dirs = array_reverse($Dirs);
3266 # for each directory
3267 foreach ($Dirs as $Location)
3269 # make sure directory includes trailing slash
3270 if (!$SkipSlashCheck)
3272 $Location = $Location
3273 .((substr($Location, -1) !=
"/") ?
"/" :
"");
3276 # remove directory from list if already present
3277 if (in_array($Location, $DirList))
3279 $DirList = array_diff(
3280 $DirList, array($Location));
3283 # add directory to list of directories
3286 array_push($DirList, $Location);
3290 array_unshift($DirList, $Location);
3294 # return updated directory list to caller
3305 private function ArrayPermutations(
$Items, $Perms = array())
3309 $Result = array($Perms);
3314 for ($Index = count(
$Items) - 1; $Index >= 0; --$Index)
3318 list($Segment) = array_splice($NewItems, $Index, 1);
3319 array_unshift($NewPerms, $Segment);
3320 $Result = array_merge($Result,
3321 $this->ArrayPermutations($NewItems, $NewPerms));
3333 private function OutputModificationCallbackShell($Matches)
3335 # call previously-stored external function
3336 return call_user_func($this->OutputModificationCallbackInfo[
"Callback"],
3338 $this->OutputModificationCallbackInfo[
"Pattern"],
3339 $this->OutputModificationCallbackInfo[
"Page"],
3340 $this->OutputModificationCallbackInfo[
"SearchPattern"]);
3351 return $this->DB->UpdateValue(
"ApplicationFrameworkSettings",
3352 $FieldName, $NewValue, NULL, $this->Settings);
3356 private $InterfaceDirList = array(
3357 "local/interface/%ACTIVEUI%/",
3358 "interface/%ACTIVEUI%/",
3359 "local/interface/default/",
3360 "interface/default/",
3366 private $IncludeDirList = array(
3367 "local/interface/%ACTIVEUI%/include/",
3368 "interface/%ACTIVEUI%/include/",
3369 "local/interface/default/include/",
3370 "interface/default/include/",
3373 private $ImageDirList = array(
3374 "local/interface/%ACTIVEUI%/images/",
3375 "interface/%ACTIVEUI%/images/",
3376 "local/interface/default/images/",
3377 "interface/default/images/",
3380 private $FunctionDirList = array(
3381 "local/interface/%ACTIVEUI%/include/",
3382 "interface/%ACTIVEUI%/include/",
3383 "local/interface/default/include/",
3384 "interface/default/include/",
3389 const NOVALUE =
".-+-.NO VALUE PASSED IN FOR ARGUMENT.-+-.";
MaxTasks($NewValue=DB_NOVALUE)
Get/set maximum number of tasks to have running simultaneously.
const LOGLVL_ERROR
ERROR error logging level.
GetOrphanedTaskList($Count=100, $Offset=0)
Retrieve list of tasks currently in queue.
SuppressHTMLOutput($NewSetting=TRUE)
Suppress loading of HTML files.
AddInterfaceDirectories($Dir, $SearchLast=FALSE, $SkipSlashCheck=FALSE)
Add additional directory(s) to be searched for user interface (HTML/TPL) files.
AddIncludeDirectories($Dir, $SearchLast=FALSE, $SkipSlashCheck=FALSE)
Add additional directory(s) to be searched for user interface include (CSS, JavaScript, common PHP, common HTML, etc) files.
static GetScriptUrl()
Retrieve SCRIPT_URL server value, pulling it from elsewhere if that variable isn't set...
const LOGLVL_INFO
INFO error logging level.
AddUnbufferedCallback($Callback, $Parameters=array())
Add a callback that will be executed after buffered content has been output and that won't have its o...
QueueUniqueTask($Callback, $Parameters=NULL, $Priority=self::PRIORITY_LOW, $Description="")
Add task to queue if not already in queue or currently running.
const LOGLVL_FATAL
FATAL error logging level.
UseMinimizedJavascript($NewSetting=NULL)
Get/set whether or not to check for and use minimized JavaScript files when getting a JavaScript UI f...
AddPostProcessingCall($FunctionName, &$Arg1=self::NOVALUE, &$Arg2=self::NOVALUE, &$Arg3=self::NOVALUE, &$Arg4=self::NOVALUE, &$Arg5=self::NOVALUE, &$Arg6=self::NOVALUE, &$Arg7=self::NOVALUE, &$Arg8=self::NOVALUE, &$Arg9=self::NOVALUE)
Add function to be called after HTML has been loaded.
GetCleanUrlForPath($Path)
Get the clean URL mapped for a path.
const PRIORITY_LOW
Lower priority.
Abstraction for forum messages and resource comments.
GetQueuedTaskList($Count=100, $Offset=0)
Retrieve list of tasks currently in queue.
LogFile($NewValue=NULL)
Get/set log file name.
GetCleanUrl()
Get the clean URL for the current page if one is available.
MaxExecutionTime($NewValue=NULL)
Get/set maximum PHP execution time.
RequireUIFile($FileName)
Add file to list of required UI files.
static FullUrl()
Get current full URL.
Top-level framework for web applications.
static BaseUrl()
Get current base URL (usually the part before index.php).
GetOrphanedTaskCount()
Retrieve current number of orphaned tasks.
SQL database abstraction object with smart query caching.
LogSlowPageLoads($NewValue=DB_NOVALUE)
Get/set whether logging of long page load times is enabled.
SlowPageLoadThreshold($NewValue=DB_NOVALUE)
Get/set how long a page load can take before it should be considered "slow" and may be logged...
GetTaskQueueSize($Priority=NULL)
Retrieve current number of tasks in queue.
GetQueuedTaskCount($Callback=NULL, $Parameters=NULL, $Priority=NULL, $Description=NULL)
Get number of queued tasks that match supplied values.
DeleteTask($TaskId)
Remove task from task queues.
const LOGLVL_DEBUG
DEBUG error logging leve.
const EVENTTYPE_NAMED
Named result event type.
const EVENTTYPE_FIRST
First response event type.
static WasUrlRewritten($ScriptName="index.php")
Determine if the URL was rewritten, i.e., the script is being accessed through a URL that isn't direc...
const EVENTTYPE_DEFAULT
Default event type.
GetPageUrl()
Get the full URL to the page.
IsStaticOnlyEvent($EventName)
Report whether specified event only allows static callbacks.
IsRegisteredEvent($EventName)
Check if event has been registered (is available to be signaled).
static AddObjectDirectory($Dir, $Prefix="", $ClassPattern=NULL, $ClassReplacement=NULL)
Add directory to be searched for object files when autoloading.
SignalEvent($EventName, $Parameters=NULL)
Signal that an event has occured.
static BasePath()
Get current base path (usually the part after the host name).
const LOGLVL_TRACE
TRACE error logging level.
const LOGLVL_WARNING
WARNING error logging level.
const PRIORITY_MEDIUM
Medium (default) priority.
LogError($Level, $Msg)
Write error message to log.
OnCrash()
Called automatically at program termination to ensure output is written out.
GetKnownPeriodicEvents()
Get list of known periodic events.
const EVENTTYPE_CHAIN
Result chaining event type.
GetSecondsBeforeTimeout()
Get remaining available (PHP) execution time.
TaskIsInQueue($Callback, $Parameters=NULL)
Check if task is already in queue or currently running.
AddFunctionDirectories($Dir, $SearchLast=FALSE, $SkipSlashCheck=FALSE)
Add additional directory(s) to be searched for function ("F-") files.
LoggingLevel($NewValue=DB_NOVALUE)
Get/set logging level.
const ORDER_MIDDLE
Run hooked function after ORDER_FIRST and before ORDER_LAST events.
RegisterEvent($EventsOrEventName, $EventType=NULL)
Register one or more events that may be signaled.
SetJumpToPage($Page, $IsLiteral=FALSE)
Set URL of page to autoload after PHP page file is executed.
GetPageName()
Get name of page being loaded.
CleanUrlIsMapped($Path)
Report whether clean URL has already been mapped.
const PRIORITY_HIGH
Highest priority.
LoadFunction($Callback)
Attempt to load code for function or method if not currently available.
GetRunningTaskList($Count=100, $Offset=0)
Retrieve list of tasks currently in queue.
FindCommonTemplate($BaseName)
Preserved for backward compatibility for use with code written prior to October 2012.
EventWillNextRunAt($EventName, $Callback)
Get date/time a periodic event will next run.
static SessionLifetime($NewValue=NULL)
Get/set session timeout in seconds.
HookEvent($EventsOrEventName, $Callback=NULL, $Order=self::ORDER_MIDDLE)
Hook one or more functions to be called when the specified event is signaled.
IsHookedEvent($EventName)
Check if an event is registered and is hooked to.
AddImageDirectories($Dir, $SearchLast=FALSE, $SkipSlashCheck=FALSE)
Add additional directory(s) to be searched for image files.
HtmlCharset($NewSetting=NULL)
Get/set HTTP character encoding value.
const ORDER_FIRST
Run hooked function first (i.e.
HtaccessSupport()
Determine if .htaccess files are enabled.
GetUncleanUrlForPath($Path)
Get the unclean URL for mapped for a path.
TemplateLocationCacheExpirationInterval($NewInterval=DB_NOVALUE)
Get/set UI template location cache expiration period in minutes.
GetUncleanUrl()
Get the unclean URL for the current page.
JumpToPageIsSet()
Report whether a page to autoload has been set.
const ORDER_LAST
Run hooked function last (i.e.
UseBaseTag($NewValue=NULL)
Get/set whether or not to use the "base" tag to ensure relative URL paths are correct.
GetFreeMemory()
Get current amount of free memory.
UpdateSetting($FieldName, $NewValue=DB_NOVALUE)
Convenience function for getting/setting our settings.
GetTask($TaskId)
Retrieve task info from queue (either running or queued tasks).
TaskExecutionEnabled($NewValue=DB_NOVALUE)
Get/set whether automatic task execution is enabled.
LoadPage($PageName)
Load page PHP and HTML/TPL files.
AddEnvInclude($FileName)
Add file to be included to set up environment.
ReQueueOrphanedTask($TaskId, $NewPriority=NULL)
Move orphaned task back into queue.
GUIFile($FileName)
Search UI directories for specified image or CSS file and return name of correct file.
QueueTask($Callback, $Parameters=NULL, $Priority=self::PRIORITY_LOW, $Description="")
Add task to queue.
GetUserInterfaces()
Get the list of available user interfaces.
PUIFile($FileName)
Search UI directories for specified image or CSS file and print name of correct file.
ActiveUserInterface($UIName=NULL)
Get/set name of current active user interface.
GetPageLocation()
Get the URL path to the page without the base path, if present.
ObjectLocationCacheExpirationInterval($NewInterval=DB_NOVALUE)
Get/set object file location cache expiration period in minutes.
GetElapsedExecutionTime()
Get time elapsed since constructor was called.
SetBrowserDetectionFunc($DetectionFunc)
Specify function to use to detect the web browser type.
AddCleanUrl($Pattern, $Page, $GetVars=NULL, $Template=NULL)
Add clean URL mapping.
const PRIORITY_BACKGROUND
Lowest priority.
LogMessage($Level, $Msg)
Write status message to log.