Files
2026-07-03 15:46:56 -04:00

546 lines
18 KiB
PHP

<?php
class Voters extends Base {
// Variables.
private $current_user_serial = 0;
private $current_user_id = "";
private $current_user_name = "";
private $current_user_email = "";
private $pagination_size = 20;
private $pagination_page = 1;
// =================
// Class Constructor
// =================
public function __construct() {
set_error_handler(array($this, "displayError"));
date_default_timezone_set(self::TIMEZONE);
$this->current_user_serial = $_SESSION[self::USER_SERIAL] ?? 0;
$this->current_user_id = $_SESSION[self::USER_ID] ?? "";
$this->current_user_name = $_SESSION[self::USER_NAME] ?? "";
$this->current_user_email = $_SESSION[self::USER_EMAIL] ?? "";
$this->pagination_page = $_SESSION[self::PAGINATION_PAGE] ?? 1;
}
// =============
// Manage Voters
// =============
public function manageVoters() {
$voters = $this->getVotersPage();
$popovers = (new Popovers())->getPopovers();
$XML = $this->mergeXML($voters, "<XML/>");
$XML = $this->mergeXML($popovers, $XML);
// echo $XML;
// die();
$content = $this->applyXSL($XML, $this->getXSL("manageVoters"));
$this->displayContent($content);
}
// =============
// Voter Summary
// =============
public function voterSummary() {
$voter_serial = filter_input(INPUT_POST, "voter_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
$voter = $this->getVoter($voter_serial);
if ($voter->count() == 0) {
$this->logError("Invalid Voter ({$voter_serial}). " . __METHOD__);
}
$XML = $this->mergeXML($voter, "<XML/>");
$content = $this->applyXSL($XML, $this->getXSL("voterSummary"));
$this->displayContent($content);
}
// =========
// Add Voter
// =========
public function addVoter() {
$step = filter_input(INPUT_POST, "step") ?: "prompt";
switch ($step) {
case "prompt":
$content = $this->applyXSL("", $this->getXSL("addVoter"));
$this->displayContent($content);
break;
case "add":
$voter_name = filter_input(INPUT_POST, "voter_name") ?: "";
$voter_classes = filter_input(INPUT_POST, "voter_classes") ?: "";
$voter_active = filter_input(INPUT_POST, "voter_active", FILTER_VALIDATE_BOOLEAN) ?: false;
$SQL = "insert into voters
( voter_name,
voter_classes,
voter_active,
voter_creator,
voter_created )
VALUES ( :voter_name,
:voter_classes,
:voter_active,
:voter_creator,
:voter_created )";
$statement = $this->connect()->prepare($SQL);
$statement->bindValue(":voter_name", $voter_name);
$statement->bindValue(":voter_classes", $voter_classes);
$statement->bindValue(":voter_active", $voter_active, PDO::PARAM_BOOL);
$statement->bindValue(":voter_creator", $this->current_user_name);
$statement->bindValue(":voter_created", $this->getTimestamp());
$statement->execute();
break;
default:
$this->displayHome();
}
}
// =============
// Delete Voter
// =============
public function deleteVoter() {
$voter_serial = filter_input(INPUT_POST, "voter_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
$voter = $this->getVoter($voter_serial);
if ($voter->count() == 0) {
$this->logError("Invalid Voter ({$voter_serial}). " . __METHOD__);
}
$SQL = "delete from voters
where voter_serial = {$voter_serial}";
$this->executeSQL($SQL);
}
// ============================
// Determine if a Voter exists
// ============================
public function voterExists() {
$voter_serial = filter_input(INPUT_POST, "voter_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
$voter_name = filter_input(INPUT_POST, "voter_name") ?: "";
$SQL = "select voter_serial
from view_voters
where voter_serial != :voter_serial
and lower(voter_name) = :voter_name";
$statement = $this->connect()->prepare($SQL);
$statement->bindValue(":voter_serial", $voter_serial);
$statement->bindValue(":voter_name", strtolower($voter_name));
$statement->execute();
$recordset = $statement->fetchAll(PDO::FETCH_ASSOC);
$exists = (count($recordset) > 0) ? true : false;
echo json_encode($exists);
}
// ======================================
// Determine if a Voter is Active (AJAX)
// ======================================
public function voterActive() {
$voter_serial = filter_input(INPUT_POST, "voter_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
$active = false;
$SQL = "select workorder_voter
from workorders
where workorder_voter = {$voter_serial}
limit 1";
$workorders = $this->getTable("workorders", $SQL);
$active = ($workorders->count() > 0) ? true : false;
echo json_encode($active);
}
// =============
// Edit a Voter
// =============
public function editVoter() {
$step = filter_input(INPUT_POST, "step") ?: "prompt";
switch ($step) {
case "prompt":
$voter_serial = filter_input(INPUT_POST, "voter_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
$voter = $this->getVoter($voter_serial);
if ($voter->count() == 0) {
$this->logError("Invalid Voter ({$voter_serial}). " . __METHOD__);
}
$XML = $this->mergeXML($voter, "<XML/>");
$content = $this->applyXSL($XML, $this->getXSL("editVoter"));
$this->displayContent($content);
break;
case "update":
$voter_serial = filter_input(INPUT_POST, "voter_serial", FILTER_SANITIZE_NUMBER_INT) ?: 0;
$voter_name = filter_input(INPUT_POST, "voter_name") ?: "";
$voter_classes = filter_input(INPUT_POST, "voter_classes") ?: "";
$voter_active = filter_input(INPUT_POST, "voter_active", FILTER_VALIDATE_BOOLEAN) ?: false;
$voter_default = filter_input(INPUT_POST, "voter_default", FILTER_VALIDATE_BOOLEAN) ?: false;
// Verify the Voter
$voter = $this->getVoter($voter_serial);
if ($voter->count() == 0) {
$this->logError("Invalid Voter ({$voter_serial}). " . __METHOD__);
}
$SQL = "update voters
set voter_name = :voter_name,
voter_classes = :voter_classes,
voter_active = :voter_active,
voter_default = :voter_default,
voter_changer = :voter_changer,
voter_changed = :voter_changed
where voter_serial = :voter_serial";
$statement = $this->connect()->prepare($SQL);
$statement->bindValue(":voter_serial", $voter_serial);
$statement->bindValue(":voter_name", $voter_name);
$statement->bindValue(":voter_classes", $voter_classes);
$statement->bindValue(":voter_active", $voter_active, PDO::PARAM_BOOL);
$statement->bindValue(":voter_default", $voter_default, PDO::PARAM_BOOL);
$statement->bindValue(":voter_changer", $this->current_user_name);
$statement->bindValue(":voter_changed", $this->getTimestamp());
$statement->execute();
break;
default:
$this->displayHome();
}
}
// ================================
// Return an Active Voters Object
// ================================
public function getActiveVoters() {
$SQL = "select view_voters.*
from view_voters
where voter_active is true";
return $this->getTable("voters", $SQL);
}
// -------------------------
// Return the Default Voter
// -------------------------
public function getDefaultVoter() {
$SQL = "select voter_serial
from view_voters
where voter_default is true";
return $this->getTable("voters", $SQL);
}
// =======================
// Return an Voter Object
// =======================
public function getVoter($voter_serial = 0) {
$SQL = "select view_voters.*
from view_voters
where voter_serial = {$voter_serial}";
return $this->getTable("voters", $SQL);
}
// ===========================
// Return a Voters Object
// ===========================
public function getVoters() {
$SQL = "select view_voters.*
from view_voters";
return $this->getTable("voters", $SQL);
}
// ============================
// Return a Voters Page Object
// ============================
public function getVotersPage() {
// Find Criteria
$find_voter = filter_input(INPUT_POST, "find_voter") ?: "";
$find_voter = trim($this->sanitizeString($find_voter));
$connection = $this->connect();
// ==========
// Pagination
// ==========
$pagination = filter_input(INPUT_POST, "pagination") ?: "";
$count = 0;
/*
* Blank admin load:
* - keep the count
*
* Search:
* - skip the full count because it is too expensive
*/
if ($find_voter === "") {
$SQL = "select count(*) as count
from voters";
$statement = $connection->prepare($SQL);
$statement->execute();
$recordset = $statement->fetch(PDO::FETCH_ASSOC);
$count = $recordset ? (int) $recordset["count"] : 0;
$max_page = max((int) ceil($count / $this->pagination_size), 1);
} else {
// For searches, do not run an expensive count query
$max_page = max((int) $this->pagination_page, 1);
}
switch ($pagination) {
case "first":
$this->pagination_page = 1;
break;
case "previous":
$this->pagination_page = max(($this->pagination_page - 1), 1);
break;
case "next":
$this->pagination_page = ($this->pagination_page + 1);
break;
case "last":
$this->pagination_page = $max_page;
break;
default:
$this->pagination_page = max((int) $this->pagination_page, 1);
break;
}
$offset = (($this->pagination_page - 1) * $this->pagination_size);
// ==========
// Data Query
// ==========
if ($find_voter === "") {
/*
* Blank load:
* - page voters first
* - then join the tiny lookup tables to only those page rows
*/
$SQL = "select v.voter_serial,
v.voter_id,
v.voter_name_first,
v.voter_name_last,
v.voter_residence_address_1,
v.voter_residence_city,
v.voter_residence_state,
v.voter_residence_zipcode,
v.voter_gender,
racecodes.racecode_description as voter_race_code_verbose,
politicalparties.politicalparty_name as voter_party_affiliation_verbose
from (
select voter_serial,
voter_id,
voter_name_first,
voter_name_last,
voter_residence_address_1,
voter_residence_city,
voter_residence_state,
voter_residence_zipcode,
voter_gender,
voter_race,
voter_party_affiliation
from voters
order by voter_serial
limit :limit
offset :offset
) v
left join racecodes
on racecodes.racecode_code = v.voter_race
left join politicalparties
on politicalparties.politicalparty_code = v.voter_party_affiliation
order by v.voter_serial";
$statement = $connection->prepare($SQL);
$statement->bindValue(":limit", (int) ($this->pagination_size + 1), PDO::PARAM_INT);
$statement->bindValue(":offset", (int) $offset, PDO::PARAM_INT);
} else {
/*
* Search:
* - use UNION so each branch can use its own index
* - then join back to voters
* - then join lookup tables
*/
$SQL = "select v.voter_serial,
v.voter_id,
v.voter_name_first,
v.voter_name_last,
v.voter_residence_address_1,
v.voter_residence_city,
v.voter_residence_state,
v.voter_residence_zipcode,
v.voter_gender,
racecodes.racecode_description as voter_race_code_verbose,
politicalparties.politicalparty_name as voter_party_affiliation_verbose
from (
select matches.voter_serial,
voters.voter_id,
voters.voter_name_first,
voters.voter_name_last,
voters.voter_residence_address_1,
voters.voter_residence_city,
voters.voter_residence_state,
voters.voter_residence_zipcode,
voters.voter_gender,
voters.voter_race,
voters.voter_party_affiliation
from (
select voter_serial
from voters
where voter_name_first like :find_words_first
union
select voter_serial
from voters
where voter_name_last like :find_words_last
union
select voter_serial
from voters
where voter_id like :find_words_id
) matches
join voters
on voters.voter_serial = matches.voter_serial
order by voters.voter_name_last, voters.voter_name_first, voters.voter_serial
limit :limit
offset :offset
) v
left join racecodes
on racecodes.racecode_code = v.voter_race
left join politicalparties
on politicalparties.politicalparty_code = v.voter_party_affiliation
order by v.voter_name_last, v.voter_name_first, v.voter_serial";
$statement = $connection->prepare($SQL);
$statement->bindValue(":find_words_first", $find_voter . "%", PDO::PARAM_STR);
$statement->bindValue(":find_words_last", $find_voter . "%", PDO::PARAM_STR);
$statement->bindValue(":find_words_id", $find_voter . "%", PDO::PARAM_STR);
$statement->bindValue(":limit", (int) $this->pagination_size, PDO::PARAM_INT);
$statement->bindValue(":offset", (int) $offset, PDO::PARAM_INT);
}
$statement->execute();
$voters = $this->getTableXML("voters", $statement);
// ============================
// Insert Pagination Attributes
// ============================
if ($find_voter === "") {
$start = $count > 0 ? ($offset + 1) : 0;
$end = min($count, ($offset + $this->pagination_size));
} else {
/*
* Search total count is intentionally skipped.
* We only know what is on the current page.
*/
$rows_on_page = $statement->rowCount();
$count = 0;
$start = $rows_on_page > 0 ? ($offset + 1) : 0;
$end = $offset + $rows_on_page;
}
$voters->addAttribute("count", $count);
$voters->addAttribute("start", $start);
$voters->addAttribute("end", $end);
$voters->addAttribute("page", $this->pagination_page);
$_SESSION[self::PAGINATION_PAGE] = $this->pagination_page;
return $voters;
}
}
?>