diff --git a/pinc/Activity.inc b/pinc/Activity.inc
index c3cf70dcd..1c437ed16 100644
--- a/pinc/Activity.inc
+++ b/pinc/Activity.inc
@@ -123,6 +123,29 @@ class Activities
}
}
+class UserAccess
+{
+ /**
+ * @param bool $can_access
+ * user can access this activity.
+ * @param list{string, int, int, bool}[] $minima_table
+ * ( $criterion_str, $minimum, $user_score, $satisfied )
+ * @param ?('sat-unneeded'|'sat-granted'|'sat-available'|'sat-requested'|'sat-wait'|'sat-denied'|'unsat-granted'|'unsat-requested'|'unsat-ungranted'|'unsat-denied') $request_status
+ * @param ?string $evaluation_criteria
+ * message to display about evaluation
+ */
+ public function __construct(
+ public readonly ?string $username,
+ public readonly bool $can_access,
+ public readonly array $minima_table = [],
+ public readonly bool $all_minima_satisfied = false,
+ public readonly ?string $request_status = null,
+ public readonly ?string $evaluation_criteria = null,
+ public readonly ?string $activity_id = null
+ ) {
+ }
+}
+
class Activity
{
/**
@@ -137,7 +160,7 @@ class Activity
* A (possibly empty) array of minimum requirements that a user must satisfy
* in order to be allowed to participate in this activity
* (barring special permission).
- * @param string $after_satisfying_minima
+ * @param 'IMMEDIATE'|'REQ-AUTO'|'REQ-HUMAN'|'NOREQ' $after_satisfying_minima
* After satisfying the above minima (if any), does the user have to do
* anything else to work in this activity?
* ```
@@ -199,36 +222,14 @@ class Activity
}
/**
- * Return a User Access object
- *
- * Return an object with the following properties:
- * - can_access:
- * a boolean: TRUE iff the user can access this activity.
- * - minima_table:
- * an array of arrays (4-tuples):
- * ( $criterion_str, $minimum, $user_score, $satisfied )
- * - all_minima_satisfied:
- * boolean
- * - request_status:
- * enumerated type: sat-unneeded, sat-granted, sat-available, sat-requested,
- * sat-wait, sat-denied
- * unsat-granted, unsat-requested, unsat-ungranted,
- * unsat-denied
- * - evaluation_criteria:
- * message to display about evaluation
- *
* UNIMPLEMENTED:
* If $n_pages_completed is non-null, use it as the number of pages
* that the user has completed. Otherwise, consult the database.
*/
- // TODO(jchaffraix): Add a class for the UserAccess object for type soundness.
- public function user_access(?string $username, ?int $n_pages_completed = null): object
+ public function user_access(?string $username, ?int $n_pages_completed = null): UserAccess
{
if (is_null($username)) {
- $uao = new StdClass(); // user access object
- $uao->username = $username;
- $uao->can_access = false;
- return $uao;
+ return new UserAccess(username: null, can_access: false);
}
// A user's score isn't going to change in a page load but many page
@@ -252,55 +253,52 @@ class Activity
// -----------------------------------
- $uao = new StdClass(); // user access object
- $uao->username = $username;
- $uao->activity_id = $this->id;
- $uao->evaluation_criteria = $this->evaluation_criteria;
// Considering the minima...
global $ACCESS_CRITERIA;
- {
- $uao->minima_table = [];
- $uao->all_minima_satisfied = true;
- foreach ($this->access_minima as $criterion_code => $minimum) {
- $criterion_str = $ACCESS_CRITERIA[$criterion_code];
- $user_score = $user_scores[$criterion_code];
+ $minima_table = [];
+ $all_minima_satisfied = true;
+ foreach ($this->access_minima as $criterion_code => $minimum) {
+ $criterion_str = $ACCESS_CRITERIA[$criterion_code];
+ $user_score = $user_scores[$criterion_code];
- $satisfied = ($user_score >= $minimum);
- $uao->minima_table[$criterion_code] = [$criterion_str, $minimum, $user_score, $satisfied];
- if (!$satisfied) {
- $uao->all_minima_satisfied = false;
- }
+ $satisfied = ($user_score >= $minimum);
+ $minima_table[$criterion_code] = [$criterion_str, $minimum, $user_score, $satisfied];
+ if (!$satisfied) {
+ $all_minima_satisfied = false;
}
}
+ $can_access = false;
+ $requst_status = null;
+
if ($recorded_access == 'denied') {
// they are not allowed to access this activity or to request access
- $uao->can_access = false;
- if ($uao->all_minima_satisfied) {
- $uao->request_status = 'sat-denied';
+ $can_access = false;
+ if ($all_minima_satisfied) {
+ $request_status = 'sat-denied';
} else {
- $uao->request_status = 'unsat-denied';
+ $request_status = 'unsat-denied';
}
- } elseif ($uao->all_minima_satisfied) {
+ } elseif ($all_minima_satisfied) {
// They've satisfied the requirements...
switch ($this->after_satisfying_minima) {
case 'IMMEDIATE':
// They get immediate access.
- $uao->request_status = 'sat-unneeded';
- $uao->can_access = true;
+ $request_status = 'sat-unneeded';
+ $can_access = true;
break;
case 'REQ-AUTO':
// They must ask for access, but it is auto-granted.
if ($recorded_access == 'yes') {
// They already have access
- $uao->request_status = 'sat-granted';
- $uao->can_access = true;
+ $request_status = 'sat-granted';
+ $can_access = true;
} else {
// They haven't asked yet, but can
- $uao->request_status = 'sat-available';
- $uao->can_access = false;
+ $request_status = 'sat-available';
+ $can_access = false;
}
break;
@@ -308,16 +306,16 @@ class Activity
// They must ask for access, and it must be human-granted.
if ($recorded_access == 'yes') {
// They already have access
- $uao->request_status = 'sat-granted';
- $uao->can_access = true;
+ $request_status = 'sat-granted';
+ $can_access = true;
} elseif ($recorded_access == 'requested') {
// They've asked, but it hasn't been granted yet
- $uao->request_status = 'sat-requested';
- $uao->can_access = false;
+ $request_status = 'sat-requested';
+ $can_access = false;
} else {
// They haven't asked yet, but can
- $uao->request_status = 'sat-available';
- $uao->can_access = false;
+ $request_status = 'sat-available';
+ $can_access = false;
}
break;
@@ -327,12 +325,12 @@ class Activity
// they are approved.
if ($recorded_access == 'yes') {
// They already have access
- $uao->request_status = 'sat-granted';
- $uao->can_access = true;
+ $request_status = 'sat-granted';
+ $can_access = true;
} else {
// They are waiting
- $uao->request_status = 'sat-wait';
- $uao->can_access = false;
+ $request_status = 'sat-wait';
+ $can_access = false;
}
break;
@@ -343,24 +341,32 @@ class Activity
// They don't satisfy the requirements
if ($recorded_access == 'yes') {
// but they already have access anyway
- $uao->request_status = 'unsat-granted';
- $uao->can_access = true;
+ $request_status = 'unsat-granted';
+ $can_access = true;
} elseif ($recorded_access == 'requested') {
// but they've requested access, but don't have it yet
// This is unusual, but can happen.
// E.g., at some point in the past, they satisfied the minima and
// requested access, but now they no longer satisfy the minima
// (quiz-pass could expire, page-tally could be reduced by clears).
- $uao->request_status = 'unsat-requested';
- $uao->can_access = false;
+ $request_status = 'unsat-requested';
+ $can_access = false;
} else {
// and they can't ask for access
- $uao->request_status = 'unsat-ungranted';
- $uao->can_access = false;
+ $request_status = 'unsat-ungranted';
+ $can_access = false;
}
}
- return $uao;
+ return new UserAccess(
+ username: $username,
+ activity_id: $this->id,
+ evaluation_criteria: $this->evaluation_criteria,
+ minima_table: $minima_table,
+ all_minima_satisfied: $all_minima_satisfied,
+ can_access: $can_access,
+ request_status: $request_status
+ );
}
}
@@ -403,7 +409,7 @@ function get_user_score(User $user_obj, string $criterion_code): float
// --------------------------------------------------------------------------
-function show_user_access_object(object $uao, bool $will_autogrant = false): void
+function show_user_access_object(UserAccess $uao, bool $will_autogrant = false): void
{
global $code_url;
@@ -427,7 +433,7 @@ function show_user_access_object(object $uao, bool $will_autogrant = false): voi
echo "
";
echo "| $criterion_str | ";
echo "$minimum | ";
- td_w_bgcolor($user_score, $satisfied);
+ td_w_bgcolor((string)$user_score, $satisfied);
echo "
\n";
}
echo "\n";
@@ -508,7 +514,7 @@ function show_user_access_object(object $uao, bool $will_autogrant = false): voi
}
}
-function grant_user_access_if_sat(object &$uao): void
+function grant_user_access_if_sat(UserAccess &$uao): void
{
$activity = Activities::get_by_id($uao->activity_id);
if ($uao->request_status == 'sat-available' &&
diff --git a/pinc/ProjectState.inc b/pinc/ProjectState.inc
index 27c2bc6f4..dfe2e8f0f 100644
--- a/pinc/ProjectState.inc
+++ b/pinc/ProjectState.inc
@@ -328,6 +328,19 @@ function get_project_status_descriptors(): array
return ['posted', 'PPd', 'proofed', 'created'];
}
+class ProjectStatusDescriptor
+{
+ public function __construct(
+ public readonly string $state_selector,
+ public readonly string $Xed_title,
+ public readonly string $projects_Xed_title,
+ public readonly string $graphs_title,
+ public readonly string $per_day_title,
+ public readonly string $cumulative_title
+ ) {
+ }
+}
+
/**
* Return an object with details about a project status
*
@@ -340,20 +353,19 @@ function get_project_status_descriptors(): array
* @param 'created'|'proofed'|'PPd'|'posted' $which
* A word denoting a possible status of a project
*/
-function get_project_status_descriptor(string $which): object
+function get_project_status_descriptor(string $which): ProjectStatusDescriptor
{
- $obj = new stdClass();
-
switch ($which) {
case 'created':
$not_created_states = [PROJ_NEW, PROJ_DELETE];
- $obj->state_selector = "(state NOT IN (" . surround_and_join($not_created_states, "'", "'", ",") . "))";
- $obj->Xed_title = _('Created');
- $obj->projects_Xed_title = _('Projects Created');
- $obj->graphs_title = _('Created Projects Graphs');
- $obj->per_day_title = _('Projects Created Each Day');
- $obj->cumulative_title = _('Cumulative Projects Created');
- break;
+ return new ProjectStatusDescriptor(
+ state_selector: "(state NOT IN (" . surround_and_join($not_created_states, "'", "'", ",") . "))",
+ Xed_title: _('Created'),
+ projects_Xed_title: _('Projects Created'),
+ graphs_title: _('Created Projects Graphs'),
+ per_day_title: _('Projects Created Each Day'),
+ cumulative_title: _('Cumulative Projects Created')
+ );
case 'proofed':
$proofed_states = [
@@ -365,13 +377,14 @@ function get_project_status_descriptor(string $which): object
PROJ_SUBMIT_PG_POSTED,
PROJ_POST_COMPLETE,
];
- $obj->state_selector = "(state IN (" . surround_and_join($proofed_states, "'", "'", ",") . "))";
- $obj->Xed_title = _('Proofread');
- $obj->projects_Xed_title = _('Projects Proofread');
- $obj->graphs_title = _('Proofread Projects Graphs');
- $obj->per_day_title = _('Projects Proofread Each Day');
- $obj->cumulative_title = _('Cumulative Projects Proofread');
- break;
+ return new ProjectStatusDescriptor(
+ state_selector: "(state IN (" . surround_and_join($proofed_states, "'", "'", ",") . "))",
+ Xed_title: _('Proofread'),
+ projects_Xed_title: _('Projects Proofread'),
+ graphs_title: _('Proofread Projects Graphs'),
+ per_day_title: _('Projects Proofread Each Day'),
+ cumulative_title: _('Cumulative Projects Proofread')
+ );
case 'PPd':
$pped_states = [
@@ -379,26 +392,26 @@ function get_project_status_descriptor(string $which): object
PROJ_POST_SECOND_CHECKED_OUT,
PROJ_SUBMIT_PG_POSTED,
];
- $obj->state_selector = "(state IN (" . surround_and_join($pped_states, "'", "'", ",") . "))";
- $obj->Xed_title = _('Post-Processed');
- $obj->projects_Xed_title = _('Projects Post-Processed');
- $obj->graphs_title = _('PPd Projects Graphs');
- $obj->per_day_title = _('Projects Post-Processed Each Day');
- $obj->cumulative_title = _('Cumulative Projects PPd');
- break;
+ return new ProjectStatusDescriptor(
+ state_selector: "(state IN (" . surround_and_join($pped_states, "'", "'", ",") . "))",
+ Xed_title: _('Post-Processed'),
+ projects_Xed_title: _('Projects Post-Processed'),
+ graphs_title: _('PPd Projects Graphs'),
+ per_day_title: _('Projects Post-Processed Each Day'),
+ cumulative_title: _('Cumulative Projects PPd')
+ );
case 'posted':
- $obj->state_selector = "(state = '" . PROJ_SUBMIT_PG_POSTED . "')";
- $obj->Xed_title = _('Posted to PG');
- $obj->projects_Xed_title = _('Projects Posted');
- $obj->graphs_title = _('Posted Projects Graphs');
- $obj->per_day_title = _('Projects Posted to PG Each Day');
- $obj->cumulative_title = _('Cumulative Projects Posted to PG');
- break;
+ return new ProjectStatusDescriptor(
+ state_selector: "(state = '" . PROJ_SUBMIT_PG_POSTED . "')",
+ Xed_title: _('Posted to PG'),
+ projects_Xed_title: _('Projects Posted'),
+ graphs_title: _('Posted Projects Graphs'),
+ per_day_title: _('Projects Posted to PG Each Day'),
+ cumulative_title: _('Cumulative Projects Posted to PG')
+ );
default:
throw new UnexpectedValueException(html_safe("bad value for 'which': '$which'"));
}
-
- return $obj;
}
diff --git a/pinc/Stage.inc b/pinc/Stage.inc
index 8f746117c..b6ef2b014 100644
--- a/pinc/Stage.inc
+++ b/pinc/Stage.inc
@@ -64,7 +64,7 @@ class Stage extends Activity
echo "$title
\n" . get_page_header_image($this->id);
}
- public function page_top(object $uao): void
+ public function page_top(UserAccess $uao): void
{
$this->page_header("{$this->id}: {$this->name}");
diff --git a/pinc/TallyBoard.inc b/pinc/TallyBoard.inc
index fd2b1a21c..e0ee0beab 100644
--- a/pinc/TallyBoard.inc
+++ b/pinc/TallyBoard.inc
@@ -539,15 +539,11 @@ class TallyBoard
);
$result = DPDatabase::query($sql);
- $row = mysqli_fetch_assoc($result);
- if (!$row) {
+ if (!is_array($row = mysqli_fetch_assoc($result))) {
// No snapshots for this TallyBoard yet.
- $max_timestamp = $default;
- } else {
- $max_timestamp = $row["max_timestamp"];
+ return $default;
}
-
- return $max_timestamp;
+ return (int) $row["max_timestamp"];
}
// -------------------------------------------------------------------------
@@ -796,34 +792,54 @@ class TallyBoard
*
* This is just a convenience function.
*/
- public function get_vitals(int $holder_id): Object
+ public function get_vitals(int $holder_id): Vitals
{
- $obj = new StdClass();
-
- $obj->current_tally = $this->get_current_tally($holder_id);
- $obj->current_rank = $this->get_rank($holder_id);
-
+ $current_tally = $this->get_current_tally($holder_id);
+ $current_rank = $this->get_rank($holder_id);
$snapshot_info = $this->get_info_from_latest_snapshot($holder_id);
- $obj->latest_snapshot_timestamp = $snapshot_info['timestamp'];
- $obj->latest_snapshot_delta = $snapshot_info['tally_delta'];
- $obj->latest_snapshot_tally = $snapshot_info['tally_value'];
- [$obj->best_delta, $obj->best_delta_timestamp] =
+ [$best_delta, $best_delta_timestamp] =
$this->get_info_re_largest_delta($holder_id);
- $today_delta = $obj->current_tally - $obj->latest_snapshot_tally;
- if ($today_delta > $obj->best_delta) {
- $obj->best_delta = $today_delta;
- $obj->best_delta_timestamp = time();
+ $today_delta = $current_tally - $snapshot_info['tally_delta'];
+ if ($today_delta > $best_delta) {
+ $best_delta = $today_delta;
+ $best_delta_timestamp = time();
}
- [$obj->best_rank, $obj->best_rank_timestamp] =
+ [$best_rank, $best_rank_timestamp] =
$this->get_info_re_best_rank($holder_id);
- if ($obj->current_rank < $obj->best_rank) {
- $obj->best_rank = $obj->current_rank;
- $obj->best_rank_timestamp = time();
+ if ($current_rank < $best_rank) {
+ $best_rank = $current_rank;
+ $best_rank_timestamp = time();
}
- return $obj;
+ return new Vitals(
+ current_tally: $current_tally,
+ current_rank: $current_rank,
+ latest_snapshot_timestamp: $snapshot_info['timestamp'],
+ latest_snapshot_delta: $snapshot_info['tally_delta'],
+ latest_snapshot_tally: $snapshot_info['tally_value'],
+ best_delta: $best_delta,
+ best_delta_timestamp: $best_delta_timestamp,
+ best_rank: $best_rank,
+ best_rank_timestamp: $best_rank_timestamp
+ );
+
+ }
+}
+class Vitals
+{
+ public function __construct(
+ public readonly int $current_tally,
+ public readonly int $current_rank,
+ public readonly int $latest_snapshot_timestamp,
+ public readonly int $latest_snapshot_delta,
+ public readonly int $latest_snapshot_tally,
+ public readonly int $best_delta,
+ public readonly int $best_delta_timestamp,
+ public readonly int $best_rank,
+ public readonly int $best_rank_timestamp,
+ ) {
}
}
diff --git a/pinc/autorelease.inc b/pinc/autorelease.inc
index e637ce2ab..1b2548a2e 100644
--- a/pinc/autorelease.inc
+++ b/pinc/autorelease.inc
@@ -47,7 +47,33 @@ function attempt_to_release(Round $round, array $project, string $queue_name): b
}
-
+class QueueDefn
+{
+ public readonly string $cooked_project_selector;
+ /**
+ * @param $name
+ * A human-readable name for this queue.
+ *
+ * $param $project_selector
+ * An SQL condition that defines the kind of project
+ * that can be released by this queue.
+ *
+ * @param $projects_target
+ * @param $pages_target
+ * Integers that specify the circumstances under which
+ * this queue can release a project.
+ *
+ * For more details, see SETUP/site_admin_notes.txt under "Defining queues".
+ */
+ public function __construct(
+ public readonly string $name,
+ public readonly string $project_selector,
+ public readonly int $projects_target,
+ public readonly int $pages_target,
+ ) {
+ $this->cooked_project_selector = cook_project_selector($project_selector);
+ }
+}
function autorelease_for_round(Round $round): void
{
@@ -109,22 +135,13 @@ function autorelease_for_round(Round $round): void
);
$q_res = DPDatabase::query($sql);
- while ($qd = mysqli_fetch_object($q_res)) {
- // $qd->name
- // A human-readable name for this queue.
- //
- // $qd->project_selector
- // An SQL condition that defines the kind of project
- // that can be released by this queue.
- //
- // $qd->projects_target
- // $qd->pages_target
- // Integers that specify the circumstances under which
- // this queue can release a project.
- //
- // For more details, see SETUP/site_admin_notes.txt under "Defining queues".
-
- $qd->cooked_project_selector = cook_project_selector($qd->project_selector);
+ while ($row = mysqli_fetch_assoc($q_res)) {
+ $qd = new QueueDefn(
+ (string) $row['name'],
+ (string) $row['project_selector'],
+ (int) $row['projects_target'],
+ (int) $row['pages_target']
+ );
// Release available projects of a given type (defined by $qd->project_selector)
// as long as the condition implied by the targets is true for projects of that type.
@@ -207,16 +224,25 @@ function autorelease_for_round(Round $round): void
// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+class NumProjects
+{
+ public function __construct(
+ public readonly int $waiting,
+ public readonly int $considered,
+ public readonly int $blocked,
+ public readonly int $failed,
+ public readonly int $released,
+ ) {
+ }
+}
function maybe_release_projects(
Round $round,
- ?Object $qd,
+ ?QueueDefn $qd,
bool $observe_release_restrictions,
bool $release_at_most_one
-): Object {
- $n_projects = new StdClass();
-
+): NumProjects {
$and_extra_condition = ($qd ? "AND ($qd->cooked_project_selector)" : "");
- $q_name = ($qd ? $qd->name : "");
+ $q_name = $qd ? $qd->name : "";
// set of candidates for release:
// Projects that are in this round's waiting state,
@@ -240,24 +266,24 @@ function maybe_release_projects(
";
$waiting_res = DPDatabase::query($sql);
- $n_projects->waiting = mysqli_num_rows($waiting_res);
+ $waiting = mysqli_num_rows($waiting_res);
echo "\n";
if ($qd) {
- echo " There are {$n_projects->waiting} projects waiting for release in this queue.\n";
+ echo " There are {$waiting} projects waiting for release in this queue.\n";
} else {
- echo "There are {$n_projects->waiting} projects waiting for release in this round.\n";
+ echo "There are {$waiting} projects waiting for release in this round.\n";
}
- $n_projects->considered = 0;
- $n_projects->blocked = 0;
- $n_projects->failed = 0;
- $n_projects->released = 0;
+ $considered = 0;
+ $blocked = 0;
+ $failed = 0;
+ $released = 0;
while ($project = mysqli_fetch_assoc($waiting_res)) {
echo "\n";
echo " considering {$project['projectid']} \"{$project['nameofwork']}\"...\n";
- $n_projects->considered++;
+ $considered++;
if ($observe_release_restrictions) {
$release_restrictor = ReleaseRestrictor::$restrictors[$round->id] ?? null;
@@ -265,7 +291,7 @@ function maybe_release_projects(
if (!$release_restrictor->approves_project($project)) {
// Messages have been echoed.
- $n_projects->blocked++;
+ $blocked++;
// Go to the next project in the list.
continue;
}
@@ -273,7 +299,7 @@ function maybe_release_projects(
if (!attempt_to_release($round, $project, $q_name)) {
// Something went wrong. Error messages have been output.
- $n_projects->failed++;
+ $failed++;
// Go to the next project in the list.
continue;
}
@@ -282,7 +308,7 @@ function maybe_release_projects(
echo " Project released!\n";
- $n_projects->released++;
+ $released++;
$release_restrictor = ReleaseRestrictor::$restrictors[$round->id] ?? null;
if ($release_restrictor) {
@@ -324,17 +350,23 @@ function maybe_release_projects(
}
}
- if ($n_projects->waiting > 0) {
+ if ($waiting > 0) {
echo "\n";
- echo sprintf(" Of the %d projects that were waiting...\n", $n_projects->waiting);
- echo sprintf(" %3d projects were blocked by release restrictions\n", $n_projects->blocked);
- echo sprintf(" %3d projects failed the pre-release check or the state transition\n", $n_projects->failed);
- echo sprintf(" %3d projects were released\n", $n_projects->released);
- echo sprintf(" %3d projects were not considered\n", $n_projects->waiting - $n_projects->considered);
+ echo sprintf(" Of the %d projects that were waiting...\n", $waiting);
+ echo sprintf(" %3d projects were blocked by release restrictions\n", $blocked);
+ echo sprintf(" %3d projects failed the pre-release check or the state transition\n", $failed);
+ echo sprintf(" %3d projects were released\n", $released);
+ echo sprintf(" %3d projects were not considered\n", $waiting - $considered);
echo "\n";
}
- return $n_projects;
+ return new NumProjects(
+ $waiting,
+ $considered,
+ $blocked,
+ $failed,
+ $released
+ );
}
// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
diff --git a/pinc/page_tally.inc b/pinc/page_tally.inc
index 7656a84cd..feb56edb3 100644
--- a/pinc/page_tally.inc
+++ b/pinc/page_tally.inc
@@ -221,6 +221,19 @@ $SECONDS_TO_YESTERDAY = 1 + 3 * 60 * 60;
// -----------------------------------------------------------------------------
+class SitePageTally
+{
+ public function __construct(
+ public readonly int $curr_day_goal,
+ public readonly int $prev_day_goal,
+ public readonly int $curr_month_goal,
+ public readonly int $curr_day_actual,
+ public readonly int $prev_day_actual,
+ public readonly int $curr_month_actual
+ ) {
+ }
+}
+
/**
* Return an object whose attributes are various useful statistics about
* the site page tally.
@@ -230,57 +243,42 @@ $SECONDS_TO_YESTERDAY = 1 + 3 * 60 * 60;
* - prev_day_{goal,actual}
* - curr_month_{goal,actual}
*/
-function get_site_page_tally_summary(string $tally_name): object
+function get_site_page_tally_summary(string $tally_name): SitePageTally
{
- $site_stats = new StdClass();
-
- // Goals
+ $tallyboard = new TallyBoard($tally_name, 'S');
+ $holder_id = 1;
+ $current_tally = $tallyboard->get_current_tally($holder_id);
+ $snapshot_info = $tallyboard->get_info_from_latest_snapshot($holder_id);
+ $today = getdate();
+ $curr_day_actual = $current_tally - $snapshot_info['tally_value'];
- $site_stats->curr_day_goal =
- get_site_tally_goal_summed(
+ return new SitePageTally(
+ // Goals
+ curr_day_goal: get_site_tally_goal_summed(
$tally_name,
"date = CURRENT_DATE"
- );
-
- $site_stats->prev_day_goal =
- get_site_tally_goal_summed(
+ ),
+ prev_day_goal: get_site_tally_goal_summed(
$tally_name,
"date = (CURRENT_DATE - INTERVAL 1 DAY)"
- );
-
- $site_stats->curr_month_goal =
- get_site_tally_goal_summed(
+ ),
+ curr_month_goal: get_site_tally_goal_summed(
$tally_name,
"date >= DATE_FORMAT(CURRENT_DATE, '%%Y-%%m-01') AND
date <= LAST_DAY(CURRENT_DATE)"
- );
+ ),
- // Actuals
-
- $tallyboard = new TallyBoard($tally_name, 'S');
-
- $holder_id = 1;
-
- $current_tally = $tallyboard->get_current_tally($holder_id);
-
- $snapshot_info = $tallyboard->get_info_from_latest_snapshot($holder_id);
-
- $site_stats->curr_day_actual =
- $current_tally - $snapshot_info['tally_value'];
-
- $site_stats->prev_day_actual = $snapshot_info['tally_delta'];
-
- $today = getdate();
- $site_stats->curr_month_actual =
- $tallyboard->get_delta_sum(
+ // Actuals
+ curr_day_actual: $curr_day_actual,
+ prev_day_actual: $snapshot_info['tally_delta'],
+ curr_month_actual: $tallyboard->get_delta_sum(
$holder_id,
mktime(0, 0, 0, $today['mon'], 1, $today['year']),
mktime(0, 0, 0, $today['mon'] + 1, 1, $today['year'])
)
+
- $site_stats->curr_day_actual;
-
- return $site_stats;
+ $curr_day_actual
+ );
}
function get_site_tally_goal_summed(string $tally_name, string $date_condition): int
diff --git a/pinc/wordcheck_engine.inc b/pinc/wordcheck_engine.inc
index 21396051d..6e6455132 100644
--- a/pinc/wordcheck_engine.inc
+++ b/pinc/wordcheck_engine.inc
@@ -877,11 +877,9 @@ function get_wordcheck_file_names(): array
* @param string $code
* Must match one of the keys in array returned from `get_wordcheck_file_names()`
*
- * @return object
- *
* @see get_wordcheck_file_names()
*/
-function get_project_word_file(string $projectid, string $code): object
+function get_project_word_file(string $projectid, string $code): FileInfoObject
{
global $projects_dir, $projects_url;
@@ -910,7 +908,7 @@ function get_site_word_paths(): array
*
* @param 'good'|'bad'|'possible_bad' $code
*/
-function get_site_word_file(string $langcode3, string $code): object
+function get_site_word_file(string $langcode3, string $code): FileInfoObject
{
[$site_words_dir, $site_words_url] = get_site_word_paths();
@@ -928,33 +926,35 @@ function get_site_word_file(string $langcode3, string $code): object
);
}
+class FileInfoObject
+{
+ public function __construct(
+ public readonly string $filename,
+ public readonly string $abs_path,
+ public readonly string $abs_url,
+ public readonly bool $exists,
+ public readonly int $size,
+ public readonly int $mod_time
+ ) {
+ }
+}
/**
* Returns an object containing information about the specified
* word-related file for the given project.
- *
- * Attributes include:
- * - filename: its filename
- * - abs_path: its absolute path
- * - abs_url: its absolute URL
- * - exists: a boolean indicating whether it exists
- * - size: its size in bytes
- * - mod_time: the time it was last modified, as a unix timestamp.
- * Size and mod_time are set to zero if the file doesn't exist.
*/
-function get_file_info_object(string $filename, string $base_dir, string $base_url): Object
+function get_file_info_object(string $filename, string $base_dir, string $base_url): FileInfoObject
{
clearstatcache();
-
- $o = new StdClass();
-
- $o->filename = $filename;
- $o->abs_path = "$base_dir/{$o->filename}";
- $o->abs_url = "$base_url/{$o->filename}";
- $o->exists = @file_exists($o->abs_path);
- $o->size = $o->exists ? filesize($o->abs_path) : 0;
- $o->mod_time = $o->exists ? filemtime($o->abs_path) : 0;
-
- return $o;
+ $abs_path = "$base_dir/{$filename}";
+ $exists = @file_exists($abs_path);
+ return new FileInfoObject(
+ filename: $filename,
+ abs_path: $abs_path,
+ abs_url: "$base_url/{$filename}",
+ exists: $exists,
+ size: $exists ? filesize($abs_path) : 0,
+ mod_time: $exists ? filemtime($abs_path) : 0,
+ );
}
// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
diff --git a/tools/proofers/round.php b/tools/proofers/round.php
index 0f0bbb9d6..d5dd7e08c 100644
--- a/tools/proofers/round.php
+++ b/tools/proofers/round.php
@@ -34,7 +34,7 @@
// show user how to access this round
if (!$uao->can_access) {
- show_user_access_object($uao, true /* will_autogrant */);
+ show_user_access_object($uao, will_autogrant: true);
}
encourage_highest_round($pguser, $round->id);