isStaticOnlyEvent($Parameters[0])) {
$Callback = $Parameters[1];
$Parameters = $Parameters[2];
}
# function name
if (!is_array($Callback)) {
$Name = $Callback;
} else { # callback array or object
if (is_object($Callback[0])) {
if ($Callback[0] instanceof PluginCaller) {
$Name = $Callback[0]->getCallbackAsText();
} else {
$ClassName = get_class($Callback[0]);
$BaseClassName = basename(str_replace("\\", "/", $ClassName));
$Name = $BaseClassName."::".$Callback[1];
}
} else {
$Name = $Callback[0] . "::" . $Callback[1];
}
}
return $Name;
}
function GetTaskCallbackParameterString($Task)
{
$String = null;
$Parameters = $Task["Parameters"];
if (is_array($Parameters) && (count($Parameters) == 3) &&
$GLOBALS["AF"]->isStaticOnlyEvent($Parameters[0])) {
$Parameters = $Parameters[2];
}
if (is_array($Parameters)) {
if (isset($Parameters[0]) && (strpos($Parameters[0], "EVENT_") === 0) &&
isset($Parameters[1][0]) && ($Parameters[1][0] instanceof PluginCaller)) {
return $String;
}
$Separator = "";
foreach ($Parameters as $Parameter) {
$String .= $Separator;
if (is_int($Parameter) || is_float($Parameter)) {
$String .= $Parameter;
} elseif (is_string($Parameter)) {
$String .= "\"".htmlspecialchars($Parameter)."\"";
} elseif (is_array($Parameter)) {
$String .= "ARRAY";
} elseif (is_object($Parameter)) {
$String .= "OBJECT";
} elseif (is_null($Parameter)) {
$String .= "NULL";
} elseif (is_bool($Parameter)) {
$String .= $Parameter ? "TRUE" : "FALSE";
} elseif (is_resource($Parameter)) {
$String .= get_resource_type($Parameter);
} else {
$String .= "????";
}
$Separator = ", ";
}
}
return $String;
}
function GetTaskCrashInfo($Task)
{
$CrashInfo = null;
if (isset($Task["CrashInfo"])) {
$CrashData = unserialize($Task["CrashInfo"]);
if (isset($CrashData["LastError"])) {
$Error = $CrashData["LastError"];
$File = preg_replace(":".getcwd()."/:", "", $Error["file"]);
$Message = $Error["message"];
$Line = $Error["line"];
$CrashInfo = "ERROR: ".htmlspecialchars($Message)."
"
."FILE: ".$File."
"
."LINE: ".$Line;
if (isset($CrashData["REQUEST_URI"])) {
$CrashInfo .= "
URI: "
.$CrashData["REQUEST_URI"];
}
if (isset($CrashData["ElapsedTime"])) {
$CrashInfo .= "
ELAPSED: "
.gmdate("i:s", $CrashData["ElapsedTime"]);
}
if (isset($CrashData["FreeMemory"])) {
$CrashInfo .= "
FREE: "
.sprintf("%.1F", (
$CrashData["FreeMemory"] / 1000000))
." MB";
}
}
}
return $CrashInfo;
}
# ----- MAIN -----------------------------------------------------------------
$MaxTasksToDisplay = 50;
$RunningTasks = $GLOBALS["AF"]->GetRunningTaskList();
$RunningTaskCount = count($RunningTasks);
$QueuedTasks = $GLOBALS["AF"]->GetQueuedTaskList($MaxTasksToDisplay);
$QueuedTaskCount = $GLOBALS["AF"]->GetTaskQueueSize();
$OrphanedTasks = $GLOBALS["AF"]->GetOrphanedTaskList($MaxTasksToDisplay);
$OrphanedTaskCount = $GLOBALS["AF"]->GetOrphanedTaskCount();
$PeriodicEventInfo = $GLOBALS["AF"]->GetKnownPeriodicEvents();
$PeriodicEventCount = count($PeriodicEventInfo);
uasort($PeriodicEventInfo, function ($A, $B) {
return ($A["NextRun"] < $B["NextRun"]) ? -1 : 1;
});
$BaseFields = [
"TaskId" => [
"Heading" => "Task ID",
],
"Callback" => [
"ValueFunction" => function ($Task) {
return GetTaskCallbackName($Task)."(".GetTaskCallbackParameterString($Task).")";
},
],
"Description" => [
"AllowHTML" => true
],
"Priority" => [
"ValueFunction" => function ($Task) {
return AF::$AvailablePriorities[$Task["Priority"]];
},
],
];
$BaseLink = "index.php?P=TaskQueue";
$ButtonLinkPrefix = $BaseLink."&ID=\$ID&AC=";
$DeleteLink = $ButtonLinkPrefix."DELETE";
$RequeueLink = $ButtonLinkPrefix."REQUEUE";
$RunLink = $ButtonLinkPrefix."RUN";
$RequeueAllLink = $BaseLink."&ID=ALL&AC=REQUEUEALL";
# ----- RUNNING TASKS
$RFields = [
"TaskId" => $BaseFields["TaskId"],
"Callback" => $BaseFields["Callback"],
"Description" => $BaseFields["Description"],
"Priority" => $BaseFields["Priority"],
"Started" => [
"ValueFunction" => function ($Task) {
return StdLib::getPrettyTimestamp($Task["StartedAt"]);
},
],
];
$RListUI = new ItemListUI($RFields);
$RListUI->fieldsSortableByDefault(false);
$RListUI->heading("Running Tasks");
if ($RunningTaskCount) {
$RListUI->subheading($RunningTaskCount." "
.StdLib::pluralize("task", $RunningTaskCount)." currently running");
}
$RListUI->baseLink($BaseLink);
$RListUI->noItemsMessage("(no tasks currently running)");
$RListUI->willDisplayEmptyTable(true);
$RListUI->addTopCheckbox(
"Automatic Task Execution Enabled
",
$GLOBALS["AF"]->TaskExecutionEnabled(),
"F_TaskExecutionEnabled",
$BaseLink."&CE=1"
);
# ----- QUEUED TASKS
$QFields = $BaseFields;
$QListUI = new ItemListUI($QFields);
$QListUI->fieldsSortableByDefault(false);
$QListUI->heading("Queued Tasks");
if ($QueuedTaskCount) {
$Subheading = $QueuedTaskCount." "
.StdLib::pluralize("task", $QueuedTaskCount)." currently queued";
if ($QueuedTaskCount > count($QueuedTasks)) {
$Subheading .= " (first ".$MaxTasksToDisplay." displayed)";
}
$QListUI->subheading($Subheading);
}
$QListUI->baseLink($BaseLink);
$QListUI->addActionButton("Delete", $DeleteLink, "cross.png");
$QListUI->addActionButton("Run", $RunLink, "accept.png");
$QListUI->noItemsMessage("(no tasks currently in queue)");
$QListUI->willDisplayEmptyTable(true);
# ----- ORPHANED TASKS
if ($OrphanedTaskCount) {
$OListUI = new ItemListUI($RFields);
$OListUI->fieldsSortableByDefault(false);
$OListUI->heading("Orphaned Tasks");
if ($OrphanedTaskCount) {
$Subheading = $OrphanedTaskCount." "
.StdLib::pluralize("task", $OrphanedTaskCount)." currently orphaned";
if ($OrphanedTaskCount > count($OrphanedTasks)) {
$Subheading .= " (first ".$MaxTasksToDisplay." displayed)";
}
$OListUI->subheading($Subheading);
}
$OListUI->heading("Orphaned Tasks");
$OListUI->baseLink($BaseLink);
$OListUI->addActionButton("Requeue", $RequeueLink, "RefreshArrow.svg");
$OListUI->addActionButton("Run", $RunLink, "accept.png");
$OListUI->addActionButton("Delete", $DeleteLink, "cross.png");
$OListUI->addTopButton("Requeue All", $RequeueAllLink, "RefreshArrow.svg");
}
# ----- PERIODIC EVENTS
$PFields = [
"Callback" => $BaseFields["Callback"],
"Frequency" => [
"ValueFunction" => function ($Task) {
return ucfirst(strtolower(preg_replace("/EVENT_/", "", $Task["Period"])));
},
],
"Last Run" => [
"ValueFunction" => function ($Task) {
return ($Task["LastRun"] === false)
? "-" : StdLib::getPrettyTimestamp($Task["LastRun"]);
},
],
"Next Queued" => [
"ValueFunction" => function ($Task) {
$NextRun = $Task["NextRun"];
if ($NextRun === false) {
$Value = "-";
} else {
$Value = StdLib::getPrettyTimestamp($NextRun);
$MinutesUntil = floor(max(($NextRun - time()), 0) / 60);
if ($MinutesUntil < 60) {
$Value .= " (".$MinutesUntil." ".StdLib::pluralize("minute", $MinutesUntil).")";
}
}
return $Value;
},
],
];
$PListUI = new ItemListUI($PFields);
$PListUI->fieldsSortableByDefault(false);
$PListUI->heading("Periodic Events");
if ($PeriodicEventCount) {
$PListUI->subheading($PeriodicEventCount." periodic "
.StdLib::pluralize("events", $PeriodicEventCount)." found");
}
$PListUI->baseLink($BaseLink);
$PListUI->addActionButton("Run", $RunLink, "accept.png");
$PListUI->noItemsMessage("(no periodic events found)");
$PListUI->willDisplayEmptyTable(true);
$RListUI->display($RunningTasks);
$QListUI->display($QueuedTasks);
if ($OrphanedTaskCount) {
$OListUI->display($OrphanedTasks);
}
$PListUI->display($PeriodicEventInfo);
if ($GLOBALS["AF"]->TaskExecutionEnabled()) {
?>